linux操作系统添加看门狗定时

先贴代码
//看门狗物理地址
#define WATCHDOG_BASE                        0x01C20000                   //基地址
#define BLOCK_SIZE                                                 0X1000                          //4K大小

#define rWDOG0_IRQ_EN                                         0xCA0                                 
#define rWDOG0_IRQ_STA                                         0xCA4 
#define rWDOG0_CTRL                                         0xCB0 
#define rWDOG0_CFG                                                0xCB4 
#define rWDOG0_MODE                                         0xCB8 





/**
*@brief          看门狗和time定时
*/
void *wdog_timer(void *b)
{        
        int mem_fd = -1;  
        unsigned char *wdog_map = NULL;
        volatile unsigned int *WDOG0_IRQ_EN = NULL;
        volatile unsigned int *WDOG0_IRQ_STA = NULL;
        volatile unsigned int *WDOG0_CTRL = NULL;
        volatile unsigned int *WDOG0_CFG = NULL;
        volatile unsigned int *WDOG0_MODE = NULL;        
        /* open /dev/mem */  
        if ((mem_fd = open("/dev/mem", O_RDWR | O_CREAT, 0666)) < 0) 
        {  
                printf("can't open /dev/mem \n");
                exit(-1);  
        }  
        /* mmap WDOG0 */  
        wdog_map = (unsigned char *)mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, WATCHDOG_BASE);
        close(mem_fd);
        if (wdog_map == MAP_FAILED) 
        {
                printf("mmap error %d\n", (int)wdog_map);
                exit(-1);  
        }
   // Always use volatile pointer!
        WDOG0_IRQ_EN = (volatile unsigned int *)(wdog_map + rWDOG0_IRQ_EN);
        WDOG0_IRQ_STA = (volatile unsigned int *)(wdog_map + rWDOG0_IRQ_STA);
        WDOG0_CTRL = (volatile unsigned int *)(wdog_map + rWDOG0_CTRL);
        WDOG0_CFG = (volatile unsigned int *)(wdog_map + rWDOG0_CFG);
        WDOG0_MODE = (volatile unsigned int *)(wdog_map + rWDOG0_MODE);
        
        *(volatile unsigned int *)WDOG0_IRQ_EN = 0x01;
        *(volatile unsigned int *)WDOG0_CFG = 0x01;
        *(volatile unsigned int *)WDOG0_MODE = 0x30;                        //看门狗3秒
        *(volatile unsigned int *)WDOG0_MODE |= 0X01;
   while(1)
   {           
                //添加自己的程序
             //这里可以加一个判断,如果正常返回,我们就关闭看门狗,否则退出就重启了






if(join_thread_flag == 1)     //如果标志置1,我们就正常返回,关闭看门狗
                {                
                        *(volatile unsigned int *)WDOG0_MODE &= ~(0X01 << 0);
                        *(volatile unsigned int *)WDOG0_IRQ_EN = 0x0;
                        munmap(0, BLOCK_SIZE); 
                        break;
                }
                *(volatile unsigned int *)WDOG0_CTRL |= ((0XA57 << 1) | (0X01 << 0));        //喂狗
   }
}




mmap系统调用的过程:
void *addr;
addr = mmap(0,0x1000, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
参数1:如果是0,内核帮找一块内存区域,起始地址是返回值addr
参数2:虚拟内存的大小,0x1000一页(如果申请的内存空间没有对齐,内核会帮我们对齐,会经过一次if/else判断,浪费开销)
参数3:权限
参数4:权限
参数5:fd,将该文件映射到该区域
参数6:映射的偏移量




通过数据手册我查到看门狗的基地址0x01C20C00,但是我们通过mmap函数传参的地址只能传页(4k)的整数倍,所以我传的地址是0x01C20000,然后这个函数给我们返回了一个指针,通过操作这个指针,加上实际物理地址的偏移量,我们就能操作寄存器了,比如我的寄存器rWDOG0_IRQ_EN的偏移量是0xA0,但是我传参时少传了一个0xC00,所以偏移量加上这个即可,就成了0xCA0,以此类推

猜你喜欢

转载自blog.csdn.net/a3535719/article/details/80768716