【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统(优化版本)
上三篇文章:
【MM32F5270开发板试用】一、依靠SPI_SD,移植FatFs文件系统
【MM32F5270开发板试用】SysTick+Scheduler轮询
【MM32F5270开发板试用】如何将数据存放在DTCM
本次所有代码按照以前习惯全部开源:我的Github地址是:https://github.com/kings669/MM32F5
可能关注我的朋友发现,我最近没有更新文章,那是因为我前段时间去参加今年的智能车竞赛。现在,已经比完,可以有时间完成我后续的计划😄。
一、优化背景
在测试的过程中,发现播放音频卡顿十分卡顿,经过排除后发现,在官方适配的SPI是软件SPI。想到我们的整体流程是从SD卡开始,源头就卡了,何来最大吞吐率😄。
二、优化过程
1、开启时钟,在clock_init.c中
/* SPI3. */
RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_SPI3, true);
RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_SPI3);
2、引脚设置,在pin_init.c中
/* PC12 - GPIO output: SPI3_MOSI. */
gpio_init.Pins = GPIO_PIN_12;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_6);
/* PC11 - GPIO input: SPI3_MISO. */
gpio_init.Pins = GPIO_PIN_11;
gpio_init.PinMode = GPIO_PinMode_In_Floating;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_6);
/* PC10 - GPIO output: SPI3_SCK. */
gpio_init.Pins = GPIO_PIN_10;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
GPIO_PinAFConf(GPIOC, gpio_init.Pins, GPIO_AF_6);
/* PA15 - GPIO output: SPI3_CS. */
gpio_init.Pins = GPIO_PIN_15;
gpio_init.PinMode = GPIO_PinMode_AF_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_init);
GPIO_PinAFConf(GPIOA, gpio_init.Pins, GPIO_AF_6);
3、修改sdspi_port.c文件
/*
* Copyright 2022 MindMotion Microelectronics Co., Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "board_init.h"
#include "sdspi.h"
#include "hal_spi.h"
/* pins:
* tx : PC12/SPI_MOSI
* rx : PC8/SPI0_MISO
* clk: PC12/SPI0_SCK
* cs : PC11/SPI0_PCS0
*/
#define BOARD_SDSPI_TX_GPIO_PORT GPIOC
#define BOARD_SDSPI_TX_GPIO_PIN GPIO_PIN_12
#define BOARD_SDSPI_RX_GPIO_PORT GPIOC
#define BOARD_SDSPI_RX_GPIO_PIN GPIO_PIN_11
#define BOARD_SDSPI_CLK_GPIO_PORT GPIOC
#define BOARD_SDSPI_CLK_GPIO_PIN GPIO_PIN_10
#define BOARD_SDSPI_CS_GPIO_PORT GPIOA
#define BOARD_SDSPI_CS_GPIO_PIN GPIO_PIN_15
SDSPI_ApiRetStatus_Type sdspi_spi_init(void);
SDSPI_ApiRetStatus_Type sdspi_spi_freq(uint32_t hz);
SDSPI_ApiRetStatus_Type sdspi_spi_xfer(uint8_t *in, uint8_t *out, uint32_t len);
const SDSPI_Interface_Type board_sdspi_if =
{
.baudrate = 1000000u, /* 1mhz. */
.spi_init = sdspi_spi_init,
.spi_freq = sdspi_spi_freq,
.spi_xfer = sdspi_spi_xfer
};
uint32_t board_sdspi_delay_count;
static void board_sdspi_delay(uint32_t count)
{
for (uint32_t i = count; i > 0u; i--)
{
__NOP();
}
}
SDSPI_ApiRetStatus_Type sdspi_spi_init(void)
{
GPIO_WriteBit(BOARD_SDSPI_CS_GPIO_PORT , BOARD_SDSPI_CS_GPIO_PIN , 1u);
// GPIO_WriteBit(BOARD_SDSPI_TX_GPIO_PORT , BOARD_SDSPI_TX_GPIO_PIN , 0u);
// GPIO_WriteBit(BOARD_SDSPI_CLK_GPIO_PORT, BOARD_SDSPI_CLK_GPIO_PIN, 0u);
/* Setup SPI module. */
SPI_Master_Init_Type spi_init;
spi_init.ClockFreqHz = CLOCK_APB1_FREQ;
spi_init.BaudRate = SDMMC_CLOCK_400KHZ;
spi_init.XferMode = SPI_XferMode_TxRx;
spi_init.PolPha = SPI_PolPha_Alt2;
spi_init.DataWidth = SPI_DataWidth_8b;
spi_init.LSB = false;
spi_init.AutoCS = true;
SPI_InitMaster(SPI3, &spi_init);
/* Enable SPI. */
SPI_Enable(SPI3, true);
// board_sdspi_delay_count = 100u;
return SDSPI_ApiRetStatus_Success;
}
void SPI_SetBaudRate(SPI_Type * SPIx, uint32_t src_clk, uint32_t baudrate)
{
uint32_t div = src_clk / baudrate;
if (div < 2u)
{
/* div = 0, 1 is not allowed. */
div = 2u;
}
SPIx->SPBRG = div;
if (div <= 4)
{
/* to support high speed mode. */
SPIx->CCTL |= (SPI_I2S_CCTL_TXEDGE_MASK | SPI_I2S_CCTL_RXEDGE_MASK);
}
else
{
SPIx->CCTL &= ~(SPI_I2S_CCTL_TXEDGE_MASK | SPI_I2S_CCTL_RXEDGE_MASK);
}
}
SDSPI_ApiRetStatus_Type sdspi_spi_freq(uint32_t hz)
{
switch (hz)
{
case SDMMC_CLOCK_400KHZ:
SPI_Enable(SPI3, false);
SPI_SetBaudRate(SPI3,CLOCK_APB1_FREQ,SDMMC_CLOCK_400KHZ);
SPI_Enable(SPI3, true);
break;
default:
SPI_Enable(SPI3, false);
SPI_SetBaudRate(SPI3,CLOCK_APB1_FREQ,SD_CLOCK_25MHZ);
SPI_Enable(SPI3, true);
break;
}
return SDSPI_ApiRetStatus_Success;
}
//SDSPI_ApiRetStatus_Type sdspi_spi_freq(uint32_t hz)
//{
// switch (hz)
// {
// case SDMMC_CLOCK_400KHZ:
// board_sdspi_delay_count = 100u;
// break;
// default:
// board_sdspi_delay_count = 0u;
// break;
// }
// return SDSPI_ApiRetStatus_Success;
//}
/* SPI tx. */
void app_spi_putbyte(uint8_t c)
{
/* Polling for tx empty. */
while ( SPI_STATUS_TX_FULL & SPI_GetStatus(SPI3) )
{}
SPI_PutData(SPI3, c);
}
/* SPI rx. */
uint8_t app_spi_getbyte(void)
{
/* Polling for rx done. */
while (0u == (SPI_STATUS_RX_DONE & SPI_GetStatus(SPI3)) )
{}
return SPI_GetData(SPI3);
}
uint8_t spi_xfer(uint8_t tx_dat)
{
uint8_t rx_dat = 0u;
app_spi_putbyte(tx_dat);
rx_dat=app_spi_getbyte();
return rx_dat;
}
//uint8_t spi_xfer(uint8_t tx_dat)
//{
// uint8_t rx_dat = 0u;
// for (uint8_t i = 0u; i < 8u; i++)
// {
// GPIO_WriteBit(BOARD_SDSPI_CLK_GPIO_PORT, BOARD_SDSPI_CLK_GPIO_PIN, 0u );
// GPIO_WriteBit(BOARD_SDSPI_TX_GPIO_PORT, BOARD_SDSPI_TX_GPIO_PIN, (0u != (tx_dat & (1u << (7u-i)))) ? 1u : 0u );
// board_sdspi_delay(board_sdspi_delay_count);
// GPIO_WriteBit(BOARD_SDSPI_CLK_GPIO_PORT, BOARD_SDSPI_CLK_GPIO_PIN, 1u );
// board_sdspi_delay(board_sdspi_delay_count);
// rx_dat = (rx_dat << 1u) | GPIO_ReadInDataBit(BOARD_SDSPI_RX_GPIO_PORT, BOARD_SDSPI_RX_GPIO_PIN);
// }
// return rx_dat;
//}
void spi_assert_cs(bool enable)
{
GPIO_WriteBit(BOARD_SDSPI_CS_GPIO_PORT, BOARD_SDSPI_CS_GPIO_PIN, (enable ? 0u: 1u) );
}
SDSPI_ApiRetStatus_Type sdspi_spi_xfer(uint8_t *in, uint8_t *out, uint32_t len)
{
uint8_t inbuf, outbuf;
//spi_assert_cs(true);
for (uint32_t i = 0u; i < len; i++)
{
inbuf = (in == NULL) ? SDSPI_DUMMY_DATA: *in++;
outbuf = spi_xfer(inbuf);
if (out)
{
*out = outbuf;
out++;
}
}
//spi_assert_cs(false);
return SDSPI_ApiRetStatus_Success;
}
/* EOF. */