对称多处理(Symmetric Multi-Processing)是现代嵌入式系统突破性能瓶颈的关键技术。与传统的单核MCU不同,SMP系统允许多个处理器核心平等地访问共享内存和外围设备,就像一支分工明确的施工队——每个工人(核心)都能独立处理任务,同时共享同一套施工图纸(内存空间)。这种架构在ESP32、树莓派CM4等主流嵌入式平台上已成标配。
FreeRTOS从v10.4.0开始引入SMP支持,其实现有几个关键特征:
注意:FreeRTOS的SMP实现并非完全对称,中断处理仍由主核(通常是Core 0)负责,这与Linux等完整操作系统有所不同。
FreeRTOS SMP采用改进的抢占式优先级调度,其工作流程如下:
c复制// 典型调度决策逻辑伪代码
void vTaskSwitchContext(void) {
Task_t *pxNewTask = listGET_OWNER_OF_HEAD_ENTRY(pxReadyTasksLists);
int idleCore = xGetIdleCore();
if(idleCore >= 0) {
vAssignTaskToCore(pxNewTask, idleCore);
} else {
Task_t *pxRunningTask = xGetRunningTaskOnCore(xCoreToPreempt);
if(pxNewTask->uxPriority > pxRunningTask->uxPriority) {
vTriggerPreemption(xCoreToPreempt, pxNewTask);
}
}
}
FreeRTOS采用两种负载均衡机制:
实测发现,在ESP32平台上,默认的tick周期(通常100Hz)可能导致负载响应延迟。对于计算密集型应用,建议通过修改configTICK_RATE_HZ提高tick频率,但需注意会增加上下文切换开销。
SMP环境下最常见的坑是资源竞争。除了常规的互斥量(mutex),FreeRTOS SMP特别需要注意:
c复制// 自旋锁使用示例
SpinlockHandle_t xSpinlock = xSpinlockCreate();
xSpinlockAcquire(xSpinlock);
/* 临界区操作 */
xSpinlockRelease(xSpinlock);
c复制// 确保变量独占缓存行
__attribute__((aligned(32))) uint32_t sharedCounter;
在ESP32等平台上,中断默认由Core 0处理,可能导致负载不均。可通过以下方式优化:
c复制// ESP32中断分配示例
esp_intr_alloc(ETS_INTR_SOURCE, ESP_INTR_FLAG_IRAM,
handler, arg, NULL);
通过vTaskCoreAffinitySet可以优化任务布局:
c复制// 将关键任务绑定到Core 1
vTaskCoreAffinitySet(xTaskHandle, 1 << 1);
典型配置策略:
SMP系统中内存访问延迟对性能影响显著。通过以下方法可提升性能:
TASK_STACK_DEPTH宏增加关键任务栈大小优先级反转:低优先级任务持有锁时被中优先级任务抢占
c复制xSemaphore = xSemaphoreCreateMutex();
xSemaphoreTake(xSemaphore, portMAX_DELAY);
双核死锁:两个核心互相等待对方释放资源
c复制// 启用运行时间统计
configGENERATE_RUN_TIME_STATS = 1
esp_app_trace可实时监控任务状态我在实际项目中遇到过因缓存一致性问题导致的数据异常,最终通过将共享变量定义为volatile并添加内存屏障解决:
c复制// 正确声明跨核共享变量
volatile uint32_t __attribute__((aligned(32))) sharedFlag;
portMEMORY_BARRIER();