esp8266,esp32中的SPI FLASH 访问模式(QIO QOUT DIO DOUT)

本文

ESP8266 和 ESP32 支持四种不同的 SPI flash 访问模式:DIO、DOUT、QIO 和 QOUT。 这些可以通过 esptool.py write_flash--flash_mode 选项设置。

这些控制选项决定哪些 I/O 引脚与连接的 SPI 闪存芯片进行通信,以及使用哪些 SPI 命令。

ESP8266 和 ESP32 在从 SPI 闪存芯片读取或执行代码和数据时使用这些命令。 读取数据然后缓存到芯片内部。

概要

按性能排序:

可选项模式名称引脚速度(ESP8266 & ESP32)
qio Quad I/O地址和数据 4pins最快
qout Quad Output数据 4pins约比 qio 模式下慢 15%
dio Dual I/O地址和数据 2pins约比 qio 模式下慢 45%
doutDual Output数据 2pins约比 qio 模式下慢 50%

通常选择与设备相适应的最快的工作模式, 并非所有设备都支持所有模式。 有关详细信息,请参阅下文中的常见问题解答。

模式说明 

 正常SPI
传统的“单”SPI(串行外设接口)总线使用 4 个引脚进行通信:

ᴥ 时钟 (CLK)
ᴥ 主出从入 (MOSI)
ᴥ 主进从出 (MISO)
ᴥ 片选 (CS)
维基百科有相当完整的描述。

所有这些信号都是单向的。 在单 SPI 模式下,数据从设备发送到主机使用 MISO 引脚,从主机发送到设备使用 MOSI 引脚。

正常 SPI 的最大数据速率是以位为单位的时钟速率 ,因此 40MHz 时钟 = 40Mbits/sec = 5Mbytes/sec。

Dual SPI

为了提高性能,SPI 闪存制造商推出了“Dual SPI”。在Dual SPI 模式下,MOSI 和 MISO 引脚都用于以每个时钟周期两位的方式同时读取或写入数据。与单个 SPI 相比,这使某些命令的数据速率加倍。

dout模式下,主机使用“双输出快速读取”(3BH)命令来读取数据。每个读取命令和读取地址通过正常的 SPI 从主机发送到闪存芯片,然后主机通过 MOSI 和 MISO 引脚同时读取数据,每个时钟两位。与仅使用 MISO 读取数据的单个 SPI 相比,这使数据传输速率加倍。

dio模式下,主机使用“双I/O快速读取”(BBH)命令来读取数据。每个读取命令都通过正常的 SPI 从主机发送到闪存芯片,然后地址通过 MOSI 和 MISO 引脚以每个时钟两位的方式发送到闪存芯片。此后,主机以与“双输出快速读取”相同的方式读取每个时钟两位的数据位。

对于 ESP8266 和 ESP32,每个命令读取 32 个字节,dio 模式比 dout 快大约 5%。

请查阅您的特定 SPI 闪存芯片的数据表,以确定它是否支持这些命令中的一个或两个。

Quad SPI

为了进一步提高SPI flash数据传输的性能,SPI flash厂商推出了“Quad SPI”模式。这种模式增加了两个额外的引脚(否则使用闪存芯片 WP 和 HOLD 信号)用于数据传输。这允许双 SPI 的数据速率加倍。

并非所有闪存芯片都支持 Quad SPI 模式,并且并非所有 ESP8266 和 ESP32 芯片都将这些引脚连接到 SPI 闪存芯片。一些闪存芯片需要特殊命令来启用quad modes(见下文)。

qout 模式下,主机使用“四输出快速读取”(6BH)命令读取数据。此命令与“双输出快速读取”相同,区别在每个时钟周期 在 4 个引脚上读取数据,而不是在2 个引脚上读取数据。这使得数据传输的速度恰好是“双输出快速读取”的两倍。

qio模式下,主机使用“Quad I/O Fast Read”(EBH)命令来读取数据。此命令与“双 I/O 快速读取”相同,只是地址和数据每个时钟周期都在 4 个引脚上传输,而不是用 2 个引脚。这使得地址和数据传输速度是“双 I/O 快速读取”的两倍。

常见问题解答

为什么 qio 和 qout 模式不适用于我的乐鑫芯片/模块? 

通常是以下原因之一:

