最近在玩412,这款在CUBEMX上很便宜的芯片,结果拿到样品之后,采购告诉我要6个美金,哭晕在厕所。 CUBEMX 不能相信价格啊。
言归正传,最近需要大存储量更新外部flash,利用的是华邦的w25系列。 拟解决的方案有以下几个:
1.采用大数组进行先整体发送到串口然后再整体烧写外部FLASH
2.利用两个数组交替存储的方式写入外部FLASH(不使用DMA)
3.利用DMA 双缓冲的方式
4.利用HALF中断和全部完成中断的方式
首先第一个方案,测试之后丢失数据严重,PASS;
第二个方案,人为模拟双缓冲,太冗余,PASS(代码能力有限)
第三个方案,在利用HAL库的双缓冲的时候出现了一些问题,最终放弃掉了。
出现的问题:
HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength);
这个函数 的解释 Starts the multi_buffer DMA Transfer with interrupt enabled. 只要开启DMA中断就可以实现 ,
函数里面有一句
/* Memory-to-memory transfer not supported in double buffering mode */
if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
{
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
return HAL_ERROR;
}
两个内存之间不可以用这种方式通信, 但是我的DMA配置是 hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; 从外设到内存
然而还是返回 HAL_ERROR . 我的SRCAddress的地址是USART6->DR,这个是内存地址? 这个还有待解决,为此,我就把这个方案pass了。。
最后我想到了half中断,一个half中断和 完成中断, 中断两次,我们可以利用一个数组就解决了双缓冲的问题。
在这里我参考了 原子哥的flash驱动,以及开源电子网的1201yuge 这个楼主的方法。
先测了写入flash的时间,然后开始更新数据,更新的方法在原来的基础上做了改动,可以一直更新数据。
在更新开始之前要先将需要的扇区擦除。之后再写入。
主要思想:
先定义一个8192字节的数组,在一个HALF中断或者完成中断来来之后,开始更新数据。最后将最后一部分的DMA数据写入FLASH。
DMA配置的注意事项
hdma_usart6_rx.Init.Mode = DMA_CIRCULAR;环形模式
__HAL_LINKDMA(huart,hdmarx,hdma_usart6_rx); 将DMA和USART RX连接
HAL_UART_Receive_DMA(&huart6,USART6_RX_Buf3,8192);//开启DMA中断接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//USART 完成回调
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)USART HAL回调
工程文件太大,上传不了论坛
需要的可以私信我,我传到网盘了。
希望大家对双缓冲有理解的多多交流,
|