You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32L452启用FreeRTOS后SDMMC通信异常问题求助

问题原因与解决办法

核心问题分析

  1. FatFS未适配RTOS环境:默认FatFS配置未开启线程安全选项,多任务下文件操作会触发资源竞争,导致SD卡写入失败。
  2. HAL_Delay在FreeRTOS下的行为冲突:开启FreeRTOS后,SysTick被接管用于任务调度,原代码中的HAL_Delay会导致任务阻塞逻辑异常,可能打断SDMMC的通信时序。
  3. 外设资源无互斥保护:SDMMC与SPI若共享总线或GPIO资源,多任务并行访问会引发冲突,干扰SD卡通信。

具体修复步骤

1. 开启FatFS的RTOS支持

在CubeIDE的Middleware > FATFS配置界面,找到USE_FREERTOS选项并设置为Enabled,让FatFS自动用FreeRTOS互斥量保护文件操作,避免资源竞争。

2. 重构为FreeRTOS任务结构

将SD卡写入和SPI采集拆分为独立任务,示例代码如下:

/* 任务句柄定义 */
TaskHandle_t xSDWriteTaskHandle = NULL;
TaskHandle_t xSPICollectTaskHandle = NULL;

/* SD卡写入任务 */
void vSDWriteTask(void *pvParameters)
{
    FRESULT res;
    FIL fil;
    UINT bytesWritten;
    uint8_t writeBuf[128] = "Test data from SD task\r\n";

    // 仅初始化时挂载一次文件系统
    res = f_mount(&SDFatFS, SDPath, 1);
    if(res != FR_OK)
    {
        // 挂载失败处理,进入死循环
        for(;;);
    }

    for(;;)
    {
        // 打开文件(不存在则创建)
        res = f_open(&fil, "test.txt", FA_OPEN_ALWAYS | FA_WRITE);
        if(res == FR_OK)
        {
            f_lseek(&fil, f_size(&fil)); // 移动到文件末尾
            res = f_write(&fil, writeBuf, sizeof(writeBuf)-1, &bytesWritten);
            f_close(&fil);
        }

        vTaskDelay(pdMS_TO_TICKS(1000)); // 主动让出CPU
    }
}

/* SPI数据采集任务 */
void vSPICollectTask(void *pvParameters)
{
    uint8_t spiData[32];

    for(;;)
    {
        // SPI数据采集逻辑
        HAL_SPI_Receive(&hspi1, spiData, sizeof(spiData), HAL_MAX_DELAY);
        // 数据处理逻辑
        // ...

        vTaskDelay(pdMS_TO_TICKS(100)); // 主动让出CPU
    }
}

/* main函数初始化任务 */
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SDMMC1_SD_Init();
    MX_SPI1_Init();
    MX_FATFS_Init();

    // 创建SD写入任务(栈大小1024,优先级2)
    xTaskCreate(vSDWriteTask, "SD_Write_Task", 1024, NULL, 2, &xSDWriteTaskHandle);
    // 创建SPI采集任务(栈大小512,优先级2)
    xTaskCreate(vSPICollectTask, "SPI_Collect_Task", 512, NULL, 2, &xSPICollectTaskHandle);

    vTaskStartScheduler(); // 启动RTOS调度器

    // 调度器启动失败则进入死循环
    for(;;);
}

3. 优化任务调度逻辑

  • 用vTaskDelay替代HAL_Delay:vTaskDelay是FreeRTOS原生延时函数,会主动让出CPU,避免任务独占资源。
  • 调整任务优先级:SD卡写入任务涉及磁盘IO,优先级不宜过高,避免长时间占用CPU影响SPI采集;两个任务优先级可设为相同,让调度器公平分配时间片。

4. 外设资源互斥保护(可选)

如果SPI与SDMMC共享总线或GPIO资源,需用FreeRTOS互斥量保护访问:

// 定义互斥量
SemaphoreHandle_t xPeriphMutex = NULL;

// main函数中创建互斥量
xPeriphMutex = xSemaphoreCreateMutex();

// SD任务中访问外设前获取互斥量
if(xSemaphoreTake(xPeriphMutex, portMAX_DELAY) == pdTRUE)
{
    // SD卡操作代码
    xSemaphoreGive(xPeriphMutex);
}

// SPI任务中访问外设前获取互斥量
if(xSemaphoreTake(xPeriphMutex, portMAX_DELAY) == pdTRUE)
{
    // SPI操作代码
    xSemaphoreGive(xPeriphMutex);
}

内容的提问来源于stack exchange,提问作者Hakob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:32:12