ᴥ SPI flash 芯片的 WP 和 HOLD 引脚未连接到乐鑫芯片的正确 GPIO。这些引脚必须正确连接才能使四路模式工作,而且并非所有板子/模块都连接它们。
ᴥ SPI 闪存芯片不支持四模式。查看闪存芯片数据表以了解它支持哪些模式。您可以直观地识别闪存芯片,或使用 esptool.py flash_id 命令来识别闪存芯片。
ᴥ 此芯片型号未正确启用quad mode模式。 SPI 闪存不是标准,因此每个制造商实现的方式都是不同的。大多数闪存芯片需要发送某些命令才能启用 Quad SPI 模式,这些命令各不相同。对于 ESP8266 和 ESP32,这通常意味着芯片首先以Dual SPI 模式启动,然后软件(ESP32 的引导加载程序或 ESP8266 的 SDK)检测芯片类型并尝试启用 Quad SPI 模式。如果软件不支持特定的芯片型号,那么它将无法进入quad mode。

为什么 qout/dout 模式有效,而 qio/dio 模式无效?

某些 SPI 闪存芯片型号仅支持“双输出快速读取”和/或“四输出快速读取”命令,而不支持qio/dio模式。

与 Quad SPI 相比,我的代码在 Dual SPI 模式下的运行速度会减半吗?


不。ESP8266 和 ESP32 都直接从 Flash 执行代码,但是因为从 Flash 读取数据很慢,所以数据被透明地缓存在 RAM 中。闪存读取命令仅在发生缓存未命中时发送。但是,使用Dual SPI 读取重新填充缓存的速度大约是其 Quad SPI 等效项的一半。

如果您无法使用 Quad SPI 模式,请确保您正在配置在您的板子/模块上可靠运行的最快 SPI Flash 时钟速率。 Dual I/O 模式下的 80MHz SPI 时钟比 Quad I/O 模式下的 40MHz SPI 时钟快。

Flash 模式如何与 ESP8266/ESP32 通信?

烧录到SPI flash上的bootloader.bin文件包含一个标头,其中包含闪存速度、闪存模式和一些其他数据。复位后由 ROM 代码读取此标头时确定主机的模式。将“-flash_mode”参数传递给 esptool.py 将在文件写入闪存时更新此标头。

这仅确定用于从复位初始引导的模式。然后,作为引导过程的一部分,软件可能会以不同方式配置闪存模式。

例如,在 ESP32 上,如果 ESP-IDF 配置为 qio/qout 模式,那么 IDF 软件引导加载程序实际上是使用 dio/dout 模式刷新的。当 ROM 代码从闪存引导此引导加载程序时,引导加载程序软件会检查闪存芯片模型并为引导过程的其余部分启用正确的 Quad SPI 模式。这是因为在不同芯片型号上启用 Quad SPI 的方法有多种。

原文链接:https://github.com/espressif/esptool/wiki/SPI-Flash-Modes

  • 7
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DOUT、DIO、QOUT和QIOSPI闪存芯片的四种不同的接口模式。其,DOUT和QOUT是输出模式DIOQIO是双向模式。这些模式的选择取决于具体的应用场景和性能需求。 DOUT模式下,数据从主设备输出到闪存器件,闪存器件的输出数据也是从单个数据线上输出。DIO模式下,数据可以在单个数据线上进行双向传输,但是在传输过程需要切换数据线的输入输出方向。QOUT模式下,数据从主设备输出到闪存器件,闪存器件的输出数据是从四个数据线上同时输出。QIO模式下,数据可以在四个数据线上进行双向传输。 以下是四种模式的示例代码: DOUT模式: ```python import spidev spi = spidev.SpiDev() spi.open(0, 0) spi.mode = 0b00 spi.max_speed_hz = 1000000 address = 0x00 data = [0x01, 0x02, 0x03, 0x04] spi.xfer2([0x02, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]) spi.xfer2(data) ``` DIO模式: ```python import spidev spi = spidev.SpiDev() spi.open(0, 0) spi.mode = 0b11 spi.max_speed_hz = 1000000 address = 0x00 data = [0x01, 0x02, 0x03, 0x04] spi.xfer2([0x02, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]) spi.xfer2(data) ``` QOUT模式: ```python import spidev spi = spidev.SpiDev() spi.open(0, 0) spi.mode = 0b01 spi.max_speed_hz = 1000000 address = 0x00 data = [0x01, 0x02, 0x03, 0x04] spi.xfer2([0x6b, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]) spi.xfer2(data) ``` QIO模式: ```python import spidev spi = spidev.SpiDev() spi.open(0, 0) spi.mode = 0b10 spi.max_speed_hz = 1000000 address = 0x00 data = [0x01, 0x02, 0x03, 0x04] spi.xfer2([0xeb, (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff]) spi.xfer2(data) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值