RK3288_Android7.1调试RTC总结(一)主要是讲解rtc的调试和驱动框架浅析,
RK3288_Android7.1调试RTC总结(二)主要讲解看门狗方面的内容。
我这里主要是基于rtc芯片:am1805的驱动来说明。

rtc1805驱动跑起来就默认看门狗是kernel feeddog,每隔2s feeddog一次(feeddog就是向特定的寄存器写入值,这就是喂狗的实质),如果没有feeddog就会触发系统强制复位而重启系统,喂狗的方式有内核自动喂狗和用户喂狗两种方式实现:
1、用户喂狗:
在用户空间定时地去操作喂狗的动作,让rtc芯片在定时器到来之前,不触发系统强制复位而重启系统:

2、内核喂狗:
驱动循环运行一个工作队列去执行喂狗的动作,只要内核运行就会一直自动喂狗。

/**  am1805_watchdog_feeddog- set up the watchdog timer   ** Inputs:*    period - timeout period in ms (65 to 124,000)*  pin - pin to generate the watchdog signal*      0 => disable WDT*       1 => generate an interrupt on FOUT/nIRQ*        2 => generate an interrupt on PSW/nIRQ2*        3 => generate a reset on nRST (AM18xx only)**/am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);//设置feeddog,并且使能reset pin,发送feeddog信号
am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_DISABLE); //设置disabled feeddog

rtc_am1805看门狗验证

首先确认有以下两个节点:

sys/class/rtc_am1805/feeddog //feddog 操作
sys/class/rtc_am1805/timer //设置disabled feeddog之后,然后重新使能kernel feeddog在time之后系统重启

feeddog节点对应代码实现:

static ssize_t am1805_show_feeddog(struct class *class,struct class_attribute *attr, char *buf)
{int ret;if (rtc_info->watchdog_enable==TYPE_DISABLE){ret = sprintf(buf, "0 -- disable\n");}else if(rtc_info->watchdog_enable==TYPE_KERNLE){ret = sprintf(buf, "1 -- kernel feed\n");}else{ret = sprintf(buf, "2 -- user feed\n");}return ret;
}static ssize_t am1805_store_feeddog(struct class *class,struct class_attribute *attr, const char *buf, size_t count)
{int type;RTC_DBG(RTC_DBG_VAL, "%s ,run \n",__func__);sscanf(buf,"%i",&type);if(type==0){rtc_info->watchdog_enable = TYPE_DISABLE;am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_DISABLE);}else if(type==1){rtc_info->watchdog_enable = TYPE_KERNLE;am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);}else{rtc_info->watchdog_enable = TYPE_USER;am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);}return count;
}static struct class_attribute rtc_class_attrs[] = {__ATTR(show_all_reg, S_IRUGO | S_IWUSR, show_all_reg, NULL),__ATTR(time, S_IRUGO | S_IWUSR, show_time, store_time),__ATTR(regwrite, S_IRUGO | S_IWUSR, NULL, store_reg),__ATTR(regread, S_IRUGO | S_IWUSR, NULL,show_reg),__ATTR(feeddog, S_IRUGO | S_IWUSR, am1805_show_feeddog,am1805_store_feeddog),__ATTR(timer, S_IRUGO | S_IWUSR, aml1805_show_timer, am1805_store_timer),__ATTR(setalarm, S_IRUGO | S_IWUSR, am1805_set_alarm,NULL),__ATTR_NULL
};static struct class rtc_am1805_class = {.name = "rtc_am1805",.class_attrs = rtc_class_attrs,
};

probe函数中调用以下接口创建class节点[这里只节选部分代码]:

static int rtc_am1805_probe(struct platform_device *pdev)
{...
ret = class_register(&rtc_am1805_class);if (ret){pr_info(" class register rtc_class fail!\n");return -1;}
...
}

设置和查看看门狗(WDT)的状态:

root@stvs912:/ # cat sys/class/rtc_am1805/feeddog
1 -- kernel feed //驱动默认起来就是kernel feeddog状态root@stvs912:/ # echo 0 > sys/class/rtc_am1805/feeddog //关闭看门狗功能
root@stvs912:/ # echo 1 > sys/class/rtc_am1805/feeddog //kernel feeddog,kernel有定时器设置,每隔一定时间(feeddog time)kernel会自动feeddog,这里时间是2s
root@stvs912:/ # echo 2 > sys/class/rtc_am1805/feeddog //user feeddog,需要用户每隔一定时间feeddog一次(shell-env下执行echo 2 > sys/class/rtc_am1805/feeddog),否则会自动复位重启系统

对应代码如下:

static ssize_t am1805_show_feeddog(struct class *class,struct class_attribute *attr, char *buf)
{int ret;if (rtc_info->watchdog_enable==TYPE_DISABLE){ret = sprintf(buf, "0 -- disable\n");}else if(rtc_info->watchdog_enable==TYPE_KERNLE){ret = sprintf(buf, "1 -- kernel feed\n");}else{ret = sprintf(buf, "2 -- user feed\n");}return ret;
}

