• imx6ull内置温度传感器实践1:输出一个采样


    前言

            先写代码,然后再一个问题,一个问题分析。不是应该先分析问题,再写代码吗?因为笨呗。分析不明白。只有看到现象,才能明白手册上说的是啥意思。   

            实例1 主要完成以下几个事情

            1 创建一个misc驱动

            2 在驱动中将寄存器remap过来,需要映射的寄存器的列表,不要怕,代码都有。

             3 配置寄存器的值,然后在1秒定时器中输出TEMP_CNT值

     

    一 使用到的函数

            映射和解除映射函数

            如下,ioremap其实是一个宏,但是宏看起来不好理解,所以,我就把它当成一个下面这样的函数来用,好理解,ioremap的返回值,可以作为iounmap的参数,ioremap的第一个参数paddr就是前面列表中的寄存器地址,例如0x20c 8180,它是32位寄存器,4个字节,所以参数byte_count传入4。

    1. #include
    2. volatile void __iomem *ioremap(void *paddr,int byte_count);
    3. void iounmap (volatile void __iomem *addr)

    读寄存器函数

    u8 readb ( const volatile void __iomem * addr )
    u16 readw ( const volatile void __iomem * addr )
    u32 readl ( const volatile void __iomem * addr )
    readb readw readl 这三个函数分别对应 8bit 16bit 32bit 读操作,参数 addr 就是要
    读取写内存地址,返回值就是读取到的数据。

    写寄存器函数

    void writeb ( u8 value , volatile void __iomem * addr )
    void writew ( u16 value , volatile void __iomem * addr )
    void writel ( u32 value , volatile void __iomem * addr )
    writeb writew writel 这三个函数分别对应 8bit 16bit 32bit 写操作,参数 value 是要
    写入的数值, addr 是要写入的地址。

    本次实例,我们使用writel readl

    二 实例代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #define DEBUG_TEMP(format,...) printk("%s,%d:"format"\n", \
    15. __func__,__LINE__,##__VA_ARGS__)
    16. /* 寄存器物理地址 */
    17. #define TEMPMON_TEMPSENSE0 (0x020C8180)
    18. #define TEMPMON_TEMPSENSE0_SET (0x020C8184)
    19. #define TEMPMON_TEMPSENSE0_CLR (0x020C8188)
    20. #define TEMPMON_TEMPSENSE0_TOG (0x020C818C)
    21. #define TEMPMON_TEMPSENSE1 (0x020C8190)
    22. #define TEMPMON_TEMPSENSE1_SET (0x020C8184)
    23. #define TEMPMON_TEMPSENSE1_CLR (0x020C8198)
    24. #define TEMPMON_TEMPSENSE1_TOG (0x020C819C)
    25. #define TEMPMON_TEMPSENSE2 (0x020C8290)
    26. #define TEMPMON_TEMPSENSE2_SET (0x020C8294)
    27. #define TEMPMON_TEMPSENSE2_CLR (0x020C8298)
    28. #define TEMPMON_TEMPSENSE2_TOG (0x020C829C)
    29. /* 映射后的寄存器虚拟地址指针 */
    30. static void __iomem *IMX6U_TEMPMON_TEMPSENSE0;
    31. static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_SET;
    32. static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_CLR;
    33. static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_TOG;
    34. static void __iomem *IMX6U_TEMPMON_TEMPSENSE1;
    35. static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_SET;
    36. static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_CLR;
    37. static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_TOG;
    38. static void __iomem *IMX6U_TEMPMON_TEMPSENSE2;
    39. static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_SET;
    40. static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_CLR;
    41. static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_TOG;
    42. struct temperature_register{
    43. void __iomem *ctrl;
    44. void __iomem *set;
    45. void __iomem *clr;
    46. void __iomem *tog;
    47. };
    48. struct _temperature_sensor_{
    49. struct miscdevice misc;
    50. struct file_operations fops;
    51. struct temperature_register reg[3];
    52. struct timer_list timer;
    53. };
    54. #define IMX6U_TEMPMON_TEMPSENSE(num) (IMX6U_TEMPMON_TEMPSENSE##num)
    55. #define IMX6U_TEMPMON_TEMPSENSE_XXX(num,text) (IMX6U_TEMPMON_TEMPSENSE##num##text)
    56. static int imx_temperature_monitor_init(struct _temperature_sensor_ *p)
    57. {
    58. int i = 0;
    59. u32 val;
    60. IMX6U_TEMPMON_TEMPSENSE0 = ioremap(TEMPMON_TEMPSENSE0,4);
    61. IMX6U_TEMPMON_TEMPSENSE0_SET = ioremap(TEMPMON_TEMPSENSE0_SET,4);
    62. IMX6U_TEMPMON_TEMPSENSE0_CLR = ioremap(TEMPMON_TEMPSENSE0_CLR,4);
    63. IMX6U_TEMPMON_TEMPSENSE0_TOG = ioremap(TEMPMON_TEMPSENSE0_TOG,4);
    64. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0);
    65. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_SET);
    66. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_CLR);
    67. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_TOG);
    68. IMX6U_TEMPMON_TEMPSENSE1 = ioremap(TEMPMON_TEMPSENSE1,4);
    69. IMX6U_TEMPMON_TEMPSENSE1_SET = ioremap(TEMPMON_TEMPSENSE1_SET,4);
    70. IMX6U_TEMPMON_TEMPSENSE1_CLR = ioremap(TEMPMON_TEMPSENSE1_CLR,4);
    71. IMX6U_TEMPMON_TEMPSENSE1_TOG = ioremap(TEMPMON_TEMPSENSE1_TOG,4);
    72. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1);
    73. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_SET);
    74. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_CLR);
    75. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_TOG);
    76. IMX6U_TEMPMON_TEMPSENSE2 = ioremap(TEMPMON_TEMPSENSE2,4);
    77. IMX6U_TEMPMON_TEMPSENSE2_SET = ioremap(TEMPMON_TEMPSENSE2_SET,4);
    78. IMX6U_TEMPMON_TEMPSENSE2_CLR = ioremap(TEMPMON_TEMPSENSE2_CLR,4);
    79. IMX6U_TEMPMON_TEMPSENSE2_TOG = ioremap(TEMPMON_TEMPSENSE2_TOG,4);
    80. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2);
    81. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_SET);
    82. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_CLR);
    83. DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_TOG);
    84. p->reg[0].ctrl = IMX6U_TEMPMON_TEMPSENSE(0);
    85. p->reg[0].set = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_SET);
    86. p->reg[0].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_CLR);
    87. p->reg[0].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_TOG);
    88. p->reg[1].ctrl = IMX6U_TEMPMON_TEMPSENSE(1);
    89. p->reg[1].set = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_SET);
    90. p->reg[1].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_CLR);
    91. p->reg[1].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_TOG);
    92. p->reg[2].ctrl = IMX6U_TEMPMON_TEMPSENSE(2);
    93. p->reg[2].set = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_SET);
    94. p->reg[2].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_CLR);
    95. p->reg[2].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_TOG);
    96. for(i = 0;i < 3;i++){
    97. DEBUG_TEMP("p->reg[%d].ctrl = %p",i,p->reg[i].ctrl);
    98. DEBUG_TEMP("p->reg[%d].set = %p",i,p->reg[i].set);
    99. DEBUG_TEMP("p->reg[%d].clr = %p",i,p->reg[i].clr);
    100. DEBUG_TEMP("p->reg[%d].tog = %p",i,p->reg[i].tog);
    101. }
    102. DEBUG_TEMP("");
    103. DEBUG_TEMP("");
    104. for(i = 0;i < 3;i++){
    105. DEBUG_TEMP("p->reg[%d].ctrl = %08x",i,readl(p->reg[i].ctrl));
    106. DEBUG_TEMP("p->reg[%d].set = %08x",i,readl(p->reg[i].set));
    107. DEBUG_TEMP("p->reg[%d].clr = %08x",i,readl(p->reg[i].clr));
    108. DEBUG_TEMP("p->reg[%d].tog = %08x",i,readl(p->reg[i].tog));
    109. }
    110. writel(1 << 0,p->reg[0].clr);
    111. writel(2 << 0,p->reg[0].clr);
    112. writel(1 << 1,p->reg[0].set);
    113. writel(1,p->reg[1].clr);
    114. return 0;
    115. }
    116. static long imx_temperature_unlocked_ioctl (
    117. struct file *file, unsigned int cmd, unsigned long arg)
    118. {
    119. DEBUG_TEMP("");
    120. return 0;
    121. }
    122. struct _temperature_sensor_ imx_temperature_sensor = {
    123. .fops = {
    124. .owner = THIS_MODULE,
    125. .unlocked_ioctl = imx_temperature_unlocked_ioctl,
    126. },
    127. .misc = {
    128. .name = "imx_temp",
    129. .minor = MISC_DYNAMIC_MINOR,
    130. },
    131. };
    132. void temperature_timer_function(unsigned long arg)
    133. {
    134. struct _temperature_sensor_ *p = (struct _temperature_sensor_ *)arg;
    135. u32 val = readl(p->reg[0].ctrl);
    136. static int last_val = 0;
    137. while(1){
    138. if((val & 0x04) == 0){
    139. break;
    140. }
    141. DEBUG_TEMP("val = %08x,%d,%d,temperature = %d",val,val-last_val,(val&0xfff00000)>>20,(val&0xfff00)>>8);
    142. last_val = val;
    143. writel(1 << 0,p->reg[0].clr);
    144. writel(2 << 0,p->reg[0].clr);
    145. writel(1 << 1,p->reg[0].set);
    146. break;
    147. }
    148. mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
    149. }
    150. static int __init temperature_init(void)
    151. {
    152. struct _temperature_sensor_ *p = &imx_temperature_sensor;
    153. p->misc.fops = &p->fops;
    154. imx_temperature_monitor_init(p);
    155. if(misc_register(&p->misc) != 0){
    156. DEBUG_TEMP("misc_register error");
    157. return -EINVAL;
    158. }
    159. init_timer(&p->timer);
    160. p->timer.data = (unsigned long)p;
    161. p->timer.function = temperature_timer_function;
    162. mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
    163. DEBUG_TEMP("");
    164. return 0;
    165. }
    166. static void __exit temperature_exit(void)
    167. {
    168. struct _temperature_sensor_ *p = &imx_temperature_sensor;
    169. int i = 0;
    170. del_timer_sync(&p->timer);
    171. for(i = 0;i < 3;i++){
    172. iounmap(p->reg[i].ctrl);
    173. iounmap(p->reg[i].set);
    174. iounmap(p->reg[i].clr);
    175. iounmap(p->reg[i].tog);
    176. }
    177. misc_deregister(&p->misc);
    178. DEBUG_TEMP("");
    179. }
    180. module_init(temperature_init);
    181. module_exit(temperature_exit);
    182. MODULE_LICENSE("GPL");

    Makefile

    1. export ARCH=arm
    2. export CROSS_COMPILE=arm-linux-gnueabihf-
    3. KERN_DIR = /home/lkmao/imx/linux/linux-imx
    4. FILE_NAME=temperature
    5. obj-m += $(FILE_NAME).o
    6. all:
    7. make -C $(KERN_DIR) M=$(shell pwd) modules
    8. sudo cp $(FILE_NAME).ko /big/nfsroot/buildrootfs/home/root/
    9. sudo scp $(FILE_NAME).ko root@192.168.0.3:/home/root/
    10. .PHONY:clean
    11. clean:
    12. make -C $(KERN_DIR) M=$(shell pwd) clean
    13. rm app -rf

    测试结果

    1. [ 1428.046419] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
    2. [ 1429.046419] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
    3. [ 1430.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    4. [ 1431.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    5. [ 1432.046418] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
    6. [ 1433.046425] temperature_timer_function,166:val = 49a4d006,0,1178,temperature = 1232
    7. [ 1434.046415] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
    8. [ 1435.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    9. [ 1436.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    10. [ 1437.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    11. [ 1438.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    12. [ 1439.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    13. [ 1440.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
    14. [ 1441.046421] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231

    小结

  • 相关阅读:
    电信保温杯笔记——《统计学习方法(第二版)——李航》第19章 马尔可夫链蒙特卡罗法
    算法题Day71
    SQL语言---数据的查询
    【校招VIP】前端专业课之七层模型
    超详细讲解Redis基础类型String增删改查及加减数据(带Java库源码)
    云计算 - 云安全探索
    js获取当前日期并转化为yyyy-MM-dd hh:mm:ss 格式
    Bee2.1.8支持Spring Boot 3.0.11,active命令行选择多环境,多表查改增删(bee-spring-boot发布,更新maven)
    vcontact2:病毒聚类(失败)
    .NET Aspire 预览版 6 发布
  • 原文地址:https://blog.csdn.net/yueni_zhao/article/details/127889836