主题中讨论的其他器件:CC2538
大家好、
我在这方面花了几个小时、我感到很损失。 我们有一款使用 OpenThread 框架的产品、我正在尝试让看门狗计时器在该框架上工作、以便器件在现场发生故障时可以自行恢复。
在发生这种情况时、看门狗计时器正是为了实现这一点、阅读文档似乎就足够简单了。 问题是… 可能狗发出的声音不够大、无法重置 MCU。
作为参考、我 在这里提交了我的更改。 工具链是在 Linux/AMD64上运行的 GNU ARM GCC (用于 ARM 嵌入式处理器6-2017-Q2-update 的 GNU 工具)。
下面是 objdump 的输出、显示了 C 和汇编…中的初始化序列 我的眼睛看、该汇编代码看起来是正确的。 初始化代码基于我在基础固件中看到的内容以及我对文档的理解。 这样做的目的是:
1、通过清零 EN 位来关闭看门狗
2.将当前配置读入临时存储器
3.将计时器间隔设置为32768个周期(~1秒)
4.将其写入配置寄存器
5.重新读取配置
6.清除(未记录!) 模式位
7.设置使能位
8.将临时值写入配置寄存器
/*初始化看门狗*/ { uint32_t tmp; HWREG (SMWDTHROSC_WDCTL)&=~(1 << 3); /*关闭*/ 21184a: 4b0d LDR R3,[PC,#52];(211880 ) 21184c: 681a LDR R2、[R3、#0] 21184e: F022 0208 BIC.w R2、R2、#8 211852: 601a 结构 R2、[R3、#0] tmp = HWREG (SMWDTHROSC_WDCTL); 211854: 681a LDR R2、[R3、#0] tmp &=~0x03; 211856: F022 0203 BIC.w R2、R2、#3. tmp |=(0 << 0); HWREG (SMWDTHROSC_WDCTL)=温度; 21185a: 601a 结构 R2、[R3、#0] tmp = HWREG (SMWDTHROSC_WDCTL); 21185c: 681a LDR R2、[R3、#0] tmp &=~(1 << 2); 21185e: F022 0204 BIC.w R2、R2、#4. tmp |=(1 << 3); 211862: F042 0208 ORR.w R2、R2、#8 HWREG (SMWDTHROSC_WDCTL)=温度; 211866: 601a 结构 R2、[R3、#0] 211868: BD08 弹出 {R3、PC} HWREG (GPIO_C_BASE |(0x0F << 2))^= 0xff; 21186A: 6813. LDR R3、[R2、#0] 21186c: f083 03ff EOR.w R3、R3、#255;0xff 211870: 6013. 结构 R3、[R2、#0] 211872: e7e8. b.n 211846. 211874: 400d9400 .word 0x400d9400 211878: 400db420 .word 0x400db420 21187c: 400d40d0 .word 0x400d40d0 211880: 400d5000 .word 0x400d5000
在主循环中、执行以下代码(再次显示了与 objdump 源代码的反汇编):
void PlatformProcessDrivers (otInstance * aInstance) { 211884: b538 按{R3、R4、R5、LR} 静态 uint16_t LED_DELAY = 0; 静态 uint8_t LED_dir = 0; 静态 uint16_t LED_SPEED = 10000; sInstance = aInstance; 如果(!LED_DELAY){ 211886: 4a25. LDR R2,[PC,#148];(21191c. ) sInstance = aInstance; 211888: 4b25. LDR R3,[PC,#148];(211920 ) { 21188a: 4604. MOV R4、r0 sInstance = aInstance; 21188c: 6018. 结构 R0、[R3、#0] 如果(!LED_DELAY){ 21188e: 8813. ldrh R3、[R2、#0] 211890: 4615 MOV R5、R2 211892: b9f3 cbnz R3、2118d2 如果(LED_DIR) 211894: 4923. LDR R1,[PC,#140];(211924 ) 211896: 4b24. LDR r3,[PC,#144];(21928) ) 211898: 780a ldrb R2、[R1、#0] LED >=1; 21189a: 7818. ldrb r0、[R3、#0] 如果(LED_DIR) 21189c: b1aa CBZ R2、2118ca LED >=1; 21189e: 0840 LSR r0、r0、#1 其他 LED <= 1; 2118a0: 7018. strb r0、[R3、#0] 如果(!(LED 和0x0F)){ 2118a2: 7818. ldrb r0、[R3、#0] 2118a4: 0700 lls r0、r0、#28 2118a6: D106 BNE.n 2118b6 如果(LED_DIR) 2118a8: b18a CBZ R2、2118ce LED = 2; 2118aa: 2002年 MOV r0、#2 其他 LED = 4; LED_dir =!LED_dir; 2118ac: 晶圆制造厂2 f282. CLZ R2、R2 2118b0: 0952. LSR R2、R2、#5 LED = 4; 2118b2: 7018. strb r0、[R3、#0] LED_dir =!LED_dir; 2118b4: 700A strb R2、[R1、#0] } HWREG (GPIO_C_BASE |(0x0F <<2))= LED; 2118b6: 781a ldrb R2、[R3、#0] 2118b8: 4b1c LDR r3、[PC、#112];(21192c. ) 2118ba: 601a 结构 R2、[R3、#0] LED_DELAY = LED_SPEED; 2118bc: 4b1c LDR r3,[PC,#112];(21930 ) 2118be: 881b ldrh R3、[R3、#0] 2118c0: 802b. strh R3、[R5、#0] } 否则{ LED_DELAY_-; } /*如果按住按钮,则暂停*/ 如果(!HWREG (GPIO_C_base |((1 << 4)<< 2))){ 2118c2: 4b1c LDR R3,[PC,#112];(211934. ) 2118c4: 681b LDR R3、[R3、#0] 2118c6: b93b cbnz R3、2118d8 2118c8: e7fe b.n 2118c8. LED <<= 1; 2118ca: 0040. lsls r0、r0、#1 2118cc: e7e8. b.n 2118a0 LED = 4; 2118ce: 2004年 MOV r0、#4 2118d0: e7ec b.n 2118交流 LEDS_DELAY_-; 2118d2: 3B01 SUS R3、#1 2118d4: 8013. strh R3、[R2、#0] 2118d6: e7f4. b.n 2118c2. while (1); } 如果(!HWREG (GPIO_C_base |((1 << 6)<< 2))) 2118d8: 4b17. LDR R3,[PC,#92];(21938 ) 2118da: 681b LDR R3、[R3、#0] 2118dc: b91b cbnz R3、2118e6 LED_SPEED = 2500; 2118de: f640 12c4. movw R2、#2500 ;0x9c4 2118e2: 4b13. LDR r3,[PC,#76];(21930 ) 2118e4: 801a strh R2、[R3、#0] 如果(!HWREG (GPIO_C_base |((1 << 7)<< 2))) 2118e6: 4b15. LDR r3,[PC,#84];(21193c. ) 2118e8: 681b LDR R3、[R3、#0] 2118ea: b91b cbnz r3、2118f4 LED_SPEED = 40000; 2118ec: f649 4240 movw R2、#40000 ;0x9c40 2118f0: 4b0f LDR r3,[PC,#60];(21930 ) 2118f2: 801a strh R2、[R3、#0] /*喂入看门狗*/ { uint32_t tmp = HWREG (SMWDTHROSC_WDCTL)& 0x0F; 2118f4: 4a12. LDR R2,[PC,#72];(211940 ) 2118f6: 6813. LDR R3、[R2、#0] 2118f8: f003 030f AND。w R3、R3、#15 HWREG (SMWDTHROSC_WDCTL)= 0x50 | tmp; 2118fc: f043 0150 ORR.w R1、R3、#80 ;0x50 HWREG (SMWDTHROSC_WDCTL)= 0xa0 | tmp; 211900: F043 03A0 ORR.w R3、R3、#160;0xa0 HWREG (SMWDTHROSC_WDCTL)= 0x50 | tmp; 211904: 6011. 结构 R1、[R2、#0] HWREG (SMWDTHROSC_WDCTL)= 0xa0 | tmp; 211906: 6013. 结构 R3、[R2、#0] } //应该在这里睡眠并等待中断 cc2538UartProcess (); 211908: F000 fc48 BL 21219c cc2538RadioProcess (aInstance); 21190c: 4620 MOV R0、R4 21190e: F000 f9cf BL 211cb0 cc2538AlarmProcess (aInstance); 211912: 4620 MOV R0、R4 } 211914: e8bd 4038 ldmia。w sp!、{R3、R4、R5、LR} cc2538AlarmProcess (aInstance); 211918: f7ff bf1e b.w 211758. 21191c: 20002aba .word 0x20002aba 211920: 20002980 .word 0x20002980 211924: 20002abc. .word 0x20002abc 211928: 20002ab9. .word 0x20002ab9 21192c: 400db03c .word 0x400db03c 211930: 20000008. .word 0x20000008 211934: 400db040 .word 0x400db040 211938: 400db100 .word 0x400db100 21193c: 400db200 .word 0x400db200 211940: 400d5000 .word 0x400d5000
现在有一些指令的重新排序、但所说的要点仍然存在。 值得注意的是、按下左侧按钮时的 while (1)循环。 这是对 CPU 卡滞且需要看门狗复位的仿真。 但看门狗永远不会触发。 如果我点击该按钮、然后使用调试器进入代码、我会看到以下状态:
(gdb) printf "ctl=%08x stat=%08x WDT=%08x\n"、(*(volatile UINT32_t*)(0x400d2000))、(*(volatile UINT32_t*)(0x400d2004))、(*(volatile UINT32_t)(0x400d5000) dDT=00000008=c00000000000
即时钟控制和状态寄存器以及看门狗寄存器的状态。 可以看到、两个晶体振荡器都打开并运行、I/O 和系统时钟以32MHz 运行、看门狗也打开。 文档指出、对于这些设置、它应该在一秒后复位(32.768kHz 时为32768个周期= 1秒)。
显然、我需要做更多的事情来启用看门狗、但 CC2538的用户指南和基础固件中的示例都没有说明这应该如何工作。