你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32CubeMX+FreeRTOS+SD+FATFS碰到 DMA FIFO溢出问题

[复制链接]
juky2008 提问时间:2018-2-17 10:46 /
本帖最后由 juky2008 于 2018-2-19 09:46 编辑

大家好:
      我最近在使用的原子哥的STM32F407的开发板,芯片是STM32F407ZET6,原先我使用CubeMX4.21和F4库 1.16.0 调试SD卡驱动,用CubeMX配置收发DMA传输,但是生成的sd_disk.c中SD_read,SD_write函数并没有调用BSP_SD_ReadBlocks_DMA,BSP_SD_WriteBlocks_DMA函数。生成代码可以读取SD卡的信息,fatfs也可以挂载,但是多次新建文件打开和关闭后,fatfs返回FR_DISK_ERR;可能是由于SD卡无响应后超时导致。
    然后我下载STM32CubeMX4.24和1.19.0库文件,配置好后,生成的sd_disk.c中SD_read,SD_write函数使用了BSP_SD_ReadBlocks_DMA,BSP_SD_WriteBlocks_DMA函数和信号量(队列),进行了线程保护,但是生成的代码并不能使用。读写函数都卡在了 event = osMessageGet(SDQueueID, SD_TIMEOUT);分析后发现程序中并没有释放信号量,于是我在sd_disk.c文件最后添加了
  1. void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
  2. {
  3.   BSP_SD_ReadCpltCallback();
  4. }

  5. void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
  6. {
  7.   BSP_SD_WriteCpltCallback();
  8. }
复制代码


void DMA2_Stream6_IRQHandler(void)中断调用了HAL_SD_TxCpltCallback回调函数,但是HAL_SD_RxCpltCallback()回调函数并没有被调用。FatFs不能正常读写SD卡。
最后我在CubeMX中开启了SDIO global interrupt 中断后SD卡后,HAL_SD_RxCpltCallback()才被调用。现在Fatfs可以正常读写SD卡(8GB)了。
间隔200ms给Fatfs测试任务发送通知,Fatfs测试任务完成创建文件(文件名不重复),写入数据(8192字节),关闭文件的功能,25000次(大概3小时)都没有问题,但是任务的完成时间由原来的200ms间隔(每次给任务发送通知),逐渐增加到1.2秒(每次任务完成后,会通过串口打印将信息发给电脑,串口助手有时间戳)。这个原因我现在不清楚。
通过仿真发现在中断函数中一直进入FIFO Error错误。但是SD卡可以正常读写。我没有找到原因。
  1. void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
  2. {
  3.   /* FIFO Error Interrupt management ******************************************/
  4.   if ((tmpisr & (DMA_FLAG_FEIF0_4 << hdma->StreamIndex)) != RESET)
  5.   {
  6.     if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != RESET)
  7.     {
  8.       /* Clear the FIFO error flag */
  9.      regs->IFCR = DMA_FLAG_FEIF0_4 << hdma->StreamIndex;

  10.      /* Update error code */
  11.      hdma->ErrorCode |= HAL_DMA_ERROR_FE;
  12.     }
  13.   }
  14. }
复制代码




请大家多多指教,谢谢!


收藏 1 评论11 发布时间:2018-2-17 10:46

举报

11个回答
juky2008 回答时间:2018-2-18 20:26:57
本帖最后由 juky2008 于 2018-2-19 09:48 编辑

