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

FatFs初始化导致DMA传输异常

[复制链接]
elsearch 提问时间:2020-3-6 12:50 /
问题描述:
1、使用MCU:STM32f103RE
2、开发环境:CubeIDE
3、固件版本:STM32Cube FW_F1 V1.8.04、硬件连接:4位共阴极数码管,GPIOA0~7通过100Ω电阻连接数码管7断码和DP位,GPIOC0~3连接NPN三极管基极控制数码管阴极接地实现位选;SPI2(GPIOB端口)连接W25Q64 Flash芯片。
5、问题概述:定时器TIM2更新事件和定时器TIM2通道1比较输出事件,分别触发DMA1_Ch2向GPIOC,DMA1_Ch5向GPIOA,传输数据,驱动数码管动态扫描显示,并且正常工作。但,当运行MX_FATFS_Init()始化FatFs文件后,数码管显示异常,跟踪定位到函数FATFS_LinkDriverEx()中的【disk.drv[disk.nbr] = drv;】,运行该句后数码管显示异常。

希望知道原因的大神不吝赐教,在此万分感谢!!!

主要实现代码如下://DMA1通道5传输数据volatile uint32_t LDS_Buffer[8]={0x00ff00f0, 0x00ff0000, 0x00ff000f, 0x00ff0000, 0x00ff00f0, 0x00ff0000, 0x00ff000f, 0x00ff0000};
//DMA1通道2传输数据
volatile uint32_t SEG_Buffer[8]={0x000f0008, 0x000f0000, 0x000f0004, 0x000f0000, 0x000f0002, 0x000f0000, 0x000f0001, 0x000f0000};
int main(void)
{
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
W25QXX_Init();
MX_TIM2_Init();
HAL_DMA_Start(&hdma_tim2_ch1, (uint32_t)LDS_Buffer, (uint32_t)(&(GPIOA->BSRR)), 32);
HAL_DMA_Start(&hdma_tim2_up, (uint32_t)SEG_Buffer, (uint32_t)(&(GPIOC->BSRR)), 32);
__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_CC1|TIM_DMA_UPDATE);
HAL_TIM_Base_Start(&htim2);

运行完以上代码,数码管正常显示
MX_FATFS_Init();  //运行完该函数,数码管显示异常
while (1)
{
   }
}

代码跟踪:
  1. void MX_FATFS_Init(void)
  2. {
  3. /*## FatFS: Link the Flash driver ###########################*/
  4. retFlash = FATFS_LinkDriver(&Flash_Driver, FlashPath);
  5. }

  6. uint8_t FATFS_LinkDriver(Diskio_drvTypeDef *drv, char *path)
  7. {
  8. return FATFS_LinkDriverEx(drv, path, 0);
  9. }

  10. uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, char *path, uint8_t lun)
  11. {
  12. uint8_t ret = 1;
  13. uint8_t DiskNum = 0;

  14. if(disk.nbr <= _VOLUMES)
  15. {
  16. disk.is_initialized[disk.nbr] = 0;
  17. <b style="background-color: red;">disk.drv[disk.nbr] = drv; //跟踪至该句,运行该句后数码管显示异常</b>
  18. disk.lun[disk.nbr] = lun;
  19. DiskNum = disk.nbr++;
  20. path[0] = DiskNum + '0';
  21. path[1] = ':';
  22. path[2] = '/';
  23. path[3] = 0;
  24. ret = 0;
  25. }

  26. return ret;
  27. }
复制代码

