一、什么是看門狗定時器
看門狗是一個定時器(倒計時),有計時的功能,當看門狗的計數值減為0,會產生一個復位信號給處理器,這樣處理器就會重啟,軟體就會重新運行,
二、看門狗定時器的作用
當系統在運行的程序中,由于受到干擾(雷擊、電機運行、手機、汽車…)或者系統的錯誤,而產生了死機(程式跑飛)不能正常作業,看門狗可以讓系統自動重啟,重新開始運行代碼,讓系統恢復到正常作業的狀態,
看門狗不是用來解決產品設計的bug,
三、S5PV210的看門狗
1、計時值是16bits的,
2、看門狗定時器有兩個功能:
1)作為看門狗,可以產生復位信號(講解)
2)作為一個普通的定時器,可以產生周期性的中斷
四、S5PV210看門狗的原理(復位功能)
見看門狗框圖
五、看門狗的暫存器
只需要理解WTCON和WTCNT兩個暫存器,
六、解決三個問題
1)C語言的位操作運算
在處理器中,一般一個暫存器都是32bits的,每個位都有特殊的含義,通常配置暫存器的時候,不是配置暫存器的整個值,而是配置暫存器的某個位,
C位操作運算子:&、|、~、^、<<、>>
求:
1<<2 + 3 = 1<<(2+3)=32
例1:求一個位元組資料中,有多少個位為1?
int byte_cnt(unsigned char data)
{
int count = 0;
for(int i=0;i<8;i++)
{
if(data & (1<<i))
count++;
}
return count;
}
例2:unsigned int data,將data的第10位置1,其他位保持不變,
data = data | (1<<10);
data |= (1<<10);
例3:unsigned int data,將data的第10位清0,其他位保持不變,
data = data & ~(1<<10);
data &= ~(1<<10);
例4:unsigned int data,將data的第10位取反,其他位保持不變,
data ^= (1<<10);
2)如何通過地址訪問地址下的資料
在處理器中,每個暫存器都有唯一的地址,我們配置暫存器的時候,通常都是通過暫存器的地址來配置的,所以需要理解通過暫存器的地址如何訪問地址下的內容,
例1:將0xaa66寫入地址0x67a9
0x67a9 = 0xaa66;不對
unsigned short *p=NULL;//定義一個指向unsigned short資料的指標,思考:sizeof§\sizeof(*p)
p = (unsigned short *)0x67a9;
*p = 0xaa66;
或者:
*(unsigned short *)0x67a9 = 0xaa66
題目是有問題的,
例2:將0x12345678寫入0x40000000地址,
答:
*(unsigned int *)0x40000000 = 0x12345678;
例3:讀出0x40000000地址下int的資料給a;
答:
unsigned int a;
a = *(unsigned int *)0x40000000;
3)在驅動中,如何訪問處理器的暫存器?
物理地址:硬體實際的地址,在原理圖或者處理器的使用手冊中,得到的都是物理地址,在裸機環境下,可以直接訪問物理地址,
虛擬地址:作業系統使用的地址是虛擬地址,虛擬地址是對應到物理地址的,操作做系統不能直接使用物理地址,要使用物理地址對應的虛擬地址,
驅動程式是作業在Linux內核中的,是的地址是虛擬地址,
結論:我們需要知道WTCON和WTCNT這兩個暫存器物理地址對應的虛擬地址,然后通過虛擬地址再訪問暫存器,
七、如何得到物理地址對應的虛擬地址


