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

如何使用SPI的DMA模式读写FLASH

[复制链接]
ldptest 提问时间:2019-12-3 16:13 /
环境:HAL + USB + W25Q64 + Fatfs
硬件:stm32f103c8t6 + MX25L64

我使用普通模式,完成在W25Q64中写入文件,通过USB可以再PC中读取出来。

因为我下一步想做一个监测系统,想提高flash读写效率,使用DMA模式
MCU一直在监测,不断往数组中写入数据,一旦满了,数据通过DMA模式往FLASH传,MCU继续监测。读也一样。

1、为了试验,我先把读的部分置换为DMA操作
HAL_SPI_Receive_DMA(&hspi1,buffer,4096);
在回调函数中
再Flash_cs端设置为高电平
但程序不能正常运行,请问需要增加什么代码?

2、写入,因为FLASH一个扇区4096bytes,但每次只能写入1Page(256bytes)
请问是否可以通过DMA循环传输功能实现不需要MCU介入一次写入扇区内容?

收藏 评论7 发布时间:2019-12-3 16:13

举报

7个回答
maxtch 回答时间:2019-12-4 10:39:44
您的这种场景其实不适合用这种 SPI 闪存,更适合的应该是 microSD 卡或 eMMC:容量更大,也更耐擦写。
ldptest 回答时间:2019-12-4 12:20:58
maxtch 发表于 2019-12-4 10:39
您的这种场景其实不适合用这种 SPI 闪存,更适合的应该是 microSD 卡或 eMMC:容量更大,也更耐擦写。 ...

因为数据量不大,所以想用spi flash
ldptest 回答时间:2019-12-11 21:49:48
我分解步骤测试,擦写扇区后写入数据,再回读检查是否正确。
方法一:正常方法写读
void ExtFlash_PageProg(uint8_t* pBuffer, uint32_t WriteAddr,uint16_t NumberOfBytes)
{
  ExtFlash_WaitForWriteEnd();                           //检查FLASH是否忙
  ExtFlash_WriteEnable();                               //允许写入
  ExtFlash_CS_LOW();
  InstructionSynthesis(W25X_PageProgram,WriteAddr);     //页编程
  SPI_Send(Send32Bits, 4);
  SPI_Send(pBuffer, NumberOfBytes);
  ExtFlash_CS_HIGH();
  ExtFlash_WriteDisable();                              //禁止写入
}
再执行
  if (ExtFlash_ReadBackTest() == HAL_OK)
  {
    HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
  }

结果,亮灯。

方法一:DMA写,正常读
void ExtFlash_PageProg(uint8_t* pBuffer, uint32_t WriteAddr,uint16_t NumberOfBytes)
{
  ExtFlash_WaitForWriteEnd();                           //检查FLASH是否忙
  ExtFlash_WriteEnable();                               //允许写入
  ExtFlash_CS_LOW();
  InstructionSynthesis(W25X_PageProgram,WriteAddr);     //页编程
  SPI_Send(Send32Bits, 4);
  SPI_Send_DMA(pBuffer, NumberOfBytes);
}
回调函数
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
  if(hspi == &hspi1)
  {
    ExtFlash_CS_HIGH();
    ExtFlash_WriteDisable();                              //禁止写入
    if (ExtFlash_ReadBackTest() == HAL_OK)
    {
      HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
    }
  }
}
结果,不亮灯。
调试,能进入回调函数,能运行读页,但读回的都是0xFF(ReadBuff是清0的)。

出问题可能性:
1、SPI在DMA不能正常传输数据
2、Flash不能正确接收DMA方式传输的数据
3、还没传输,就进入中断(因为第一个数字都没写进flash)

求助:如何解决?


SPI设置:
void MX_SPI1_Init(void)
{

  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_64;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

}


DMA设置:
    hdma_spi1_tx.Instance = DMA1_Channel3;
    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_HIGH;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx);
ldptest 回答时间:2019-12-12 23:51:17
唉,又是时钟先后顺序问题
Cubemx生成代码有问题

Step1:适用逻辑分析仪发现DMA根本没发数据
SPI.png


在Main.c

  MX_SPI1_Init();
  MX_DMA_Init();

在MX_SPI1_Init ————》 HAL_SPI_Init —————》 HAL_SPI_MspInit
HAL_SPI_MspInit中
先激活
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
然后进行GPIO设置
再进行DMA设置

MX_DMA_Init中
先激活
__HAL_RCC_DMA1_CLK_ENABLE();
然后再进行中断设置

以上代码是CubeMX自动生成。

我突然想起前段时间看到的文章
__HAL_RCC_DMA1_CLK_ENABLE();与SPI、GPIO时钟一起激活。
OK,DMA就能正常发送数据。
butterflyspring 回答时间:2019-12-17 17:14:39
是外设时钟没使能好,然后就初始化外设不成功吧?
ldptest 回答时间:2019-12-18 09:15:00
butterflyspring 发表于 2019-12-17 17:14
是外设时钟没使能好,然后就初始化外设不成功吧?

是时钟先后顺序问题
Cubemx生成代码有问题

在Main.c

  MX_SPI1_Init();
  MX_DMA_Init();

在MX_DMA_Init中才激活DMA时钟
ldptest 回答时间:2019-12-18 09:57:57
目前进展,
1、非DMA模式下,已经调通了。
2、DMA模式下的SPI flash的扇区读写也正常
3、但在USB + Fatfs 在DMA模式下仍不正常。

stm32f103c8t6的RAM只有20K,一个扇区就用4K,是否与这个有关,还是fatfs不支持DMA.
正在找其他RAM比较多的机进行移植测试。

所属标签

相似问题

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