Flash驱动移植:
  1. Diskio_drvTypeDef Flash_Driver =
  2. {
  3. Flash_initialize,
  4. Flash_status,
  5. Flash_read,
  6. #if _USE_WRITE == 1
  7. Flash_write,
  8. #endif /* _USE_WRITE == 1 */
  9. #if _USE_IOCTL == 1
  10. Flash_ioctl,
  11. #endif /* _USE_IOCTL == 1 */
  12. };

  13. DSTATUS Flash_initialize(BYTE pdrv) /* Physical drive nmuber to identify the drive */
  14. {
  15. W25QXX_Init();
  16. return RES_OK;
  17. }


  18. DSTATUS Flash_status(BYTE pdrv) /* Physical drive nmuber to identify the drive */
  19. {
  20. /* USER CODE BEGIN STATUS */
  21. Stat = STA_NOINIT;
  22. Stat = RES_OK;

  23. return Stat;
  24. /* USER CODE END STATUS */
  25. }


  26. DRESULT Flash_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
  27. {
  28. if (!count)
  29. return RES_PARERR;

  30. for(;count>0;count--)
  31. {
  32. W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
  33. sector++;
  34. buff+=FLASH_SECTOR_SIZE;
  35. }

  36. return RES_OK;
  37. }


  38. #if _USE_WRITE == 1
  39. DRESULT Flash_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
  40. {
  41. if (!count)
  42. {
  43. return RES_PARERR;
  44. }

  45. for(;count>0;count--)
  46. {
  47. W25QXX_Erase_Sector(sector);
  48. W25QXX_Write_NoCheck((uint8_t*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
  49. sector++;
  50. buff+=FLASH_SECTOR_SIZE;
  51. }

  52. return RES_OK;
  53. }
  54. #endif /* _USE_WRITE == 1 */


  55. #if _USE_IOCTL == 1
  56. DRESULT Flash_ioctl (BYTE pdrv, BYTE cmd, void *buff)
  57. {
  58. DRESULT res;
  59. switch(cmd)
  60. {
  61. case CTRL_SYNC:
  62. res = RES_OK;
  63. break;
  64. case GET_SECTOR_SIZE:
  65. *(WORD*)buff = FLASH_SECTOR_SIZE;
  66. res = RES_OK;
  67. break;
  68. case GET_BLOCK_SIZE:
  69. *(WORD*)buff = FLASH_BLOCK_SIZE;
  70. res = RES_OK;
  71. break;
  72. case GET_SECTOR_COUNT:
  73. *(DWORD*)buff = FLASH_SECTOR_COUNT;
  74. res = RES_OK;
  75. break;
  76. default:
  77. res = RES_PARERR;
  78. break;
  79. }
  80. return res;
  81. }
复制代码

外设初始化:
  1. void MX_TIM2_Init(void)
  2. {
  3. TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  4. TIM_MasterConfigTypeDef sMasterConfig = {0};
  5. TIM_OC_InitTypeDef sConfigOC = {0};

  6. htim2.Instance = TIM2;
  7. htim2.Init.Prescaler = 7199;
  8. htim2.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数
  9. htim2.Init.Period = 5;
  10. htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  11. htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; //自动重载
  12. if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  13. {
  14. Error_Handler();
  15. }
  16. sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  17. if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  18. {
  19. Error_Handler();
  20. }
  21. sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  22. sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  23. if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  24. {
  25. Error_Handler();
  26. }

  27. sConfigOC.OCMode = TIM_OCMODE_TIMING;
  28. sConfigOC.Pulse = 5;
  29. sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  30. sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  31. if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  32. {
  33. Error_Handler();
  34. }
  35. }

  36. void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
  37. {

  38. if(tim_baseHandle->Instance==TIM2)
  39. {
  40. /* TIM2 clock enable */
  41. __HAL_RCC_TIM2_CLK_ENABLE();

  42. /* TIM2 DMA Init */
  43. /* TIM2_UP Init */
  44. hdma_tim2_up.Instance = DMA1_Channel2;
  45. hdma_tim2_up.Init.Direction = DMA_MEMORY_TO_PERIPH;
  46. hdma_tim2_up.Init.PeriphInc = DMA_PINC_DISABLE;
  47. hdma_tim2_up.Init.MemInc = DMA_MINC_ENABLE;
  48. hdma_tim2_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; //WORD
  49. hdma_tim2_up.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  50. hdma_tim2_up.Init.Mode = DMA_CIRCULAR;
  51. hdma_tim2_up.Init.Priority = DMA_PRIORITY_LOW;
  52. if (HAL_DMA_Init(&hdma_tim2_up) != HAL_OK)
  53. {
  54. Error_Handler();
  55. }

  56. __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim2_up);

  57. /* TIM2_CH1 Init */
  58. hdma_tim2_ch1.Instance = DMA1_Channel5;
  59. hdma_tim2_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
  60. hdma_tim2_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
  61. hdma_tim2_ch1.Init.MemInc = DMA_MINC_ENABLE;
  62. hdma_tim2_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  63. hdma_tim2_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  64. hdma_tim2_ch1.Init.Mode = DMA_CIRCULAR;
  65. hdma_tim2_ch1.Init.Priority = DMA_PRIORITY_LOW;
  66. if (HAL_DMA_Init(&hdma_tim2_ch1) != HAL_OK)
  67. {
  68. Error_Handler();
  69. }

  70. __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_CC1],hdma_tim2_ch1);
  71. }
  72. }


  73. void MX_DMA_Init(void)
  74. {
  75. /* DMA controller clock enable */
  76. __HAL_RCC_DMA1_CLK_ENABLE();
  77. }

  78. void W25QXX_Init(void)
  79. {
  80. //        uint8_t temp = 0;
  81. GPIO_InitTypeDef GPIO_InitStruct = {0};
  82. __HAL_RCC_GPIOB_CLK_ENABLE();

  83. /**SPI2 GPIO Configuration
  84. PB12 ------> SPI2_CS
  85. PB13 ------> SPI2_SCK
  86. PB14 ------> SPI2_MISO
  87. PB15 ------> SPI2_MOSI
  88. */

  89. //PB12
  90. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
  91. GPIO_InitStruct.Pin=GPIO_PIN_12; //PB12
  92. GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
  93. GPIO_InitStruct.Pull=GPIO_PULLUP; //上拉
  94. GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;//高速
  95. HAL_GPIO_Init(GPIOB,&GPIO_InitStruct); //初始化


  96. hspi2.Instance = SPI2;
  97. hspi2.Init.Mode = SPI_MODE_MASTER; //设置SPI工作模式:设置为主SPI

  98. hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  99. hspi2.Init.DataSize = SPI_DATASIZE_8BIT; //设置SPI的数据大小:SPI发送接收8位帧结构
  100. hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; //选择了串行时钟的稳态:时钟悬空高
  101. hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; //数据捕获(采样)于第二个时钟沿
  102. hspi2.Init.NSS = SPI_NSS_SOFT;
  103. hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;

  104. hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  105. hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  106. hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  107. hspi2.Init.CRCPolynomial = 10; //CRC值计算的多项式
  108. if (HAL_SPI_Init(&hspi2) != HAL_OK)
  109. {
  110. Error_Handler();
  111. }

  112. __HAL_SPI_ENABLE(&hspi2); //使能SPI2
  113. SPI2_ReadWriteByte(0Xff); //启动传输

  114. }
