ARM Cortex-M 内存屏障与原子操作详解

引言 在多任务和中断驱动的嵌入式系统中,数据竞争和内存访问顺序问题是导致系统不稳定的常见原因。本文深入探讨 ARM Cortex-M 处理器的内存模型、原子操作实现机制,以及内存屏障指令(DMB/DSB/ISB)的实际应用场景。 1. ARM Cortex-M 内存模型 1.1 弱内存序(Weak Memory Ordering) ARM Cortex-M 采用弱内存序模型,这意味着: CPU 可以重新排序内存访问指令以提高性能 不保证程序中的内存访问顺序与实际执行顺序一致 多核或多主设备系统中可能出现数据不一致 示例问题: // 线程 1 flag = 1; // 步骤 1 data = 0x1234; // 步骤 2 // 线程 2 while (flag == 0); // 等待 flag read = data; // 期望读到 0x1234 问题:由于内存重排序,线程 2 可能在 data 写入之前就读到 flag==1,导致读到旧数据。 1.2 Cortex-M 内存类型 内存类型 特性 使用场景 Normal Memory 可缓存、可缓冲 SRAM、外部 RAM Device Memory 不可缓存、顺序访问 外设寄存器 Strongly Ordered 严格顺序、无缓冲 共享内存区域 2. 原子操作实现原理 2.1 什么是原子操作? 原子操作是不可中断的操作,在执行过程中不会被其他任务或中断打断。 ...

March 31, 2026 · 3 min · Tech Snippets

实时操作系统(RTOS)基础与 FreeRTOS 实战

