最近在STM32H7平台移植ThreadX做FTP服务器时候遇到了一些坑,记录一下
1、现象
在CM7内核直接调用STM32HAL库的SDMMC写块和读块均没有问题,但是用FileX和NetX的代码做FTP写入就会导致异常。现象是写入偶发性的失败,SDMMC一直跳错误码UNDERRUN或者OVERRUN。表现在FTP客户端上就是上传文件时候无法获取写入速度,同时不停的断开连接重传。
2、排查路线
- 排查SDMMC是否正常初始化——正常初始化
- 检查发送缓冲区是否被缓存影响、是否正确清除缓存——正常
- 进行了降低SDMMC外设频率——无效
- 检查发送缓冲区是否32字节对齐——无效
- 对NetX接收而来的数据包做一次拷贝——解决
3、问题分析
主要问题来自于STM32H7下的SDMMC外设对不同内存段的访问能力有区别,STM32H7有两个SDMMC外设,根据手册得知,SDMMC1具备AXIRAM(0x24000000~0x24080000)的访问能力,SDMMC2具备对AXIRAM、SRAM(0x30000000~0x30048000)的访问能力。

在STM32CubeMX生成的NetX与FileX代码中,FileX的驱动会直接对NetX接收到的网络数据包做32字节对齐的检查,如果是32字节对齐就直接触发SDMMC的DMA传输,以此达到零拷贝的目的。但是如果用的是SDMMC1,NetX的PackPool通常会被分配在SRAM3,也就是SDMMC1无法访问的位置。此时如果走向0拷贝的分支,SDMMC1的DMA传输就会异常。如果PackPool不是32字节对齐,就会走向拷贝一次到临时32字节对齐Buffer的分支,由于代码运行在CM7核心,其栈一般被分配在AXIRAM,此时就会正常触发DMA传输。解决方案是把判断32字节对齐的代码注释掉,直接强制拷贝一次
// unaligned_buffer = (UINT)(media_ptr->fx_media_driver_buffer) & 0x1u;
unaligned_buffer = 1;
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,
unaligned_buffer)
== FX_SUCCESS)
{
media_ptr->fx_media_driver_status = FX_SUCCESS;
}
参与讨论