如何在双核MCU的FreeRTOS中跨核停止并重启任务?
双核FreeRTOS跨核任务控制解决方案
问题1:获取Core1当前运行任务句柄
- 提前保存Core1任务句柄:在创建Core1任务时,将返回的任务句柄存入全局变量(跨核访问需用FreeRTOS互斥锁或原子操作保证线程安全)。示例代码:
TaskHandle_t xCore1TaskHandle = NULL; // Core1初始化时创建任务 void core1_init() { xTaskCreatePinnedToCore(mytask_01, "Task01", 4096, NULL, 1, &xCore1TaskHandle, 1); } - 专用API查询:部分FreeRTOS移植(如ESP-IDF)提供
xTaskGetCurrentTaskHandleForCore(uint32_t uxCoreID)接口,直接传入Core编号即可获取对应核的当前任务句柄。 - 遍历任务筛选:若没有专用API,可通过
uxTaskGetNumberOfTasks()获取任务总数,配合xTaskGetHandleFromIndex()遍历所有任务,用uxTaskGetCoreID()判断任务所属核、eTaskGetState()判断运行状态,筛选出Core1正在运行的任务。
问题2:让任务从头执行而非断点续行
vTaskSuspend/resume仅保留任务上下文,要实现从头运行,推荐两种可靠方式:
方式1:删除后重建任务
- Core0中断触发时的执行逻辑:
- 通过全局句柄或跨核API获取Core1目标任务的句柄。
- 调用
vTaskSuspendFromISR(xCore1TaskHandle)暂停任务,再调用vTaskDelete(xCore1TaskHandle)删除任务。 - 重新创建并挂载Core1任务:
xTaskCreatePinnedToCore(mytask_01, "Task01", 4096, NULL, 1, &xCore1TaskHandle, 1); - 创建并启动Core1的初始化任务(优先级需高于原任务,确保执行优先),完成后通过
xTaskNotifyGiveFromISR(xCore1TaskHandle, NULL)给新任务发送通知,使其进入循环执行。
方式2:任务内部嵌入重置逻辑
- 修改Core1任务代码,添加跨核同步的重置标志:
volatile BaseType_t xTaskResetFlag = pdFALSE; SemaphoreHandle_t xResetMutex; void mytask_01( void* pvParameters ) { xResetMutex = xSemaphoreCreateMutex(); while (1) { // 检查重置标志 xSemaphoreTake(xResetMutex, portMAX_DELAY); if(xTaskResetFlag == pdTRUE) { xTaskResetFlag = pdFALSE; xSemaphoreGive(xResetMutex); continue; // 直接回到循环开头,等待通知 } xSemaphoreGive(xResetMutex); ulTaskNotifyTake(pdTRUE, portMAX_DELAY); do_something_first_01(); do_something_else_02(); do_something_different_03(); } } - Core0中断中的触发逻辑:
void core0_interrupt_handler() { vTaskSuspendFromISR(xCore1TaskHandle); // 设置重置标志 xSemaphoreTakeFromISR(xResetMutex, NULL); xTaskResetFlag = pdTRUE; xSemaphoreGiveFromISR(xResetMutex, NULL); // 创建并启动Core1初始化任务 xTaskCreatePinnedToCore(init_task, "InitTask", 4096, NULL, 2, NULL, 1); // 恢复任务,使其检测标志后回到循环起点 vTaskResumeFromISR(xCore1TaskHandle); }
跨核操作关键注意事项
- 跨核访问的全局变量必须加
volatile修饰,必要时用互斥锁或原子操作同步,避免数据竞争。 - 中断中调用FreeRTOS API必须使用带
FromISR后缀的版本,保证操作安全。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

