先写代码,然后再一个问题,一个问题分析。不是应该先分析问题,再写代码吗?因为笨呗。分析不明白。只有看到现象,才能明白手册上说的是啥意思。
实例1 主要完成以下几个事情
1 创建一个misc驱动
2 在驱动中将寄存器remap过来,需要映射的寄存器的列表,不要怕,代码都有。

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

如下,ioremap其实是一个宏,但是宏看起来不好理解,所以,我就把它当成一个下面这样的函数来用,好理解,ioremap的返回值,可以作为iounmap的参数,ioremap的第一个参数paddr就是前面列表中的寄存器地址,例如0x20c 8180,它是32位寄存器,4个字节,所以参数byte_count传入4。
- #include
- volatile void __iomem *ioremap(void *paddr,int byte_count);
- 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 ;
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define DEBUG_TEMP(format,...) printk("%s,%d:"format"\n", \
- __func__,__LINE__,##__VA_ARGS__)
-
- /* 寄存器物理地址 */
- #define TEMPMON_TEMPSENSE0 (0x020C8180)
- #define TEMPMON_TEMPSENSE0_SET (0x020C8184)
- #define TEMPMON_TEMPSENSE0_CLR (0x020C8188)
- #define TEMPMON_TEMPSENSE0_TOG (0x020C818C)
-
- #define TEMPMON_TEMPSENSE1 (0x020C8190)
- #define TEMPMON_TEMPSENSE1_SET (0x020C8184)
- #define TEMPMON_TEMPSENSE1_CLR (0x020C8198)
- #define TEMPMON_TEMPSENSE1_TOG (0x020C819C)
-
- #define TEMPMON_TEMPSENSE2 (0x020C8290)
- #define TEMPMON_TEMPSENSE2_SET (0x020C8294)
- #define TEMPMON_TEMPSENSE2_CLR (0x020C8298)
- #define TEMPMON_TEMPSENSE2_TOG (0x020C829C)
-
- /* 映射后的寄存器虚拟地址指针 */
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE0;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_SET;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_CLR;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE0_TOG;
-
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE1;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_SET;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_CLR;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE1_TOG;
-
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE2;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_SET;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_CLR;
- static void __iomem *IMX6U_TEMPMON_TEMPSENSE2_TOG;
-
- struct temperature_register{
- void __iomem *ctrl;
- void __iomem *set;
- void __iomem *clr;
- void __iomem *tog;
- };
-
- struct _temperature_sensor_{
- struct miscdevice misc;
- struct file_operations fops;
- struct temperature_register reg[3];
- struct timer_list timer;
- };
-
- #define IMX6U_TEMPMON_TEMPSENSE(num) (IMX6U_TEMPMON_TEMPSENSE##num)
- #define IMX6U_TEMPMON_TEMPSENSE_XXX(num,text) (IMX6U_TEMPMON_TEMPSENSE##num##text)
-
- static int imx_temperature_monitor_init(struct _temperature_sensor_ *p)
- {
- int i = 0;
- u32 val;
- IMX6U_TEMPMON_TEMPSENSE0 = ioremap(TEMPMON_TEMPSENSE0,4);
- IMX6U_TEMPMON_TEMPSENSE0_SET = ioremap(TEMPMON_TEMPSENSE0_SET,4);
- IMX6U_TEMPMON_TEMPSENSE0_CLR = ioremap(TEMPMON_TEMPSENSE0_CLR,4);
- IMX6U_TEMPMON_TEMPSENSE0_TOG = ioremap(TEMPMON_TEMPSENSE0_TOG,4);
-
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_SET);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_CLR);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE0_TOG);
-
- IMX6U_TEMPMON_TEMPSENSE1 = ioremap(TEMPMON_TEMPSENSE1,4);
- IMX6U_TEMPMON_TEMPSENSE1_SET = ioremap(TEMPMON_TEMPSENSE1_SET,4);
- IMX6U_TEMPMON_TEMPSENSE1_CLR = ioremap(TEMPMON_TEMPSENSE1_CLR,4);
- IMX6U_TEMPMON_TEMPSENSE1_TOG = ioremap(TEMPMON_TEMPSENSE1_TOG,4);
-
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_SET);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_CLR);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE1_TOG);
-
- IMX6U_TEMPMON_TEMPSENSE2 = ioremap(TEMPMON_TEMPSENSE2,4);
- IMX6U_TEMPMON_TEMPSENSE2_SET = ioremap(TEMPMON_TEMPSENSE2_SET,4);
- IMX6U_TEMPMON_TEMPSENSE2_CLR = ioremap(TEMPMON_TEMPSENSE2_CLR,4);
- IMX6U_TEMPMON_TEMPSENSE2_TOG = ioremap(TEMPMON_TEMPSENSE2_TOG,4);
-
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_SET);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_CLR);
- DEBUG_TEMP("%p",IMX6U_TEMPMON_TEMPSENSE2_TOG);
-
- p->reg[0].ctrl = IMX6U_TEMPMON_TEMPSENSE(0);
- p->reg[0].set = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_SET);
- p->reg[0].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_CLR);
- p->reg[0].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(0,_TOG);
-
- p->reg[1].ctrl = IMX6U_TEMPMON_TEMPSENSE(1);
- p->reg[1].set = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_SET);
- p->reg[1].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_CLR);
- p->reg[1].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(1,_TOG);
-
- p->reg[2].ctrl = IMX6U_TEMPMON_TEMPSENSE(2);
- p->reg[2].set = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_SET);
- p->reg[2].clr = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_CLR);
- p->reg[2].tog = IMX6U_TEMPMON_TEMPSENSE_XXX(2,_TOG);
-
- for(i = 0;i < 3;i++){
- DEBUG_TEMP("p->reg[%d].ctrl = %p",i,p->reg[i].ctrl);
- DEBUG_TEMP("p->reg[%d].set = %p",i,p->reg[i].set);
- DEBUG_TEMP("p->reg[%d].clr = %p",i,p->reg[i].clr);
- DEBUG_TEMP("p->reg[%d].tog = %p",i,p->reg[i].tog);
- }
- DEBUG_TEMP("");
- DEBUG_TEMP("");
- for(i = 0;i < 3;i++){
- DEBUG_TEMP("p->reg[%d].ctrl = %08x",i,readl(p->reg[i].ctrl));
- DEBUG_TEMP("p->reg[%d].set = %08x",i,readl(p->reg[i].set));
- DEBUG_TEMP("p->reg[%d].clr = %08x",i,readl(p->reg[i].clr));
- DEBUG_TEMP("p->reg[%d].tog = %08x",i,readl(p->reg[i].tog));
- }
-
- writel(1 << 0,p->reg[0].clr);
- writel(2 << 0,p->reg[0].clr);
- writel(1 << 1,p->reg[0].set);
-
-
- writel(1,p->reg[1].clr);
- return 0;
- }
- static long imx_temperature_unlocked_ioctl (
- struct file *file, unsigned int cmd, unsigned long arg)
- {
- DEBUG_TEMP("");
- return 0;
- }
- struct _temperature_sensor_ imx_temperature_sensor = {
- .fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = imx_temperature_unlocked_ioctl,
- },
- .misc = {
- .name = "imx_temp",
- .minor = MISC_DYNAMIC_MINOR,
- },
- };
- void temperature_timer_function(unsigned long arg)
- {
- struct _temperature_sensor_ *p = (struct _temperature_sensor_ *)arg;
- u32 val = readl(p->reg[0].ctrl);
- static int last_val = 0;
-
- while(1){
- if((val & 0x04) == 0){
- break;
- }
-
- DEBUG_TEMP("val = %08x,%d,%d,temperature = %d",val,val-last_val,(val&0xfff00000)>>20,(val&0xfff00)>>8);
- last_val = val;
-
- writel(1 << 0,p->reg[0].clr);
- writel(2 << 0,p->reg[0].clr);
- writel(1 << 1,p->reg[0].set);
- break;
- }
- mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
- }
- static int __init temperature_init(void)
- {
- struct _temperature_sensor_ *p = &imx_temperature_sensor;
- p->misc.fops = &p->fops;
- imx_temperature_monitor_init(p);
-
-
- if(misc_register(&p->misc) != 0){
- DEBUG_TEMP("misc_register error");
- return -EINVAL;
- }
- init_timer(&p->timer);
- p->timer.data = (unsigned long)p;
- p->timer.function = temperature_timer_function;
- mod_timer(&p->timer,msecs_to_jiffies(1000) + jiffies);
- DEBUG_TEMP("");
- return 0;
- }
- static void __exit temperature_exit(void)
- {
- struct _temperature_sensor_ *p = &imx_temperature_sensor;
- int i = 0;
- del_timer_sync(&p->timer);
- for(i = 0;i < 3;i++){
- iounmap(p->reg[i].ctrl);
- iounmap(p->reg[i].set);
- iounmap(p->reg[i].clr);
- iounmap(p->reg[i].tog);
- }
-
- misc_deregister(&p->misc);
- DEBUG_TEMP("");
- }
- module_init(temperature_init);
- module_exit(temperature_exit);
- MODULE_LICENSE("GPL");
-
- export ARCH=arm
- export CROSS_COMPILE=arm-linux-gnueabihf-
- KERN_DIR = /home/lkmao/imx/linux/linux-imx
-
- FILE_NAME=temperature
- obj-m += $(FILE_NAME).o
-
- all:
- make -C $(KERN_DIR) M=$(shell pwd) modules
- sudo cp $(FILE_NAME).ko /big/nfsroot/buildrootfs/home/root/
- sudo scp $(FILE_NAME).ko root@192.168.0.3:/home/root/
- .PHONY:clean
- clean:
- make -C $(KERN_DIR) M=$(shell pwd) clean
- rm app -rf
- [ 1428.046419] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
- [ 1429.046419] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
- [ 1430.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1431.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1432.046418] temperature_timer_function,166:val = 49a4d006,256,1178,temperature = 1232
- [ 1433.046425] temperature_timer_function,166:val = 49a4d006,0,1178,temperature = 1232
- [ 1434.046415] temperature_timer_function,166:val = 49a4cf06,-256,1178,temperature = 1231
- [ 1435.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1436.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1437.046420] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1438.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1439.046418] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1440.046419] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231
- [ 1441.046421] temperature_timer_function,166:val = 49a4cf06,0,1178,temperature = 1231