当前位置: 首页 > web >正文

深入理解drv_spi.c后,完全正向亲手移植rt-thread的drv_spi.c驱动 (基于stm32h750 artpi)

1. 按照移植rt-thread驱动的三部曲

  • 第1步,用cubeMX创建spi/qspi的工程,并在Keil下测试成功spi/qspi读写spi-flash。分别用dma模式和polling模式测试。这一步前面已经ok。
  • 第2步,在rt-thread环境下,创建test.c文件,将前面CubeMX工程的相应函数copy过来(main.c中的gpio/spi/dma初始化函数及测试函数及回调函数, stm32h7xx_hal_msp.c中的msp_init, msp_denit函数,以及stm32h7xx_it.c中的中断函数),并通过msh_cmd测试成功。
  • 第3步,修改drv_spi.c,实现相应的函数,并测试它直到成功。

2. drv_spi.c

  • spixfer中,定义#define DMA_MIN_SIZE 10 /set this=10000, means always use polling. set this=0, means always use dma. both works fine./
  • 我们定义了noncache region,方便dma使用。
  • 对于dma发送,我们无条件copy send_buf到tx_buffer,再发送。对于dma接收,我们总是使用rx_buffer执行dma,然后无条件copy rx_buffer到recv_buffer中。这样大大简化了操作。
  • 注意GPIO速度要HIGH
  • 注意分频比配置。先开始尽量让频率低,等成功了再逐步提高频率。
  • 注意DMA配置,先关闭fifo。测试成功了,再可以考虑开启fifo。
  • 注意检查drv_mpu.c配置nocache region
  • 注意检查link.lds配置nocache region
  • 注意rt_spi_configure函数存在一个提前return的bug,我已经修正了。
  • 在spixfer函数中,我调用底层HAL库函数的时候,大量使用了RT_ASSSERT()宏,感觉非常不错。
  • 注意,我们定义了DMA_SIZE=8192,这意味着支持的单个包的最大传输是8192 bytes。如果应用程序超过8192 bytes,需要做分包处理。
  • 后续优化,可以考虑修改spixfer函数,让其实现分包功能。这样软件应用层无需做分包处理,没有传输size限制。
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2018-11-5      SummerGift   first version* 2018-12-11     greedyhao    Porting for stm32f7xx* 2019-01-03     zylx         modify DMA initialization and spixfer function* 2020-01-15     whj4674672   Porting for stm32h7xx* 2020-06-18     thread-liu   Porting for stm32mp1xx* 2020-10-14     Dozingfiretruck   Porting for stm32wbxx*/#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "trace_log.h"#ifdef BSP_USING_SPI#include "drv_spi.h"
#include "drv_config.h"//#define DRV_DEBUG
#define LOG_TAG              "drv.spi"
#include <drv_log.h>#define DMA_SIZE 8192
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
#define USB_MEM_ALIGNX __attribute__((aligned(32)))
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t tx_buffer[DMA_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rx_buffer[DMA_SIZE];SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi2_tx;
DMA_HandleTypeDef hdma_spi2_rx;static void MX_SPI1_Init(void);
static void MX_DMA_Init(void);struct rt_completion spi_cpt;
struct rt_spi_bus spi_bus;static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{#define DMA_MIN_SIZE 10 /*set this=10000, means always use polling. set this=0, means always use dma. both works fine.*/HAL_StatusTypeDef state = HAL_OK;rt_size_t message_length, already_send_length;rt_uint16_t send_length;rt_uint8_t *recv_buf;const rt_uint8_t *send_buf;    /*pull cs*/if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE)){if (device->config.mode & RT_SPI_CS_HIGH){rt_pin_write(device->cs_pin, PIN_HIGH);}else{rt_pin_write(device->cs_pin, PIN_LOW);}}message_length = message->length;recv_buf = message->recv_buf;send_buf = message->send_buf;if(message_length < DMA_MIN_SIZE){ /*small length, use polling*/ if (message->send_buf && message->recv_buf){RT_ASSERT(HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)send_buf, (uint8_t *)recv_buf, message_length, 1000) == HAL_OK);}else if (message->send_buf){RT_ASSERT(HAL_SPI_Transmit(&hspi1, (uint8_t *)send_buf, message_length, 1000) == HAL_OK);}else if (message->recv_buf){RT_ASSERT(HAL_SPI_Receive(&hspi1, (uint8_t *)recv_buf, message_length, 1000) == HAL_OK);}while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);}else { /*large length, use dma*/RT_ASSERT(message_length <= DMA_SIZE); /*now only support dma length < 8192 bytes*//*copy to nocache tx_buffer*/if(message->send_buf){rt_memcpy(tx_buffer, send_buf, message_length);}/*start dma*/if (message->send_buf && message->recv_buf){RT_ASSERT(HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t *)tx_buffer, (uint8_t *)rx_buffer, message_length) == HAL_OK);}else if (message->send_buf){RT_ASSERT(HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)tx_buffer, message_length) == HAL_OK);}else if (message->recv_buf){RT_ASSERT(HAL_SPI_Receive_DMA(&hspi1, (uint8_t *)rx_buffer, message_length) == HAL_OK);}  /*wait dma finish*/RT_ASSERT(rt_completion_wait(&spi_cpt, 1000) == RT_EOK);/*copy from nocache rx_buffer*/if(message->recv_buf){rt_memcpy(recv_buf, rx_buffer, message_length);}}/*pull cs*/if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE)){if (device->config.mode & RT_SPI_CS_HIGH){rt_pin_write(device->cs_pin, PIN_LOW);}else{rt_pin_write(device->cs_pin, PIN_HIGH);}} return message->length;
}static rt_err_t spi_configure(struct rt_spi_device *device,struct rt_spi_configuration *configuration)
{MX_DMA_Init();MX_SPI1_Init();return RT_EOK;
}static const struct rt_spi_ops stm_spi_ops =
{.configure = spi_configure,.xfer = spixfer,
};rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
{RT_ASSERT(bus_name != RT_NULL);RT_ASSERT(device_name != RT_NULL);rt_err_t result;struct rt_spi_device *spi_device;/* attach the device to spi bus*/spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));RT_ASSERT(spi_device != RT_NULL);result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);RT_ASSERT(result == RT_EOK);return result;
}void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{rt_completion_done(&spi_cpt);
}void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{rt_completion_done(&spi_cpt);
}void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{rt_completion_done(&spi_cpt);
}int rt_hw_spi_init(void)
{rt_err_t result;rt_completion_init(&spi_cpt);result = rt_spi_bus_register(&spi_bus, "spi1", &stm_spi_ops);RT_ASSERT(result == RT_EOK);return result;
}
INIT_BOARD_EXPORT(rt_hw_spi_init);/*** @brief SPI1 Initialization Function* @param None* @retval None*/static void MX_SPI1_Init(void){/* USER CODE BEGIN SPI1_Init 0 *//* USER CODE END SPI1_Init 0 *//* USER CODE BEGIN SPI1_Init 1 *//* USER CODE END SPI1_Init 1 *//* SPI1 parameter configuration*/hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; /*must <25MHz is ok*/hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 0x0;hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 *//* USER CODE END SPI1_Init 2 */}/*** @brief SPI MSP Initialization* This function configures the hardware resources used in this example* @param hspi: SPI handle pointer* @retval None*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(hspi->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* Peripheral clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOG_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB5     ------> SPI1_MOSIPG9     ------> SPI1_MISOPA5     ------> SPI1_SCK*/GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* SPI1 DMA Init *//* SPI1_TX Init */hdma_spi1_tx.Instance = DMA1_Stream0;hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi1_tx.Init.Mode = DMA_NORMAL;hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;hdma_spi1_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;hdma_spi1_tx.Init.MemBurst = DMA_MBURST_SINGLE;hdma_spi1_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);/* SPI1_RX Init */hdma_spi1_rx.Instance = DMA1_Stream1;hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi1_rx.Init.Mode = DMA_NORMAL;hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;hdma_spi1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;hdma_spi1_rx.Init.MemBurst = DMA_MBURST_SINGLE;hdma_spi1_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);/* SPI1 interrupt Init */HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(SPI1_IRQn);/* USER CODE BEGIN SPI1_MspInit 1 *//* USER CODE END SPI1_MspInit 1 */}else if(hspi->Instance==SPI2){/* USER CODE BEGIN SPI2_MspInit 0 *//* USER CODE END SPI2_MspInit 0 *//* Peripheral clock enable */__HAL_RCC_SPI2_CLK_ENABLE();__HAL_RCC_GPIOI_CLK_ENABLE();/**SPI2 GPIO ConfigurationPI1     ------> SPI2_SCKPI2     ------> SPI2_MISOPI3     ------> SPI2_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);/* SPI2 DMA Init *//* SPI2_TX Init */hdma_spi2_tx.Instance = DMA1_Stream2;hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi2_tx.Init.Mode = DMA_NORMAL;hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(hspi,hdmatx,hdma_spi2_tx);/* SPI2_RX Init */hdma_spi2_rx.Instance = DMA1_Stream3;hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX;hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;hdma_spi2_rx.Init.Mode = DMA_NORMAL;hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;hdma_spi2_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;hdma_spi2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; /*要用single, spi dma才可以正常工作*/if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK){Error_Handler();}__HAL_LINKDMA(hspi,hdmarx,hdma_spi2_rx);/* SPI2 interrupt Init */HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);HAL_NVIC_EnableIRQ(SPI2_IRQn);/* USER CODE BEGIN SPI2_MspInit 1 *//* USER CODE END SPI2_MspInit 1 */}}/*** @brief SPI MSP De-Initialization* This function freeze the hardware resources used in this example* @param hspi: SPI handle pointer* @retval None*/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{if(hspi->Instance==SPI1){/* USER CODE BEGIN SPI1_MspDeInit 0 *//* USER CODE END SPI1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI1_CLK_DISABLE();/**SPI1 GPIO ConfigurationPB5     ------> SPI1_MOSIPG9     ------> SPI1_MISOPA5     ------> SPI1_SCK*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5);HAL_GPIO_DeInit(GPIOG, GPIO_PIN_9);HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);/* SPI1 DMA DeInit */HAL_DMA_DeInit(hspi->hdmatx);HAL_DMA_DeInit(hspi->hdmarx);/* SPI1 interrupt DeInit */HAL_NVIC_DisableIRQ(SPI1_IRQn);/* USER CODE BEGIN SPI1_MspDeInit 1 *//* USER CODE END SPI1_MspDeInit 1 */}else if(hspi->Instance==SPI2){/* USER CODE BEGIN SPI2_MspDeInit 0 *//* USER CODE END SPI2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI2_CLK_DISABLE();/**SPI2 GPIO ConfigurationPI1     ------> SPI2_SCKPI2     ------> SPI2_MISOPI3     ------> SPI2_MOSI*/HAL_GPIO_DeInit(GPIOI, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);/* SPI2 DMA DeInit */HAL_DMA_DeInit(hspi->hdmatx);HAL_DMA_DeInit(hspi->hdmarx);/* SPI2 interrupt DeInit */HAL_NVIC_DisableIRQ(SPI2_IRQn);/* USER CODE BEGIN SPI2_MspDeInit 1 *//* USER CODE END SPI2_MspDeInit 1 */}}/*** Enable DMA controller clock*/static void MX_DMA_Init(void){/* DMA controller clock enable */__HAL_RCC_DMA1_CLK_ENABLE();/* DMA interrupt init *//* DMA1_Stream0_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);/* DMA1_Stream1_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);/* DMA1_Stream2_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);/* DMA1_Stream3_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);}/*** @brief This function handles DMA1 stream0 global interrupt.*/
void DMA1_Stream0_IRQHandler(void)
{/* USER CODE BEGIN DMA1_Stream0_IRQn 0 *//* USER CODE END DMA1_Stream0_IRQn 0 */rt_base_t level = rt_hw_interrupt_disable();HAL_DMA_IRQHandler(&hdma_spi1_tx);rt_hw_interrupt_enable(level);/* USER CODE BEGIN DMA1_Stream0_IRQn 1 *//* USER CODE END DMA1_Stream0_IRQn 1 */
}/*** @brief This function handles DMA1 stream1 global interrupt.*/
void DMA1_Stream1_IRQHandler(void)
{/* USER CODE BEGIN DMA1_Stream1_IRQn 0 *//* USER CODE END DMA1_Stream1_IRQn 0 */rt_base_t level = rt_hw_interrupt_disable();HAL_DMA_IRQHandler(&hdma_spi1_rx);rt_hw_interrupt_enable(level);/* USER CODE BEGIN DMA1_Stream1_IRQn 1 *//* USER CODE END DMA1_Stream1_IRQn 1 */
}/*** @brief This function handles SPI1 global interrupt.*/void SPI1_IRQHandler(void){/* USER CODE BEGIN SPI1_IRQn 0 *//* USER CODE END SPI1_IRQn 0 */rt_base_t level = rt_hw_interrupt_disable();HAL_SPI_IRQHandler(&hspi1);rt_hw_interrupt_enable(level);/* USER CODE BEGIN SPI1_IRQn 1 *//* USER CODE END SPI1_IRQn 1 */}#endif /* BSP_USING_SPI */

3. port_spi_flash.c 挂载flash disk

#include <rtdevice.h>
#include <rtthread.h>
#include <board.h>
#include <dev_spi_flash.h>
#include <drv_spi.h>
#include "dev_spi_flash_sfud.h"
#include <dfs_fs.h>
#include <fal.h>
#include "trace_log.h"// #define DBG_TAG "app.port_spi_flash"
// #define DBG_LVL DBG_INFO
// #include <rtdbg.h>#define SPI_BUS_NAME "spi1"
#define SPI_DEVICE_NAME "spi10"
#define SPI_FLASH_DEVICE_NAME "W25Q64S"
#define SPI_SECT_DEVICE_NAME "flashdb"#define SPI_FLASH_CS_PIN    GET_PIN(A, 4)   // CS=PA4
int spi_flash_init(void)
{/* 挂载SPI Flash设备到软SPI1总线 */if (rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEVICE_NAME, SPI_FLASH_CS_PIN) != RT_EOK){rt_kprintf("Failed to attach SPI Flash!\n");return -RT_ERROR;}    if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_DEVICE_NAME, SPI_DEVICE_NAME)){return -RT_ERROR;};fal_init();fal_blk_device_create(SPI_SECT_DEVICE_NAME);/* 挂载文件系统 */#ifdef BSP_USING_FATFS_ROOTFSint try=10;while(dfs_mount(SPI_SECT_DEVICE_NAME, "/spi", "elm", 0, 0) != 0){LOG_W("mount to '/spi' failed! try again...");rt_thread_mdelay(100);try--;if(try<=0) break;}LOG_I("mount to '/spi' success!");// if (dfs_mount(SPI_SECT_DEVICE_NAME, "/spi", "elm", 0, 0) != 0)// {//     LOG_W("mount to '/spi' failed! try to mkfs %s", SPI_SECT_DEVICE_NAME);//     // dfs_mkfs("elm", SPI_SECT_DEVICE_NAME);//     if (dfs_mount(SPI_SECT_DEVICE_NAME, "/spi", "elm", 0, 0) == 0)//     {//         LOG_I("mount to '/spi' success!");//         goto _exit;//     }// }// LOG_I("mount to '/spi' success!");#endif_exit:return 0;
}
INIT_APP_EXPORT(spi_flash_init); 

