linux watchdog 分析


WatchDog接口適配

1sp805相關驅動接口

(1)sp805 支持的接口===具體芯片支持的接口

static const structwatchdog_ops wdt_ops = {

.owner =THIS_MODULE,

.start =wdt_enable,

.stop =wdt_disable,

.ping = wdt_ping,

.set_timeout =wdt_setload,

.get_timeleft =wdt_timeleft,

};

wdt->wdd.ops = &wdt_ops;

(2) watch_core支持的接口======通用框架接口

static const structfile_operations watchdog_fops = {

.owner =THIS_MODULE,

.write =watchdog_write,

.unlocked_ioctl =watchdog_ioctl,

.open =watchdog_open,

.release =watchdog_release,};

struct cdev {

struct kobject kobj;

ruct module *owner;

const structfile_operations *ops;

struct list_head list;

dev_t dev;

unsigned int count;};

cdev_init(&watchdog->cdev,&watchdog_fops);

這裏對字符設備的註冊,爲後續open文件系統接口,提供獲取具體設備的信息,後續inode通過設備文件節點號關聯到cdev,從而訪問驅動。

static intwatchdog_open(struct inode *inode, struct file *file)

{

int err = -EBUSY;

struct watchdog_device*wdd;

/* Get the correspondingwatchdog device */

if (imajor(inode) ==MISC_MAJOR)

wdd = old_wdd;

else

wdd =container_of(inode->i_cdev, struct watchdog_device, cdev);

…........................................

}

其中ioctl通過獲取具體wdd設備,從而可以獲取具體設備的功能接口,支持上層ioctl功能

static longwatchdog_ioctl(struct file *file, unsigned int cmd,

unsigned long arg)

{

struct watchdog_device*wdd = file->private_data;

void __user *argp =(void __user *)arg;

int __user *p = argp;

unsigned int val;

int err;

…..............................

}

ioctl支持的功能

case WDIOC_GETSUPPORT:

case WDIOC_GETSTATUS:

case WDIOC_GETBOOTSTATUS:

case WDIOC_SETOPTIONS:

case WDIOC_KEEPALIVE:

case WDIOC_SETTIMEOUT:

case WDIOC_GETTIMEOUT:

case WDIOC_GETTIMELEFT:


2sp805標準實現

注意sp805標準實現:目前實現沒有WDIOF_GETTIMEOUT WDIOC_GETTIMELEFT:

其中WDIOC_GETTIMELEFT操作的寄存器觀察都是0

static const structwatchdog_info wdt_info = {

.options =WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,

.identity = MODULE_NAME,

};

3、測試代碼:

int main(intargc, char *argv[])

{

int flags = 0;

unsigned inttime = 0;

structwatchdog_info wdgInfo;

int err = 0;

fd =open("/dev/watchdog0", O_RDWR);

if (fd == -1){

fprintf(stderr,"Watchdog device not enabled.\n");

fflush(stderr);

exit(-1);

           }

if (argc >1) {

if(!strncasecmp(argv[1], "-d", 2)) {

flags =WDIOS_DISABLECARD;

ioctl(fd,WDIOC_SETOPTIONS, &flags);

fprintf(stderr,"Watchdog card disabled.\n");

fflush(stderr);

goto end;

} else if(!strncasecmp(argv[1], "-e", 2)) {

flags =WDIOS_ENABLECARD;

ioctl(fd,WDIOC_SETOPTIONS, &flags);

fprintf(stderr,"Watchdog card enabled.\n");

fflush(stderr);

goto end;

}else if (!strncasecmp(argv[1], "-settimeout", 11)) { //代碼問題

time =atoi(argv[2]) ;

err =ioctl(fd, WDIOC_SETTIMEOUT, &time);

if(err <0)

{

fprintf(stderr,"settimefailed,errno is %d\n",err);

}

fprintf(stderr,"Watchdog set time %d.\n",time);

fflush(stderr);

goto end;

}else if (!strncasecmp(argv[1], "-gettimeout", 11)) { //代碼問題

err =ioctl(fd, WDIOC_GETTIMEOUT, &time);

if(err <0)

{

fprintf(stderr,"gettimeout failed,errno is %d\n",err);

}

fflush(stderr);

goto end;

} elseif (!strncasecmp(argv[1], "-gettimeleft",12)) {

time = 0;

err =ioctl(fd, WDIOC_GETTIMELEFT, &time);

if( err <0)

{

fprintf(stderr,"gettimeleft failed,errno is %d\n",err);

}

fprintf(stderr,"Watchdog get time %d.\n",time);

fflush(stderr);

goto end;

} else if(!strncasecmp(argv[1], "-getsupport", 11)) {

ioctl(fd,WDIOC_GETSUPPORT, &wdgInfo);

fprintf(stderr,"Watchdog card info.\n");

fprintf(stderr,"Watchdog card is %#x, %s.\n",wdgInfo.options,wdgInfo.identity);

fflush(stderr);

goto end;

} elseif(!strncasecmp(argv[1], "-ping", 5)) {

fprintf(stderr,"ping.\n");

fprintf(stderr,"run by itself to tick the card.\n");

fflush(stderr);

goto end;

}else{

fprintf(stderr,"errorintput.\n");

fflush(stderr);

}

}

end:

close(fd);

return 0;

}

4sp805適配問題

GetTimeout功能適配需要修改sp805watchdog_dev.c中的代碼。

IOCTl 函數:

case WDIOC_SETTIMEOUT:

if(get_user(val, p))

return-EFAULT;

err =watchdog_set_timeout(wdd, val);//這裏最終只修改了wdt中的timeout,不是wdd中的timeout

pr_err("WDIOC_SETTIMEOUT errno %d,wdd->timeout %d\n",err,wdd->timeout);

if (err< 0)

returnerr;

/* Ifthe watchdog is active then we send a keepalive ping

* tomake sure that the watchdog keep's running (and if

*possible that it takes the new timeout) */

watchdog_ping(wdd);

/* Fall*/

caseWDIOC_GETTIMEOUT:

pr_err("WDIOC_GETTIMEOUT in\n");

/*timeout == 0 means that we don't know the timeout */

if (wdd->timeout == 0) //所以這裏會出現問題,應該算是代碼bug

return-EOPNOTSUPP;

intret=put_user(wdd->timeout, p);

pr_err("WDIOC_GETTIMEOUT %d,return ret%d\n",wdd->timeout,ret);

Sp805中剩餘時間硬件寄存器爲0導致GET_TIMELEFT功能不正常,可能是硬件不支持,也可能是沒有配置正確,需要硬件人員提供信息,但是sp805中本省對外提供的capility也沒有GET_TIMELEFT功能,暫時mark一下。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章