仿真时发现 在stm32f4xx_hal_sd.c ,只要一执行SDIO_ConfigData(hsd->Instance, &config);后就出现错误。
  1. HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
  2. {
  3.   SDIO_DataInitTypeDef config;
  4.   uint32_t errorstate = HAL_SD_ERROR_NONE;
  5.   
  6.   if(NULL == pData)
  7.   {
  8.     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
  9.     return HAL_ERROR;
  10.   }
  11.   
  12.   if(hsd->State == HAL_SD_STATE_READY)
  13.   {
  14.     hsd->ErrorCode = HAL_DMA_ERROR_NONE;
  15.    
  16.     if((BlockAdd + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
  17.     {
  18.       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
  19.       return HAL_ERROR;
  20.     }
  21.    
  22.     hsd->State = HAL_SD_STATE_BUSY;
  23.    
  24.     /* Initialize data control register */
  25.     hsd->Instance->DCTRL = 0U;
  26.    
  27.     /* Enable SD Error interrupts */  
  28. #ifdef SDIO_STA_STBITER
  29.     __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR));   
  30. #else /* SDIO_STA_STBITERR not defined */
  31.     __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));   
  32. #endif /* SDIO_STA_STBITERR */
  33.    
  34.     /* Set the DMA transfer complete callback */
  35.     hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt;
  36.    
  37.     /* Set the DMA error callback */
  38.     hsd->hdmatx->XferErrorCallback = SD_DMAError;
  39.    
  40.     /* Set the DMA Abort callback */
  41.     hsd->hdmatx->XferAbortCallback = NULL;
  42.    
  43.     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
  44.     {
  45.       BlockAdd *= 512U;
  46.     }
  47.    
  48.     /* Set Block Size for Card */
  49.     errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
  50.     if(errorstate != HAL_SD_ERROR_NONE)
  51.     {
  52.       /* Clear all the static flags */
  53.       __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
  54.       hsd->ErrorCode |= errorstate;
  55.       hsd->State = HAL_SD_STATE_READY;
  56.       return HAL_ERROR;
  57.     }
  58.    
  59.     /* Write Blocks in Polling mode */
  60.     if(NumberOfBlocks > 1U)
  61.     {
  62.       hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
  63.       
  64.       /* Write Multi Block command */
  65.       errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, BlockAdd);
  66.     }
  67.     else
  68.     {
  69.       hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
  70.       
  71.       /* Write Single Block command */
  72.       errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, BlockAdd);
  73.     }
  74.     if(errorstate != HAL_SD_ERROR_NONE)
  75.     {
  76.       /* Clear all the static flags */
  77.       __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
  78.       hsd->ErrorCode |= errorstate;
  79.       hsd->State = HAL_SD_STATE_READY;
  80.       return HAL_ERROR;
  81.     }
  82.    
  83.     /* Enable SDIO DMA transfer */
  84.     __HAL_SD_DMA_ENABLE(hsd);
  85.    
  86.     /* Enable the DMA Channel */
  87.     HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4);   //DMA2 stream6 发送0x80个数据,执行这条语句后,寄存器S6NDTR从0x80变成0xFFFF,太奇怪了。此时寄存器TCIF6=0,FEIF6=0;
  88.    
  89.     /* Configure the SD DPSM (Data Path State Machine) */
  90.     config.DataTimeOut   = SDMMC_DATATIMEOUT;
  91.     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
  92.     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
  93.     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
  94.     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
  95.     config.DPSM          = SDIO_DPSM_ENABLE;
  96.     SDIO_ConfigData(hsd->Instance, &config);//执行完这条语句后,S6NDTR=0xFF7F, 相当于发送的字节数0xFFFF-0xFF7F=0x80,难道是巧合?此时寄存器TCIF6=1,FEIF6=1;接着就进入DMA2_Stream6的FIFO ERROR中断了,每次都一样。但是数据已经发送出去了,TCIF也等于1了,Fatfs的f_write() 返回FR_OK。
  97.    
  98.     return HAL_OK;
  99.   }
  100.   else
  101.   {
  102.     return HAL_BUSY;
  103.   }
  104. }
复制代码


大家有没有碰到过这个问题啊?




feixiang20 回答时间:2018-3-16 09:49:22
是不是相关寄存器配置错误呢?FIFO失能?

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

wenyangzeng 回答时间:2018-3-16 10:10:33
FIFO关掉试看看,这个FIFO不那么好玩。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

无薪税绵 回答时间:2018-3-16 10:29:24
会不会是SD卡的问题?
换一张SD卡再试试。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

juky2008 回答时间:2018-3-16 11:30:18
本帖最后由 juky2008 于 2018-3-16 11:40 编辑

换过SD卡了,一样的问题。但都可以正常读写,用FATFS读写时间长后,sd卡的存储时间变长。
我主要想用STM32CubeMX生成,比较方便,SDIO的DMA配置上不能取消FIFO功能。如果不用DMA功能,SD卡响应会超时。
谢谢大家的回复。
七哥 回答时间:2018-3-16 14:14:55
这个问题太高端,我没搞过,只能帮你攒人气。
希望有能力的大佬快来帮忙!
yygkqzh 回答时间:2018-3-16 17:21:07
SDIO有3种方式 ,polling、IT,DMA,既然DMA不能使用,你可以首先试试POLLING、IT模式。
再退一步讲,你可以使用裸机试试能否成功,有没有错误消息,一步一步来。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

juky2008 回答时间:2018-3-16 19:14:41
谢谢大家的提醒,我按照大家的方法去一步一步调试。
枫天123 回答时间:2018-11-22 15:08:44
既然解决了?怎么不说明是哪的问题,怎么解决的呢
insect2006 回答时间:2019-1-25 16:54:59
枫天2015 发表于 2018-11-22 15:08
既然解决了?怎么不说明是哪的问题,怎么解决的呢

同意!当初求种像条狗,如今撸完嫌人丑!
陳勝・呉広 回答时间:2019-2-21 14:05:15
本帖最后由 ccschen 于 2019-2-21 14:19 编辑

原谅我笑了。第一次看到这句。

当初求种像条狗,如今撸完嫌人丑!


所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版