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 ...
最新文章
- 关闭VMware 不用的服务
- spring 全局变量_精华:关于Spring的15点总结
- 在python中查看关键字需要在python解释器中执行_现有代码 d={},在Python3解释器中执行 d[([1,2])] = 'b'得到的结果为( )。...
- python: line=f.readlines() 后如何消除line中的’\n’
- linux结束进程_生人勿近之Linux里养僵尸
- pipeline 发布war包
- 苹果又想出涨价新招,iPhone 12将标配AirPods耳机?
- java跨系统和跨域_java web服务解决跨域问题
- linux下打印用户态段错误信息的一种方法
- 从零基础入门Tensorflow2.0 ----五、25TF1.0自定义estimator
- java中包定义_java中包的定义与使用
- 信号与系统的基本概念与通信系统模型
- C# 回调函数的实现和应用场景
- Java 遍历JsonNode
- 如何在vue3.0项目中集成Element-plus
- Birt时间参数添加My97日历控件
- 信息系统项目管理师-3项目立项管理
- android如何使用so库,Android 使用SO库
- C语言程序设计作业04
- 算法图解 第7章 狄克斯特拉算法
热门文章
- Handlebars 安装
- 停车还能360全方位影像_德国首创“新型汽车”不仅能无人驾驶,还能360度无死角停车...
- android开源项目!来一份全面的面试宝典练练手,通用流行框架大全
- OpenTSDB的故障排除
- c#动画(两点动画,旋转动画,变色动画)及案例
- python计算excel crc_CRC计算器的Python实现
- 用 Java 实现天天酷跑(附源码),这个真的有点强了!
- Github上的开源项目4
- 用于降低EMI的时钟展频技术
- 【蠢哭自己系列】Linux转到桌面目录下