IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统(优化版本) -> 正文阅读

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

【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. */
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:58:04  更:2022-10-08 21:00:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 17:44:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码