什么是 RTOS? RTOS(Real-Time Operating System)实时操作系统是一种能够保证在确定时间内完成任务调度的操作系统。 RTOS vs 通用 OS 特性 RTOS 通用 OS(Windows/Linux) 实时性 确定性响应 非确定性 任务调度 优先级驱动 时间片轮转 内存占用 KB 级别 MB/GB 级别 应用场景 嵌入式、工业控制 桌面、服务器 硬实时 vs 软实时 硬实时:必须在规定时间内完成(如汽车安全气囊) 软实时:尽量在规定时间内完成(如视频播放) FreeRTOS 基础 核心概念 概念 说明 任务(Task) 独立的执行线程 调度器(Scheduler) 管理任务执行顺序 优先级(Priority) 决定任务执行顺序 队列(Queue) 任务间通信机制 信号量(Semaphore) 资源同步机制 互斥量(Mutex) 保护共享资源 任务管理 创建任务 #include "FreeRTOS.h" #include "task.h" // 任务函数 void vTaskFunction(void *pvParameters) { char *pcTaskName = (char *)pvParameters; for (;;) { printf("%s is running\n", pcTaskName); vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒 } } // 创建任务 void vStartTasks(void) { xTaskCreate( vTaskFunction, // 任务函数 "Task1", // 任务名称 configMINIMAL_STACK_SIZE,// 栈大小 (void *)"Task1", // 参数 1, // 优先级 NULL // 任务句柄 ); } 任务优先级 // 优先级数字越大,优先级越高 #define TASK_PRIORITY_HIGH 3 #define TASK_PRIORITY_NORMAL 2 #define TASK_PRIORITY_LOW 1 xTaskCreate(vTask1, "Task1", 128, NULL, TASK_PRIORITY_HIGH, NULL); xTaskCreate(vTask2, "Task2", 128, NULL, TASK_PRIORITY_LOW, NULL); 删除任务 // 删除自己 vTaskDelete(NULL); // 删除其他任务 vTaskDelete(xTaskHandle); 延时与超时 阻塞延时 // 延时 500ms vTaskDelay(pdMS_TO_TICKS(500)); // 相对延时(从当前时刻开始) vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100)); 精确延时 TickType_t xLastWakeTime = xTaskGetTickCount(); void vTaskFunction(void *pvParameters) { for (;;) { // 执行任务 // 精确延时 100ms vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100)); } } 任务间通信 队列(Queue) #include "queue.h" // 创建队列 QueueHandle_t xQueue = xQueueCreate(10, sizeof(int)); // 发送数据(阻塞等待) int data = 42; xQueueSend(xQueue, &data, portMAX_DELAY); // 接收数据(阻塞等待) int receivedData; xQueueReceive(xQueue, &receivedData, portMAX_DELAY); 队列示例:生产者 - 消费者 QueueHandle_t xQueue; void vProducerTask(void *pvParameters) { int data = 0; for (;;) { xQueueSend(xQueue, &data, portMAX_DELAY); data++; vTaskDelay(pdMS_TO_TICKS(100)); } } void vConsumerTask(void *pvParameters) { int receivedData; for (;;) { xQueueReceive(xQueue, &receivedData, portMAX_DELAY); printf("Received: %d\n", receivedData); } } void vStartSystem(void) { xQueue = xQueueCreate(10, sizeof(int)); xTaskCreate(vProducerTask, "Producer", 128, NULL, 1, NULL); xTaskCreate(vConsumerTask, "Consumer", 128, NULL, 1, NULL); vTaskStartScheduler(); } 同步与互斥 二值信号量 #include "semphr.h" SemaphoreHandle_t xBinarySemaphore; void vInterruptHandler(void) { // 中断中释放信号量 BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void vTaskFunction(void *pvParameters) { for (;;) { // 等待信号量 if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) { // 处理事件 } } } void vStartSystem(void) { xBinarySemaphore = xSemaphoreCreateBinary(); xTaskCreate(vTaskFunction, "Task", 128, NULL, 1, NULL); vTaskStartScheduler(); } 互斥量(Mutex) SemaphoreHandle_t xMutex; void vTask1(void *pvParameters) { for (;;) { // 获取互斥量 if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) { // 访问共享资源 printf("Task1 accessing shared resource\n"); vTaskDelay(pdMS_TO_TICKS(100)); xSemaphoreGive(xMutex); } vTaskDelay(pdMS_TO_TICKS(200)); } } 内存管理 堆管理方案 方案 特点 适用场景 heap_1 只分配,不释放 简单系统 heap_2 分配 + 释放,不合并 固定大小块 heap_3 使用 malloc/free 通用场景 heap_4 分配 + 释放,合并空闲块 推荐 heap_5 支持多个内存区域 复杂系统 配置示例 // FreeRTOSConfig.h #define configTOTAL_HEAP_SIZE ((size_t)(10 * 1024)) #define configUSE_MALLOC_FAILED_HOOK 1 void vApplicationMallocFailedHook(void) { // 内存分配失败处理 } 实际项目:多传感器数据采集 #include "FreeRTOS.h" #include "task.h" #include "queue.h" typedef struct { float temperature; float humidity; uint32_t timestamp; } SensorData_t; QueueHandle_t xSensorQueue; // 温度采集任务 void vTempTask(void *pvParameters) { SensorData_t data; for (;;) { data.temperature = readTemperature(); data.timestamp = xTaskGetTickCount(); xQueueSend(xSensorQueue, &data, portMAX_DELAY); vTaskDelay(pdMS_TO_TICKS(1000)); } } // 湿度采集任务 void vHumidityTask(void *pvParameters) { SensorData_t data; for (;;) { data.humidity = readHumidity(); data.timestamp = xTaskGetTickCount(); xQueueSend(xSensorQueue, &data, portMAX_DELAY); vTaskDelay(pdMS_TO_TICKS(1000)); } } // 数据处理任务 void vProcessTask(void *pvParameters) { SensorData_t data; for (;;) { xQueueReceive(xSensorQueue, &data, portMAX_DELAY); printf("Temp: %.2f, Hum: %.2f, Time: %lu\n", data.temperature, data.humidity, data.timestamp); } } void vStartSystem(void) { xSensorQueue = xQueueCreate(10, sizeof(SensorData_t)); xTaskCreate(vTempTask, "Temp", 256, NULL, 1, NULL); xTaskCreate(vHumidityTask, "Humidity", 256, NULL, 1, NULL); xTaskCreate(vProcessTask, "Process", 512, NULL, 2, NULL); vTaskStartScheduler(); } 调试技巧 常见问题 问题 可能原因 解决方法 系统不启动 栈太小 增加 configMINIMAL_STACK_SIZE 任务不执行 优先级太低 提高优先级 内存不足 堆太小 增加 configTOTAL_HEAP_SIZE 死锁 互斥量使用不当 检查获取顺序 性能监控 // 获取空闲任务计数 uint32_t ulIdleCount = uxTaskGetNumberOfTasks(); // 获取系统运行时间 TickType_t xUptime = xTaskGetTickCount(); // 获取任务列表 TaskStatus_t xTaskStatus[10]; UBaseType_t uxTasks = uxTaskGetNumberOfTasks(); vTaskGetList(xTaskStatus, uxTasks); 结语 FreeRTOS 是嵌入式 RTOS 的事实标准。通过本教程,你掌握了任务管理、通信和同步机制。动手做一个多任务项目吧! ...

March 24, 2026 · 3 min · Tech Snippets