STM32 QSPI双闪存操作
@STM32 QSPI双闪存操作
使用CubeMX或者CubeIDE生成框架
使用野火的开发板,MCU型号为stm32h750/743,他们家核心板上使用了QSPI挂了2片FLASH,型号为W25Q256,但是提供的例程里只有单个FLASH的QSPI操作例程。根据了解,他们本来计划在核心板上只保留1片FLASH的,只是我买的比较早了 。
在开发板上的原理图接线如上,其中PB2为时钟,PG6为片选,两片FLASH共用。
QSPI双FLASH模式的配置注意把片选设置为1个片选选中2片FLASH就可以了,其他引脚设置按照原理图中进行设置即可。在CubeIDE中,点击保存后会自动弹框,询问是否生成代码,非常的方便。
双闪存需要注意的地方
开发板厂家提供了该flash的底层驱动,bsp_qspi_flash.c bsp_qspi_flash.h,在驱动里提供了擦除、写入、读取等函数接口,在擦除和写入的函数中都调用了一个轮询等待的子函数。因为FLASH进行擦除和写入都需要耗费一定时间,在这段时间内无法进行其他操作,比如读取,因此在FLASH内部有许多状态寄存器。轮询等待的实现就是去查询相应的寄存器,只有当表示空闲的那一位数据为1时,表示可以进行读取操作,为0则表示繁忙。
/*** @brief 擦除QSPI存储器的指定块* @param BlockAddress: 需要擦除的块地址* @retval QSPI存储器状态*/
uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress)
{QSPI_CommandTypeDef s_command;/* 初始化擦除命令 */s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;s_command.Instruction = SECTOR_ERASE_CMD;s_command.AddressMode = QSPI_ADDRESS_1_LINE;s_command.AddressSize = QSPI_ADDRESS_32_BITS;s_command.Address = BlockAddress;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode = QSPI_DATA_NONE;s_command.DummyCycles = 0;s_command.DdrMode = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;/* 启用写操作 */if (QSPI_WriteEnable() != QSPI_OK){return QSPI_ERROR;}/* 发送命令 */if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK){return QSPI_ERROR;}/* 配置自动轮询模式等待擦除结束 */if (QSPI_AutoPollingMemReady(W25Q256JV_SECTOR_ERASE_MAX_TIME) != QSPI_OK){return QSPI_ERROR;}return QSPI_OK;
}
厂家提供的驱动只有单个FLASH状态寄存器读取的设置,因此需要修改该函数。
首先看一下原来的自动轮询模式等待函数QSPI_AutoPollingMemReady
/*** @brief 读取存储器的SR并等待EOP* @param hqspi: QSPI句柄* @param Timeout 超时* @retval 无*/
static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout)
{QSPI_CommandTypeDef s_command;QSPI_AutoPollingTypeDef s_config;/* 配置自动轮询模式等待存储器准备就绪 */s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;s_command.Instruction = READ_STATUS_REG1_CMD;s_command.AddressMode = QSPI_ADDRESS_NONE;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode = QSPI_DATA_1_LINE;s_command.DummyCycles = 0;s_command.DdrMode = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;s_config.Match = 0x00;s_config.Mask = W25Q256JV_FSR_BUSY;s_config.MatchMode = QSPI_MATCH_MODE_AND;s_config.StatusBytesSize = 1;s_config.Interval = 0x10;s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, Timeout) != HAL_OK){return QSPI_ERROR;}return QSPI_OK;
}
该函数是向FLASH发送READ_STATUS_REG1_CMD(05H)命令读取FLASH内部的寄存器,我们只关注这个状态寄存器的第0 位“BUSY”,当这个位为“1”时,表明FLASH 芯片处于忙碌状态,它可能正在对内部的存储矩阵进行“擦除”或“数据写入”的操作。调用HAL_QSPI_AutoPolling 库函数,设定命令参数及自动轮询参数,最后设定超时返回,如果在超时等待时间内确定FLASH 就绪则返回存储器就绪状态,否则返回存储器错误。其实主要就是检查它的W25Q256FV_FSR_BUSY (01H)(即BUSY 位),通过QUADSPI_PSMAR
与**QUADSPI_QUADSPI _PSMKR **作‘与’运算或者是作‘或’运算。如果满足条件才退出本函数,以便继续后面与FLASH 芯片的数据通讯。
单个FLASH需要判断一个字节,而双闪存操作的情况下,有可能一片FLASH已经处于空闲状态,而另一片还在繁忙,若此时进行其他操作则会导致结果异常(亲测只判断一片空闲就写入数据,导致只有一片FLASH中有数据)。由于双闪存模式下HAL库读取为:第一个字节为FLASH1的数据,第二个字节为FLASH2的数据,第三个字节为FLASH1的数据,这样奇偶交替,因此轮询等待读取状态寄存器的函数
修改为:
static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout)
{QSPI_CommandTypeDef s_command;QSPI_AutoPollingTypeDef s_config;/* 配置自动轮询模式等待存储器准备就绪 */s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;s_command.Instruction = READ_STATUS_REG1_CMD;s_command.AddressMode = QSPI_ADDRESS_NONE;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode = QSPI_DATA_1_LINE;s_command.DummyCycles = 0;s_command.DdrMode = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;s_config.Match = 0x00;s_config.Mask = W25Q256JV_FSR_BUSY + (W25Q256JV_FSR_BUSY <<8);/*双闪存判断两个字节*/s_config.MatchMode = QSPI_MATCH_MODE_AND;s_config.StatusBytesSize = 2;/*双闪存判断两个字节*/s_config.Interval = 0x10;s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, Timeout) != HAL_OK){return QSPI_ERROR;}return QSPI_OK;
}
这样就可以判断出两片FLASH都处于就绪状态了
STM32 QSPI双闪存操作相关推荐
- STM32之 W25Q128闪存(SPI协议)驱动代码(程序稳定,清晰明了)
第一部分:W25Q128代码头文件 (W25Q128.h) #ifndef W25Q128_H #define W25Q128_H #include "stm32f10x.h" # ...
- stm32闪存的理解
STM32f1xxx的闪存模块由:主存储器.信息块和闪存存储器接口寄存器等3部分组成. 各个部分的大小因不同型号有一定的差异,数据手册中可以看到 小容量产品主存储块1-32KB,每页1KB.系统存储器 ...
- nRF52832闪存FDS使用(SDK17.1.0)
陈拓 2022/10/29-2022/11/22 1. 简介 对于Nordic芯片内部FLASH存储管理有两种方式,FS (Flash Storage)和FDS (Flash Data Storage ...
- 洋桃开发板笔记(六 ) STM32自带的Flash闪存使用,主要配合其他外设
Flash闪存与其他外设的使用 杜洋工作室 www.DoYoung.net 洋桃电子 www.DoYoung.net/YT 在此声明一下所有代码均为 杜洋工作室 的不允许复制,转发等,本人只是在此程序 ...
- (39)STM32——FLASH闪存
目录 学习目标 成果展示 介绍 组成 主存储器 系统存储器 OTP 区域 选项字节 读取 编程 寄存器 步骤 擦除 扇区擦除 批量擦除 寄存器 代码 总结 学习目标 本节我们要来介绍一下关于FLASH ...
- STM32存储器组织-STM32存储器映像-嵌入式SRAM-STM32位段-嵌入式闪存-STM32启动配置
STM使用说明第二篇 [1]STM32存储器组织 [2]STM32存储器映像 [3]嵌入式SRAM [4]STM32位段 [5]嵌入式闪存 [6]STM32启动配置 [1]STM32存储器组织 程序存 ...
- 使用大于 16MB 的闪存时, Zynq 和 QSPI 的复位要求
原文地址:http://blog.csdn.net/pengwangguo/article/details/54963702 哪个 Zynq-7000 平台会受影响? 在以下任何配置中使用大于 16M ...
- 使用大于 16MB 的闪存时 Zynq 和 QSPI 的复位要求
哪个 Zynq-7000 平台会受影响? 在以下任何配置中使用大于 16MB QSPI 闪存进行启动的任何 Zynq-7000 平台:单路.双堆叠.双路并行. 注意:具有两个 16MB QSPI 闪存 ...
- 【STM32】详解嵌入式中FLASH闪存的特性和代码示例
一.存储器 我们正常编译生成的二进制文件,需要下载烧录到单片机里面去,这个文件保存在单片机的ROM(read only memory)中,所有可以完成这种特性的存储介质都可以称为ROM. 分类 ROM ...
最新文章
- 重构机房收费系统你要用的——异常处理和抛出异常(try catch finally)——(vb.net)...
- Android Canvas 绘图
- python 常量_大疆机甲大师Python开发: 两只老虎
- Windows和Linux环境下搭建SVN服务器
- PageRanke算法
- Angular Observable数据类型的单元测试数据准备
- WeakReference与SoftReference
- java mediator_java—mediator中介模式
- k-means及变种
- jni java与c++交互返回三维数组jobjectArray
- cisco路由器配置DHCP实例
- LoadRunner教程(28)-LoadRunner连接mysql
- Win10 1607 频繁断网,迅雷断网以及迅雷下载崩溃解决方案
- 013.自驾游加油方案
- educoder:第3关:嵌套循环 - 跃迁能量表
- MATLAB长除法求z变换逆变换
- 发卡网源码(企业和个人发卡网源码二合一)及代理系统附搭建教程
- vue过滤器如何使用
- 吴恩达新动向揭晓:加入精神健康领域的人工智能Woebot
- 菜谱系统小成阶段,Python Web 领域终于攻占一个小山头
热门文章
- 一篇介绍LSTM的博客,写的很好
- 真是嘴上硬的人大多心里软,又把事做了还讨不了好
- tomcat无法启动 Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardConte
- python线上培训班5月是淡季
- 双向链表的定义及基本操作
- Springboot毕设项目班费管理系统16me6(java+VUE+Mybatis+Maven+Mysql)
- 给母猪接生,这事我干过!
- Uncaught SyntaxError: Unexpected identifier 和 Uncaught SyntaxError: Invalid or unexpected token
- 通过ping++平台完成移动端H5支付
- Tomcat 如何实现一键式启停?