4. 测试结果

  • 将#define DMA_MIN_SIZE 10,混合使用polling+dma,测试成功
  • 将#define DMA_MIN_SIZE 0,相当于只使用dma,测试成功
  • 将#define DMA_MIN_SIZE 10000,相当于只使用polling,测试成功

在这里插入图片描述

http://www.xdnf.cn/news/19312.html

相关文章:

  • Java函数式编程之【流(Stream)性能优化】
  • WPF和WinFrom区别
  • 计算机毕设 java 阿歹果园养鸡场管理系统 基于 SSM 框架的果园养鸡场全流程管理系统设计与实现 Java+MySQL 的养殖生产与进销存一体化平台开发
  • 汽车专卖店管理系统的设计与实现(代码+数据库+LW)
  • Langflow核心技术学习笔记
  • 探索 XGBoost 与 LightGBM 的差异:哪个更适合你的项目?
  • 基于TCN-BiLSTM-SelfAttention神经网络的多输入单输出回归预测【MATLAB】
  • 力扣(LeetCode) ——645. 错误的集合(C语言)
  • 整体设计 的语言设计:通用模型语言的标准模板语言的规格模式语言(搜狗汪仔答问)
  • GooglePlay提审问题记录
  • 国家统计局数据分析01——机器学习
  • wpf之附加属性
  • Odoo与Django 的区别是什么?
  • ADFS 和 OAuth 的区别
  • 龙迅#LT7641GX适用于四路HDMI2.1/DP/TPYE-C转HDMI2.1混切应用,分辨率高达8K60HZ!
  • 线性表和顺序表
  • 数据存储——数据库
  • 安卓开发---SimpleAdapter
  • ansible的playbook练习题
  • shell学习(二)
  • 【完整源码+数据集+部署教程】传送带建筑材料识别系统源码和数据集:改进yolo11-AFPN-P345
  • 网站酷炫换皮肤?——PC 端 H5 换肤方案实战分享
  • PCIe 6.0 TLP结构解析:深入理解事务层数据包的设计与实现
  • IDEA编译报错:Error:(3, 28) java: 程序包com.alibaba.fastjson不存在
  • 图解帕累托前沿(pareto frontier)
  • 海康相机开发---设备布防(Setup Alarm)
  • python 解码 视频解码
  • RAG教程6:cohere rerank重排
  • openEuler系统实现MySQL数据库主从复制
  • 基于站点、模式、遥感多源降水数据融合与评估;Python驱动下,从基础处理、机器学习建模到气候态产品生成的全流程解析