通过以下节点可以设置feeddog time,验证看门狗功能:

rk3399_all:/ # ls -l sys/class/rtc_am1805/timer
-rw-r--r-- 1 root root 4096 2019-11-13 09:19 sys/class/rtc_am1805/timer

例如feeddog设置disabled feeddog之后,然后重新使能kernel feeddog在time(10s)之后系统重启可以这样验证:

rk3399_all:/ # echo 0 > sys/class/rtc_am1805/feeddog //disabled feeddog
rk3399_all:/ # echo 1 > sys/class/rtc_am1805/feeddog //enable kernel feeddog
rk3399_all:/ # echo 10000 > sys/class/rtc_am1805/timer //设置feeddog = 10s,也就是设置喂狗的时间为10s,10s之前要喂狗(或者kernel喂狗或者user喂狗)
rk3399_all:/ # cat sys/class/rtc_am1805/timer
10000
rk3399_all:/ # echo 2 > sys/class/rtc_am1805/feeddog //设置用户喂狗,并且每次周期的10s之前要喂狗一次

对应代码实现如下[节选部分]:

static ssize_t aml1805_show_timer(struct class* class,struct class_attribute *att, char* buf)
{RTC_DBG(RTC_DBG_VAL, "%s ,run \n",__func__);return sprintf(buf, "%d\n", rtc_info->watchdog_timer);
}static ssize_t am1805_store_timer(struct class* class,struct class_attribute* att, const char* buf, size_t count)
{int value;RTC_DBG(RTC_DBG_VAL, "%s ,run \n",__func__);sscanf(buf,"%i",&value);RTC_DBG(RTC_DBG_VAL, "value = %d \n", value);rtc_info->watchdog_timer = value;am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);return count;
}

真待机导致机器在进入休眠之后会重启

原因分析:
目前我们的板子都是做的假待机,所以feeddog不会受影响,如果是真待机情况下[kernel进入休眠,不跑kernel],kernel就不自动feeddog就会导致系统重启,所以需要在suspend的情况下关闭feeddog,在唤醒系统的时候再重新打开,以下是feeddog的接口函数。

解决方法:添加休眠唤醒的处理函数,当机器进入休眠的时候,disabled掉watchdog功能,在机器唤醒之后,重新使能watchdog功能即可。

具体代码实现(代码来自rk3399 7.1):

