您的位置:首页 > 运维架构 > Linux

linux watchdog 分析

2014-06-27 16:30 281 查看
WatchDog接口适配
1、sp805相关驱动接口
(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:

2、sp805标准实现
注意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;

}
4、sp805适配问题
GetTimeout功能适配需要修改sp805和watchdog_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一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: