Giter VIP home page Giter VIP logo

sfud's Introduction

SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库


0、SFUD 是什么

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 (点击这里查看)。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。
    • 不支持 SFDP 怎么办 :如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 ( /sfud/inc/sfud_flash_def.h ) 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息(添加方法详细见 2.5 添加库目前不支持的 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|OSChina|Coding)

如果觉得这个开源项目很赞,可以点击 项目主页 右上角的 Star ,同时把它推荐给更多有需要的朋友。

型号 制造商 容量 最高速度 SFDP 标准 QSPI 模式 备注
W25Q40BV Winbond 4Mb 50Mhz 不支持 双线 已停产
W25Q80DV Winbond 8Mb 104Mhz 支持 双线
W25Q16BV Winbond 16Mb 104Mhz 不支持 双线 by slipperstree
W25Q16CV Winbond 16Mb 104Mhz 支持 未测试
W25Q16DV Winbond 16Mb 104Mhz 支持 未测试 by slipperstree
W25Q32BV Winbond 32Mb 104Mhz 支持 双线
W25Q64CV Winbond 64Mb 80Mhz 支持 四线
W25Q128BV Winbond 128Mb 104Mhz 支持 四线
W25Q256FV Winbond 256Mb 104Mhz 支持 四线
MX25L3206E Macronix 32Mb 86MHz 支持 双线
MX25L3233F Macronix 32Mb 133MHz 支持 未测试 by JiapengLi
KH25L4006E Macronix 4Mb 86Mhz 支持 未测试 by JiapengLi
KH25L3206E Macronix 32Mb 86Mhz 支持 双线
SST25VF016B Microchip 16Mb 50MHz 不支持 不支持 SST 已被 Microchip 收购
M25P40 Micron 4Mb 75Mhz 不支持 未测试 by redocCheng
M25P80 Micron 8Mb 75Mhz 不支持 未测试 by redocCheng
M25P32 Micron 32Mb 75Mhz 不支持 不支持
EN25Q32B EON 32Mb 104MHz 不支持 未测试
GD25Q16B GigaDevice 16Mb 120Mhz 不支持 未测试 by TanekLiang
GD25Q32C GigaDevice 32Mb 120Mhz 不支持 未测试 by gaupen1186
GD25Q64B GigaDevice 64Mb 120Mhz 不支持 双线
S25FL216K Cypress 16Mb 65Mhz 不支持 双线
S25FL032P Cypress 32Mb 104Mhz 不支持 未测试 by yc_911
S25FL164K Cypress 64Mb 108Mhz 支持 未测试
A25L080 AMIC 8Mb 100Mhz 不支持 双线
A25LQ64 AMIC 64Mb 104Mhz 支持 支持
F25L004 ESMT 4Mb 100Mhz 不支持 不支持
PCT25VF016B PCT 16Mb 80Mhz 不支持 不支持 SST 授权许可,会被识别为 SST25VF016B
AT45DB161E ADESTO 16Mb 85MHz 不支持 不支持 ADESTO 收购 Atmel 串行闪存产品线
NM25Q128EV Nor_Mem 128Mb 未测试 不支持 未测试 SFDP可能会读取到信息后识别为超过32Gb
P25D40H PUYA 4Mb 未测试 支持 未测试 by Shan
P25Q80H PUYA 8Mb 未测试 支持 未测试 by Shan

注: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 状态。

sfud_err sfud_init(void)

2.2.2 初始化指定的 Flash 设备

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 扩展信息表 中匹配最合适的、速度最快的快速读命令,之后用户在调用 sfud_read() 时,会使用 QSPI 模式的传输函数发送该命令。

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.hSFUD_FLASH_DEVICE_TABLE 宏定义,详细配置方法参照 2.3 配置方法 Flash)。本方法通过 Flash 设备位于设备表中索引值来返回 Flash 设备对象,超出设备表范围返回 NULL

sfud_flash *sfud_get_device(size_t index)
参数 描述
index Flash 设备位于 FLash 设备表中的索引值

2.2.5 读取 Flash 数据

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 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。

sfud_err sfud_erase(const sfud_flash *flash, uint32_t addr, size_t size)
参数 描述
flash Flash 设备对象
addr 起始地址
size 从起始地址开始擦除数据的总大小

2.2.7 擦除 Flash 全部数据

sfud_err sfud_chip_erase(const sfud_flash *flash)
参数 描述
flash Flash 设备对象

2.2.8 往 Flash 写数据

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 芯片的擦除粒度对齐,否则执行擦除操作后,将会导致其他数据丢失。

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 状态

sfud_err sfud_read_status(const sfud_flash *flash, uint8_t *status)
参数 描述
flash Flash 设备对象
status 当前状态寄存器值

2.2.11 写(修改) Flash 状态

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 是否使用快速读模式(SPI模式)

打开/关闭 SFUD_USING_FAST_READ 宏定义。许多Flash的读模式可能并不能满足较高的SPI频率(具体可查阅各Flash的数据手册交流特性部分),此时需要使能快速读模式。

注意:由于快速读模式在读时插入了默认一个空字节,在SPI速率较慢时可能相较于读模式速度更慢。

2.3.4 是否使用该库自带的 Flash 参数信息表

打开/关闭 SFUD_USING_FLASH_INFO_TABLE 宏定义

注意:关闭后该库只驱动支持 SFDP 规范的 Flash,也会适当的降低部分代码量。另外 2.3.2 及 2.3.3 这两个宏定义至少定义一种,也可以两种方式都选择。

2.3.5 既不使用 SFDP ,也不使用 Flash 参数信息表

为了进一步降低代码量,SFUD_USING_SFDPSFUD_USING_FLASH_INFO_TABLE 也可以 都不定义

此时,只要在定义 Flash 设备时,指定好 Flash 参数,之后再调用 sfud_device_init 对该设备进行初始化。参考如下代码:

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.6 Flash 设备表

如果产品中存在多个 Flash ,可以添加 Flash 设备表。修改 SFUD_FLASH_DEVICE_TABLE 这个宏定义,示例如下:

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_INDEXSFUD_GD25Q64B_DEVICE_INDEX 这两个枚举定义了两个设备位于设备表中的索引,可以通过 sfud_get_device_table() 方法获取到设备表,再配合这个索引值来访问指定的设备。

2.3.7 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 idcapacity idGD25Q64B 对应这两个 ID 分别为 0x400x17 。上面要求的其他 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 STM32F10X 裸机平台
/demo/stm32f2xx_rtt STM32F2XX + RT-Thread 操作系统平台
/demo/stm32l475_non_os_qspi STM32L475 + QSPI 模式 裸机平台
/demo/esp32_ext_spi_flash ESP32C3 + SPI外部Flash ESP-IDF框架

2.7 许可

采用 MIT 开源协议,细节请阅读项目中的 LICENSE 文件内容。

sfud's People

Contributors

armink avatar enkiller avatar gastonfeng avatar gaupen1186 avatar gbcwbz avatar hubertxie avatar jiapengli avatar joechenchen avatar kaidegit avatar lanxb avatar liangyongxiang avatar liquanqing avatar mysterywolf avatar redoccheng avatar slipperstree avatar smartelec avatar soym avatar svchao avatar wang-huachen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sfud's Issues

upport JEDEC Basic Flash ParameterDword-8

