【瑞萨RA × Zephyr评测】多线程和看门狗 电子说
本文章旨在评估使用 Zephyr RTOS 在 Renesas FPB-RA6E2 开发板上实现多线程调度与硬件看门狗功能的应用。评估内容包括任务调度、看门狗初始化流程、主程序逻辑的详细解析,以及实验现象与数据分析。
本实验涉及的任务调度和看门狗功能不依赖特定的物理引脚,但需要确保开发板支持硬件看门狗外设。
| 功能 | 物理引脚 (Pin) | 信号定义 | 接线说明 |
|---|---|---|---|
| 看门狗 | 内部外设 | WDT Timer | 无需外部连接 |
设备树用于定义硬件看门狗的初始状态。以下是关键配置:
wdt: wdt@40083400 {
compatible = "renesas,ra-wdt"; /* in externalzephyrdtsarmrenesasrara6ra6-cm33-common.dtsi:542 */
reg = < 0x40083400 0x200 >; /* in externalzephyrdtsarmrenesasrara6ra6-cm33-common.dtsi:543 */
clocks = < &pclkb 0x0 0x0 >; /* in externalzephyrdtsarmrenesasrara6ra6-cm33-common.dtsi:544 */
status = "okay"; /* in externalzephyrboardsrenesasfpb_ra6e2fpb_ra6e2.dts:135 */
};
};
};
prj.conf)确保启用了多线程和看门狗驱动支持:
CONFIG_MULTITHREADING=y
CONFIG_WATCHDOG=y
CONFIG_TASK_WDT=y
CONFIG_LOG=y
#include < zephyr/kernel.h >
#include < zephyr/device.h >
#include < zephyr/drivers/watchdog.h >
#include < zephyr/sys/reboot.h >
#include < zephyr/task_wdt/task_wdt.h >
#include < zephyr/sys/printk.h >
#include < stdbool.h >
/*
* To use this sample, either the devicetree's /aliases must have a
* 'watchdog0' property, or one of the following watchdog compatibles
* must have an enabled node.
*
* If the devicetree has a watchdog node, we get the watchdog device
* from there. Otherwise, the task watchdog will be used without a
* hardware watchdog fallback.
*/
#if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(watchdog0))
#define WDT_NODE DT_ALIAS(watchdog0)
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_window_watchdog)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_window_watchdog)
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_watchdog)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_watchdog)
#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_wdt)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nordic_nrf_wdt)
#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_watchdog)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(espressif_esp32_watchdog)
#elif DT_HAS_COMPAT_STATUS_OKAY(silabs_gecko_wdog)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(silabs_gecko_wdog)
#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_wdog32)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_wdog32)
#elif DT_HAS_COMPAT_STATUS_OKAY(microchip_xec_watchdog)
#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(microchip_xec_watchdog)
#else
#define WDT_NODE DT_INVALID_NODE
#endif
static void task_wdt_callback(int channel_id, void *user_data)
{
printk("Task watchdog channel %d callback, thread: %sn",
channel_id, k_thread_name_get((k_tid_t)user_data));
/*
* If the issue could be resolved, call task_wdt_feed(channel_id) here
* to continue operation.
*
* Otherwise we can perform some cleanup and reset the device.
*/
printk("Resetting device...n");
sys_reboot(SYS_REBOOT_COLD);
}
int main(void)
{
int ret;
const struct device *const hw_wdt_dev = DEVICE_DT_GET_OR_NULL(WDT_NODE);
printk("Task watchdog sample application.n");
if (!device_is_ready(hw_wdt_dev)) {
printk("Hardware watchdog not ready; ignoring it.n");
ret = task_wdt_init(NULL);
} else {
ret = task_wdt_init(hw_wdt_dev);
}
if (ret != 0) {
printk("task wdt init failure: %dn", ret);
return 0;
}
/* passing NULL instead of callback to trigger system reset */
int task_wdt_id = task_wdt_add(1100U, NULL, NULL);
while (true) {
printk("Main thread still alive...n");
task_wdt_feed(task_wdt_id);
k_sleep(K_MSEC(1000));
}
return 0;
}
/*
* This high-priority thread needs a tight timing
*/
void control_thread(void)
{
int task_wdt_id;
int count = 0;
printk("Control thread started.n");
/*
* Add a new task watchdog channel with custom callback function and
* the current thread ID as user data.
*/
task_wdt_id = task_wdt_add(100U, task_wdt_callback,
(void *)k_current_get());
while (true) {
if (count == 50) {
printk("Control thread getting stuck...n");
k_sleep(K_FOREVER);
}
task_wdt_feed(task_wdt_id);
k_sleep(K_MSEC(50));
count++;
}
}
K_THREAD_DEFINE(control, 1024, control_thread, NULL, NULL, NULL, -1, 0, 1000);
control_thread,用于模拟实时任务。task_wdt_feed 函数喂养看门狗。以下是代码中使用的关键 API:
K_THREAD_DEFINE(thread_name, stack_size, entry_point, arg1, arg2, arg3, prio, options, delay);
thread_name: 线程名称。stack_size: 线程栈大小。entry_point: 线程入口函数。prio: 线程优先级。int task_wdt_init(const struct device *hw_wdt_dev);
hw_wdt_dev: 硬件看门狗设备句柄(可为空)。int task_wdt_add(uint32_t timeout_ms, task_wdt_callback_t callback, void *user_data);
void task_wdt_feed(int channel_id);
timeout_ms: 超时时间(毫秒)。callback: 超时回调函数。channel_id: 看门狗通道 ID。终端应显示如下数据流:
*** Booting Zephyr OS build v4.2.0 ***
Task watchdog sample application.
[00:00:00.005,000] [0m< inf > wdt_renesas_ra: actual window min = 0.00 ms[0m
[00:00:00.012,000] [0m< inf > wdt_renesas_ra: actual window max = 671.00 ms[0m
[00:00:00.019,000] [0m< inf > wdt_renesas_ra: wdt timeout was set successfully[0m
Main thread still alive...
Control thread started.
Main thread still alive...
Main thread still alive...
Main thread still alive...
Control thread getting stuck...
Task watchdog channel 1 callback, thread: control
Resetting d?*** Booting Zephyr OS build v4.2.0 ***
Task watchdog sample application.
[00:00:00.005,000] [0m< inf > wdt_renesas_ra: actual window min = 0.00 ms[0m
[00:00:00.012,000] [0m< inf > wdt_renesas_ra: actual window max = 671.00 ms[0m
[00:00:00.019,000] [0m< inf > wdt_renesas_ra: wdt timeout was set successfully[0m
Main thread still alive...
Control thread started.
本程序成功演示了 Renesas RA6E2 在 Zephyr RTOS 下的多线程调度与看门狗功能。通过模拟高优先级任务卡住的场景,验证了任务看门狗对系统稳定性的保护作用。代码结构清晰,适配了最新的驱动 API,适用于初学者学习和开发者快速验证硬件功能。
全部0条评论
快来发表一下你的评论吧 !