kings669669 · 2022年08月26日 · 江西

【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统(优化版本)

【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统(优化版本)

上三篇文章:
【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_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. */

推荐阅读
关注数
6108
内容数
272
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息