【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统(优化版本)
本篇文章来自极术社区与灵动组织的MM32F5270开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:kings669669
上三篇文章:
【MM32F5270开发板试用】一、依靠SPI_SD,移植FatFs文件系统
【MM32F5270开发板试用】SysTick+Scheduler轮询
【MM32F5270开发板试用】如何将数据存放在DTCM
本次所有代码按照以前习惯全部开源:我的Github地址是:https://github.com/kings669/M…
可能关注我的朋友发现,我最近没有更新文章,那是因为我前段时间去参加今年的智能车竞赛。现在,已经比完,可以有时间完成我后续的计划 。
一、优化背景
在测试的过程中,发现播放音频卡顿十分卡顿,经过排除后发现,在官方适配的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_15SDSPI_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 SPBRG = div; if (div 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. */