//驅動的頭檔案
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#define WDT_START 1 //看門狗打開
#define WDT_STOP 2 //看門狗關閉
#define WDT_ALIVE 3 //看門狗喂狗
static void __iomem * WTBASE_VA;
static void __iomem * WTCON_VA; //WTCON的虛擬地址
static void __iomem * WTCNT_VA; //WTCNT的虛擬地址
//定義一個檔案操作集--給應用程式提供介面
//給應用程式open()的介面
static int mini210_wdt_open(struct inode *inode, struct file *filp)
{
printk("mini210 wdt driver openning\n");
return 0;
}
//給應用程式read()的介面
static ssize_t mini210_wdt_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
char wdt_flag;
int ret,i;
if(len != 1)
return -EINVAL;//Invalid argument
ret = copy_from_user(&wdt_flag, buf, len);
if(ret != 0){
return -EFAULT;
}
switch(wdt_flag){
case WDT_START:
*(unsigned int *)WTCON_VA |= (1<<5); //enable wdt
break;
case WDT_STOP:
*(unsigned int *)WTCON_VA &= ~(1<<5); //disable wdt
break;
case WDT_ALIVE:
*(unsigned int *)WTCNT_VA = 26050;//計數值重新賦值
break;
default:
return -EINVAL;
}
return len;
}
//給應用程式close()的介面
static int mini210_wdt_release(struct inode *inode, struct file *filp)
{
printk("mini210 wdt driver closing\n");
return 0;
}
static struct file_operations mini210_wdt_fops = {
.owner = THIS_MODULE,
.open = mini210_wdt_open,
.write = mini210_wdt_write,
.release = mini210_wdt_release,
};
//定義一個混雜設備驅動模型
static struct miscdevice mini210_misc = {
.minor = MISC_DYNAMIC_MINOR,//內核自動分配次設備號
.name = "wdt_drv",//混雜設備的名字,也是設備檔案的名字
.fops = &mini210_wdt_fops, //檔案操作集
};
//看門狗驅動的安裝函式
static int __init mini210_wdt_init(void)
{
//看門狗驅動的安裝程序
int ret,i;
//得到虛擬地址對應的物理地址
WTBASE_VA = ioremap(0xE2700000, 16);
if(WTBASE_VA == NULL)
{
printk("ioremap failed\n");
return -EFAULT;
}
WTCON_VA = WTBASE_VA + 0x00;
WTCNT_VA = WTBASE_VA + 0x08;
printk("VA: %p,%p\n", WTCON_VA,WTCNT_VA);
//將混雜設備驅動模型注冊到內核
ret = misc_register(&mini210_misc);
if(ret < 0){
printk("wdt misc register error\n");
goto misc_reg_err;
}
printk("mini210 wdt driver init....\n");
//初始化看門狗(不能讓看門狗作業)
//prescaler value=199,disable wdt,division factor=128,enable reset
*(unsigned int *)WTCON_VA = (199<<8)+(3<<3)+(1<<0);//看門狗的計數頻率:2605Hz
//設定看看門狗的計數值,確定看門狗的復位時間是10秒
*(unsigned int *)WTCNT_VA = 26050;// 26050/2605=10秒
return 0;
misc_reg_err:
iounmap(WTBASE_VA);
return ret;
}
//蜂鳴器驅動的卸載函式
static void __exit mini210_wdt_exit(void)
{
int i;
//蜂鳴器驅動的卸載程序
iounmap(WTBASE_VA);
misc_deregister(&mini210_misc);
printk("mini210 wdt driver exit....\n");
}
//模塊的入口和出口
module_init(mini210_wdt_init);//#insmod wdt_drv.ko-->驅動的入口
module_exit(mini210_wdt_exit);//#rmmod wdt_drv-->驅動的出口
//模塊的描述(驅動的描述)
MODULE_AUTHOR("bobeyfeng@163.com");
MODULE_DESCRIPTION("S5PV210 wdt Device Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("V1.0");
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define WDT_START 1 //看門狗打開
#define WDT_STOP 2 //看門狗關閉
#define WDT_ALIVE 3 //看門狗喂狗
/**開啟看門狗,10秒內喂狗,測驗看門狗不復位功能,過一段時間,關閉看門狗,系統不會復位**/
int main(void)
{
int fd_wdt,count=0;
unsigned char wdt_cmd;
fd_wdt = open("/dev/wdt_drv", O_RDWR);
if(fd_wdt == -1)
{
perror("open wdt error");
return -1;
}
wdt_cmd = WDT_START;
write(fd_wdt, &wdt_cmd , 1);//打開看門狗
pirntf("wdt is starting, please keep alive in 10 second\n");
while(1)
{
sleep(8);
wdt_cmd = WDT_ALIVE;
write(fd_wdt, &wdt_cmd , 1);//看門狗喂狗
printf("wdt keepalive \n");
count++;
if(count == 5)
break;
}
wdt_cmd = WDT_STOP;
write(fd_wdt, &wdt_cmd , 1);//關閉看門狗
while(1)
{
pirntf("wdt was stopped, no reset\n");
sleep(1);
}
close(fd_wdt);
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define WDT_START 1 //看門狗打開
#define WDT_STOP 2 //看門狗關閉
#define WDT_ALIVE 3 //看門狗喂狗
/**開啟看門狗,10秒內沒有喂狗,測驗自動復位功能**/
int main(void)
{
int fd_wdt;
unsigned char wdt_cmd;
fd_wdt = open("/dev/wdt_drv", O_RDWR);
if(fd_wdt == -1)
{
perror("open wdt error");
return -1;
}
wdt_cmd = WDT_START;
write(fd_wdt, &wdt_cmd , 1);//打開看門狗
pirntf("wdt is starting, please keep alive in 10 second\n");
while(1)
{
for(i=9;i>0;i--)
{
printf("%d second\n",i);
sleep(1);
}
printf("wdt resetting \n");
}
close(fd_wdt);
return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define WDT_START 1 //看門狗打開
#define WDT_STOP 2 //看門狗關閉
#define WDT_ALIVE 3 //看門狗喂狗
/**開啟看門狗,10秒內喂狗,測驗看門狗不復位功能**/
int main(void)
{
int fd_wdt;
unsigned char wdt_cmd;
fd_wdt = open("/dev/wdt_drv", O_RDWR);
if(fd_wdt == -1)
{
perror("open wdt error");
return -1;
}
wdt_cmd = WDT_START;
write(fd_wdt, &wdt_cmd , 1);//打開看門狗
pirntf("wdt is starting, please keep alive in 10 second\n");
while(1)
{
sleep(8);
wdt_cmd = WDT_ALIVE;
write(fd_wdt, &wdt_cmd , 1);//看門狗喂狗
printf("wdt keepalive \n");
}
close(fd_wdt);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/301485.html
標籤:其他
上一篇:ONAP — 系統架構
下一篇:HTTP之URL