/* 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++;
}
}

the offset of the table[28] replace 28->24 ,can support JEDEC Basic Flash ParameterDword-8

SFUD在DSP的C28x上的移植问题

由于DSP的C28x的数据访问最小是16位,即在C28x上定义不了1字节类型的变量,最小只能定义2字节类型的变量,也即使用char定义的变量是占用两个字节的,这种情况下要移植SFUD的话有什么好的办法兼容吗?

Release

@armink 您好,尽管中间改动过几次了,但是SFUD 的版本在头文件里一直没有变化,期待能定期发 Release 或者打上 Tag,这样在使用的时候能看到代码变化和对应的版本号。多谢!

软件复位失效

某些FLASH,例如 CYPRESS S25HL01GT 要求 发送 0x66 命令后 必须紧接着发送 0x99 命令才能复位,中间不能插入其他命令。
并且要复位后才能使用 0x9F 命令读取信息。

[FR]支持FastRead

有些Flash在Read模式和FastRead模式下速率差距有点大,SFUD似乎没做FastRead的支持,可能会导致某些Flash跑不到满速

image
image

SST25VF080B芯片支持

板子上用的这个芯片,自己加上了,分享一下
{"SST25VF080B", SFUD_MF_ID_SST, 0x25, 0x8E, 1L * 1024L * 1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20}, \

W25Q32JV测试sfdp成功

[7.137 637] [SFUD](../../middlewares/sfud/src/sfud.c:117) Start (SFUD) V1.1.0.
[SFUD](../../middlewares/sfud/src/sfud.c:872) The flash device manufacturer ID is 0xEF, memory type ID is 0x40, capacity
             ID is 0x16.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:132) Check SFDP header is OK. The reversion is V1.5, NPN is 0.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:175) Check JEDEC basic flash parameter header is OK. The table id is 0, re
            version is V1.5, length is 16, parameter table pointer is 0x000080.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:203) JEDEC basic flash parameter table info:
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:204) MSB-LSB  3    2    1    0
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0001] 0xFF 0xF9 0x20 0xE5
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0002] 0x01 0xFF 0xFF 0xFF
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0003] 0x6B 0x08 0xEB 0x44
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0004] 0xBB 0x42 0x3B 0x08
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0005] 0xFF 0xFF 0xFF 0xFE
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0006] 0x00 0x00 0xFF 0xFF
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0007] 0xEB 0x40 0xFF 0xFF
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0008] 0x52 0x0F 0x20 0x0C
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:207) [0009] 0x00 0x00 0xD8 0x10
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:215) 4 KB Erase is supported throughout the device. Command is 0x20.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:234) Write granularity is 64 bytes or larger.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:245) Target flash status register is non-volatile.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:271) 3-Byte only addressing.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:305) Capacity is 4194304 Bytes.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:312) Flash device supports 4KB block erase. Command is 0x20.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:312) Flash device supports 32KB block erase. Command is 0x52.
[SFUD](../../middlewares/sfud/src/sfud_sfdp.c:312) Flash device supports 64KB block erase. Command is 0xD8.
[SFUD]Found a Winbond flash chip. Size is 4194304 bytes.
[SFUD](../../middlewares/sfud/src/sfud.c:850) Flash device reset success.
[SFUD]W25Q32JVSIQ flash device initialized successfully.

QSPI未测试,直接使用W25Q32BV的参数初始化也可以用。

#define SFUD_FLASH_DEVICE_TABLE                                                     \
    {                                                                               \
        [SFUD_W25Q32BV_DEVICE_INDEX] = {.name = "W25Q32JVSIQ", .spi.name = "SPI2", .chip = {"W25Q32BV", SFUD_MF_ID_WINBOND, 0x40, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20}}, \
    }

W25Q64BV Write Enable Failed

你好,你的工具设计很不错,我尝试了下,修改def为winbod W25Q64BV,运行后发现在
“sfud_erase”中执行write enable报错,但我用其它驱动读写都没问题,说明板子是可以write enable的,看你的代码中有lock spi 然后unlock spi这个动作,不太明白为什么需要,也不清楚为什么Status Register的WEL位没有置1,请问可以帮我看看么,谢谢!

*SFUD](......\sfud\src\sfud.c:861) The flash device manufacturer ID is 0xEF, memory type ID is
0x40, capacity ID is 0x17.
SFUD Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P').
[SFUD]Warning: Read SFDP parameter header information failed. The W25Q64BV is not support JEDEC SFDP.
[SFUD]Find a Winbond W25Q64BV flash chip. Size is 8388608 bytes.
SFUD Flash device reset success.
[SFUD]W25Q64BV flash device is initialize success.
[SFUD]Error: Can't enable write status.
Erase the W25Q64BV flash data failed.

增加 Power down 功能讨论

移植 SFUD 模块,用着很舒服。
最近考虑低功耗,需要把 flash 进入到低功耗模式,代码增加起来也很简单,但一直没想好是应该放到主 sfud 模块中,还是 port m模块中,亦或者单独增加个 misc 或 utility 模块。
毕竟 power down 不属于 sfud 核心功能。
有结果了我就提交 pull request.

初始化时没有锁定SPI

在对 sfud_spi_port_init 完成调用,返回成功候,应该锁定SPI再进行信息状态的读操作

添加国产SPI flash(P25Q16H) 出现问题

[SFUD] Warning: Read SFDP parameter header information failed. The P25Q16H is not support JEDEC SFDP.
[SFUD] Warning: This flash device is not found or not support.
[SFUD] Error: P25Q16H flash device is initialize fail.
ERROR: SPI flash probe failed by SPI device spi30.
rt sfud flash probe fail

JEDECID 0X85可以正常读取

MX25L51245G 使能 qspi 模式之后,后续读、写操作都要用4线,目前 sfud 库的写都是 1线。

MX25L51245G 使能 qspi 模式之后,后续读、写操作都要用4线,目前 sfud 库的写都是 1线。

实测 MX25L51245G 芯片:
1、上电之后,在 sfdp 读取阶段(1线模式)正常;
2、进入 qspi 模式之后,后续命令(开启 4byte addr、write、erase等等)全部失败。

请问这个问题怎么解决比较好?
我想到的是修改 spi_write_read 函数,根据芯片 状态、配置信息 决定用 1线 还是 4线操作。

image

新添加SPI的flash无法正常工作(BY25D16)

@armink 请帮忙看下这是什么问题呢.
<00> info> app: Start initialize Serial Flash Universal Driver(SFUD) V1.1.0.
<00> info> app: You can get the latest version on https://github.com/armink/SFUD .
<00> info> app: The flash device manufacturer ID is 0x00, memory type ID is 0x00, capacity ID is 0xBD.
<00> info> app: Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P').
<00> info> app: Warning: Read SFDP parameter header information fail<info> app: Warning: This flash device is not found or not support.
<00> info> app: Error: BY25D16 flash device is initialize fail.

在SFUD_FLASH_CHIP_TABLE的末尾已经添加了{"BY25D16", SFUD_MF_ID_BOYA, 0x40, 0x15, 2L1024L1024L, SFUD_WM_PAGE_256B, 4096, 0x20},

感谢

一些语言特性不被Keil C51支持

Keil的C编译器是基于C90的,所以有很多C99的特性不被支持导致无法编译。比如可变参数的宏定义 XXX(...) 等。
这导致51单片机全军覆没。有没有可能用一个开关来切换这些不被支持的语法,并最低限度的支持C51?

N25Q64 只能读,不能写

N25Q64 只能读,不能写,写完之后,读出来还是 0xFF,还是擦除后的状态。
M25P32 板子上同样的程序,正常读写。
请问下,这种情况,可能是什么原因呢?

AT45DB321 default page size 528

现在使用的是AT45DB321,库里支持的是AT45DB16,已经通过查询手册增加了AT45DB321,现在看到手册上说默认是528,而SFUD里面写的是512,请问一下这里有什么问题。
 User configurable page size
 512 bytes per page
 528 bytes per page (default)
 Page size can be factory pre-configured for 512 bytes

STM32H723+GD25Q256不正常工作

我是用STM32H723+GD25Q256的方式,使用OSPI的4线或者1线模式可以读取sfdp信息,但是进行读写测试不能成功,读回来的数据都是0xff。请问这里大概会是什么原因呢?下面是我的port部分代码:
/*

  • This file is part of the Serial Flash Universal Driver Library.
  • 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
  • '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: Portable interface for each platform.
  • Created on: 2016-04-23
    */

