FATFS STM32F103 上的 R0.11 读取速度较慢 - SPI

FATFS R0.11 slow read speeds on STM32F103 - SPI

我正在使用 STM32F103C8,我的 FATFS R0.11 在它上面运行良好(这是 CUBEMX 默认在 STM32F103C8Tx 上使用的最新版本),但读取速度相当低,在附近共 100 kB/s.

SPI 时钟设置为 18 MHz(从 9 MHz 更改,但这没有任何区别,与 4.5 MHz 相反,它对读取速度的影响很明显 - 读取时间增加了 30%),我已经转向关闭大多数附加选项以节省 RAM。打开两个文件后,我还剩下大约 10 kB(从 20 kB 开始)的 RAM(在 KEIL 中编译时,STM32CUBEIDE 使用了更多的 RAM),这对于我的项目的其余部分应该足够了。

文件被读入 4096 字节的缓冲区,一次 2048 字节(这将是一个 wav 文件,将以等于 22050 Hz 的采样率发送到 I2C DAC,大小上述缓冲区的大小,取决于我项目的其他重要部分的 RAM 使用情况,最终可能会增加,但目前尚不清楚。

单个 2048 字节读取操作大约需要 20 毫秒。我使用的是 class 4 和 class 10 SD 卡,但结果是一样的。所述 SD 卡的簇大小,当减少到 512 字节时,允许我在不同的格式设置下实现每次读取 20-21 毫秒而不是 25 毫秒。由于我还打算显示图像,因此将不胜感激任何较低的读取速度。时间是在 HAL_GetTick() 函数的帮助下测量的。

我尝试一次读取 4096 字节,甚至 8192 字节,但这样做所花费的时间适当缩放,因此在这些测试期间没有记录任何好处。我什至尝试使用完整格式而不是默认的快速选项,但没有任何改变。

您是否认为我可以做些什么来进一步减少阅读时间,或者这是否在某种程度上、形状或形式上受限于我的设置,或者我做错了什么?下面,我把存档和我的项目链接起来,你可以自己编译和测试它(我是在Keil uVision5下编译的,0个错误和0个警告)

出于纯粹的好奇心,我还在读取文件期间探测了 SPI 接口(这是我唯一正在做的事情,目前没有写入 SD 卡)。

Link to .rar archive

从上到下:SCK-黄色,MISO-洋红色,MOSI-青色,CS-蓝色。我添加了额外的延迟以显示传输的不同部分:第一个块负责加载和打开第一个文件,在 4 毫秒延迟后我打开第二个文件(延迟打开第一个文件不会导致任何延迟),然后在 2 毫秒后执行第一次读取,并在额外 2 毫秒延迟后读取下一个 2048 字节。

我的 SD 卡适配器和连接:标准微型 SD 到 SD 适配器,带有焊接的金针和电线连接无焊面包板上的所有东西,ST-LINK V2.1 从 STM32F429ZI-DISC1“借来”。 PA4-CS、PA5-SCK、PA6-MISO、PA7-MOSI。感谢阅读:)

好的,我想通了,你可以在上面的附图中清楚地看到,SPI总线上连续动作之间的延迟很长,这似乎是HAL做了大量开销的原因工作,这会减慢速度。我用自定义函数替换了默认函数来传输和接收数据,它在寄存器上完成所有操作,读取时间减少了四倍,现在我可以在 5-6 毫秒内读取 2 kB 数据,等于大约 400 kB/s。它仍然很低,所以我会等待一段时间,看看是否有人对如何进一步改进有更好的想法。我还将 FATFS 升级到版本 R0.12c,但这并没有改变任何东西。在我看来,使用 DMA 可以加快速度。有问题的函数如下所示:

######### from file fatfs_sd.c #########
uint8_t SPI1_Transfer(uint8_t data){
    SPI1->CR1 |= SPI_CR1_SPE;               //enable SPI1
    SPI1->DR = data;                        // Write data to be transmitted to the SPI data register
    while (!(SPI1->SR & (SPI_SR_TXE)));     // Wait until transmit complete
    while (!(SPI1->SR & (SPI_SR_RXNE)));    // Wait until receive complete
    while (SPI1->SR & (SPI_SR_BSY));        // Wait until SPI is not busy anymore
    return SPI1->DR;                        // Return received data from SPI data register
}

static void SPI_TxByte(BYTE data){
    SPI1_Transfer(data);
}
static uint8_t SPI_RxByte(void){
    return SPI1_Transfer(0xff);
}

Link to updated .rar archive

这个问题对我也有帮助: How to decrease SPI overhead time for STM32L4 HAL library