STM32H7使用FileX库BUG,SD卡挂载失败

问题描述:

使用STM32H7+ThreadX+FileX,之前使用swissbit牌的存储卡可正常使用,最近项目用了金士顿的存储卡,发现无法挂载文件系统。

原因分析:

调试过程发现,关闭D-Cache可以挂载使用exfat文件系统。

FileX对SD卡读写接口全部位于fx_stm32_sdio_driver.c中,查看该文件可以发现在读写函数中已经考虑到使用Cache与DMA的情况,如下代码所示。

c 复制代码
SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, DEFAULT_SECTOR_SIZE);
SCB_InvalidateDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * DEFAULT_SECTOR_SIZE);

SCB_InvalidateDCache_by_Addr()函数用于将该地址D-Cache无效化,无效化的意思是将Cache Line 标记为无效,等同于删除操作。这样下次读写该地址数据时,D-Cache中无此数据,CPU直接对SRAM读写数据,保证CPU读取到的数据是真实的。
源码分析:

以读取函数为例:

c 复制代码
        case FX_DRIVER_READ:
        {
            media_ptr->fx_media_driver_status = FX_IO_ERROR;
            //TX_DISABLE /* disable interrupts */
           if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x03)
           {
              if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
                                media_ptr->fx_media_driver_sectors, 1) == FX_SUCCESS)
              {
                  media_ptr->fx_media_driver_status = FX_SUCCESS;
              }
           }
           ......

if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x03)判断读取地址是否4字节对齐,因为使用MDMA读写SD卡需要地址4字节对齐,并对sd_read_data()函数传入相应值。

sd_read_data()函数如下:

c 复制代码
static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
{
    INT i = 0;
    UINT status;
    if (use_scratch_buffer)
    {
        memset(scratch, '\0', DEFAULT_SECTOR_SIZE);
        for (i = 0; i < num_sectors; i++)
        {
            status = BSP_SD_ReadBlocks_DMA((uint32_t*)scratch, start_sector++, 1);

            if (status != BSP_ERROR_NONE)
            {
                status = FX_IO_ERROR;
                break;
            }

            if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
            {
                status = FX_BUFFER_ERROR;
                break;
            }
            else
            {
#if (ENABLE_CACHE_MAINTENANCE == 1)
                SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, DEFAULT_SECTOR_SIZE);
#endif

                _fx_utility_memory_copy(scratch, media_ptr->fx_media_driver_buffer, DEFAULT_SECTOR_SIZE);
                media_ptr->fx_media_driver_buffer += DEFAULT_SECTOR_SIZE;
            }
        }

        if (i == num_sectors)
        {
            status = FX_SUCCESS;
        }
    }
    else
    {
        status = BSP_SD_ReadBlocks_DMA((uint32_t*)media_ptr->fx_media_driver_buffer, start_sector, num_sectors);

        if (status == BSP_ERROR_NONE)
        {
            if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
            {
#if (ENABLE_CACHE_MAINTENANCE == 1)
                SCB_InvalidateDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * DEFAULT_SECTOR_SIZE);
#endif
                status = FX_SUCCESS;
            }
            else
            {
                status =  FX_BUFFER_ERROR;
            }
        }
    }

    return status;
}

根据传入参数判断,若传输地址不是4字节对齐,则使用内部定义的一块32字节对齐的地址作为中转站,先用MDMA读取到数据,再将数据拷贝到用户提供地址。else分支若地址已经是4字节对齐,则直接使用用户提供的地址进行MDMA传输。

然而else分支的代码存在一个bug,当用户传入的地址为4字节对齐时,进入else分支,在MDMA传输完成后,进行SCB_InvalidateDCache_by_Addr()操作。但是该函数要求传入的地址为32字节对齐,因为Cortex-M7内核的Cache line大小为8个字。所以当传入的地址为4字节对齐但非32字节对齐时,SCB_InvalidateDCache_by_Addr()调用传入的参数不符合要求,D-Cache缓存清除错误,使CPU读取到缓存中错误的值。

解决方案:

在判断地址是否4字节对齐的地方,改成判断地址是否32字节对齐(即0x03改成0x1f),共修改2行代码,在代码中搜索media_ptr->fx_media_driver_buffer即可找到。

c 复制代码
if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x1f)
相关推荐
python百炼成钢4 小时前
10.串口
linux·stm32·单片机·嵌入式硬件
Jason_zhao_MR9 小时前
RK3576机器人核心:三屏异显+八路摄像头,重塑机器人交互与感知
linux·人工智能·嵌入式硬件·计算机视觉·机器人·嵌入式·交互
充哥单片机设计11 小时前
【STM32项目开源】基于STM32的智能水质检测系统
stm32·单片机·嵌入式硬件
wuk99812 小时前
基于STM32平台的ADS1292心电采集驱动程序
stm32·单片机·嵌入式硬件
gihigo199813 小时前
基于STM32F4系列MCU和CS5530 24位SDADC的称重传感器系统实现
stm32·单片机·嵌入式硬件
zhmc13 小时前
STM32的GPIOx_IDR 与 GPIOx_ODR
stm32·单片机·嵌入式硬件
黄毛火烧雪下14 小时前
51、STM32 与 ESP32 单片机全面对比:架构、性能与应用场景详解
stm32·单片机·嵌入式硬件
大聪明-PLUS21 小时前
用 C 语言实现 cat 实用程序
linux·嵌入式·arm·smarc
兆龙电子单片机设计1 天前
【STM32项目开源】STM32单片机智能台灯系统
stm32·单片机·物联网·开源·毕业设计
liujing102329291 天前
stm32_基于 STM32U575 的飞行器姿态实时监控系统
stm32