#include <sfud.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "cmsis_os.h"

static char log_buf[256];

void sfud_log_debug(const char *file, const long line, const char *format, ...);

void sfud_log_info(const char *format, ...);
sfud_err qspi_send_then_recv(const sfud_spi *spi,const void *send_buf, size_t send_length, void *recv_buf, size_t recv_length);
extern OSPI_HandleTypeDef hospi1;

typedef struct
{
OSPI_HandleTypeDef *spix;
GPIO_TypeDef *cs_gpiox;
uint16_t cs_gpio_pin;
} spi_user_data, *spi_user_data_t;

static void spi_lock(const sfud_spi *spi)
{
//__disable_irq();
}

static void spi_unlock(const sfud_spi *spi)
{
//__enable_irq();
}
void cmdhandler_default(OSPI_RegularCmdTypeDef * Cmdhandler)
{
Cmdhandler->OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
Cmdhandler->FlashId = HAL_OSPI_FLASH_ID_1;
Cmdhandler->Instruction = 0;
Cmdhandler->InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
Cmdhandler->InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
Cmdhandler->InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

Cmdhandler->Address = 0;
Cmdhandler->AddressSize = HAL_OSPI_ADDRESS_24_BITS;
Cmdhandler->AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
Cmdhandler->AddressMode = HAL_OSPI_ADDRESS_1_LINE;

Cmdhandler->AlternateBytes = 0;
Cmdhandler->AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
Cmdhandler->AlternateBytesSize = 0;
Cmdhandler->AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;

Cmdhandler->NbData = 0;
Cmdhandler->DataMode = HAL_OSPI_DATA_1_LINE;
Cmdhandler->DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;

Cmdhandler->DummyCycles = 0;
Cmdhandler->SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
Cmdhandler->DQSMode = HAL_OSPI_DQS_DISABLE;

}

