micropython多线程与看门狗WDT实践笔记

1、umodbus2.3.7做modbus slaver客户端后,while True:result = client.process()非阻塞,这个如果不用多线程,其他的工作都得放到这个while True死循环里面来运行了。

2、deepseek推荐了一个健壮的多线程管理器,试了好用。

# MicroPython多线程Ctrl+C处理方案
import _thread
import time
import sys

class ThreadManager:
    def __init__(self):
        self.exit_flag = False
        self.threads = []

    def thread_function(self, name):
        while not self.exit_flag:
            try:
                print(f"Thread {name} is running")
                time.sleep(1)
            except Exception as e:
                print(f"Thread {name} caught exception: {e}")
                break
        print(f"Thread {name} exiting")

    def start_thread(self, name):
        thread_id = _thread.start_new_thread(self.thread_function, (name,))
        self.threads.append(thread_id)
        return thread_id

    def stop_all_threads(self):
        self.exit_flag = True
        # 等待所有线程退出
        time.sleep(1.5)  # 根据线程清理所需时间调整

def main():
    manager = ThreadManager()
    
    # 启动多个线程
    manager.start_thread("A")
    manager.start_thread("B")
    
    try:
        # 主线程工作
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        print("\nReceived Ctrl+C, stopping threads...")
        manager.stop_all_threads()
        print("All threads stopped. Exiting.")
        sys.exit(0)

if __name__ == "__main__":
    main()

3、看门狗没用过,想试试,那就再建一个看门狗线程?用上面这个多线程管理器。

    def thread_function(self, name):
        while not self.exit_flag:
            try: # 按照参数name运行不同的函数
                if name == 'mbslaver':
                    MbSlave.call_mbslaver()
                if name == 'watchdog':
                    wdt.feed()  # 重置看门狗计时器
                print(f"Thread {name} is running")
                time.sleep(1)
            except Exception as e:
                print(f"Thread {name} caught exception: {e}")
                break
        print(f"Thread {name} exiting")

deepseek说“通常喂狗操作应该放在主循环中,以确保主程序正常运行”。所以思路不对,应该改成主线程喂狗。

def main():
    manager = ThreadManager()
    # 启动多个线程
    manager.start_thread("mbslaver")
    #manager.start_thread("watchdog") #思路不对,应该是主线程喂狗,注释掉

    # 初始化硬件看门狗,超时时间为5秒(单位:毫秒)
    wdt = machine.WDT(timeout=5000)

    try:
        # 主线程工作
        while True:
            time.sleep(6)
            # 通常喂狗操作应该放在主循环中,以确保主程序正常运行
            wdt.feed()
    except KeyboardInterrupt:
        print("\nReceived Ctrl+C, stopping threads...")
        manager.stop_all_threads()
        print("All threads stopped. Exiting.")
        sys.exit(0)

if __name__ == "__main__":
    main()

测试一下,wdt = machine.WDT(timeout=5000) 让主线程time.sleep(6),不停的复位:

E (11667) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (11667) task_wdt:  - mpy_machine_wdt (CPU 0/1)
E (11667) task_wdt: Tasks currently running:
E (11667) task_wdt: CPU 0: IDLE0
E (11667) task_wdt: CPU 1: IDLE1
E (11667) task_wdt: Print CPU 0 (current core) backtrace

Backtrace: 0x40160D1F:0x3FFC0020 0x40085A21:0x3FFC0050 0x4009268B:0x3FFBBE20 0x4015F2CA:0x3FFBBE40 0x400D2F94:0x3FFBBE60 0x40096248:0x3FFBBE80

E (11667) task_wdt: Aborting.
E (11667) task_wdt: Print CPU 1 backtrace

A fatal error occurred. The crash dump printed below may be used to help
determine what caused it. If you are not already running the most recent
version of MicroPython, consider upgrading. New versions often fix bugs.

To learn more about how to debug and/or report this crash visit the wiki
page at: https://github.com/micropython/micropython/wiki/ESP32-debugging

MPY version : v1.25.0 on 2025-04-15
IDF version : v5.2.2
Machine     : Generic ESP32 module with ESP32

Backtrace: 0x4009268b:0x3ffbc420 0x4015f2ca:0x3ffbc440 0x400d2f94:0x3ffbc460 0x40096248:0x3ffbc480

ELF file SHA256: b93509347

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:4892
ho 0 tail 12 room 4
load:0x40078000,len:14896
load:0x40080400,len:4
load:0x40080404,len:3372
entry 0x400805b0