+static int rtc_am1805_suspend(struct device *dev)
+{+       pr_info("%s,line(%d): enter suspend\n", __func__, __LINE__);
+       //rtc_info->watchdog_enable = TYPE_DISABLE;
+       am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_DISABLE);
+
+       return 0;
+}
+
+static int rtc_am1805_resume(struct device *dev)
+{+
+       pr_info("%s,line(%d): enter resume\n", __func__, __LINE__);
+       if(rtc_info->watchdog_enable != TYPE_DISABLE)
+               am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);
+       return 0;
+}
+static void rtc_am1805_shutdown(struct i2c_client * client){unsigned char val=0;
@@ -1374,6 +1392,9 @@ static void rtc_am1805_shutdown(struct i2c_client * client)rtc_am1805_i2c_write(&val, WDT_REG, 0x01);}+static SIMPLE_DEV_PM_OPS(rtc_am1805_pm_ops, rtc_am1805_suspend,
+                                               rtc_am1805_resume);
+static const struct i2c_device_id am1805_id[] = {{ "rtc_am1805", 0 },{ }
@@ -1389,6 +1410,7 @@ struct i2c_driver rtc_am1805_driver = {.name = "rtc_am1805",.owner = THIS_MODULE,.of_match_table = am1805_rtc_dt_match,
+               .pm = &rtc_am1805_pm_ops,},.probe = rtc_am1805_probe,.remove = (rtc_am1805_remove),

设置feeddog间隔时间 echo xxxx > sys/class/rtc_am1805/timer ,之后到时间就自动重启了

static ssize_t am1805_store_timer(struct class* class,struct class_attribute* att, const char* buf, size_t count)
{int value;RTC_DBG(RTC_DBG_VAL, "%s ,run \n",__func__);sscanf(buf,"%i",&value);RTC_DBG(RTC_DBG_VAL, "value = %d \n", value);rtc_info->watchdog_timer = value;
//      am1805_watchdog_feeddog(rtc_info->watchdog_timer,WATCHDOG_INT_PIN_RST);  //注释掉这句就可以,因为只设置时间即可,不需要再去执行写寄存器的操作return count;
}

RK3288_Android7.1调试RTC总结(二)相关推荐

  1. RK3399外设驱动之RTC驱动(二):hym8563驱动

    RK3399外设驱动之RTC驱动(二):hym8563驱动 文章目录 RK3399外设驱动之RTC驱动(二):hym8563驱动 hym8563硬件相关 注册驱动 probe函数 hym8563_in ...

  2. Linux调试之(二)gdb+vmlinux

    文章目录 Linux调试之(二)gdb+vmlinux [1]定位arm-eabi-gdb 和 vmlinux [2]gdb加载内核符号表 1.查看内核符号表 2.执行arm-eabi-gdb vml ...

  3. STM32F407ZET6的RTC闹钟二次设置笔记

    在研究让用户可以通过矩阵键盘输入更改闹钟时,遇到数值传递后没有触发闹钟中断函数的情况. 经过反复测试记录下需要的步骤. RTC闹钟设置步骤为: //配置RTC闹钟A void RTC_SetAlarm ...

  4. ddr老化测试_【鼎阳硬件智库原创︱DDR 】 DDR硬件调试篇:DDR硬件设计调试测试 之二...

    DDR硬件调试篇 前言:大家自己设计的产品出来后都有遇到一些什么样的DDR问题呢?这些问题是否为致命问题,一定要解吗?如果机器已经生产出来,却发现DDR硬件问题导致系统不稳定,机器是否作废了,有没有软 ...

  5. 高通Camera 驱动调试要点(二)

    这篇文章主要介绍数据流这边Camera ISP这块所遇到的问题,主要介绍bus overflow和sof freeze: (一)bus overflow   摄像头传感器时钟通道(即 MIPI DDR ...

  6. 第十三届蓝桥杯嵌入式备赛-STM32G431-进阶模块调试⑦RTC时钟

    目录 0.前言 1.功能要求 2.STM32Cubemx初始化 3.程序实现 main.c相关初始化 RTC函数 RTC_CalendarGet()日期时间获取函数 设置日期RTC_SetDate和时 ...

  7. SAP Spartacus 服务器端渲染单步调试步骤之二:在服务器端执行应用程序 Angular 代码

    前文:SAP Spartacus 服务器端渲染单步调试步骤之一:应用程序准备工作 入口: 进入 platform-server.js: 入口: 最终在服务器端执行 bootstrap,输入 Compo ...

  8. GDB调试技术(二)

    1) 恢复程序运行和单步调试 当程序被停住了,你可以用continue命令恢复程序的运行直到程序结束,或下一个断点到来.也可以使用step或next命令单步跟踪程序. continue [ignore ...

  9. S32K144调试记录(二)

    最近在调试一个新板子,我负责板子上通讯模块程序的编写和调试,调试的时候断断续续遇到不少问题,在这里记录下. 调试CAN收发过程中遇到的问题 1 现象 接上篇CAN/LIN的收发程序调通了之后,紧接着整 ...

  10. 5G时代带动陶瓷PCB成长——GPS陶瓷天线调试方法(二)

    2.2开槽Slot-Y 切削Slot-Y位置,在Smith Chart 上可看出其轨迹图会以外圈为圆心,依顺时针的方向旋转偏向电容性阻抗.需要特别注意的是切削Slot-Y位置,原则上左右两边都开槽会对 ...

最新文章

  1. java如何画出表格_Java利用iText7画个性化表格
  2. 第三章 使用单元测试测试简单的首页
  3. LeetCode 网易-1. 分割环(前缀和 + 哈希)
  4. wampserver橙色如何变成绿色_实验室如何自建数据库和网站主页
  5. 河南省队选拔 HAOI2015 解题报告
  6. 失意时,你是怎么救自己的?
  7. 不知道图片加文字水印怎么弄?这3个方法自媒体达人必学
  8. RPA风潮席卷全行业,本土厂商如何把握未来?
  9. ch341a i2c 安卓_CH341A安卓平板OTG连接成功但读取不到数据
  10. 摩托车新手驾驶教程[2]
  11. java swing实训项目(图书管理系统)
  12. 鸿蒙开发板Hi3861_通过GPIO12 PWM蜂鸣器播放<涛声依旧>-——基于code-2.0-CANARY
  13. JAVA实现随机生成航班数据
  14. L1-044. 稳赢
  15. 微信公众号项目开发笔记 一
  16. 快速认识陌生字的方法!几秒钟就可查到怎么读!
  17. Processon一款免费好用的画图工具
  18. 支付宝与微信新年红包战之我见
  19. Access教程 第二章 建立数据库
  20. camera sensor简单曝光原理

热门文章

  1. Objective-C的动态特性
  2. 两个小的java程序,用于练习java基本语法
  3. 转:你真的懂iOS的autorelease吗?
  4. cocos-2d iphone入门(二) cocos2d源代码生成查询文档
  5. .NET 指南:属性与方法之间的选择
  6. 赛尔笔记 | 事件间因果关系方向数据调研
  7. 【赛尔原创】如何自动地向知识图谱中添加属性?
  8. 教练级导师带你打5场AI大赛,还有奖金5万元的工业级AI实战赛等你来战!
  9. python—IFrame:在jupyter notebook中展示某个网页的情况
  10. 服务器远程登录工具、文件运行以Python为例