/**

  • SPI write data then read data
    */
    static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, size_t write_size, uint8_t *read_buf,
    size_t read_size) {
    sfud_err result = SFUD_SUCCESS;

    spi_user_data_t spi_dev = (spi_user_data_t) spi->user_data;

    if (write_size)
    {
    SFUD_ASSERT(write_buf);
    }
    if (read_size)
    {
    SFUD_ASSERT(read_buf);
    }

    /* reset cs pin */
    if (spi_dev->cs_gpiox != NULL)
    HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_RESET);

    if (write_size && read_size)
    {
    /* read data /
    qspi_send_then_recv(spi,write_buf, write_size, read_buf, read_size);
    }
    else if (write_size)
    {
    /
    send data */
    qspi_send_then_recv(spi,write_buf, write_size, NULL, NULL);
    }

    /* set cs pin */
    if (spi_dev->cs_gpiox != NULL)
    HAL_GPIO_WritePin(spi_dev->cs_gpiox, spi_dev->cs_gpio_pin, GPIO_PIN_SET);

    return result;
    }

#ifdef SFUD_USING_QSPI
/**

  • read flash data by QSPI
    */
    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) {

    sfud_err result = SFUD_SUCCESS;
    OSPI_RegularCmdTypeDef Cmdhandler;
    spi_user_data * hqspi;
    //QSPI_CommandTypeDef Cmdhandler;
    //extern QSPI_HandleTypeDef hqspi;
    hqspi = (spi_user_data *)spi->user_data;

    cmdhandler_default(&Cmdhandler);

    /* set cmd struct */
    Cmdhandler.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
    Cmdhandler.FlashId = HAL_OSPI_FLASH_ID_1;
    Cmdhandler.Instruction = qspi_read_cmd_format->instruction;

    if(qspi_read_cmd_format->instruction_lines == 0)
    {
    Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_NONE;
    }else if(qspi_read_cmd_format->instruction_lines == 1)
    {
    Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
    }else if(qspi_read_cmd_format->instruction_lines == 2)
    {
    Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_2_LINES;
    }else if(qspi_read_cmd_format->instruction_lines == 4)
    {
    Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
    }

    Cmdhandler.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
    Cmdhandler.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;

    Cmdhandler.Address = addr;
    Cmdhandler.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
    Cmdhandler.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
    if(qspi_read_cmd_format->address_lines == 0)
    {
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_NONE;
    }else if(qspi_read_cmd_format->address_lines == 1)
    {
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
    }else if(qspi_read_cmd_format->address_lines == 2)
    {
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_2_LINES;
    }else if(qspi_read_cmd_format->address_lines == 4)
    {
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
    }

    Cmdhandler.AlternateBytes = 0;
    Cmdhandler.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.AlternateBytesSize = 0;
    Cmdhandler.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;

    Cmdhandler.DummyCycles = qspi_read_cmd_format->dummy_cycles;

    Cmdhandler.NbData = read_size;
    Cmdhandler.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
    if(qspi_read_cmd_format->data_lines == 0)
    {
    Cmdhandler.DataMode = HAL_OSPI_DATA_NONE;
    }else if(qspi_read_cmd_format->data_lines == 1)
    {
    Cmdhandler.DataMode = HAL_OSPI_DATA_1_LINE;
    }else if(qspi_read_cmd_format->data_lines == 2)
    {
    Cmdhandler.DataMode = HAL_OSPI_DATA_2_LINES;
    }else if(qspi_read_cmd_format->data_lines == 4)
    {
    Cmdhandler.DataMode = HAL_OSPI_DATA_4_LINES;
    }

    Cmdhandler.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
    Cmdhandler.DQSMode = HAL_OSPI_DQS_DISABLE;

    HAL_OSPI_Command(hqspi->spix, &Cmdhandler, 5000);

    if (HAL_OSPI_Receive(hqspi->spix, read_buf, 5000) != HAL_OK)
    {
    sfud_log_info("qspi recv data failed(%d)!", hqspi->spix->ErrorCode);
    hqspi->spix->State = HAL_OSPI_STATE_READY;
    result = SFUD_ERR_READ;
    }

    return result;
    }
    #endif /* SFUD_USING_QSPI */

/* about 100 microsecond delay */
static void retry_delay_100us(void)
{
uint32_t delay = 2400;
while (delay--);
}