复制代码






收藏 评论4 发布时间:2020-3-6 12:50

举报

4个回答
你若安好_清风徐来 回答时间:2020-3-10 09:52:12
是不是MX_FATFS_Init处理完毕跑到异常处理中断里面去了 ,显示异常是什么异常,是只显示一段了 还是全部黑了,还是全部显示一样的,还是全部不一样乱码了,建议开启串口在异常中断中打印消息

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

回答时间:2020-3-10 15:19:33
楼主可能是溢出了。Flash_Driver定义的内容是否都是有效的?
elsearch 回答时间:2020-3-11 11:34:27
你若安好_清风徐来 发表于 2020-3-10 09:52
是不是MX_FATFS_Init处理完毕跑到异常处理中断里面去了 ,显示异常是什么异常,是只显示一段了 还是全部黑 ...

程序正常运行,没有进入异常中断,加过串口,通信也都是正常,所谓显示异常是指不按设定的值显示,我设定显示1234,在运行MX_FATFS_Init之前都是正常显示1234,运行MX_FATFS_Init之后就变成了1288
elsearch 回答时间:2020-3-11 11:40:35
安 发表于 2020-3-10 15:19
楼主可能是溢出了。Flash_Driver定义的内容是否都是有效的?

程序没有进入HardFault,应该不是溢出,我堆和栈都设的挺大的0x2000;Flash这块能够正常模拟u盘的并且读写也都每天,Flash_Driver定义的内容应该不会有问题吧

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版