ST意法半导体
直播中

陈敏

7年用户 1330经验值
私信 关注
[问答]

修复STM32F4xxx STMCubeMX固件V1.18 SDIO FATFS DMA不工作怎么解决?

发表于 2018 年 1 月 2 日 12:18

  大家好,

  最近使用STM32CubeMX Ver 4.0(STMCube V1.0),固件V1.18为STM32F407生成代码,使用SDIO 4位总线通过DMA或标准IO访问SD卡。生成的代码可能无法运行。

  为了使其工作,您必须修改 STM32CubeMX 生成的三个文件:

  1. bsp_driver_sd.c

  2. sd_diskio.c

  3.fatfs.c

  以下是程序:

  1.

  bsp_driver_sd.c

  修改

  BSP_SD_WriteBlocks() 和

  BSP_SD_ReadBlocks_DMA() 支持 DMA 或标准 I/O:

  
  • // A flag indicating if to use DMA for read/write
  • uint8_t BSP_SD_Ext_UseDMA = 1;
  • /*==========================================================================
  • Description
  • DMA or polling mode of Reads block(s) from a specified address in an SD card
  • * @param pData: Pointer to the buffer that will contain the data to transmit
  • * @param ReadAddr: Address from where data is to be read
  • * @param NumOfBlocks: Number of SD blocks to read
  • * @param Timeout: Timeout for read operation
  • * @retval SD status
  • ---------------------------------------------------------------------------*/
  • uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
  • {
  • HAL_SD_StateTypeDef state_return;
  • uint32_t timeout = 0;
  • if (BSP_SD_Ext_UseDMA == 0) {
  • if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
  • return MSD_ERROR;
  • } else {
  • // Read block(s) in DMA transfer mode
  • if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*) pData, ReadAddr, NumOfBlocks) != HAL_OK)
  • return MSD_ERROR;
  • // Wait until the SDIO/SDMMC and DMA finish the read/write
  • timeout = 0;
  • do {
  • state_return = HAL_SD_GetState(&hsd);
  • timeout++;
  • } while((state_return == HAL_SD_STATE_BUSY) && (timeout < SD_DATATIMEOUT));
  • if (HAL_SD_STATE_READY != state_return)
  • return MSD_ERROR;
  • }
  • return MSD_OK;
  • }
  • /*==========================================================================
  • Description
  • DMA or polling mode of Write block(s) to a specified address in an SD card
  • * @param pData: Pointer to the buffer that will contain the data to transmit
  • * @param WriteAddr: Address from where data is to be written
  • * @param NumOfBlocks: Number of SD blocks to write
  • * @param Timeout: Timeout for write operation
  • * @retval SD status
  • ---------------------------------------------------------------------------*/
  • uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
  • {
  • HAL_SD_StateTypeDef state_return;
  • uint32_t timeout = 0;
  • if(BSP_SD_Ext_UseDMA == 0) {
  • if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
  • return MSD_ERROR;
  • } else {
  • // Read block(s) in DMA transfer mode
  • if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*) pData, WriteAddr, NumOfBlocks) != HAL_OK)
  • return MSD_ERROR;
  • // Wait until the SDIO/SDMMC and DMA finish the read/write
  • timeout = 0;
  • do {
  • state_return = HAL_SD_GetState(&hsd);
  • timeout++;
  • }
  • while((state_return == HAL_SD_STATE_BUSY) && (timeout < SD_DATATIMEOUT));
  • if (HAL_SD_STATE_READY != state_return)
  • return MSD_ERROR;
  • }
  • return MSD_OK;
  • }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


  2. sd_diskio.c

  i) 修复缺少的 SDIO 初始化代码

  原始生成代码:

  
  • DSTATUS SD_initialize(BYTE lun)
  • {
  • return SD_CheckStatus(lun);
  • }‍‍‍‍


  应该修改(我不知道

  为什么 BSP_SD_Init() 不见了!
):
  
  • DSTATUS SD_initialize(BYTE lun)
  • {
  • Stat = STA_NOINIT;
  • if (BSP_SD_Init() == MSD_OK)
  • Stat = SD_CheckStatus(lun);
  • return Stat;
  • }‍‍‍‍‍‍‍‍‍


  否则,它无法通过 HAL_SD_Init() 初始化 SDIO!

  ii) 修改SD_read()和SD_write:

  
  • DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
  • {
  • DRESULT res = RES_ERROR;
  • if (BSP_SD_ReadBlocks((uint32_t*)buff,
  • (uint32_t) (sector),
  • count,
  • SDMMC_DATATIMEOUT) == MSD_OK) {
  • // wait until the read operation is finished
  • while (BSP_SD_GetCardState()!= MSD_OK);
  • res = RES_OK;
  • }
  • return res;
  • }
  • DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
  • {
  • DRESULT res = RES_ERROR;
  • if (BSP_SD_WriteBlocks((uint32_t*)buff,
  • (uint32_t)(sector),
  • count,
  • SDMMC_DATATIMEOUT) == MSD_OK) {
  • // wait until the Write operation is finished
  • while (BSP_SD_GetCardState() != MSD_OK);
  • res = RES_OK;
  • }
  • return res;
  • }
  • ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


  3.

  fatfs.c

  添加挂载程序挂载SD卡文件系统

  原始生成代码:

  
  • void MX_FATFS_Init(void)
  • {
  • /*## FatFS: Link the SD driver ###########################*/
  • retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
  • /* USER CODE BEGIN Init */
  • /* additional user code for init */
  • /* USER CODE END Init */
  • }‍‍‍‍‍‍‍‍‍‍


  修改后的代码:

  
  • void MX_FATFS_Init(void)
  • {
  • /*## FatFS: Link the SD driver ###########################*/
  • retSD = FATFS_LinkDriver(&SD_Driver, SDPath);
  • /* USER CODE BEGIN Init */
  • /* additional user code for init */
  • if (retSD != 0)
  • Error_Handler();
  • if (f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
  • Error_Handler();
  • /* USER CODE END Init */
  • }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


  最后,我们可以编写代码来测试 FATFS:

  
  • void SDFileTest(void)
  • {
  • FIL MyFile;
  • FRESULT res; /* FatFs function common result code */
  • uint32_t byteswritten, bytesread; /* File write/read counts */
  • uint8_t wtext[] = 'Hello, STM32F4 FatFs!'; /* File write buffer */
  • uint8_t rtext[100]; /* File read buffer */
  • printf('SD File createn');
  • // Create file test
  • if (f_open(&MyFile, 'STMTXT', FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
  • Error_Handler();
  • res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
  • if ((byteswritten == 0) || (res != FR_OK))
  • Error_Handler();
  • f_close(&MyFile);
  • printf('done!n');
  • printf('SD File openn');
  • // Read file test
  • if (f_open(&MyFile, 'STMTXT', FA_READ) != FR_OK)
  • Error_Handler();
  • res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread);
  • if ((bytesread == 0) || (res != FR_OK))
  • Error_Handler();
  • f_close(&MyFile);
  • if ((bytesread != byteswritten))
  • Error_Handler();
  • printf('done!n');
  • }
  • int main(void)
  • {
  • .
  • .
  • MX_DMA_Init();
  • .
  • .
  • MX_SDIO_SD_Init();
  • .
  • .
  • MX_FATFS_Init();
  • .
  • .
  • SDFileTest();
  • while (1);
  • }
  • ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍








回帖(1)

周芸

2023-1-4 11:13:35
  我已经在 FreeRTOS 下通过使用 DMA 测试了 FATFS,它有效!
  这是设置STM32CubeMX V4.24的屏幕截图
    项目设置:
    确保启用 FATFS 配置“使用 dma 模板”:
    SDIO设置:
  启用 NVIC
    和 DMA 设置
    然后,调整 FreeRTOS、堆栈和堆大小
    生成代码后,您必须修改以下文件:
  A. sd_diskio.c(如
  
), 您必须在文件末尾插入以下代码  

  • #endif /* _USE_IOCTL == 1 *//* USER CODE BEGIN afterIoctlSection *//* can be used to modify previous code / undefine following code / add new code *//* USER CODE END afterIoctlSection *//* USER CODE BEGIN callbackSection *//* can be used to modify / following code or add new code */void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd){ osMessagePut(SDQueueID, WRITE_CPLT_MSG, osWaitForever);}void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd){ osMessagePut(SDQueueID, READ_CPLT_MSG, osWaitForever);}/* USER CODE END callbackSection */‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


  注意:HAL_SD_ReadBlocks_DMA 和 HAL_SD_WriteBlocks_DMA 需要 DMA 完成 TX/RX 中断以向前台进程发出 DMA TX/RX 是否已完成的信号。
  B. 如果您使用 MDK-ARM 作为您的 IDE,您应该删除 ''U'',否则会导致 port.c 中的编译错误
  修改stm32f407xx.h头文件修复错误:
  

  • #define __NVIC_PRIO_BITS 4 /*!< STM32F4XX uses 4 Bits for the Priority Levels */‍


  C、修改freertos.c文件,插入FATFS文件测试程序:
  

  • /* USER CODE BEGIN FunctionPrototypes */void SDFileTest(void){ FIL MyFile; FRESULT res; /* FatFs function common result code */ uint32_t byteswritten, bytesread; /* File write/read counts */ uint8_t wtext[] = ''Hello, STM32F4 FatFs!''; /* File write buffer */ uint8_t rtext[100]; /* File read buffer */// printf(''SD File create''); // Create file test if (f_open(&MyFile, ''STMTXT'', FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) Error_Handler(); res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten); if ((byteswritten == 0) || (res != FR_OK)) Error_Handler(); f_close(&MyFile);// printf(''done!'');// printf(''SD File open''); // Read file test if (f_open(&MyFile, ''STMTXT'', FA_READ) != FR_OK) Error_Handler(); res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread); if ((bytesread == 0) || (res != FR_OK)) Error_Handler(); f_close(&MyFile); if ((bytesread != byteswritten)) Error_Handler();// printf(''done!'');}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


  并将以下代码插入到
  

  • /* StartDefaultTask function */void StartDefaultTask(void const * argument){ /* init code for FATFS */ MX_FATFS_Init(); /* USER CODE BEGIN StartDefaultTask */ if (f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK) Error_Handler(); SDFileTest(); /* Infinite loop */ for(;;) { osDelay(1); } /* USER CODE END StartDefaultTask */}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍



举报

更多回帖

发帖
×
20
完善资料,
赚取积分