static spi_user_data spi1 = { .spix = &hospi1, .cs_gpiox = NULL, .cs_gpio_pin = NULL };
sfud_err sfud_spi_port_init(sfud_flash *flash) {
sfud_err result = SFUD_SUCCESS;

/**
 * add your port spi bus and device object initialize code like this:
 * 1. rcc initialize
 * 2. gpio initialize
 * 3. spi device initialize
 * 4. flash->spi and flash->retry item initialize
 *    flash->spi.wr = spi_write_read; //Required
 *    flash->spi.qspi_read = qspi_read; //Required when QSPI mode enable
 *    flash->spi.lock = spi_lock;
 *    flash->spi.unlock = spi_unlock;
 *    flash->spi.user_data = &spix;
 *    flash->retry.delay = null;
 *    flash->retry.times = 10000; //Required
 */

/* set the interfaces and data */
flash->spi.wr = spi_write_read;
flash->spi.qspi_read = qspi_read;
flash->spi.lock = spi_lock;
flash->spi.unlock = spi_unlock;
flash->spi.user_data = &spi1;
/* about 100 microsecond delay */
flash->retry.delay = retry_delay_100us;
/* adout 60 seconds timeout */
flash->retry.times = 60 * 10000;

return result;

}

/**

  • This function is print debug info.

  • @param file the file which has call this function

  • @param line the line number which has call this function

  • @param format output format

  • @param ... args
    */
    void sfud_log_debug(const char *file, const long line, const char *format, ...) {
    va_list args;

    /* args point to the first variable parameter /
    va_start(args, format);
    printf("SFUD ", file, line);
    /
    must use vprintf to print */
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf("%s\n", log_buf);
    va_end(args);
    }

/**

  • This function is print routine info.

  • @param format output format

  • @param ... args
    */
    void sfud_log_info(const char *format, ...) {
    va_list args;

    /* args point to the first variable parameter /
    va_start(args, format);
    printf("[SFUD]");
    /
    must use vprintf to print /
    vsnprintf(log_buf, sizeof(log_buf), format, args);
    printf("%s\n", log_buf);
    va_end(args);
    }
    /
    *

  • This function can send or send then receive QSPI data.
    */
    sfud_err qspi_send_then_recv(const sfud_spi *spi,const void *send_buf, size_t send_length, void *recv_buf, size_t recv_length)
    {
    assert_param(send_buf);
    assert_param(recv_buf);
    assert_param(send_length != 0);

    OSPI_RegularCmdTypeDef Cmdhandler;
    spi_user_data * hqspi;
    hqspi = (spi_user_data *)spi->user_data;

    unsigned char *ptr = (unsigned char *)send_buf;
    size_t count = 0;
    sfud_err result = SFUD_SUCCESS;

    cmdhandler_default(&Cmdhandler);

    /* get instruction */
    Cmdhandler.Instruction = ptr[0];
    Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
    count++;

    /* get address /
    if (send_length > 1)
    {
    if (send_length >= 4)
    {
    /
    address size is 3 Byte /
    Cmdhandler.Address = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
    Cmdhandler.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
    count += 3;
    }
    else
    {
    return SFUD_ERR_READ;
    }
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
    }
    else
    {
    /
    no address stage */
    Cmdhandler.Address = 0 ;
    Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_NONE;
    Cmdhandler.AddressSize = 0;
    }

    Cmdhandler.AlternateBytes = 0;
    Cmdhandler.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
    Cmdhandler.AlternateBytesSize = 0;

    Cmdhandler.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

    if (send_buf && recv_buf)
    {
    /* recv data /
    /
    set dummy cycles */
    if (count != send_length)
    {
    Cmdhandler.DummyCycles = (send_length - count) * 8;
    }
    else
    {
    Cmdhandler.DummyCycles = 0;
    }

     /* set recv size */
     Cmdhandler.DataMode = HAL_OSPI_DATA_1_LINE;
     Cmdhandler.NbData = recv_length;
     HAL_OSPI_Command(hqspi->spix, &Cmdhandler, 5000);
     
     if (recv_length != 0)
     {
         if (HAL_OSPI_Receive(hqspi->spix, recv_buf, 5000) != HAL_OK)
         {
             sfud_log_info("qspi recv data failed(%d)!", hqspi->spix->ErrorCode);
             hqspi->spix->State = HAL_OSPI_STATE_READY;
             result = SFUD_ERR_READ;
         }
     }
    
     return result;
    

    }
    else
    {
    /* send data /
    /
    set dummy cycles */
    Cmdhandler.DummyCycles = 0;

     /* determine if there is data to send */
     if (send_length - count > 0)
     {
         Cmdhandler.DataMode = HAL_OSPI_DATA_1_LINE;
     }
     else
     {
         Cmdhandler.DataMode = HAL_OSPI_DATA_NONE;
     }
    
     /* set send buf and send size */
     Cmdhandler.NbData = send_length - count;
     HAL_OSPI_Command(hqspi->spix, &Cmdhandler, 5000);
     
     if (send_length - count > 0)
     {
         if (HAL_OSPI_Transmit(hqspi->spix,(uint8_t *)(ptr + count), 5000) != HAL_OK)
         {
             sfud_log_info("qspi send data failed(%d)!", hqspi->spix->ErrorCode);
             hqspi->spix->State = HAL_OSPI_STATE_READY;
             result = SFUD_ERR_READ;
         }
     }
     
     return result;
    

    }
    }

