打印
[应用相关]

STM32硬件基础--QaudSPI总线读写片外FLASH(二)

[复制链接]
951|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
【海东青电子原创**,转载请注明出处:https://www.jianshu.com/p/77f7bd0817e9
TM32F746的文档在介绍QaudSPI时,上来就说了三种工作模式:
1、“间接”模式
2、状态轮询模式
3、内存映射模式
这是什么意思呢?本人当时读文档读到此处时,是一脸的懵逼。有了前一讲 《STM32硬件基础--QaudSPI总线读写片外FLASH(一)》的基础,再来理解就容易多了。QSPI的这三种工作模式,是相对于ST MCU而言的,是为了简化MCU对QSPI器件(多为FLASH)而设立的。MCU针对FLASH主要就是做了两件事:一个是读写数据等收发命令,还有一个是:要经常查询FLASH的状态。比如写入数据,在写FLASH之前,必须先进行擦除,擦除需要时间,后续的写入命令必须等待擦除完成。怎么能知道是否擦除完成了呢?就得不断查询FLASH的状态。所以,常用的读写等命令就对应了上面的模式一:间接模式(ST MCU又把它具体分为间接写、间接读两种模式),而查询FLASH状态就对应了模式二:状态轮询。
至于模式三:内存映射模式,是为了简化读FLASH的操作。实际应用中,片外FLASH大多用于图片等静态数据存储,其写入是在烧写MCU时通过ST-LINK之类软件工具完成的。MCU运行时,基本上都是只从FLASH中读出数据。为了简化这个操作,可以使用模式三,将片外FLASH的地址映射到片内的地址空间(BANK1的起始地址为0x9000 0000),从而可以像访问片内地址一样来访问外部FLASH。不难理解,模式三只能用于读、不能写。(而且,映射的最大地址空间不能超过256MB。)



作者:海东青电子
链接:https://www.jianshu.com/p/77f7bd0817e9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

使用特权

评论回复
沙发
parameters|  楼主 | 2020-6-26 14:30 | 只看该作者
下面先来看看读数据的实现(代码下载地址:https://github.com/haidongqing/qspi-readflash)。我们采用四线快读方式:

使用特权

评论回复
板凳
parameters|  楼主 | 2020-6-26 14:32 | 只看该作者
注意注解5:

使用特权

评论回复
地板
parameters|  楼主 | 2020-6-26 14:32 | 只看该作者
N25Q要求在这种读数据模式下,需要10个 Dummy clock cycles。时序图:

使用特权

评论回复
5
parameters|  楼主 | 2020-6-26 14:33 | 只看该作者
发出read指令后,需要等待10个 Dummy cycles。在读操作之前,需要先对FLASH设置这个参数。在《STM32硬件基础--QaudSPI总线读写片外FLASH(一)》中提到,N25Q有2个配置寄存器:Nonvolatile Configuration Register 和 Volatile Configuration Register,前者是非易失的,后者是易失的,这里派上了用场,我们的方式是修改易失的 Volatile Configuration Register(代码中,MCU每次上电都要做这个操作):先读出  Volatile Configuration Register 的值,设置 Dummy cycles,之后再写回 Volatile Configuration Register。

使用特权

评论回复
6
parameters|  楼主 | 2020-6-26 14:34 | 只看该作者

使用特权

评论回复
7
parameters|  楼主 | 2020-6-26 14:35 | 只看该作者
因为涉及了FLASH的写操作,先要使能写操作、然后才能写。代码中专门有一个函数 QSPI_WriteEnable() 来使能“写”:

使用特权

评论回复
8
parameters|  楼主 | 2020-6-26 14:36 | 只看该作者
FLASH的写使能状态保存在FLASH的状态寄存器 status register 中:

使用特权

评论回复
9
parameters|  楼主 | 2020-6-26 14:36 | 只看该作者
写状态寄存器、对FLASH编程(写)、擦除时,需要使能写。发出使能写指令后,需要查询该指令是否顺利完成了,即前面提到的“模式二”。这里使用了一个函数:HAL_QSPI_AutoPolling()。查询时,我们只关心位于 bit1 的 Write enable latch 标志位是否被置1了,所以 sConfig 结构体(轮询模式参数配置)中,屏蔽字(.Mask)设为0x02(bit1有效),匹配目标(.Match)设为0x02。

使用特权

评论回复
10
parameters|  楼主 | 2020-6-26 14:37 | 只看该作者
完整的修改Status Resgister 的代码在函数 QSPI_DummyCyclesCfg() 中实现,然后读取FLASH数据:

使用特权

评论回复
11
parameters|  楼主 | 2020-6-26 14:37 | 只看该作者
正确读出数据后,开发板上的LED慢闪;如出错,LED长亮。FLASH出厂时,数据全为0xFF。本实验中,先用预先提供的 set_01234.hex 文件烧写开发板、并复位运行,将在FLASH地址起始处写入 “0123456789” 十个字符,然后再运行上面例程,即可看到正确的读出结果。

使用特权

评论回复
12
parameters|  楼主 | 2020-6-26 14:38 | 只看该作者
再来看看模式三,内存映射模式下,如何读取FLASH数据,代码详见:https://github.com/haidongqing/qspi-readflash-mapped。

使用特权

评论回复
13
parameters|  楼主 | 2020-6-26 14:38 | 只看该作者
核心是函数:HAL_QSPI_MemoryMapped(),在其内部使用参数 QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED 调用了  QSPI_Config(),从而实现对模式三的设定:

/* Call the configuration function */

      QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED);

使用特权

评论回复
14
parameters|  楼主 | 2020-6-26 14:39 | 只看该作者
然后按内部地址方式读出数据:

使用特权

评论回复
15
parameters|  楼主 | 2020-6-26 14:40 | 只看该作者
MCU对片外FLASH的操作以读为主,到此,有关QSPI使用的关键点已经讲完了。有兴趣的同学,请继续下一讲:《QSPI如何写FLASH数据https://www.jianshu.com/p/3d8b6f2c95a3》。

使用特权

评论回复
16
parameters|  楼主 | 2020-6-26 14:40 | 只看该作者

作者:海东青电子
链接:https://www.jianshu.com/p/77f7bd0817e9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

使用特权

评论回复
17
renzheshengui| | 2020-7-10 16:43 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
18
wakayi| | 2020-7-10 16:44 | 只看该作者
英文的 看不懂啊

使用特权

评论回复
19
wowu| | 2020-7-10 16:44 | 只看该作者
楼主辛苦啦

使用特权

评论回复
20
xiaoqizi| | 2020-7-10 16:45 | 只看该作者
资料很不错

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

361

帖子

0

粉丝