summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2018-11-26 18:20:20 +0800
committerGitHub <[email protected]>2018-11-26 18:20:20 +0800
commita87914b5358092d7650d3455a163c92dd4cbcf8a (patch)
tree9404869d07d3b185f103413c43c7f11c92617501
parent3f55d915273450b769f0fc1c90256454999007e0 (diff)
parent7a6034fdf7c26c9d51dd7edb0d47967e3ef2373b (diff)
Merge pull request #2006 from armink/fix_sfud
Update sfud
-rwxr-xr-xcomponents/drivers/Kconfig11
-rw-r--r--components/drivers/include/drivers/spi.h4
-rw-r--r--components/drivers/spi/SConscript3
-rw-r--r--components/drivers/spi/qspi_core.c2
-rw-r--r--components/drivers/spi/sfud/README.md114
-rw-r--r--components/drivers/spi/sfud/inc/sfud.h19
-rw-r--r--components/drivers/spi/sfud/inc/sfud_cfg.h7
-rw-r--r--components/drivers/spi/sfud/inc/sfud_def.h46
-rw-r--r--components/drivers/spi/sfud/inc/sfud_flash_def.h50
-rw-r--r--components/drivers/spi/sfud/src/sfud.c129
-rw-r--r--components/drivers/spi/spi_flash_sfud.c136
11 files changed, 442 insertions, 79 deletions
diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig
index 94af352410..9e97aac3c3 100755
--- a/components/drivers/Kconfig
+++ b/components/drivers/Kconfig
@@ -168,7 +168,11 @@ config RT_USING_SPI
bool "Using SPI Bus/Device device drivers"
default n
- if RT_USING_SPI
+ if RT_USING_SPI
+ config RT_USING_QSPI
+ bool "Enable QSPI mode"
+ default n
+
config RT_USING_SPI_MSD
bool "Using SD/TF card driver with spi"
select RT_USING_DFS
@@ -185,6 +189,11 @@ config RT_USING_SPI
config RT_SFUD_USING_FLASH_INFO_TABLE
bool "Using defined supported flash chip information table"
default y
+
+ config RT_SFUD_USING_QSPI
+ bool "Using QSPI mode support"
+ select RT_USING_QSPI
+ default n
config RT_DEBUG_SFUD
bool "Show more SFUD debug information"
diff --git a/components/drivers/include/drivers/spi.h b/components/drivers/include/drivers/spi.h
index 7394710581..04a65421a5 100644
--- a/components/drivers/include/drivers/spi.h
+++ b/components/drivers/include/drivers/spi.h
@@ -144,8 +144,8 @@ struct rt_qspi_configuration
rt_uint32_t medium_size;
/* double data rate mode */
rt_uint8_t ddr_mode;
- /* the number of lines connected to the hardware */
- rt_uint8_t qspi_hw_lines;
+ /* the data lines max width which QSPI bus supported, such as 1, 2, 4 */
+ rt_uint8_t qspi_dl_width ;
};
struct rt_qspi_device
diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript
index ee423c33db..b88671ebc9 100644
--- a/components/drivers/spi/SConscript
+++ b/components/drivers/spi/SConscript
@@ -6,6 +6,9 @@ src = ['spi_core.c', 'spi_dev.c']
CPPPATH = [cwd, cwd + '/../include']
LOCAL_CCFLAGS = ''
+if GetDepend('RT_USING_QSPI'):
+ src += ['qspi_core.c']
+
src_device = []
if GetDepend('RT_USING_SPI_WIFI'):
diff --git a/components/drivers/spi/qspi_core.c b/components/drivers/spi/qspi_core.c
index 7676764b59..c9ff6a9637 100644
--- a/components/drivers/spi/qspi_core.c
+++ b/components/drivers/spi/qspi_core.c
@@ -25,7 +25,7 @@ rt_err_t rt_qspi_configure(struct rt_qspi_device *device, struct rt_qspi_configu
qspi_device->config.parent.reserved = cfg->parent.reserved;
qspi_device->config.medium_size = cfg->medium_size;
qspi_device->config.ddr_mode = cfg->ddr_mode;
- qspi_device->config.qspi_hw_lines = cfg->qspi_hw_lines;
+ qspi_device->config.qspi_dl_width = cfg->qspi_dl_width;
result = rt_spi_configure(&device->parent, &cfg->parent);
diff --git a/components/drivers/spi/sfud/README.md b/components/drivers/spi/sfud/README.md
index 7394321243..c732d06dbe 100644
--- a/components/drivers/spi/sfud/README.md
+++ b/components/drivers/spi/sfud/README.md
@@ -6,11 +6,13 @@
[SFUD](https://github.com/armink/SFUD) 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。
-- 主要特点:面向对象(同时支持多个 Flash 对象)、可灵活裁剪、扩展性强、支持 4 字节地址
+- 主要特点:支持 SPI/QSPI 接口、面向对象(同时支持多个 Flash 对象)、可灵活裁剪、扩展性强、支持 4 字节地址
- 资源占用
- 标准占用:RAM:0.2KB ROM:5.5KB
- 最小占用:RAM:0.1KB ROM:3.6KB
-- 设计思路:这里要首先跟大家介绍一个标准: **SFDP** ,它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数,如果该 Flash 不支持 SFDP,则查询配置文件 ( [`/sfud/inc/sfud_flash_def.h`](https://github.com/armink/SFUD/blob/master/sfud/inc/sfud_flash_def.h#L110-L122) ) 中提供的 **Flash 参数信息表** 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 [2.5 添加库目前不支持的 Flash](#25-添加库目前不支持的-flash))。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。
+- 设计思路:
+ - **什么是 SFDP** :它是 JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。
+ - **不支持 SFDP 怎么办** :如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 ( [`/sfud/inc/sfud_flash_def.h`](https://github.com/armink/SFUD/blob/4bee2d0417a7ce853cc7aa3639b03fe825611fd9/sfud/inc/sfud_flash_def.h#L116-L142) ) 中提供的 **Flash 参数信息表** 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 [2.5 添加库目前不支持的 Flash](#25-添加库目前不支持的-flash))。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。
## 1、为什么选择 SFUD
@@ -23,37 +25,43 @@
### 2.1 已支持 Flash
-下表为所有在 Demo 平台上进行过真机测试的 Flash。目前 SFUD 提供的 **Flash 参数信息表** 只包括下表中 **不支持** SFDP 标准的 Flash,其他不支持 SFDP 标准的 Flash 需要大家以后 **共同来完善和维护** **([Github](https://github.com/armink/SFUD)|[OSChina](http://git.oschina.net/armink/SFUD)|[Coding](https://coding.net/u/armink/p/SFUD/git))** 。如果觉得这个开源项目很赞,可以点击 [项目主页](https://github.com/armink/SFUD) 右上角的 **Star** ,同时把它推荐给更多有需要的朋友。
+下表为所有已在 Demo 平台上进行过真机测试过的 Flash。显示为 **不支持** SFDP 标准的 Flash 已经在 Flash 参数信息表中定义,更多不支持 SFDP 标准的 Flash 需要大家以后 **共同来完善和维护** **([Github](https://github.com/armink/SFUD)|[OSChina](http://git.oschina.net/armink/SFUD)|[Coding](https://coding.net/u/armink/p/SFUD/git))** 。
-|型号|制造商|容量|最高速度|SFDP 标准|备注|
-|:--:|:----:|:--:|:--:|:--:|:--:|
-|[W25Q40BV](http://microchip.ua/esp8266/W25Q40BV(EOL).pdf)|Winbond|4Mb|50Mhz|不支持|已停产|
-|[W25Q80DV](http://www.winbond.com/resource-files/w25q80dv_revg_07212015.pdf)|Winbond|8Mb|104Mhz|支持||
-|[W25Q16BV](https://media.digikey.com/pdf/Data%20Sheets/Winbond%20PDFs/W25Q16BV.pdf)|Winbond|16Mb|104Mhz|不支持| by [slipperstree](https://github.com/slipperstree)|
-|[W25Q16CV](http://www.winbond.com/resource-files/da00-w25q16cvf1.pdf)|Winbond|16Mb|104Mhz|支持||
-|[W25Q16DV](http://www.winbond.com/resource-files/w25q16dv%20revk%2005232016%20doc.pdf)|Winbond|16Mb|104Mhz|支持| by [slipperstree](https://github.com/slipperstree)|
-|[W25Q32BV](http://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf)|Winbond|32Mb|104Mhz|支持||
-|[W25Q64CV](http://www.winbond.com/resource-files/w25q64cv_revh_052214[2].pdf)|Winbond|64Mb|80Mhz|支持||
-|[W25Q128BV](http://www.winbond.com/resource-files/w25q128bv_revh_100313_wo_automotive.pdf)|Winbond|128Mb|104Mhz|支持||
-|[W25Q256FV](http://www.winbond.com/resource-files/w25q256fv%20revi%2002262016%20kms.pdf)|Winbond|256Mb|104Mhz|支持||
-|[MX25L3206E](http://www.macronix.com/Lists/DataSheet/Attachments/3199/MX25L3206E,%203V,%2032Mb,%20v1.5.pdf)|Macronix|32Mb|86MHz|支持||
-|[KH25L4006E](http://www.macronix.com.hk/Lists/Datasheet/Attachments/117/KH25L4006E.pdf)|Macronix|4Mb|86Mhz|支持| by [JiapengLi](https://github.com/JiapengLi)|
-|[KH25L3206E](http://www.macronix.com.hk/Lists/Datasheet/Attachments/131/KH25L3206E.pdf)|Macronix|32Mb|86Mhz|支持||
-|[SST25VF016B](http://ww1.microchip.com/downloads/en/DeviceDoc/20005044C.pdf)|Microchip|16Mb|50MHz|不支持| SST 已被 Microchip 收购|
-|[M25P40](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p40.pdf)|Micron|4Mb|75Mhz|不支持| by [redocCheng](https://github.com/redocCheng)|
-|[M25P80](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p80.pdf)|Micron|8Mb|75Mhz|不支持| by [redocCheng](https://github.com/redocCheng)|
-|[M25P32](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p32.pdf)|Micron|32Mb|75Mhz|不支持||
-|[EN25Q32B](http://www.kean.com.au/oshw/WR703N/teardown/EN25Q32B%2032Mbit%20SPI%20Flash.pdf)|EON|32Mb|104MHz|不支持||
-|[GD25Q16B](http://www.gigadevice.com/product/detail/5/410.html)|GigaDevice|16Mb|120Mhz|不支持| by [TanekLiang](https://github.com/TanekLiang) |
-|[GD25Q64B](http://www.gigadevice.com/product/detail/5/364.html)|GigaDevice|64Mb|120Mhz|不支持||
-|[S25FL216K](http://www.cypress.com/file/197346/download)|Cypress|16Mb|65Mhz|不支持||
-|[S25FL032P](http://www.cypress.com/file/196861/download)|Cypress|32Mb|104Mhz|不支持| by [yc_911](https://gitee.com/yc_911) |
-|[S25FL164K](http://www.cypress.com/file/196886/download)|Cypress|64Mb|108Mhz|支持||
-|[A25L080](http://www.amictechnology.com/datasheets/A25L080.pdf)|AMIC|8Mb|100Mhz|不支持||
-|[A25LQ64](http://www.amictechnology.com/datasheets/A25LQ64.pdf)|AMIC|64Mb|104Mhz|支持||
-|[F25L004](http://www.esmt.com.tw/db/manager/upload/f25l004.pdf)|ESMT|4Mb|100Mhz|不支持||
-|[PCT25VF016B](http://pctgroup.com.tw/attachments/files/files/248_25VF016B-P.pdf)|PCT|16Mb|80Mhz|不支持|SST 授权许可,会被识别为 SST25VF016B|
-|[AT45DB161E](http://www.adestotech.com/wp-content/uploads/doc8782.pdf)|ADESTO|16Mb|85MHz|不支持|ADESTO 收购 Atmel 串行闪存产品线|
+如果觉得这个开源项目很赞,可以点击 [项目主页](https://github.com/armink/SFUD) 右上角的 **Star** ,同时把它推荐给更多有需要的朋友。
+
+|型号|制造商|容量|最高速度|SFDP 标准|QSPI 模式|备注|
+|:--:|:----:|:--:|:--:|:--:|:--:|----|
+|[W25Q40BV](http://microchip.ua/esp8266/W25Q40BV(EOL).pdf)|Winbond|4Mb|50Mhz|不支持|双线|已停产|
+|[W25Q80DV](http://www.winbond.com/resource-files/w25q80dv_revg_07212015.pdf)|Winbond|8Mb|104Mhz|支持|双线||
+|[W25Q16BV](https://media.digikey.com/pdf/Data%20Sheets/Winbond%20PDFs/W25Q16BV.pdf)|Winbond|16Mb|104Mhz|不支持|双线| by [slipperstree](https://github.com/slipperstree)|
+|[W25Q16CV](http://www.winbond.com/resource-files/da00-w25q16cvf1.pdf)|Winbond|16Mb|104Mhz|支持|未测试||
+|[W25Q16DV](http://www.winbond.com/resource-files/w25q16dv%20revk%2005232016%20doc.pdf)|Winbond|16Mb|104Mhz|支持|未测试| by [slipperstree](https://github.com/slipperstree)|
+|[W25Q32BV](http://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf)|Winbond|32Mb|104Mhz|支持|双线||
+|[W25Q64CV](http://www.winbond.com/resource-files/w25q64cv_revh_052214[2].pdf)|Winbond|64Mb|80Mhz|支持|四线||
+|[W25Q128BV](http://www.winbond.com/resource-files/w25q128bv_revh_100313_wo_automotive.pdf)|Winbond|128Mb|104Mhz|支持|四线||
+|[W25Q256FV](http://www.winbond.com/resource-files/w25q256fv%20revi%2002262016%20kms.pdf)|Winbond|256Mb|104Mhz|支持|四线||
+|[MX25L3206E](http://www.macronix.com/Lists/DataSheet/Attachments/3199/MX25L3206E,%203V,%2032Mb,%20v1.5.pdf)|Macronix|32Mb|86MHz|支持|双线||
+|[KH25L4006E](http://www.macronix.com.hk/Lists/Datasheet/Attachments/117/KH25L4006E.pdf)|Macronix|4Mb|86Mhz|支持|未测试| by [JiapengLi](https://github.com/JiapengLi)|
+|[KH25L3206E](http://www.macronix.com.hk/Lists/Datasheet/Attachments/131/KH25L3206E.pdf)|Macronix|32Mb|86Mhz|支持|双线||
+|[SST25VF016B](http://ww1.microchip.com/downloads/en/DeviceDoc/20005044C.pdf)|Microchip|16Mb|50MHz|不支持|不支持| SST 已被 Microchip 收购|
+|[M25P40](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p40.pdf)|Micron|4Mb|75Mhz|不支持|未测试| by [redocCheng](https://github.com/redocCheng)|
+|[M25P80](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p80.pdf)|Micron|8Mb|75Mhz|不支持|未测试| by [redocCheng](https://github.com/redocCheng)|
+|[M25P32](https://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/m25p/m25p32.pdf)|Micron|32Mb|75Mhz|不支持|不支持||
+|[EN25Q32B](http://www.kean.com.au/oshw/WR703N/teardown/EN25Q32B%2032Mbit%20SPI%20Flash.pdf)|EON|32Mb|104MHz|不支持|未测试||
+|[GD25Q16B](http://www.gigadevice.com/product/detail/5/410.html)|GigaDevice|16Mb|120Mhz|不支持|未测试| by [TanekLiang](https://github.com/TanekLiang) |
+|[GD25Q64B](http://www.gigadevice.com/product/detail/5/364.html)|GigaDevice|64Mb|120Mhz|不支持|双线||
+|[S25FL216K](http://www.cypress.com/file/197346/download)|Cypress|16Mb|65Mhz|不支持|双线||
+|[S25FL032P](http://www.cypress.com/file/196861/download)|Cypress|32Mb|104Mhz|不支持|未测试| by [yc_911](https://gitee.com/yc_911) |
+|[S25FL164K](http://www.cypress.com/file/196886/download)|Cypress|64Mb|108Mhz|支持|未测试||
+|[A25L080](http://www.amictechnology.com/datasheets/A25L080.pdf)|AMIC|8Mb|100Mhz|不支持|双线||
+|[A25LQ64](http://www.amictechnology.com/datasheets/A25LQ64.pdf)|AMIC|64Mb|104Mhz|支持|支持||
+|[F25L004](http://www.esmt.com.tw/db/manager/upload/f25l004.pdf)|ESMT|4Mb|100Mhz|不支持|不支持||
+|[PCT25VF016B](http://pctgroup.com.tw/attachments/files/files/248_25VF016B-P.pdf)|PCT|16Mb|80Mhz|不支持|不支持|SST 授权许可,会被识别为 SST25VF016B|
+|[AT45DB161E](http://www.adestotech.com/wp-content/uploads/doc8782.pdf)|ADESTO|16Mb|85MHz|不支持|不支持|ADESTO 收购 Atmel 串行闪存产品线|
+
+> 注:QSPI 模式中,双线表示支持双线快读,四线表示支持四线快读。
+>
+> 一般情况下,支持四线快读的 FLASH 也支持两线快读。
### 2.2 API 说明
@@ -63,7 +71,7 @@
将会调用 `sfud_device_init` ,初始化 Flash 设备表中的全部设备。如果只有一个 Flash 也可以只使用 `sfud_device_init` 进行单一初始化。
-> 注意:初始化完的 SPI Flash 默认都 **已取消写保护** 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。
+> **注意**:初始化完的 SPI Flash 默认都 **已取消写保护** 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。
```C
sfud_err sfud_init(void)
@@ -79,7 +87,24 @@ sfud_err sfud_device_init(sfud_flash *flash)
|:----- |:----|
|flash |待初始化的 Flash 设备|
-#### 2.2.3 获取 Flash 设备对象
+#### 2.2.3 使能快速读模式(仅当 SFUD 开启 QSPI 模式后可用)
+
+当 SFUD 开启 QSPI 模式后,SFUD 中的 Flash 驱动支持使用 QSPI 总线进行通信。相比传统的 SPI 模式,使用 QSPI 能够加速 Flash 数据的读取,但当数据需要写入时,由于 Flash 本身的数据写入速度慢于 SPI 传输速度,所以 QSPI 模式下的数据写入速度提升并不明显。
+
+所以 SFUD 对于 QSPI 模式的支持仅限于快速读命令。通过该函数可以配置 Flash 所使用的 QSPI 总线的实际支持的数据线最大宽度,例如:1 线(默认值,即传统的 SPI 模式)、2 线、4 线。
+
+设置后,SFUD 会去结合当前设定的 QSPI 总线数据线宽度,去 [QSPI Flash 扩展信息表](https://github.com/armink/SFUD/blob/069d2b409ec239f84d675b2c3d37894e908829e6/sfud/inc/sfud_flash_def.h#L149-L177) 中匹配最合适的、速度最快的快速读命令,之后用户在调用 sfud_read() 时,会使用 QSPI 模式的传输函数发送该命令。
+
+```C
+sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width)
+```
+
+| 参数 | 描述 |
+| :-------------- | :------------------------------------------- |
+| flash | Flash 设备 |
+| data_line_width | QSPI 总线支持的数据线最大宽度,例如:1、2、4 |
+
+#### 2.2.4 获取 Flash 设备对象
在 SFUD 配置文件中会定义 Flash 设备表,负责存放所有将要使用的 Flash 设备对象,所以 SFUD 支持多个 Flash 设备同时驱动。设备表的配置在 `/sfud/inc/sfud_cfg.h` 中 `SFUD_FLASH_DEVICE_TABLE` 宏定义,详细配置方法参照 [2.3 配置方法 Flash](#23-配置方法))。本方法通过 Flash 设备位于设备表中索引值来返回 Flash 设备对象,超出设备表范围返回 `NULL` 。
@@ -91,7 +116,7 @@ sfud_flash *sfud_get_device(size_t index)
|:----- |:----|
|index |Flash 设备位于 FLash 设备表中的索引值|
-#### 2.2.4 读取 Flash 数据
+#### 2.2.5 读取 Flash 数据
```C
sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data)
@@ -104,7 +129,7 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t
|size |从起始地址开始读取数据的总大小|
|data |读取到的数据|
-#### 2.2.5 擦除 Flash 数据
+#### 2.2.6 擦除 Flash 数据
> 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。
@@ -118,7 +143,7 @@ sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size)
|addr |起始地址|
|size |从起始地址开始擦除数据的总大小|
-#### 2.2.6 擦除 Flash 全部数据
+#### 2.2.7 擦除 Flash 全部数据
```C
sfud_err sfud_chip_erase(const sfud_flash *flash)
@@ -128,7 +153,7 @@ sfud_err sfud_chip_erase(const sfud_flash *flash)
|:----- |:----|
|flash |Flash 设备对象|
-#### 2.2.7 往 Flash 写数据
+#### 2.2.8 往 Flash 写数据
```C
sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data)
@@ -141,7 +166,7 @@ sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const u
|size |从起始地址开始写入数据的总大小|
|data |待写入的数据|
-#### 2.2.8 先擦除再往 Flash 写数据
+#### 2.2.9 先擦除再往 Flash 写数据
> 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。
@@ -156,7 +181,7 @@ sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, c
|size |从起始地址开始写入数据的总大小|
|data |待写入的数据|
-#### 2.2.9 读取 Flash 状态
+#### 2.2.10 读取 Flash 状态
```C
sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status)
@@ -167,7 +192,7 @@ sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status)
|flash |Flash 设备对象|
|status |当前状态寄存器值|
-#### 2.2.10 写(修改) Flash 状态
+#### 2.2.11 写(修改) Flash 状态
```C
sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status)
@@ -234,6 +259,12 @@ enum {
上面定义了两个 Flash 设备(大部分产品一个足以),两个设备的名称为 `"W25Q64CV"` 及 `"GD25Q64B"` ,分别对应 `"SPI1"` 及 `"SPI3"` 这两个 SPI 设备名称(在移植 SPI 接口时会用到,位于 `/sfud/port/sfud_port.c` ), `SFUD_W25Q16CV_DEVICE_INDEX` 与 `SFUD_GD25Q64B_DEVICE_INDEX` 这两个枚举定义了两个设备位于设备表中的索引,可以通过 `sfud_get_device_table()` 方法获取到设备表,再配合这个索引值来访问指定的设备。
+#### 2.3.6 QSPI 模式
+
+打开/关闭 `SFUD_USING_QSPI` 宏定义
+
+开启后,SFUD 也将支持使用 QSPI 总线连接的 Flash。
+
### 2.4 移植说明
移植文件位于 `/sfud/port/sfud_port.c` ,文件中的 `sfud_err sfud_spi_port_init(sfud_flash *flash)` 方法是库提供的移植方法,在里面完成各个设备 SPI 读写驱动(必选)、重试次数(必选)、重试接口(可选)及 SPI 锁(可选)的配置。更加详细的移植内容,可以参考 demo 中的各个平台的移植文件。
@@ -258,6 +289,7 @@ enum {
|:----- |:----|
|[/demo/stm32f10x_non_os](https://github.com/armink/SFUD/tree/master/demo/stm32f10x_non_os) |STM32F10X 裸机平台|
|[/demo/stm32f2xx_rtt](https://github.com/armink/SFUD/tree/master/demo/stm32f2xx_rtt) |STM32F2XX + [RT-Thread](http://www.rt-thread.org/) 操作系统平台|
+|[/demo/stm32l475_non_os_qspi](https://github.com/armink/SFUD/tree/master/demo/stm32l475_non_os_qspi) |STM32L475 + QSPI 模式 裸机平台|
### 2.7 许可
diff --git a/components/drivers/spi/sfud/inc/sfud.h b/components/drivers/spi/sfud/inc/sfud.h
index be1ccb208e..2b68c38216 100644
--- a/components/drivers/spi/sfud/inc/sfud.h
+++ b/components/drivers/spi/sfud/inc/sfud.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Serial Flash Universal Driver Library.
*
- * Copyright (c) 2016, Armink, <[email protected]>
+ * Copyright (c) 2016-2018, Armink, <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -75,6 +75,23 @@ size_t sfud_get_device_num(void);
*/
const sfud_flash *sfud_get_device_table(void);
+#ifdef SFUD_USING_QSPI
+/**
+ * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
+ *
+ * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
+ * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
+ *
+ * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
+ *
+ * @param flash flash device
+ * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
+ *
+ * @return result
+ */
+sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width);
+#endif /* SFUD_USING_QSPI */
+
/**
* read flash data
*
diff --git a/components/drivers/spi/sfud/inc/sfud_cfg.h b/components/drivers/spi/sfud/inc/sfud_cfg.h
index 59189a9693..051de6d577 100644
--- a/components/drivers/spi/sfud/inc/sfud_cfg.h
+++ b/components/drivers/spi/sfud/inc/sfud_cfg.h
@@ -46,6 +46,13 @@
#endif
/**
+ * SFUD will support QSPI mode.
+ */
+#ifdef RT_SFUD_USING_QSPI
+#define SFUD_USING_QSPI
+#endif
+
+/**
* Using probe flash JEDEC ID then query defined supported flash chip information table. @see SFUD_FLASH_CHIP_TABLE
*/
#ifdef RT_SFUD_USING_FLASH_INFO_TABLE
diff --git a/components/drivers/spi/sfud/inc/sfud_def.h b/components/drivers/spi/sfud/inc/sfud_def.h
index 1b0e8a3986..fe7876618b 100644
--- a/components/drivers/spi/sfud/inc/sfud_def.h
+++ b/components/drivers/spi/sfud/inc/sfud_def.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Serial Flash Universal Driver Library.
*
- * Copyright (c) 2016, Armink, <[email protected]>
+ * Copyright (c) 2016-2018, Armink, <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -78,7 +78,7 @@ if (!(EXPR)) \
else {if (__delay_temp) {__delay_temp();} retry --;}
/* software version number */
-#define SFUD_SW_VERSION "1.0.6"
+#define SFUD_SW_VERSION "1.1.0"
/*
* all defined supported command
*/
@@ -118,6 +118,22 @@ if (!(EXPR)) \
#define SFUD_CMD_READ_DATA 0x03
#endif
+#ifndef SFUD_CMD_DUAL_OUTPUT_READ_DATA
+#define SFUD_CMD_DUAL_OUTPUT_READ_DATA 0x3B
+#endif
+
+#ifndef SFUD_CMD_DUAL_IO_READ_DATA
+#define SFUD_CMD_DUAL_IO_READ_DATA 0xBB
+#endif
+
+#ifndef SFUD_CMD_QUAD_IO_READ_DATA
+#define SFUD_CMD_QUAD_IO_READ_DATA 0xEB
+#endif
+
+#ifndef SFUD_CMD_QUAD_OUTPUT_READ_DATA
+#define SFUD_CMD_QUAD_OUTPUT_READ_DATA 0x6B
+#endif
+
#ifndef SFUD_CMD_MANUFACTURER_DEVICE_ID
#define SFUD_CMD_MANUFACTURER_DEVICE_ID 0x90
#endif
@@ -183,6 +199,21 @@ typedef enum {
SFUD_ERR_ADDR_OUT_OF_BOUND = 5, /**< address is out of flash bound */
} sfud_err;
+#ifdef SFUD_USING_QSPI
+/**
+ * QSPI flash read cmd format
+ */
+typedef struct {
+ uint8_t instruction;
+ uint8_t instruction_lines;
+ uint8_t address_size;
+ uint8_t address_lines;
+ uint8_t alternate_bytes_lines;
+ uint8_t dummy_cycles;
+ uint8_t data_lines;
+} sfud_qspi_read_cmd_format;
+#endif /* SFUD_USING_QSPI */
+
/* SPI bus write read data function type */
typedef sfud_err (*spi_write_read_func)(const uint8_t *write_buf, size_t write_size, uint8_t *read_buf, size_t read_size);
@@ -218,7 +249,12 @@ typedef struct __sfud_spi {
char *name;
/* SPI bus write read data function */
sfud_err (*wr)(const struct __sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
- size_t read_size);
+ size_t read_size);
+#ifdef SFUD_USING_QSPI
+ /* QSPI fast read function */
+ sfud_err (*qspi_read)(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format,
+ uint8_t *read_buf, size_t read_size);
+#endif
/* lock SPI bus */
void (*lock)(const struct __sfud_spi *spi);
/* unlock SPI bus */
@@ -243,6 +279,10 @@ typedef struct {
} retry;
void *user_data; /**< some user data */
+#ifdef SFUD_USING_QSPI
+ sfud_qspi_read_cmd_format read_cmd_format; /**< fast read cmd format */
+#endif
+
#ifdef SFUD_USING_SFDP
sfud_sfdp sfdp; /**< serial flash discoverable parameters by JEDEC standard */
#endif
diff --git a/components/drivers/spi/sfud/inc/sfud_flash_def.h b/components/drivers/spi/sfud/inc/sfud_flash_def.h
index 2022a043b2..8922375557 100644
--- a/components/drivers/spi/sfud/inc/sfud_flash_def.h
+++ b/components/drivers/spi/sfud/inc/sfud_flash_def.h
@@ -1,7 +1,7 @@
/*
* This file is part of the Serial Flash Universal Driver Library.
*
- * Copyright (c) 2016-2017, Armink, <[email protected]>
+ * Copyright (c) 2016-2018, Armink, <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -59,11 +59,21 @@ typedef struct {
uint8_t type_id; /**< memory type ID */
uint8_t capacity_id; /**< capacity ID */
uint32_t capacity; /**< flash capacity (bytes) */
- uint16_t write_mode; /**< write mode @see sfud_write_mode */
+ uint16_t write_mode; /**< write mode @see sfud_write_mode */
uint32_t erase_gran; /**< erase granularity (bytes) */
uint8_t erase_gran_cmd; /**< erase granularity size block command */
} sfud_flash_chip;
+#ifdef SFUD_USING_QSPI
+/* QSPI flash chip's extended information compared with SPI flash */
+typedef struct {
+ uint8_t mf_id; /**< manufacturer ID */
+ uint8_t type_id; /**< memory type ID */
+ uint8_t capacity_id; /**< capacity ID */
+ uint8_t read_mode; /**< supported read mode on this qspi flash chip */
+} sfud_qspi_flash_ext_info;
+#endif
+
/* SFUD support manufacturer JEDEC ID */
#define SFUD_MF_ID_CYPRESS 0x01
#define SFUD_MF_ID_FUJITSU 0x04
@@ -131,6 +141,42 @@ typedef struct {
}
#endif /* SFUD_USING_FLASH_INFO_TABLE */
+#ifdef SFUD_USING_QSPI
+/* This table saves flash read-fast instructions in QSPI mode,
+ * SFUD can use this table to select the most appropriate read instruction for flash.
+ * | mf_id | type_id | capacity_id | qspi_read_mode |
+ */
+#define SFUD_FLASH_EXT_INFO_TABLE \
+{ \
+ /* W25Q40BV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x13, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* W25Q80JV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* W25Q16BV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* W25Q32BV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* W25Q64JV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
+ /* W25Q128JV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
+ /* W25Q256FV */ \
+ {SFUD_MF_ID_WINBOND, 0x40, 0x19, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO}, \
+ /* EN25Q32B */ \
+ {SFUD_MF_ID_EON, 0x30, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_IO}, \
+ /* S25FL216K */ \
+ {SFUD_MF_ID_CYPRESS, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* A25L080 */ \
+ {SFUD_MF_ID_AMIC, 0x30, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO}, \
+ /* A25LQ64 */ \
+ {SFUD_MF_ID_AMIC, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_IO}, \
+ /* MX25L3206E and KH25L3206E */ \
+ {SFUD_MF_ID_MICRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+ /* GD25Q64B */ \
+ {SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT}, \
+}
+#endif /* SFUD_USING_QSPI */
+
#ifdef __cplusplus
}
#endif
diff --git a/components/drivers/spi/sfud/src/sfud.c b/components/drivers/spi/sfud/src/sfud.c
index e3376555ca..6cfd1191ef 100644
--- a/components/drivers/spi/sfud/src/sfud.c
+++ b/components/drivers/spi/sfud/src/sfud.c
@@ -1,7 +1,7 @@
/*
* This file is part of the Serial Flash Universal Driver Library.
*
- * Copyright (c) 2016, Armink, <[email protected]>
+ * Copyright (c) 2016-2018, Armink, <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -46,6 +46,22 @@ static const sfud_mf mf_table[] = SFUD_MF_TABLE;
static const sfud_flash_chip flash_chip_table[] = SFUD_FLASH_CHIP_TABLE;
#endif
+#ifdef SFUD_USING_QSPI
+/**
+ * flash read data mode
+ */
+enum sfud_qspi_read_mode {
+ NORMAL_SPI_READ = 1 << 0, /**< mormal spi read mode */
+ DUAL_OUTPUT = 1 << 1, /**< qspi fast read dual output */
+ DUAL_IO = 1 << 2, /**< qspi fast read dual input/output */
+ QUAD_OUTPUT = 1 << 3, /**< qspi fast read quad output */
+ QUAD_IO = 1 << 4, /**< qspi fast read quad input/output */
+};
+
+/* QSPI flash chip's extended information table */
+static const sfud_qspi_flash_ext_info qspi_flash_ext_info_table[] = SFUD_FLASH_EXT_INFO_TABLE;
+#endif /* SFUD_USING_QSPI */
+
static sfud_err software_init(const sfud_flash *flash);
static sfud_err hardware_init(sfud_flash *flash);
static sfud_err page256_or_1_byte_write(const sfud_flash *flash, uint32_t addr, size_t size, uint16_t write_gran,
@@ -146,11 +162,89 @@ const sfud_flash *sfud_get_device_table(void) {
return flash_table;
}
+#ifdef SFUD_USING_QSPI
+static void qspi_set_read_cmd_format(sfud_flash *flash, uint8_t ins, uint8_t ins_lines, uint8_t addr_lines,
+ uint8_t dummy_cycles, uint8_t data_lines) {
+ /* if medium size greater than 16Mb, use 4-Byte address, instruction should be added one */
+ if (flash->chip.capacity <= 0x1000000) {
+ flash->read_cmd_format.instruction = ins;
+ flash->read_cmd_format.address_size = 24;
+ } else {
+ flash->read_cmd_format.instruction = ins + 1;
+ flash->read_cmd_format.address_size = 32;
+ }
+
+ flash->read_cmd_format.instruction_lines = ins_lines;
+ flash->read_cmd_format.address_lines = addr_lines;
+ flash->read_cmd_format.alternate_bytes_lines = 0;
+ flash->read_cmd_format.dummy_cycles = dummy_cycles;
+ flash->read_cmd_format.data_lines = data_lines;
+}
+
+/**
+ * Enbale the fast read mode in QSPI flash mode. Default read mode is normal SPI mode.
+ *
+ * it will find the appropriate fast-read instruction to replace the read instruction(0x03)
+ * fast-read instruction @see SFUD_FLASH_EXT_INFO_TABLE
+ *
+ * @note When Flash is in QSPI mode, the method must be called after sfud_device_init().
+ *
+ * @param flash flash device
+ * @param data_line_width the data lines max width which QSPI bus supported, such as 1, 2, 4
+ *
+ * @return result
+ */
+sfud_err sfud_qspi_fast_read_enable(sfud_flash *flash, uint8_t data_line_width) {
+ size_t i = 0;
+ uint8_t read_mode = NORMAL_SPI_READ;
+ sfud_err result = SFUD_SUCCESS;
+
+ SFUD_ASSERT(flash);
+ SFUD_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
+
+ /* get read_mode, If don't found, the default is SFUD_QSPI_NORMAL_SPI_READ */
+ for (i = 0; i < sizeof(qspi_flash_ext_info_table) / sizeof(sfud_qspi_flash_ext_info); i++) {
+ if ((qspi_flash_ext_info_table[i].mf_id == flash->chip.mf_id)
+ && (qspi_flash_ext_info_table[i].type_id == flash->chip.type_id)
+ && (qspi_flash_ext_info_table[i].capacity_id == flash->chip.capacity_id)) {
+ read_mode = qspi_flash_ext_info_table[i].read_mode;
+ }
+ }
+
+ /* determine qspi supports which read mode and set read_cmd_format struct */
+ switch (data_line_width) {
+ case 1:
+ qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+ break;
+ case 2:
+ if (read_mode & DUAL_IO) {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_IO_READ_DATA, 1, 2, 8, 2);
+ } else if (read_mode & DUAL_OUTPUT) {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_DUAL_OUTPUT_READ_DATA, 1, 1, 8, 2);
+ } else {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+ }
+ break;
+ case 4:
+ if (read_mode & QUAD_IO) {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_IO_READ_DATA, 1, 4, 6, 4);
+ } else if (read_mode & QUAD_OUTPUT) {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_QUAD_OUTPUT_READ_DATA, 1, 1, 8, 4);
+ } else {
+ qspi_set_read_cmd_format(flash, SFUD_CMD_READ_DATA, 1, 1, 0, 1);
+ }
+ break;
+ }
+
+ return result;
+}
+#endif /* SFUD_USING_QSPI */
+
/**
* hardware initialize
*/
static sfud_err hardware_init(sfud_flash *flash) {
- extern sfud_err sfud_spi_port_init(sfud_flash *flash);
+ extern sfud_err sfud_spi_port_init(sfud_flash * flash);
sfud_err result = SFUD_SUCCESS;
size_t i;
@@ -162,6 +256,11 @@ static sfud_err hardware_init(sfud_flash *flash) {
return result;
}
+#ifdef SFUD_USING_QSPI
+ /* set default read instruction */
+ flash->read_cmd_format.instruction = SFUD_CMD_READ_DATA;
+#endif /* SFUD_USING_QSPI */
+
/* SPI write read function must be initialize */
SFUD_ASSERT(flash->spi.wr);
/* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
@@ -315,10 +414,17 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t
result = wait_busy(flash);
if (result == SFUD_SUCCESS) {
- cmd_data[0] = SFUD_CMD_READ_DATA;
- make_adress_byte_array(flash, addr, &cmd_data[1]);
- cmd_size = flash->addr_in_4_byte ? 5 : 4;
- result = spi->wr(spi, cmd_data, cmd_size, data, size);
+#ifdef SFUD_USING_QSPI
+ if (flash->read_cmd_format.instruction != SFUD_CMD_READ_DATA) {
+ result = spi->qspi_read(spi, addr, (sfud_qspi_read_cmd_format *)&flash->read_cmd_format, data, size);
+ } else
+#endif
+ {
+ cmd_data[0] = SFUD_CMD_READ_DATA;
+ make_adress_byte_array(flash, addr, &cmd_data[1]);
+ cmd_size = flash->addr_in_4_byte ? 5 : 4;
+ result = spi->wr(spi, cmd_data, cmd_size, data, size);
+ }
}
/* unlock SPI */
if (spi->unlock) {
@@ -328,7 +434,6 @@ sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t
return result;
}
-
/**
* erase all flash data
*
@@ -715,8 +820,16 @@ static sfud_err reset(const sfud_flash *flash) {
SFUD_ASSERT(flash);
cmd_data[0] = SFUD_CMD_ENABLE_RESET;
+ result = spi->wr(spi, cmd_data, 1, NULL, 0);
+ if (result == SFUD_SUCCESS) {
+ result = wait_busy(flash);
+ } else {
+ SFUD_INFO("Error: Flash device reset failed.");
+ return result;
+ }
+
cmd_data[1] = SFUD_CMD_RESET;
- result = spi->wr(spi, cmd_data, 2, NULL, 0);
+ result = spi->wr(spi, &cmd_data[1], 1, NULL, 0);
if (result == SFUD_SUCCESS) {
result = wait_busy(flash);
diff --git a/components/drivers/spi/spi_flash_sfud.c b/components/drivers/spi/spi_flash_sfud.c
index c0e42b3cd8..0f3cba0798 100644
--- a/components/drivers/spi/spi_flash_sfud.c
+++ b/components/drivers/spi/spi_flash_sfud.c
@@ -23,11 +23,21 @@
#ifndef RT_SFUD_DEFAULT_SPI_CFG
/* read the JEDEC SFDP command must run at 50 MHz or less */
-#define RT_SFUD_DEFAULT_SPI_CFG \
-{ \
- .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \
- .data_width = 8, \
- .max_hz = 50 * 1000 * 1000, \
+#define RT_SFUD_DEFAULT_SPI_CFG \
+{ \
+ .mode = RT_SPI_MODE_0 | RT_SPI_MSB, \
+ .data_width = 8, \
+ .max_hz = 50 * 1000 * 1000, \
+}
+#endif
+
+#ifdef SFUD_USING_QSPI
+#define RT_SFUD_DEFAULT_QSPI_CFG \
+{ \
+ RT_SFUD_DEFAULT_SPI_CFG, \
+ .medium_size = 0x800000, \
+ .ddr_mode = 0, \
+ .qspi_dl_width = 4, \
}
#endif
@@ -116,31 +126,90 @@ static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, si
sfud_err result = SFUD_SUCCESS;
sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
-
+#ifdef SFUD_USING_QSPI
+ struct rt_qspi_device *qspi_dev = RT_NULL;
+#endif
if (write_size) {
RT_ASSERT(write_buf);
}
if (read_size) {
RT_ASSERT(read_buf);
}
-
- if (write_size && read_size) {
- if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
- result = SFUD_ERR_TIMEOUT;
- }
- } else if (write_size) {
- if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) {
- result = SFUD_ERR_TIMEOUT;
+#ifdef SFUD_USING_QSPI
+ if(rtt_dev->rt_spi_device->bus->mode & RT_SPI_BUS_MODE_QSPI) {
+ qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
+ if (write_size && read_size) {
+ if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) == 0) {
+ result = SFUD_ERR_TIMEOUT;
+ }
+ } else if (write_size) {
+ if (rt_qspi_send(qspi_dev, write_buf, write_size) == 0) {
+ result = SFUD_ERR_TIMEOUT;
+ }
}
- } else {
- if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) {
- result = SFUD_ERR_TIMEOUT;
+ }
+ else
+#endif
+ {
+ if (write_size && read_size) {
+ if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
+ result = SFUD_ERR_TIMEOUT;
+ }
+ } else if (write_size) {
+ if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) {
+ result = SFUD_ERR_TIMEOUT;
+ }
+ } else {
+ if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) {
+ result = SFUD_ERR_TIMEOUT;
+ }
}
}
return result;
}
+#ifdef SFUD_USING_QSPI
+/**
+ * QSPI fast read data
+ */
+static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format, uint8_t *read_buf, size_t read_size) {
+ struct rt_qspi_message message;
+ sfud_err result = SFUD_SUCCESS;
+
+ sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
+ struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
+ struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
+
+ /* set message struct */
+ message.instruction.content = qspi_read_cmd_format->instruction;
+ message.instruction.qspi_lines = qspi_read_cmd_format->instruction_lines;
+
+ message.address.content = addr;
+ message.address.size = qspi_read_cmd_format->address_size;
+ message.address.qspi_lines = qspi_read_cmd_format->address_lines;
+
+ message.alternate_bytes.content = 0;
+ message.alternate_bytes.size = 0;
+ message.alternate_bytes.qspi_lines = 0;
+
+ message.dummy_cycles = qspi_read_cmd_format->dummy_cycles;
+
+ message.parent.send_buf = RT_NULL;
+ message.parent.recv_buf = read_buf;
+ message.parent.length = read_size;
+ message.parent.cs_release = 1;
+ message.parent.cs_take = 1;
+ message.qspi_data_lines = qspi_read_cmd_format->data_lines;
+
+ if (rt_qspi_transfer_message(qspi_dev, &message) != read_size) {
+ result = SFUD_ERR_TIMEOUT;
+ }
+
+ return result;
+}
+#endif
+
static void spi_lock(const sfud_spi *spi) {
sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
@@ -203,6 +272,9 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
/* port SPI device interface */
flash->spi.wr = spi_write_read;
+#ifdef SFUD_USING_QSPI
+ flash->spi.qspi_read = qspi_read;
+#endif
flash->spi.lock = spi_lock;
flash->spi.unlock = spi_unlock;
flash->spi.user_data = flash;
@@ -213,8 +285,7 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
flash->retry.delay = retry_delay_100us;
/* 60 seconds timeout */
flash->retry.times = 60 * 10000;
-
-
+
return result;
}
@@ -246,6 +317,10 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
* @note you also can change the SPI to other configuration after initialized finish */
struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
extern sfud_err sfud_device_init(sfud_flash *flash);
+#ifdef SFUD_USING_QSPI
+ struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
+ struct rt_qspi_device *qspi_dev = RT_NULL;
+#endif
RT_ASSERT(spi_flash_dev_name);
RT_ASSERT(spi_dev_name);
@@ -277,7 +352,17 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
goto error;
}
sfud_dev->spi.name = spi_dev_name_bak;
- rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
+
+#ifdef SFUD_USING_QSPI
+ /* set the qspi line number and configure the QSPI bus */
+ if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
+ qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device;
+ qspi_cfg.qspi_dl_width = qspi_dev->config.qspi_dl_width;
+ rt_qspi_configure(qspi_dev, &qspi_cfg);
+ }
+ else
+#endif
+ rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
}
/* SFUD flash device initialize */
{
@@ -296,6 +381,17 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
rtt_dev->geometry.sector_count = sfud_dev->chip.capacity / sfud_dev->chip.erase_gran;
rtt_dev->geometry.bytes_per_sector = sfud_dev->chip.erase_gran;
rtt_dev->geometry.block_size = sfud_dev->chip.erase_gran;
+#ifdef SFUD_USING_QSPI
+ /* reconfigure the QSPI bus for medium size */
+ if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
+ qspi_cfg.medium_size = sfud_dev->chip.capacity;
+ rt_qspi_configure(qspi_dev, &qspi_cfg);
+ if(qspi_dev->enter_qspi_mode != RT_NULL)
+ qspi_dev->enter_qspi_mode(qspi_dev);
+ }
+ /* set data lines width */
+ sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width);
+#endif /* SFUD_USING_QSPI */
}
/* register device */