在IAR FOR STM8环境下的问题

形如 1<<24这种代码,虽然可以编译通过,但是会有警告提示位移超过上限。并且调试发现位移的结果是0。这会导致断言失败或条件判断错误。
目前我将上述代码改为 1L<<24可以解决问题。不知道有没有更好的办法?类似这种问题还出现在flash列表里的capacity项目,210241024在8位机环境下计算结果是0,所以同样需要在数字尾部添加L标识。还有demo函数里面的打印读取内容时,printf(%08x... 要改成 %08lx...,还有其他一些地方都是这个原因导致的。

AT45DB161的指令和sfud_def.h中的基本不同,实际不能支持?

一方面指令部分有一些差异,如读取状态位,包括状态位的位置
另一方面代码对于AT45DB161的支持也不完整?如sfud_write函数,实际上AT45DB161的SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER写模式会使其落入else if (flash->chip.write_mode & SFUD_WM_DUAL_BUFFER)中,而此处为未完成功能://TODO dual-buffer write mode

submodule管理

Hi,SFUD对于Submodule的管理遇到以下问题,
在移植SFUD时,遇到需要修改
sfud_cfg.h
sfud_flash_def.h
然而,为了不要影响的主代码,需要把inc和port文件夹单独拷贝一份到外部,然后外部指定头文件的包含路径为another/sfud_port/inc
然后git submodule add [SFUD_URL]后,发现在src中#include "../inc/sfud.h"依然包含的是自己的
sfud_flash_def.h,导致必须要修改sfud.c的头文件包含
所以,建议把sfud.c中的
#include "../inc/sfud.h"
改为
#include "sfud.h"
这样后面的工程只需要把inc和port拷贝一份,然后不影响到submodule的源码内容
把头文件路径包含到inc目录即可

Erase granularity not set correctly on non-uniform flash

Hello,

I'm using S25FL127S which does not support uniform 4k erase.

Library correctly reports via SFDP that flash chip does not supports uniform 4k erase, but it sets erase_gran and erase_gran_cmd to 4k erase anyway.

I modified library in such way that if sfdp.4k_erase is 0 then erase_gran and erase_gran_cmd is set to first eraser size which is larger than 4k, but I'm not sure if this is the correct way. I also dif not find any flags in SFDP that would tell which erase size is uniform for whole device.

Best regards

read_jedec_id

this function has a bug.
jedec id
0x9F dummy 0xEF 0xAA 0x21

eraser_index 未使用警告

..\SFUD\sfud\src\sfud.c(404): warning: #177-D: variable "eraser_index" was declared but never referenced

注释掉 SFUD_USING_SFDP,会出现上面的警告。不影响程序运行。

W25Q64FV不支持

我按照readme里面的方法尝试了一下 ,依然显示有问题
\ | /

  • RT - Thread Operating System
    / | \ 4.0.1 build Mar 12 2020
    2006 - 2019 Copyright by rt-thread team
    [SFUD] Warning: Read SFDP parameter header information failed. The W25Q64 is not support JEDEC SFDP.
    [SFUD] Warning: This flash device is not found or not support.
    [SFUD] Error: W25Q64 flash device is initialize fail.
    ERROR: SPI flash probe failed by SPI device spi20.
    msh />�[31m[E/drv.sdio] wait completed timeout�[0m

set_write_enabled失败,导致无法写AT45DB161

atmel这款旧的flash不支持SFDP标准,SFUD_CMD_WRITE_ENABLE和SFUD_CMD_WRITE_DISABLE这两个指令也不支持。需要注释set_write_enabled函数,直接返回SFUD_SUCCESS,才可以正常写数据。

Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P')

bsp:正点原子stm32f429-apollo W25Q256
根据Readme进行了 no os 裸机移植,
出现如下问题,请问这中问题一般是 啥原因造成的呢?
[SFUD]Error: W25Q256 flash device is initialize fail.?
SFUD The flash device manufacturer ID is 0x9F, memory type ID is 0x90, capacity ID is 0x4D.
SFUD Error: Check SFDP signature error. It's must be 50444653h('S' 'F' 'D' 'P').
[SFUD]Warning: Read SFDP parameter header information failed. The W25Q256 is not support JEDEC SFDP.
[SFUD]Warning: This flash device is not found or not support.

The encoding of source code cannot be processed correctly by Git | 源代码的编码无法被 Git 正确处理

Background | 背景

Some editors automatically chose the "UTF-8" encoding when opening the "sfud/src/sfud_sfdp.c" file. In VS Code, we can see the following on line 226 of this file:
一些编辑器自动选择“UTF-8”编码来打开“sfud/src/sfud_sfdp.c”。在 VS Code 中,我们能在这个文件的第226行看到如下内容:

    //TODO ĿǰΪ 1.0 ���ṩ�ķ�ʽ������֧�� V1.5 �����ϵķ�ʽ��ȡ page size

I guess the garbled text is Chinese, so I tried to reopen the file with the "GB 2312" encoding:
我猜这些乱码实际上是中文文本,因此试着用“GB 2312”编码重新打开了这个文件:

    //TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size

Now it's readable.
现在这些内容是可读的了。

Since modern frontend frameworks and web browsers are smart enough, we don't seem to be bothered by encoding issue on GitHub:
由于现代的前端框架与浏览器足够智能,在 GitHub 上我们似乎不会被编码所困扰:

//TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size

Problem | 问题

Let's make some changes in "sfud/src/sfud_sfdp.c". Open the file with "GB 2312" in VS Code and add some characters like this:
在“sfud/src/sfud_sfdp.c”里做些修改吧。以“GB 2312”编码打开它并添加一些字符:

-     //TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size
+     //TODO 目前为 1.0 所提供的方式,后期支持 V1.5 及以上的方式读取 page size 中文Chinese中文

Then, call "git diff":
接着执行“git diff”:

$ git diff --unified=0 sfud/src/sfud_sfdp.c
diff --git a/sfud/src/sfud_sfdp.c b/sfud/src/sfud_sfdp.c
index c77a755..a5f4a3c 100644
--- a/sfud/src/sfud_sfdp.c
+++ b/sfud/src/sfud_sfdp.c
@@ -226 +226 @@ static bool read_basic_table(sfud_flash *flash, sfdp_para_header *basic_header)
-    //TODO ĿǰΪ 1.0 <CB><F9><CC>ṩ<B5>ķ<BD>ʽ<A3><AC><BA><F3><C6><DA>֧<B3><D6> V1.5 <BC><B0><D2><D4><C9>ϵķ<BD>ʽ<B6><C1>ȡ page size
+    //TODO ĿǰΪ 1.0 <CB><F9><CC>ṩ<B5>ķ<BD>ʽ<A3><AC><BA><F3><C6><DA>֧<B3><D6> V1.5 <BC><B0><D2><D4><C9>ϵķ<BD>ʽ<B6><C1>ȡ page size <D6><D0><CE><C4>Chinese<D6><D0><CE><C4>

Well, these characters represented in hexadecimal are not what we expect. How to make the file encoding correctly recognized by Git?
呃,我们并不需要这些十六进制形式的字符。那么如何让 Git 正确识别文件的编码呢?

After some searching, I've found two solutions:
经过搜索,我找到了两种方法:

  • Adding working-tree-encoding=gb2312 to ".gitattributes" to make Git process source code files with the "GB 2312" encoding; | 向“.gitattributes”添加 working-tree-encoding=gb2312 使 Git 以“GB 2312”编码处理源代码文件;
  • Or, resaving source code files with the "UTF-8" encoding (I prefer). | 以“UTF-8”编码重新保存源代码文件(我更倾向于这个办法)。

Reference | 参考

SFUD不支持AT45DB161E

AT45DB161E的SFUD_CMD_READ_STATUS_REGISTER为0xD7,SFUD中默认为0x05;

#ifndef SFUD_CMD_READ_STATUS_REGISTER
#define SFUD_CMD_READ_STATUS_REGISTER                  0x05
#endif

即便在sfud_cfg.h中重定义SFUD_CMD_READ_STATUS_REGISTER

#define SFUD_CMD_READ_STATUS_REGISTER 0xD7

AT45DB161E的Status Register的BUSY在bit7上,SFUD中默认在bit0;

以下两个命令在AT45DB161E也没有找到

#ifndef SFUD_CMD_WRITE_ENABLE
#define SFUD_CMD_WRITE_ENABLE                          0x06
#endif

#ifndef SFUD_CMD_WRITE_DISABLE
#define SFUD_CMD_WRITE_DISABLE                         0x04
#endif

后面应该还有命令不一样,就不继续测试了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.