添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										22
									
								
								riscv/rtthread/components/drivers/spi/sfud/LICENSE
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								riscv/rtthread/components/drivers/spi/sfud/LICENSE
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2016-2018 Armink (armink.ztl@gmail.com) | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining | ||||
| a copy of this software and associated documentation files (the | ||||
| 'Software'), to deal in the Software without restriction, including | ||||
| without limitation the rights to use, copy, modify, merge, publish, | ||||
| distribute, sublicense, and/or sell copies of the Software, and to | ||||
| permit persons to whom the Software is furnished to do so, subject to | ||||
| the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be | ||||
| included in all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										297
									
								
								riscv/rtthread/components/drivers/spi/sfud/README.md
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										297
									
								
								riscv/rtthread/components/drivers/spi/sfud/README.md
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,297 @@ | ||||
| # SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库 | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 0、SFUD 是什么 | ||||
|  | ||||
| [SFUD](https://github.com/armink/SFUD) 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SFUD 就是为了解决这些 Flash 的差异现状而设计,让我们的产品能够支持不同品牌及规格的 Flash,提高了涉及到 Flash 功能的软件的可重用性及可扩展性,同时也可以规避 Flash 缺货或停产给产品所带来的风险。 | ||||
|  | ||||
| - 主要特点:支持 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 表参数。 | ||||
|   - **不支持 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 | ||||
|  | ||||
| - 避免项目因 Flash 缺货、Flash 停产或产品扩容而带来的风险; | ||||
| - 越来越多的项目将固件存储到串行 Flash 中,例如:ESP8266 的固件、主板中的 BIOS 及其他常见电子产品中的固件等等,但是各种 Flash 规格及命令不统一。使用 SFUD 即可避免,在相同功能的软件平台基础下,无法适配不同 Flash 种类的硬件平台的问题,提高软件的可重用性; | ||||
| - 简化软件流程,降低开发难度。现在只需要配置好 SPI 通信,即可畅快的开始玩串行 Flash 了; | ||||
| - 可以用来制作 Flash 编程器/烧写器 | ||||
|  | ||||
| ## 2、SFUD 如何使用 | ||||
|  | ||||
| ### 2.1 已支持 Flash  | ||||
|  | ||||
| 下表为所有已在 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))** 。 | ||||
|  | ||||
| 如果觉得这个开源项目很赞,可以点击 [项目主页](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|支持|双线|| | ||||
| |[MX25L3233F](https://www.macronix.com/Lists/Datasheet/Attachments/8754/MX25L3233F,%203V,%2032Mb,%20v1.7.pdf)|Macronix|32Mb|133MHz|支持|未测试|by [JiapengLi](https://github.com/JiapengLi)| | ||||
| |[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 [Liang Yongxiang](https://github.com/liangyongxiang) | | ||||
| |[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 说明 | ||||
|  | ||||
| 先说明下本库主要使用的一个结构体 `sfud_flash` 。其定义位于 `/sfud/inc/sfud_def.h`。每个 SPI Flash 会对应一个该结构体,该结构体指针下面统称为 Flash 设备对象。初始化成功后在 `sfud_flash->chip` 结构体中会存放 SPI Flash  的常见参数。如果  SPI Flash  还支持 SFDP ,还可以通过  `sfud_flash->sfdp` 看到更加全面的参数信息。以下很多函数都将使用 Flash 设备对象作为第一个入参,实现对指定 SPI Flash 的操作。 | ||||
|  | ||||
| #### 2.2.1 初始化 SFUD 库 | ||||
|  | ||||
| 将会调用 `sfud_device_init` ,初始化 Flash 设备表中的全部设备。如果只有一个 Flash 也可以只使用 `sfud_device_init` 进行单一初始化。 | ||||
|  | ||||
| > **注意**:初始化完的 SPI Flash 默认都 **已取消写保护** 状态,如需开启写保护,请使用 sfud_write_status 函数修改 SPI Flash 状态。 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_init(void) | ||||
| ``` | ||||
|  | ||||
| #### 2.2.2 初始化指定的 Flash 设备 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_device_init(sfud_flash *flash) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |待初始化的 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` 。 | ||||
|  | ||||
| ```C | ||||
| sfud_flash *sfud_get_device(size_t index) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |index                                   |Flash 设备位于 FLash 设备表中的索引值| | ||||
|  | ||||
| #### 2.2.5 读取 Flash 数据 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |addr                                    |起始地址| | ||||
| |size                                    |从起始地址开始读取数据的总大小| | ||||
| |data                                    |读取到的数据| | ||||
|  | ||||
| #### 2.2.6 擦除 Flash 数据 | ||||
|  | ||||
| > 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |addr                                    |起始地址| | ||||
| |size                                    |从起始地址开始擦除数据的总大小| | ||||
|  | ||||
| #### 2.2.7 擦除 Flash 全部数据 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_chip_erase(const sfud_flash *flash) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
|  | ||||
| #### 2.2.8 往 Flash 写数据 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |addr                                    |起始地址| | ||||
| |size                                    |从起始地址开始写入数据的总大小| | ||||
| |data                                    |待写入的数据| | ||||
|  | ||||
| #### 2.2.9 先擦除再往 Flash 写数据 | ||||
|  | ||||
| > 注意:擦除操作将会按照 Flash 芯片的擦除粒度(详见 Flash 数据手册,一般为 block 大小。初始化完成后,可以通过 `sfud_flash->chip.erase_gran` 查看)对齐,请注意保证起始地址和擦除数据大小按照 Flash 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |addr                                    |起始地址| | ||||
| |size                                    |从起始地址开始写入数据的总大小| | ||||
| |data                                    |待写入的数据| | ||||
|  | ||||
| #### 2.2.10 读取 Flash 状态 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |status                                  |当前状态寄存器值| | ||||
|  | ||||
| #### 2.2.11 写(修改) Flash 状态 | ||||
|  | ||||
| ```C | ||||
| sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status) | ||||
| ``` | ||||
|  | ||||
| |参数                                    |描述| | ||||
| |:-----                                  |:----| | ||||
| |flash                                   |Flash 设备对象| | ||||
| |is_volatile                             |是否为易闪失的,true: 易闪失的,及断电后会丢失| | ||||
| |status                                  |当前状态寄存器值| | ||||
|  | ||||
| ### 2.3 配置方法 | ||||
|  | ||||
| 所有配置位于 `/sfud/inc/sfud_cfg.h` ,请参考下面的配置介绍,选择适合自己项目的配置。 | ||||
|  | ||||
| #### 2.3.1 调试模式 | ||||
|  | ||||
| 打开/关闭 `SFUD_DEBUG_MODE` 宏定义 | ||||
|  | ||||
| #### 2.3.2 是否使用 SFDP 参数功能 | ||||
|  | ||||
| 打开/关闭 `SFUD_USING_SFDP` 宏定义 | ||||
|  | ||||
| > 注意:关闭后只会查询该库在  `/sfud/inc/sfud_flash_def.h` 中提供的 Flash 信息表。这样虽然会降低软件的适配性,但减少代码量。 | ||||
|  | ||||
| #### 2.3.3 是否使用该库自带的 Flash 参数信息表 | ||||
|  | ||||
| 打开/关闭 `SFUD_USING_FLASH_INFO_TABLE` 宏定义 | ||||
|  | ||||
| > 注意:关闭后该库只驱动支持 SFDP 规范的 Flash,也会适当的降低部分代码量。另外 2.3.2 及 2.3.3 这两个宏定义至少定义一种,也可以两种方式都选择。 | ||||
|  | ||||
| #### 2.3.4 既不使用 SFDP ,也不使用 Flash 参数信息表 | ||||
|  | ||||
| 为了进一步降低代码量,`SFUD_USING_SFDP` 与 `SFUD_USING_FLASH_INFO_TABLE` 也可以 **都不定义** 。 | ||||
|  | ||||
| 此时,只要在定义 Flash 设备时,指定好 Flash 参数,之后再调用 `sfud_device_init` 对该设备进行初始化。参考如下代码: | ||||
|  | ||||
| ```C | ||||
| sfud_flash sfud_norflash0 = { | ||||
|         .name = "norflash0", | ||||
|         .spi.name = "SPI1", | ||||
|         .chip = { "W25Q64FV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L * 1024L * 1024L, SFUD_WM_PAGE_256B, 4096, 0x20 } }; | ||||
| ...... | ||||
| sfud_device_init(&sfud_norflash0); | ||||
| ...... | ||||
| ``` | ||||
|  | ||||
| #### 2.3.5 Flash 设备表 | ||||
|  | ||||
| 如果产品中存在多个 Flash ,可以添加 Flash 设备表。修改 `SFUD_FLASH_DEVICE_TABLE` 这个宏定义,示例如下: | ||||
|  | ||||
| ```C | ||||
| enum { | ||||
|     SFUD_W25Q64CV_DEVICE_INDEX = 0, | ||||
|     SFUD_GD25Q64B_DEVICE_INDEX = 1, | ||||
| }; | ||||
|  | ||||
| #define SFUD_FLASH_DEVICE_TABLE                                                \ | ||||
| {                                                                              \ | ||||
|     [SFUD_W25Q64CV_DEVICE_INDEX] = {.name = "W25Q64CV", .spi.name = "SPI1"},   \ | ||||
|     [SFUD_GD25Q64B_DEVICE_INDEX] = {.name = "GD25Q64B", .spi.name = "SPI3"},   \ | ||||
| } | ||||
| ``` | ||||
|  | ||||
| 上面定义了两个 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 中的各个平台的移植文件。 | ||||
|  | ||||
| ### 2.5 添加库目前不支持的 Flash  | ||||
|  | ||||
| 这里需要修改 `/sfud/inc/sfdu_flash_def.h` ,所有已经支持的 Flash 见 `SFUD_FLASH_CHIP_TABLE` 宏定义,需要提前准备的 Flash 参数内容分别为:| 名称 | 制造商 ID | 类型 ID | 容量 ID | 容量 | 写模式  | 擦除粒度(擦除的最小单位) | 擦除粒度对应的命令 | 。这里以添加 兆易创新 ( GigaDevice ) 的 `GD25Q64B` Flash 来举例。 | ||||
|  | ||||
| 此款 Flash 为兆易创新的早期生产的型号,所以不支持 SFDP 标准。首先需要下载其数据手册,找到 0x9F 命令返回的 3 种 ID, 这里需要最后面两字节 ID ,即 `type id` 及 `capacity id` 。 `GD25Q64B` 对应这两个 ID 分别为 `0x40` 及 `0x17` 。上面要求的其他 Flash 参数都可以在数据手册中找到,这里要重点说明下 **写模式** 这个参数,库本身提供的写模式共计有 4 种,详见文件顶部的 `sfud_write_mode` 枚举类型,同一款 Flash 可以同时支持多种写模式,视情况而定。对于 `GD25Q64B` 而言,其支持的写模式应该为 `SFUD_WM_PAGE_256B` ,即写 1-256 字节每页。结合上述 `GD25Q64B` 的 Flash 参数应如下: | ||||
|  | ||||
| ``` | ||||
|     {"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20}, | ||||
| ``` | ||||
|  | ||||
| 再将其增加到 `SFUD_FLASH_CHIP_TABLE` 宏定义末尾,即可完成该库对 `GD25Q64B` 的支持。 | ||||
|  | ||||
| ### 2.6 Demo | ||||
|  | ||||
| 目前已支持如下平台下的 Demo | ||||
|  | ||||
| |路径                             |平台描述| | ||||
| |:-----                           |:----| | ||||
| |[/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 许可 | ||||
|  | ||||
| 采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。 | ||||
							
								
								
									
										178
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										178
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| /* | ||||
|  * This file is part of the Serial Flash Universal Driver Library. | ||||
|  * | ||||
|  * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * 'Software'), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
|  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * Function: It is an head file for this library. You can see all of the functions which can be called by user. | ||||
|  * Created on: 2016-04-23 | ||||
|  */ | ||||
|  | ||||
| #ifndef _SFUD_H_ | ||||
| #define _SFUD_H_ | ||||
|  | ||||
| #include "sfud_def.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /* ../src/sfup.c */ | ||||
| /** | ||||
|  * SFUD library initialize. | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_init(void); | ||||
|  | ||||
| /** | ||||
|  * SFUD initialize by flash device | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_device_init(sfud_flash *flash); | ||||
|  | ||||
| /** | ||||
|  * get flash device by its index which in the flash information table | ||||
|  * | ||||
|  * @param index the index which in the flash information table  @see flash_table | ||||
|  * | ||||
|  * @return flash device | ||||
|  */ | ||||
| sfud_flash *sfud_get_device(size_t index); | ||||
|  | ||||
| /** | ||||
|  * get flash device total number on flash device information table  @see flash_table | ||||
|  * | ||||
|  * @return flash device total number | ||||
|  */ | ||||
| size_t sfud_get_device_num(void); | ||||
|  | ||||
| /** | ||||
|  * get flash device information table  @see flash_table | ||||
|  * | ||||
|  * @return flash device table pointer | ||||
|  */ | ||||
| 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 | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param addr start address | ||||
|  * @param size read size | ||||
|  * @param data read data pointer | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_read(const sfud_flash *flash, uint32_t addr, size_t size, uint8_t *data); | ||||
|  | ||||
| /** | ||||
|  * erase flash data | ||||
|  * | ||||
|  * @note It will erase align by erase granularity. | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param addr start address | ||||
|  * @param size erase size | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size); | ||||
|  | ||||
| /** | ||||
|  * write flash data (no erase operate) | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param addr start address | ||||
|  * @param data write data | ||||
|  * @param size write size | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data); | ||||
|  | ||||
| /** | ||||
|  * erase and write flash data | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param addr start address | ||||
|  * @param size write size | ||||
|  * @param data write data | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_erase_write(const sfud_flash *flash, uint32_t addr, size_t size, const uint8_t *data); | ||||
|  | ||||
| /** | ||||
|  * erase all flash data | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_chip_erase(const sfud_flash *flash); | ||||
|  | ||||
| /** | ||||
|  * read flash register status | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param status register status | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status); | ||||
|  | ||||
| /** | ||||
|  * write status register | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param is_volatile true: volatile mode, false: non-volatile mode | ||||
|  * @param status register status | ||||
|  * | ||||
|  * @return result | ||||
|  */ | ||||
| sfud_err sfud_write_status(const sfud_flash *flash, bool is_volatile, uint8_t status); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SFUD_H_ */ | ||||
							
								
								
									
										75
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_cfg.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										75
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_cfg.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
|  * This file is part of the Serial Flash Universal Driver Library. | ||||
|  * | ||||
|  * Copyright (c) 2016, Armink, <armink.ztl@gmail.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * 'Software'), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
|  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * Function: It is the configure head file for this library. | ||||
|  * Created on: 2016-04-23 | ||||
|  */ | ||||
|  | ||||
| #ifndef _SFUD_CFG_H_ | ||||
| #define _SFUD_CFG_H_ | ||||
|  | ||||
| #include <rtthread.h> | ||||
|  | ||||
| /** | ||||
|  * It will print more information on debug mode. | ||||
|  * #define RT_DEBUG_SFUD open debug mode */ | ||||
| #ifdef RT_DEBUG_SFUD | ||||
| #define SFUD_DEBUG_MODE | ||||
| #endif | ||||
|  | ||||
| #ifdef RT_DEBUG_SFUD | ||||
| #define DBG_LVL DBG_LOG | ||||
| #define SFUD_DEBUG(fmt, ...)  LOG_D("(%s:%ld) "fmt"", __FILE__, __LINE__, ##__VA_ARGS__) | ||||
| #else | ||||
| #define DBG_LVL DBG_INFO | ||||
| #endif /* RT_DEBUG_SFUD */ | ||||
|  | ||||
| #define DBG_TAG "SFUD" | ||||
| #include <rtdbg.h> | ||||
| #define SFUD_INFO(...)        LOG_I(__VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * Using probe flash JEDEC SFDP parameter. | ||||
|  */ | ||||
| #ifdef RT_SFUD_USING_SFDP | ||||
| #define SFUD_USING_SFDP | ||||
| #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 | ||||
| #define SFUD_USING_FLASH_INFO_TABLE | ||||
| #endif | ||||
|  | ||||
| #define SFUD_FLASH_DEVICE_TABLE {{0}} | ||||
|  | ||||
| #endif /* _SFUD_CFG_H_ */ | ||||
							
								
								
									
										296
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_def.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										296
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_def.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| /* | ||||
|  * This file is part of the Serial Flash Universal Driver Library. | ||||
|  * | ||||
|  * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * 'Software'), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
|  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * Function: It is the macro definition head file for this library. | ||||
|  * Created on: 2016-04-23 | ||||
|  */ | ||||
|  | ||||
| #ifndef _SFUD_DEF_H_ | ||||
| #define _SFUD_DEF_H_ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <sfud_cfg.h> | ||||
| #include "sfud_flash_def.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /* debug print function. Must be implement by user. */ | ||||
| #ifdef SFUD_DEBUG_MODE | ||||
| #ifndef SFUD_DEBUG | ||||
| #define SFUD_DEBUG(...) sfud_log_debug(__FILE__, __LINE__, __VA_ARGS__) | ||||
| #endif /* SFUD_DEBUG */ | ||||
| #else | ||||
| #define SFUD_DEBUG(...) | ||||
| #endif /* SFUD_DEBUG_MODE */ | ||||
|  | ||||
| #ifndef SFUD_INFO | ||||
| #define SFUD_INFO(...)  sfud_log_info(__VA_ARGS__) | ||||
| #endif | ||||
|  | ||||
| /* assert for developer. */ | ||||
| #ifdef SFUD_DEBUG_MODE | ||||
| #define SFUD_ASSERT(EXPR)                                                      \ | ||||
| if (!(EXPR))                                                                   \ | ||||
| {                                                                              \ | ||||
|     SFUD_DEBUG("(%s) has assert failed at %s.", #EXPR, __FUNCTION__);          \ | ||||
|     while (1);                                                                 \ | ||||
| } | ||||
| #else | ||||
| #define SFUD_ASSERT(EXPR) | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * retry process | ||||
|  * | ||||
|  * @param delay delay function for every retry. NULL will not delay for every retry. | ||||
|  * @param retry retry counts | ||||
|  * @param result SFUD_ERR_TIMEOUT: retry timeout | ||||
|  */ | ||||
| #define SFUD_RETRY_PROCESS(delay, retry, result)                               \ | ||||
|     void (*__delay_temp)(void) = (void (*)(void))delay;                        \ | ||||
|     if (retry == 0) {result = SFUD_ERR_TIMEOUT;break;}                         \ | ||||
|     else {if (__delay_temp) {__delay_temp();} retry --;} | ||||
|  | ||||
| /* software version number */ | ||||
| #define SFUD_SW_VERSION                             "1.1.0" | ||||
| /* | ||||
|  * all defined supported command | ||||
|  */ | ||||
| #ifndef SFUD_CMD_WRITE_ENABLE | ||||
| #define SFUD_CMD_WRITE_ENABLE                          0x06 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_WRITE_DISABLE | ||||
| #define SFUD_CMD_WRITE_DISABLE                         0x04 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_READ_STATUS_REGISTER | ||||
| #define SFUD_CMD_READ_STATUS_REGISTER                  0x05 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_VOLATILE_SR_WRITE_ENABLE | ||||
| #define SFUD_VOLATILE_SR_WRITE_ENABLE                  0x50 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_WRITE_STATUS_REGISTER | ||||
| #define SFUD_CMD_WRITE_STATUS_REGISTER                 0x01 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_PAGE_PROGRAM | ||||
| #define SFUD_CMD_PAGE_PROGRAM                          0x02 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_AAI_WORD_PROGRAM | ||||
| #define SFUD_CMD_AAI_WORD_PROGRAM                      0xAD | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_ERASE_CHIP | ||||
| #define SFUD_CMD_ERASE_CHIP                            0xC7 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_READ_DATA | ||||
| #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 | ||||
|  | ||||
| #ifndef SFUD_CMD_JEDEC_ID | ||||
| #define SFUD_CMD_JEDEC_ID                              0x9F | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_READ_UNIQUE_ID | ||||
| #define SFUD_CMD_READ_UNIQUE_ID                        0x4B | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_READ_SFDP_REGISTER | ||||
| #define SFUD_CMD_READ_SFDP_REGISTER                    0x5A | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_ENABLE_RESET | ||||
| #define SFUD_CMD_ENABLE_RESET                          0x66 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_RESET | ||||
| #define SFUD_CMD_RESET                                 0x99 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_ENTER_4B_ADDRESS_MODE | ||||
| #define SFUD_CMD_ENTER_4B_ADDRESS_MODE                 0xB7 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_CMD_EXIT_4B_ADDRESS_MODE | ||||
| #define SFUD_CMD_EXIT_4B_ADDRESS_MODE                  0xE9 | ||||
| #endif | ||||
|  | ||||
| #ifndef SFUD_WRITE_MAX_PAGE_SIZE | ||||
| #define SFUD_WRITE_MAX_PAGE_SIZE                        256 | ||||
| #endif | ||||
|  | ||||
| /* send dummy data for read data */ | ||||
| #ifndef SFUD_DUMMY_DATA | ||||
| #define SFUD_DUMMY_DATA                                0xFF | ||||
| #endif | ||||
|  | ||||
| /* maximum number of erase type support on JESD216 (V1.0) */ | ||||
| #define SFUD_SFDP_ERASE_TYPE_MAX_NUM                      4 | ||||
|  | ||||
| /** | ||||
|  * status register bits | ||||
|  */ | ||||
| enum { | ||||
|     SFUD_STATUS_REGISTER_BUSY = (1 << 0),                  /**< busing */ | ||||
|     SFUD_STATUS_REGISTER_WEL = (1 << 1),                   /**< write enable latch */ | ||||
|     SFUD_STATUS_REGISTER_SRP = (1 << 7),                   /**< status register protect */ | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * error code | ||||
|  */ | ||||
| typedef enum { | ||||
|     SFUD_SUCCESS = 0,                                      /**< success */ | ||||
|     SFUD_ERR_NOT_FOUND = 1,                                /**< not found or not supported */ | ||||
|     SFUD_ERR_WRITE = 2,                                    /**< write error */ | ||||
|     SFUD_ERR_READ = 3,                                     /**< read error */ | ||||
|     SFUD_ERR_TIMEOUT = 4,                                  /**< timeout error */ | ||||
|     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); | ||||
|  | ||||
| #ifdef SFUD_USING_SFDP | ||||
| /** | ||||
|  * the SFDP (Serial Flash Discoverable Parameters) parameter info which used on this library | ||||
|  */ | ||||
| typedef struct { | ||||
|     bool available;                              /**< available when read SFDP OK */ | ||||
|     uint8_t major_rev;                           /**< SFDP Major Revision */ | ||||
|     uint8_t minor_rev;                           /**< SFDP Minor Revision */ | ||||
|     uint16_t write_gran;                         /**< write granularity (bytes) */ | ||||
|     uint8_t erase_4k;                            /**< 4 kilobyte erase is supported throughout the device */ | ||||
|     uint8_t erase_4k_cmd;                        /**< 4 Kilobyte erase command */ | ||||
|     bool sr_is_non_vola;                         /**< status register is supports non-volatile */ | ||||
|     uint8_t vola_sr_we_cmd;                      /**< volatile status register write enable command */ | ||||
|     bool addr_3_byte;                            /**< supports 3-Byte addressing */ | ||||
|     bool addr_4_byte;                            /**< supports 4-Byte addressing */ | ||||
|     uint32_t capacity;                           /**< flash capacity (bytes) */ | ||||
|     struct { | ||||
|         uint32_t size;                           /**< erase sector size (bytes). 0x00: not available */ | ||||
|         uint8_t cmd;                             /**< erase command */ | ||||
|     } eraser[SFUD_SFDP_ERASE_TYPE_MAX_NUM];      /**< supported eraser types table */ | ||||
|     //TODO lots of fast read-related stuff (like modes supported and number of wait states/dummy cycles needed in each) | ||||
| } sfud_sfdp, *sfud_sfdp_t; | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * SPI device | ||||
|  */ | ||||
| typedef struct __sfud_spi { | ||||
|     /* SPI device name */ | ||||
|     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); | ||||
| #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 */ | ||||
|     void (*unlock)(const struct __sfud_spi *spi); | ||||
|     /* some user data */ | ||||
|     void *user_data; | ||||
| } sfud_spi, *sfud_spi_t; | ||||
|  | ||||
| /** | ||||
|  * serial flash device | ||||
|  */ | ||||
| typedef struct { | ||||
|     char *name;                                  /**< serial flash name */ | ||||
|     size_t index;                                /**< index of flash device information table  @see flash_table */ | ||||
|     sfud_flash_chip chip;                        /**< flash chip information */ | ||||
|     sfud_spi spi;                                /**< SPI device */ | ||||
|     bool init_ok;                                /**< initialize OK flag */ | ||||
|     bool addr_in_4_byte;                         /**< flash is in 4-Byte addressing */ | ||||
|     struct { | ||||
|         void (*delay)(void);                     /**< every retry's delay */ | ||||
|         size_t times;                            /**< default times for error retry */ | ||||
|     } 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 | ||||
|  | ||||
| } sfud_flash, *sfud_flash_t; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SFUD_DEF_H_ */ | ||||
							
								
								
									
										198
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_flash_def.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										198
									
								
								riscv/rtthread/components/drivers/spi/sfud/inc/sfud_flash_def.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,198 @@ | ||||
| /* | ||||
|  * This file is part of the Serial Flash Universal Driver Library. | ||||
|  * | ||||
|  * Copyright (c) 2016-2018, Armink, <armink.ztl@gmail.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * 'Software'), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
|  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * Function: It is the flash types and specification macro definition head file for this library. | ||||
|  * Created on: 2016-06-09 | ||||
|  */ | ||||
|  | ||||
| #ifndef _SFUD_FLASH_DEF_H_ | ||||
| #define _SFUD_FLASH_DEF_H_ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <sfud_cfg.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * flash program(write) data mode | ||||
|  */ | ||||
| enum sfud_write_mode { | ||||
|     SFUD_WM_PAGE_256B = 1 << 0,                            /**< write 1 to 256 bytes per page */ | ||||
|     SFUD_WM_BYTE = 1 << 1,                                 /**< byte write */ | ||||
|     SFUD_WM_AAI = 1 << 2,                                  /**< auto address increment */ | ||||
|     SFUD_WM_DUAL_BUFFER = 1 << 3,                          /**< dual-buffer write, like AT45DB series */ | ||||
| }; | ||||
|  | ||||
| /* manufacturer information */ | ||||
| typedef struct { | ||||
|     char *name; | ||||
|     uint8_t id; | ||||
| } sfud_mf; | ||||
|  | ||||
| /* flash chip information */ | ||||
| typedef struct { | ||||
|     char *name;                                  /**< flash chip name */ | ||||
|     uint8_t mf_id;                               /**< manufacturer ID */ | ||||
|     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 */ | ||||
|     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 | ||||
| #define SFUD_MF_ID_EON                                 0x1C | ||||
| #define SFUD_MF_ID_ATMEL                               0x1F | ||||
| #define SFUD_MF_ID_MICRON                              0x20 | ||||
| #define SFUD_MF_ID_AMIC                                0x37 | ||||
| #define SFUD_MF_ID_NOR_MEM                             0x52 | ||||
| #define SFUD_MF_ID_SANYO                               0x62 | ||||
| #define SFUD_MF_ID_INTEL                               0x89 | ||||
| #define SFUD_MF_ID_ESMT                                0x8C | ||||
| #define SFUD_MF_ID_FUDAN                               0xA1 | ||||
| #define SFUD_MF_ID_HYUNDAI                             0xAD | ||||
| #define SFUD_MF_ID_SST                                 0xBF | ||||
| #define SFUD_MF_ID_MACRONIX                            0xC2 | ||||
| #define SFUD_MF_ID_GIGADEVICE                          0xC8 | ||||
| #define SFUD_MF_ID_ISSI                                0xD5 | ||||
| #define SFUD_MF_ID_WINBOND                             0xEF | ||||
|  | ||||
| /* SFUD supported manufacturer information table */ | ||||
| #define SFUD_MF_TABLE                                     \ | ||||
| {                                                         \ | ||||
|     {"Cypress",    SFUD_MF_ID_CYPRESS},                   \ | ||||
|     {"Fujitsu",    SFUD_MF_ID_FUJITSU},                   \ | ||||
|     {"EON",        SFUD_MF_ID_EON},                       \ | ||||
|     {"Atmel",      SFUD_MF_ID_ATMEL},                     \ | ||||
|     {"Micron",     SFUD_MF_ID_MICRON},                    \ | ||||
|     {"AMIC",       SFUD_MF_ID_AMIC},                      \ | ||||
|     {"Sanyo",      SFUD_MF_ID_SANYO},                     \ | ||||
|     {"Intel",      SFUD_MF_ID_INTEL},                     \ | ||||
|     {"ESMT",       SFUD_MF_ID_ESMT},                      \ | ||||
|     {"Fudan",      SFUD_MF_ID_FUDAN},                     \ | ||||
|     {"Hyundai",    SFUD_MF_ID_HYUNDAI},                   \ | ||||
|     {"SST",        SFUD_MF_ID_SST},                       \ | ||||
|     {"GigaDevice", SFUD_MF_ID_GIGADEVICE},                \ | ||||
|     {"ISSI",       SFUD_MF_ID_ISSI},                      \ | ||||
|     {"Winbond",    SFUD_MF_ID_WINBOND},                   \ | ||||
|     {"Macronix",   SFUD_MF_ID_MACRONIX},                  \ | ||||
|     {"NOR-MEM",    SFUD_MF_ID_NOR_MEM},                        \ | ||||
| } | ||||
|  | ||||
| #ifdef SFUD_USING_FLASH_INFO_TABLE | ||||
| /* SFUD supported flash chip information table. If the flash not support JEDEC JESD216 standard, | ||||
|  * then the SFUD will find the flash chip information by this table. You can add other flash to here then | ||||
|  *  notice me for update it. The configuration information name and index reference the sfud_flash_chip structure. | ||||
|  * | name | mf_id | type_id | capacity_id | capacity | write_mode | erase_gran | erase_gran_cmd | | ||||
|  */ | ||||
| #define SFUD_FLASH_CHIP_TABLE                                                                                       \ | ||||
| {                                                                                                                   \ | ||||
|     {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81},      \ | ||||
|     {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \ | ||||
|     {"W25X40CL", SFUD_MF_ID_WINBOND, 0x30, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \ | ||||
|     {"W25X16AV", SFUD_MF_ID_WINBOND, 0x30, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \ | ||||
|     {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \ | ||||
|     {"W25Q32BV", SFUD_MF_ID_WINBOND, 0x40, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \ | ||||
|     {"W25Q64CV", SFUD_MF_ID_WINBOND, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \ | ||||
|     {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \ | ||||
|     {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \ | ||||
|     {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \ | ||||
|     {"SST25VF080B", SFUD_MF_ID_SST, 0x25, 0x8E, 1L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \ | ||||
|     {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \ | ||||
|     {"M25P32", SFUD_MF_ID_MICRON, 0x20, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                  \ | ||||
|     {"M25P80", SFUD_MF_ID_MICRON, 0x20, 0x14, 1L*1024L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                  \ | ||||
|     {"M25P40", SFUD_MF_ID_MICRON, 0x20, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                      \ | ||||
|     {"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \ | ||||
|     {"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \ | ||||
|     {"GD25Q16B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \ | ||||
|     {"GD25Q32C", SFUD_MF_ID_GIGADEVICE, 0x40, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \ | ||||
|     {"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                   \ | ||||
|     {"S25FL032P", SFUD_MF_ID_CYPRESS, 0x02, 0x15, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                   \ | ||||
|     {"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \ | ||||
|     {"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},                     \ | ||||
|     {"PCT25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \ | ||||
|     {"NM25Q128EVB", SFUD_MF_ID_NOR_MEM, 0x21, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \ | ||||
| } | ||||
| #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|QUAD_OUTPUT|QUAD_IO},             \ | ||||
|     /* 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_MACRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT},                                \ | ||||
|     /* MX25L51245G */                                                                              \ | ||||
|     {SFUD_MF_ID_MACRONIX, 0x20, 0x1A, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},    \ | ||||
|     /* GD25Q64B */                                                                                 \ | ||||
|     {SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT},                              \ | ||||
|     /* NM25Q128EVB */                                                                              \ | ||||
|     {SFUD_MF_ID_NOR_MEM, 0x21, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},          \ | ||||
| } | ||||
| #endif /* SFUD_USING_QSPI */ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SFUD_FLASH_DEF_H_ */ | ||||
							
								
								
									
										1045
									
								
								riscv/rtthread/components/drivers/spi/sfud/src/sfud.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1045
									
								
								riscv/rtthread/components/drivers/spi/sfud/src/sfud.c
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										387
									
								
								riscv/rtthread/components/drivers/spi/sfud/src/sfud_sfdp.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										387
									
								
								riscv/rtthread/components/drivers/spi/sfud/src/sfud_sfdp.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,387 @@ | ||||
| /* | ||||
|  * This file is part of the Serial Flash Universal Driver Library. | ||||
|  * | ||||
|  * Copyright (c) 2016, Armink, <armink.ztl@gmail.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * 'Software'), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
|  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * Function: Analyze the SFDP (Serial Flash Discoverable Parameters) which from JESD216/A/B (V1.X) standard. | ||||
|  *           JESD216  (V1.0) document: http://www.jedec.org/sites/default/files/docs/JESD216.pdf | ||||
|  *           JESD216A (V1.5) document: http://www.jedec.org/sites/default/files/docs/JESD216A.pdf | ||||
|  *           JESD216B (V1.6) document: http://www.jedec.org/sites/default/files/docs/JESD216B.pdf | ||||
|  * | ||||
|  * Created on: 2016-05-26 | ||||
|  */ | ||||
|  | ||||
| #include "../inc/sfud.h" | ||||
|  | ||||
| /** | ||||
|  * JEDEC Standard JESD216 Terms and definitions: | ||||
|  * | ||||
|  * DWORD: Four consecutive 8-bit bytes used as the basic 32-bit building block for headers and parameter tables. | ||||
|  * | ||||
|  * Sector: The minimum granularity - size and alignment - of an area that can be erased in the data array | ||||
|  * of a flash memory device. Different areas within the address range of the data array may have a different | ||||
|  * minimum erase granularity (sector size). | ||||
|  */ | ||||
|  | ||||
| #ifdef SFUD_USING_SFDP | ||||
|  | ||||
| /* support maximum SFDP major revision by driver */ | ||||
| #define SUPPORT_MAX_SFDP_MAJOR_REV                  1 | ||||
| /* the JEDEC basic flash parameter table length is 9 DWORDs (288-bit) on JESD216 (V1.0) initial release standard */ | ||||
| #define BASIC_TABLE_LEN                             9 | ||||
| /* the smallest eraser in SFDP eraser table */ | ||||
| #define SMALLEST_ERASER_INDEX                       0 | ||||
| /** | ||||
|  *  SFDP parameter header structure | ||||
|  */ | ||||
| typedef struct { | ||||
|     uint8_t id;                                  /**< Parameter ID LSB */ | ||||
|     uint8_t minor_rev;                           /**< Parameter minor revision */ | ||||
|     uint8_t major_rev;                           /**< Parameter major revision */ | ||||
|     uint8_t len;                                 /**< Parameter table length(in double words) */ | ||||
|     uint32_t ptp;                                /**< Parameter table 24bit pointer (byte address) */ | ||||
| } sfdp_para_header; | ||||
|  | ||||
| static sfud_err read_sfdp_data(const sfud_flash *flash, uint32_t addr, uint8_t *read_buf, size_t size); | ||||
| static bool read_sfdp_header(sfud_flash *flash); | ||||
| static bool read_basic_header(const sfud_flash *flash, sfdp_para_header *basic_header); | ||||
| static bool read_basic_table(sfud_flash *flash, sfdp_para_header *basic_header); | ||||
|  | ||||
| /* ../port/sfup_port.c */ | ||||
| extern void sfud_log_debug(const char *file, const long line, const char *format, ...); | ||||
| extern void sfud_log_info(const char *format, ...); | ||||
|  | ||||
| /** | ||||
|  * Read SFDP parameter information | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return true: read OK | ||||
|  */ | ||||
| bool sfud_read_sfdp(sfud_flash *flash) { | ||||
|     SFUD_ASSERT(flash); | ||||
|  | ||||
|     /* JEDEC basic flash parameter header */ | ||||
|     sfdp_para_header basic_header; | ||||
|     if (read_sfdp_header(flash) && read_basic_header(flash, &basic_header)) { | ||||
|         return read_basic_table(flash, &basic_header); | ||||
|     } else { | ||||
|         SFUD_INFO("Warning: Read SFDP parameter header information failed. The %s does not support JEDEC SFDP.", flash->name); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Read SFDP parameter header | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return true: read OK | ||||
|  */ | ||||
| static bool read_sfdp_header(sfud_flash *flash) { | ||||
|     sfud_sfdp *sfdp = &flash->sfdp; | ||||
|     /* The SFDP header is located at address 000000h of the SFDP data structure. | ||||
|      * It identifies the SFDP Signature, the number of parameter headers, and the SFDP revision numbers. */ | ||||
|     /* sfdp parameter header address */ | ||||
|     uint32_t header_addr = 0; | ||||
|     /* each parameter header being 2 DWORDs (64-bit) */ | ||||
|     uint8_t header[2 * 4] = { 0 }; | ||||
|  | ||||
|     SFUD_ASSERT(flash); | ||||
|  | ||||
|     sfdp->available = false; | ||||
|     /* read SFDP header */ | ||||
|     if (read_sfdp_data(flash, header_addr, header, sizeof(header)) != SFUD_SUCCESS) { | ||||
|         SFUD_INFO("Error: Can't read SFDP header."); | ||||
|         return false; | ||||
|     } | ||||
|     /* check SFDP header */ | ||||
|     if (!(header[0] == 'S' && | ||||
|           header[1] == 'F' && | ||||
|           header[2] == 'D' && | ||||
|           header[3] == 'P')) { | ||||
|         SFUD_DEBUG("Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P')."); | ||||
|         return false; | ||||
|     } | ||||
|     sfdp->minor_rev = header[4]; | ||||
|     sfdp->major_rev = header[5]; | ||||
|     if (sfdp->major_rev > SUPPORT_MAX_SFDP_MAJOR_REV) { | ||||
|         SFUD_INFO("Error: This reversion(V%d.%d) of SFDP is not supported.", sfdp->major_rev, sfdp->minor_rev); | ||||
|         return false; | ||||
|     } | ||||
|     SFUD_DEBUG("Check SFDP header is OK. The reversion is V%d.%d, NPN is %d.", sfdp->major_rev, sfdp->minor_rev, | ||||
|             header[6]); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Read JEDEC basic parameter header | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return true: read OK | ||||
|  */ | ||||
| static bool read_basic_header(const sfud_flash *flash, sfdp_para_header *basic_header) { | ||||
|     /* The basic parameter header is mandatory, is defined by this standard, and starts at byte offset 08h. */ | ||||
|     uint32_t header_addr = 8; | ||||
|     /* each parameter header being 2 DWORDs (64-bit) */ | ||||
|     uint8_t header[2 * 4] = { 0 }; | ||||
|  | ||||
|     SFUD_ASSERT(flash); | ||||
|     SFUD_ASSERT(basic_header); | ||||
|  | ||||
|     /* read JEDEC basic flash parameter header */ | ||||
|     if (read_sfdp_data(flash, header_addr, header, sizeof(header)) != SFUD_SUCCESS) { | ||||
|         SFUD_INFO("Error: Can't read JEDEC basic flash parameter header."); | ||||
|         return false; | ||||
|     } | ||||
|     basic_header->id        = header[0]; | ||||
|     basic_header->minor_rev = header[1]; | ||||
|     basic_header->major_rev = header[2]; | ||||
|     basic_header->len       = header[3]; | ||||
|     basic_header->ptp       = (long)header[4] | (long)header[5] << 8 | (long)header[6] << 16; | ||||
|     /* check JEDEC basic flash parameter header */ | ||||
|     if (basic_header->major_rev > SUPPORT_MAX_SFDP_MAJOR_REV) { | ||||
|         SFUD_INFO("Error: This reversion(V%d.%d) of JEDEC basic flash parameter header is not supported.", | ||||
|                 basic_header->major_rev, basic_header->minor_rev); | ||||
|         return false; | ||||
|     } | ||||
|     if (basic_header->len < BASIC_TABLE_LEN) { | ||||
|         SFUD_INFO("Error: The JEDEC basic flash parameter table length (now is %d) error.", basic_header->len); | ||||
|         return false; | ||||
|     } | ||||
|     SFUD_DEBUG("Check JEDEC basic flash parameter header is OK. The table id is %d, reversion is V%d.%d," | ||||
|             " length is %d, parameter table pointer is 0x%06lX.", basic_header->id, basic_header->major_rev, | ||||
|             basic_header->minor_rev, basic_header->len, basic_header->ptp); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Read JEDEC basic parameter table | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * | ||||
|  * @return true: read OK | ||||
|  */ | ||||
| static bool read_basic_table(sfud_flash *flash, sfdp_para_header *basic_header) { | ||||
|     sfud_sfdp *sfdp = &flash->sfdp; | ||||
|     /* parameter table address */ | ||||
|     uint32_t table_addr = basic_header->ptp; | ||||
|     /* parameter table */ | ||||
|     uint8_t table[BASIC_TABLE_LEN * 4] = { 0 }, i, j; | ||||
|  | ||||
|     SFUD_ASSERT(flash); | ||||
|     SFUD_ASSERT(basic_header); | ||||
|  | ||||
|     /* read JEDEC basic flash parameter table */ | ||||
|     if (read_sfdp_data(flash, table_addr, table, sizeof(table)) != SFUD_SUCCESS) { | ||||
|         SFUD_INFO("Warning: Can't read JEDEC basic flash parameter table."); | ||||
|         return false; | ||||
|     } | ||||
|     /* print JEDEC basic flash parameter table info */ | ||||
|     SFUD_DEBUG("JEDEC basic flash parameter table info:"); | ||||
|     SFUD_DEBUG("MSB-LSB  3    2    1    0"); | ||||
|     for (i = 0; i < BASIC_TABLE_LEN; i++) { | ||||
|         SFUD_DEBUG("[%04d] 0x%02X 0x%02X 0x%02X 0x%02X", i + 1, table[i * 4 + 3], table[i * 4 + 2], table[i * 4 + 1], | ||||
|                 table[i * 4]); | ||||
|     } | ||||
|  | ||||
|     /* get block/sector 4 KB erase supported and command */ | ||||
|     sfdp->erase_4k_cmd = table[1]; | ||||
|     switch (table[0] & 0x03) { | ||||
|     case 1: | ||||
|         sfdp->erase_4k = true; | ||||
|         SFUD_DEBUG("4 KB Erase is supported throughout the device. Command is 0x%02X.", sfdp->erase_4k_cmd); | ||||
|         break; | ||||
|     case 3: | ||||
|         sfdp->erase_4k = false; | ||||
|         SFUD_DEBUG("Uniform 4 KB erase is unavailable for this device."); | ||||
|         break; | ||||
|     default: | ||||
|         SFUD_INFO("Error: Uniform 4 KB erase supported information error."); | ||||
|         return false; | ||||
|     } | ||||
|     /* get write granularity */ | ||||
|     //TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size | ||||
|     switch ((table[0] & (0x01 << 2)) >> 2) { | ||||
|     case 0: | ||||
|         sfdp->write_gran = 1; | ||||
|         SFUD_DEBUG("Write granularity is 1 byte."); | ||||
|         break; | ||||
|     case 1: | ||||
|         sfdp->write_gran = 256; | ||||
|         SFUD_DEBUG("Write granularity is 64 bytes or larger."); | ||||
|         break; | ||||
|     } | ||||
|     /* volatile status register block protect bits */ | ||||
|     switch ((table[0] & (0x01 << 3)) >> 3) { | ||||
|     case 0: | ||||
|         /* Block Protect bits in device's status register are solely non-volatile or may be | ||||
|          * programmed either as volatile using the 50h instruction for write enable or non-volatile | ||||
|          * using the 06h instruction for write enable. | ||||
|          */ | ||||
|         sfdp->sr_is_non_vola = true; | ||||
|         SFUD_DEBUG("Target flash status register is non-volatile."); | ||||
|         break; | ||||
|     case 1: | ||||
|         /* block protect bits in device's status register are solely volatile. */ | ||||
|         sfdp->sr_is_non_vola = false; | ||||
|         SFUD_DEBUG("Block Protect bits in device's status register are solely volatile."); | ||||
|         /* write enable instruction select for writing to volatile status register */ | ||||
|         switch ((table[0] & (0x01 << 4)) >> 4) { | ||||
|         case 0: | ||||
|             sfdp->vola_sr_we_cmd = SFUD_VOLATILE_SR_WRITE_ENABLE; | ||||
|             SFUD_DEBUG("Flash device requires instruction 50h as the write enable prior " | ||||
|                     "to performing a volatile write to the status register."); | ||||
|             break; | ||||
|         case 1: | ||||
|             sfdp->vola_sr_we_cmd = SFUD_CMD_WRITE_ENABLE; | ||||
|             SFUD_DEBUG("Flash device requires instruction 06h as the write enable prior " | ||||
|                     "to performing a volatile write to the status register."); | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     /* get address bytes, number of bytes used in addressing flash array read, write and erase. */ | ||||
|     switch ((table[2] & (0x03 << 1)) >> 1) { | ||||
|     case 0: | ||||
|         sfdp->addr_3_byte = true; | ||||
|         sfdp->addr_4_byte = false; | ||||
|         SFUD_DEBUG("3-Byte only addressing."); | ||||
|         break; | ||||
|     case 1: | ||||
|         sfdp->addr_3_byte = true; | ||||
|         sfdp->addr_4_byte = true; | ||||
|         SFUD_DEBUG("3- or 4-Byte addressing."); | ||||
|         break; | ||||
|     case 2: | ||||
|         sfdp->addr_3_byte = false; | ||||
|         sfdp->addr_4_byte = true; | ||||
|         SFUD_DEBUG("4-Byte only addressing."); | ||||
|         break; | ||||
|     default: | ||||
|         sfdp->addr_3_byte = false; | ||||
|         sfdp->addr_4_byte = false; | ||||
|         SFUD_INFO("Error: Read address bytes error!"); | ||||
|         return false; | ||||
|     } | ||||
|     /* get flash memory capacity */ | ||||
|     uint32_t table2_temp = ((long)table[7] << 24) | ((long)table[6] << 16) | ((long)table[5] << 8) | (long)table[4]; | ||||
|     switch ((table[7] & (0x01 << 7)) >> 7) { | ||||
|     case 0: | ||||
|         sfdp->capacity = 1 + (table2_temp >> 3); | ||||
|         break; | ||||
|     case 1: | ||||
|         table2_temp &= 0x7FFFFFFF; | ||||
|         if (table2_temp > sizeof(sfdp->capacity) * 8 + 3) { | ||||
|             sfdp->capacity = 0; | ||||
|             SFUD_INFO("Error: The flash capacity is grater than 32 Gb/ 4 GB! Not Supported."); | ||||
|             return false; | ||||
|         } | ||||
|         sfdp->capacity = 1L << (table2_temp - 3); | ||||
|         break; | ||||
|     } | ||||
|     SFUD_DEBUG("Capacity is %ld Bytes.", sfdp->capacity); | ||||
|     /* get erase size and erase command  */ | ||||
|     for (i = 0, j = 0; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) { | ||||
|         if (table[28 + 2 * i] != 0x00) { | ||||
|             sfdp->eraser[j].size = 1L << table[28 + 2 * i]; | ||||
|             sfdp->eraser[j].cmd = table[28 + 2 * i + 1]; | ||||
|             SFUD_DEBUG("Flash device supports %ldKB block erase. Command is 0x%02X.", sfdp->eraser[j].size / 1024, | ||||
|                     sfdp->eraser[j].cmd); | ||||
|             j++; | ||||
|         } | ||||
|     } | ||||
|     /* sort the eraser size from small to large */ | ||||
|     for (i = 0, j = 0; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) { | ||||
|         if (sfdp->eraser[i].size) { | ||||
|             for (j = i + 1; j < SFUD_SFDP_ERASE_TYPE_MAX_NUM; j++) { | ||||
|                 if (sfdp->eraser[j].size != 0 && sfdp->eraser[i].size > sfdp->eraser[j].size) { | ||||
|                     /* swap the small eraser */ | ||||
|                     uint32_t temp_size = sfdp->eraser[i].size; | ||||
|                     uint8_t temp_cmd = sfdp->eraser[i].cmd; | ||||
|                     sfdp->eraser[i].size = sfdp->eraser[j].size; | ||||
|                     sfdp->eraser[i].cmd = sfdp->eraser[j].cmd; | ||||
|                     sfdp->eraser[j].size = temp_size; | ||||
|                     sfdp->eraser[j].cmd = temp_cmd; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     sfdp->available = true; | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static sfud_err read_sfdp_data(const sfud_flash *flash, uint32_t addr, uint8_t *read_buf, size_t size) { | ||||
|     uint8_t cmd[] = { | ||||
|             SFUD_CMD_READ_SFDP_REGISTER, | ||||
|             (addr >> 16) & 0xFF, | ||||
|             (addr >> 8) & 0xFF, | ||||
|             (addr >> 0) & 0xFF, | ||||
|             SFUD_DUMMY_DATA, | ||||
|     }; | ||||
|  | ||||
|     SFUD_ASSERT(flash); | ||||
|     SFUD_ASSERT(addr < 1L << 24); | ||||
|     SFUD_ASSERT(read_buf); | ||||
|     SFUD_ASSERT(flash->spi.wr); | ||||
|  | ||||
|     return flash->spi.wr(&flash->spi, cmd, sizeof(cmd), read_buf, size); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * get the most suitable eraser for erase process from SFDP parameter | ||||
|  * | ||||
|  * @param flash flash device | ||||
|  * @param addr start address | ||||
|  * @param erase_size will be erased size | ||||
|  * | ||||
|  * @return the eraser index of SFDP eraser table  @see sfud_sfdp.eraser[] | ||||
|  */ | ||||
| size_t sfud_sfdp_get_suitable_eraser(const sfud_flash *flash, uint32_t addr, size_t erase_size) { | ||||
|     size_t index = SMALLEST_ERASER_INDEX, i; | ||||
|     /* only used when flash supported SFDP */ | ||||
|     SFUD_ASSERT(flash->sfdp.available); | ||||
|     /* the address isn't align by smallest eraser's size, then use the smallest eraser */ | ||||
|     if (addr % flash->sfdp.eraser[SMALLEST_ERASER_INDEX].size) { | ||||
|         return SMALLEST_ERASER_INDEX; | ||||
|     } | ||||
|     /* Find the suitable eraser. | ||||
|      * The largest size eraser is at the end of eraser table. | ||||
|      * In order to decrease erase command counts, so the find process is from the end of eraser table. */ | ||||
|     for (i = SFUD_SFDP_ERASE_TYPE_MAX_NUM - 1;; i--) { | ||||
|         if ((flash->sfdp.eraser[i].size != 0) && (erase_size >= flash->sfdp.eraser[i].size) | ||||
|                 && (addr % flash->sfdp.eraser[i].size == 0)) { | ||||
|             index = i; | ||||
|             break; | ||||
|         } | ||||
|         if (i == SMALLEST_ERASER_INDEX) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return index; | ||||
| } | ||||
|  | ||||
| #endif /* SFUD_USING_SFDP */ | ||||
		Reference in New Issue
	
	Block a user