<think>嗯,用户问的是AWR2944中看门狗的使用。首先,我需要回忆一下AWR2944是什么。哦,对,这是TI(德州仪器)的一款毫米波雷达传感器,属于其AWR2x系列,主要用于汽车和工业应用中的雷达系统。看门狗定时器(WDT)在嵌入式系统中非常重要,用来检测和恢复系统故障,防止程序跑飞或死锁。 首先,用户可能需要了解如何在AWR2944上配置和使用看门狗。我应该先解释看门狗的基本原理,然后具体到AWR2944的实现。不过,AWR2944的文档可能比较专业,需要确保信息准确。 接下来,我需要确认AWR2944的看门狗模块的具体细节。比如,它的时钟源、预分频设置、重载值、以及如何喂狗。不同的微控制器可能有不同的寄存器配置,所以必须参考TI的官方资料,比如Technical Reference Manual(TRM)或者相关的应用笔记。 可能用户会遇到配置看门狗的问题,比如如何初始化,如何在程序中正确喂狗,避免误触发复位。这时候需要分步骤说明,可能包括代码示例。但要注意代码的正确性,可能需要基于TI的驱动程序库,比如使用DriverLib中的函数。 另外,用户可能想知道看门狗在AWR2944中的实际应用场景,比如在雷达信号处理中的使用,如何确保关键任务按时执行,或者如何在多任务环境中合理使用看门狗。这时候需要结合实际应用场景,说明最佳实践。 还需要注意,看门狗有窗口模式吗?或者说是否有不同的工作模式?如果有的话,需要解释清楚。比如,普通的看门狗和窗口看门狗的区别,以及如何配置。 可能用户在使用过程中遇到了看门狗复位的问题,比如系统频繁复位,这时候需要排查是否喂狗不及时,或者配置错误,比如重载值太小导致看门狗超时太快。这时候需要给出调试建议,比如检查时钟配置、重载值计算是否正确,喂狗的位置是否合理。 另外,AWR2944是否支持看门狗中断?也就是说,在超时前触发中断,而不是直接复位,这样可以在中断中进行一些错误处理。如果有的话,这也是一个需要提到的点。 还要考虑电源管理方面,看门狗在低功耗模式下的行为,是否需要保持运行,或者如何配置。 总结一下,回答的结构应该是先介绍看门狗的作用,然后具体到AWR2944的配置步骤,包括初始化、喂狗方法,可能的注意事项和常见问题。确保内容准确,步骤清晰,如果有代码示例的话更好,但需要基于TI的SDK或者DriverLib来写,避免误导用户。 可能需要检查TI的官方文档,确保提到的寄存器名称和函数名称正确。比如,看门狗的寄存器基地址,控制寄存器的位定义,或者使用TI提供的API函数,比如Watchdog_init(), Watchdog_enable()等。 另外,用户可能对如何测试看门狗功能感兴趣,比如如何故意触发看门狗复位,以验证其是否正常工作。这时候可以建议在代码中暂时禁用喂狗,观察系统是否复位。 最后,提醒用户在使用看门狗时,确保喂狗逻辑不会在异常情况下无法执行,比如避免在中断服务程序中喂狗,或者在多个线程中正确同步喂狗操作,避免竞态条件。</think>在AWR2944毫米波雷达芯片中,**看门狗定时器(Watchdog Timer, WDT)** 是确保系统可靠性的关键模块。以下是其核心使用要点: --- ### **1. 看门狗基本原理** - **功能**:监控程序运行状态,若未按时"喂狗"(重置计数器),则触发系统复位,防止程序死锁或跑飞。 - **典型场景**:雷达信号处理、通信任务等需实时性的关键流程。 --- ### **2. AWR2944看门狗配置步骤** #### **(1) 初始化配置** ```c #include <ti/drivers/Watchdog.h> Watchdog_Handle wdtHandle; Watchdog_Params wdtParams; Watchdog_Params_init(&wdtParams); wdtParams.resetMode = Watchdog_RESET_ON; // 超时触发复位 wdtParams.debugStallMode = Watchdog_DEBUG_STALL_OFF; // 调试时看门狗继续运行 wdtParams.callbackFxn = NULL; // 无中断模式 wdtHandle = Watchdog_open(Board_WATCHDOG0, &wdtParams); ``` #### **(2) 设置超时时间** - 公式:`Timeout = (Clock周期) × (Reload值)` - 需根据系统时钟频率(如80MHz)计算Reload值: ```c uint32_t timeoutMs = 1000; // 设置1秒超时 uint32_t clockFreq = Watchdog_getClockFreq(wdtHandle); uint32_t reloadValue = (timeoutMs * clockFreq) / 1000; Watchdog_setReload(wdtHandle, reloadValue); ``` #### **(3) 喂狗操作** ```c // 在主循环或关键任务中定期调用 Watchdog_clear(wdtHandle); ``` --- ### **3. 关键注意事项** - **喂狗位置**:需在**非阻塞**代码段中定期执行(如主循环、高优先级任务)。 - **超时计算**:避免设置过短(易误复位)或过长(失去监控意义)。 - **调试模式**:调试时建议启用`debugStallMode`,防止单步调试触发复位。 - **多任务同步**:多线程环境中需确保喂狗操作不被重复/遗漏。 --- ### **4. 常见问题排查** - **频繁复位**: - 检查喂狗间隔是否小于超时时间 - 确认时钟源配置正确(如LFCLK/高速时钟) - **无法触发复位**: - 检查`resetMode`是否启用 - 验证看门狗是否实际使能(`Watchdog_enable()`) --- ### **5. 高级功能(参考TRM手册)** - **窗口模式**:限定喂狗时间必须在特定区间(防提前/滞后喂狗)。 - **中断模式**:超时前触发中断,可记录错误日志后再复位。 - **低功耗管理**:在休眠模式下需根据需求配置看门狗是否暂停。 建议结合TI官方文档(如**AWR2944 Technical Reference Manual**)和SDK示例代码(`ti/drivers/Watchdog.h`)进行深度调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值