硬汉嵌入式论坛

 找回密码
 立即注册
查看: 704|回复: 28
收起左侧

[Zephyr] stm32h743 qspi nor flash读写问题

[复制链接]

2

主题

20

回帖

26

积分

新手上路

积分
26
发表于 2025-8-25 14:43:13 | 显示全部楼层 |阅读模式
大家好,最近在学习zephyr尝试驱动qspi连接的w25q256时遇到了问题。以下是我的设备树配置。

[C] 纯文本查看 复制代码
&quadspi {
	status = "okay";
	pinctrl-0 = <&quadspi_bk1_ncs_pb6
			 &quadspi_clk_pb2
		     &quadspi_bk1_io0_pf8
		     &quadspi_bk1_io1_pf9
		     &quadspi_bk1_io2_pf7
		     &quadspi_bk1_io3_pf6>;
	pinctrl-names = "default";
	flash-id = <1>;

  	w25q256: qspi-nor-flash@0 {
		compatible = "st,stm32-qspi-nor";
		label = "W25Q256";
		reg = <0>; 
		size = <DT_SIZE_M(256)>; /* 256 Mbits */
		qspi-max-frequency = <DT_FREQ_M(100)>;
		spi-bus-width = <4>;
		writeoc= "PP_1_4_4"; /* W25Q256: 0x32 = 4-byte fast read */
		reset-cmd;         /* this line must be added!!!! */
		status = "okay";
		quad-enable-requirements = "S2B1v1";
	};

};

以下是conf配置
[C] 纯文本查看 复制代码
CONFIG_GPIO=y
CONFIG_LOG=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_PRINTK=y

CONFIG_FLASH=y
CONFIG_FLASH_JESD216_API=y
CONFIG_SPI_NOR=y

以下是main函数,主要就是spi_flash的例程,然后添加了写入和读写的测试
[C] 纯文本查看 复制代码
int main(void)
{
	const struct device *const dev = DEVICE_DT_GET(FLASH_NODE);

	if (!device_is_ready(dev)) {
		printf("%s: device not ready\n", dev->name);
		return 0;
	}

	const uint8_t decl_nph = 5;
	union {
		uint8_t raw[JESD216_SFDP_SIZE(decl_nph)];
		struct jesd216_sfdp_header sfdp;
	} u;
	const struct jesd216_sfdp_header *hp = &u.sfdp;
	int rc = flash_sfdp_read(dev, 0, u.raw, sizeof(u.raw));

	if (rc != 0) {
		printf("Read SFDP not supported: device not JESD216-compliant "
		       "(err %d)\n", rc);
		return 0;
	}

	uint32_t magic = jesd216_sfdp_magic(hp);

	if (magic != JESD216_SFDP_MAGIC) {
		printf("SFDP magic %08x invalid", magic);
		return 0;
	}

	printf("%s: SFDP v %u.%u AP %x with %u PH\n", dev->name,
		hp->rev_major, hp->rev_minor, hp->access, 1 + hp->nph);

	const struct jesd216_param_header *php = hp->phdr;
	const struct jesd216_param_header *phpe = php + MIN(decl_nph, 1 + hp->nph);

	while (php != phpe) {
		uint16_t id = jesd216_param_id(php);
		uint32_t addr = jesd216_param_addr(php);

		printf("PH%u: %04x rev %u.%u: %u DW @ %x\n",
		       (uint32_t)(php - hp->phdr), id, php->rev_major, php->rev_minor,
		       php->len_dw, addr);

		uint32_t dw[php->len_dw];

		rc = flash_sfdp_read(dev, addr, dw, sizeof(dw));
		if (rc != 0) {
			printf("Read failed: %d\n", rc);
			return 0;
		}

		if (id == JESD216_SFDP_PARAM_ID_BFP) {
			const struct jesd216_bfp *bfp = (struct jesd216_bfp *)dw;

			dump_bfp(php, bfp);
			printf("size = <%u>; // bits\n", (uint32_t)jesd216_bfp_density(bfp));
			printf("sfdp-bfp =");
		} else {
			printf("sfdp-%04x =", id);
		}

		dump_bytes(php, dw);

		++php;
	}

	uint8_t id[3];

	rc = flash_read_jedec_id(dev, id);
	if (rc == 0) {
		printf("jedec-id = [%02x %02x %02x];\n",
		       id[0], id[1], id[2]);
	} else {
		printf("JEDEC ID read failed: %d\n", rc);
	}

	/* 1. 填充测试数据 */
    for (int i = 0; i < BUF_SIZE; i++)
        tx[i] = i & 0xFF;

	/* 2. 擦除 4 KiB 扇区 */
    printk("Erasing sector @0x%08X\n", TEST_ADDR);
    flash_erase(dev, TEST_ADDR, 4096);

	/* 3. 写 256 字节 */
    printk("Writing %d bytes @0x%08X\n", BUF_SIZE, TEST_ADDR);
    flash_write(dev, TEST_ADDR, tx, BUF_SIZE);

	/* 4. 读回来 */
    memset(rx, 0, BUF_SIZE);
    flash_read(dev, TEST_ADDR, rx, BUF_SIZE);

    /* 5. 校验 */
    if (memcmp(tx, rx, BUF_SIZE) == 0) {
        printk("QSPI W25Q256 R/W test OK!\n");
    } else {
        printk("QSPI W25Q256 R/W test FAIL!\n");
    }

	return 0;
}

现在测试的结果是,sfdp的magic测试通过,jedec-id输出的值是[19 00 00],但是对于w25q256应该是[ef 40 19]。然后就是写入数据再读取校验失败(flash_shell例程也是一样,调用write质量显示的是write成功但是verify失败)。
各位大佬能不能指导一下小弟,看看接下来应该如何调试。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
118335
QQ
发表于 2025-8-26 08:50:49 | 显示全部楼层
帮顶。
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-26 10:05:58 | 显示全部楼层
参考这个的设备树配置  zephyr/boards/fanke/fk743m5_xih6/fk743m5_xih6.dts
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-26 22:08:58 | 显示全部楼层
tovinz 发表于 2025-8-26 10:05
参考这个的设备树配置  zephyr/boards/fanke/fk743m5_xih6/fk743m5_xih6.dts

好的,参考这个设备树配置了quadspi节点
[C] 纯文本查看 复制代码
&quadspi {
	status = "okay";
	pinctrl-0 = <&quadspi_bk1_ncs_pb6
			 &quadspi_clk_pb2
		     &quadspi_bk1_io0_pf8
		     &quadspi_bk1_io1_pf9
		     &quadspi_bk1_io2_pf7
		     &quadspi_bk1_io3_pf6>;
	pinctrl-names = "default";

  	w25q256: qspi-nor-flash@0 {
		compatible = "st,stm32-qspi-nor";
		label = "W25Q256";
		reg = <0>; 
		size = <DT_SIZE_M(256)>; /* 256 Mbits */
		qspi-max-frequency = <40000000>;
		spi-bus-width = <4>;
		writeoc = "PP_1_1_4";
		status = "okay";


		partitions {
			compatible = "fixed-partitions";
			#address-cells = <1>;
			#size-cells = <1>;

			lfs1_partition: partition@0 {
				label = "storage";
				reg = <0x0 DT_SIZE_M(32)>;
			};
		};
	};
};

然后参考例程中的driver/spi_flash配置了conf
[C] 纯文本查看 复制代码
CONFIG_GPIO=y
CONFIG_LOG=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_PRINTK=y

CONFIG_FLASH=y

运行spi_flash例程输出为
[C] 纯文本查看 复制代码
W25Q256 SPI flash testing
==========================

Perform test on single sector
Test 1: Flash erase
Flash erase failed at offset 0x1000 got 0x6afe4d88

Perform test on multiple consecutive sectors
Test 1: Flash erase
Flash erase failed at offset 0x1000 got 0x6afe4d88
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: SFDP v 1.0 AP ff with 1 PH
[00:00:00.000,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.0: 9 DW @ 80
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: 32 MiBy flash
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 4 instr [0x6b] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] will be used
[00:00:00.000,000] <wrn> flash_stm32_qspi: Unable to decode QE requirement [DW15]: -134
[00:00:00.000,000] <inf> flash_stm32_qspi: QE requirement mode: 2
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad mode enabled
[00:00:00.000,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x2000000 bytes)
*** Booting Zephyr OS build v4.2.0-346-g9f0dc127c072 ***

仍然是flash擦除失败
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-27 09:17:48 | 显示全部楼层
本帖最后由 tovinz 于 2025-8-27 09:18 编辑
Ljiangwei 发表于 2025-8-26 22:08
好的,参考这个设备树配置了quadspi节点
[mw_shl_code=c,true]&quadspi {
        status = "okay";

我试过了是没有问题的,spi_flash,flash_shell, jesd216 这三个 sample 都是正常的
- 检查一下引脚是否有冲突是否被其他节点使用了
- 检查是否有写保护问题
- 你使用的是什么板子,检查一下硬件。我用的是反客的 FK750M6_XBH6,zephyr里暂时还没有,我用的 fk743m5_xih6 的改的,基本上没太大差别,和你的设备树配置只有 cs 和 clk 引脚不相同
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-27 10:20:34 | 显示全部楼层
tovinz 发表于 2025-8-27 09:17
我试过了是没有问题的,spi_flash,flash_shell, jesd216 这三个 sample 都是正常的
- 检查一下引脚是否 ...

感谢提醒,我发现设备树里面qspi的bk1_ncs引脚也被lpusart使用了。我把lpusart disable一下,等下班了晚上再测测
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-27 22:50:38 | 显示全部楼层
tovinz 发表于 2025-8-27 09:17
我试过了是没有问题的,spi_flash,flash_shell, jesd216 这三个 sample 都是正常的
- 检查一下引脚是否 ...

还是失败了。我用的正点原子的h743开发板。应该没有写保护的问题。用正点原子提供的程序测试过flash是没有问题的。接下来我打算试试将正点原子的程序移植到zephyr上试试看看问题到底出在哪里
Snipaste_2025-08-27_22-47-39.png
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-28 09:11:26 | 显示全部楼层
Ljiangwei 发表于 2025-8-27 22:50
还是失败了。我用的正点原子的h743开发板。应该没有写保护的问题。用正点原子提供的程序测试过flash是没 ...

我只能尽力帮你。
是stm32h743水星开发板吗,zephyr 程序是基于哪个h7板子的呢
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-28 10:06:48 | 显示全部楼层
tovinz 发表于 2025-8-28 09:11
我只能尽力帮你。
是stm32h743水星开发板吗,zephyr 程序是基于哪个h7板子的呢

感谢感谢。我的板子是阿波罗STM32H743IIT6。zephyr基于的板子是nucleo_h743zi,路径为zephyrproject\zephyr\boards\st\nucleo_h743zi。
我把板子弄了个module上传了github,地址为https://github.com/Ljiangw/alientek.git
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-28 15:04:24 | 显示全部楼层
Ljiangwei 发表于 2025-8-28 10:06
感谢感谢。我的板子是阿波罗STM32H743IIT6。zephyr基于的板子是nucleo_h743zi,路径为zephyrproject\zeph ...

链接访问不到
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-28 16:12:33 | 显示全部楼层

抱歉,默认推到github变成私有仓库了,我转成public的了
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-28 17:14:01 | 显示全部楼层
Ljiangwei 发表于 2025-8-28 16:12
抱歉,默认推到github变成私有仓库了,我转成public的了

逆天,排查了半天以为是其他设备节点的问题,结果发现是 quadspi 节点中你用的是 writeoc = "PP_1_4_4" 我用的是 writeoc = "PP_1_1_4"

看头像你也是东大男子职业技术学院的?
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-28 17:27:00 | 显示全部楼层
tovinz 发表于 2025-8-28 17:14
逆天,排查了半天以为是其他设备节点的问题,结果发现是 quadspi 节点中你用的是 writeoc = "P_1_4_4"  ...

这两个我都试了,结果都是一样的
是的,我是13界9院的
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-28 17:54:01 | 显示全部楼层
Ljiangwei 发表于 2025-8-28 17:27
这两个我都试了,结果都是一样的
是的,我是13界9院的

我直接用你的整个设备树替换到我的,只改了 cs 和 clk,测试是正常的
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-29 06:43:30 | 显示全部楼层
tovinz 发表于 2025-8-28 17:54
我直接用你的整个设备树替换到我的,只改了 cs 和 clk,测试是正常的

好吧,那可能是我的板子有些问题了
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-29 09:26:44 | 显示全部楼层
本帖最后由 tovinz 于 2025-8-29 09:29 编辑
Ljiangwei 发表于 2025-8-29 06:43
好吧,那可能是我的板子有些问题了

不知道是不是flash型号的问题

这是上面你的输出
[C] 纯文本查看 复制代码
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: SFDP v 1.0 AP ff with 1 PH
[00:00:00.000,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.0: 9 DW @ 80
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: 32 MiBy flash
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 4 instr [0x6b] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] will be used
[00:00:00.000,000] <wrn> flash_stm32_qspi: Unable to decode QE requirement [DW15]: -134
[00:00:00.000,000] <inf> flash_stm32_qspi: QE requirement mode: 2
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad mode enabled
[00:00:00.000,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x2000000 bytes)


这是我的输出
[C] 纯文本查看 复制代码
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: SFDP v 1.5 AP ff with 1 PH
[00:00:00.000,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.5: 16 DW @ 80
[00:00:00.000,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.000,000] <inf> flash_stm32_qspi: W25Q256: 32 MiBy flash
[00:00:00.000,000] <inf> flash_stm32_qspi: Flash - address mode: 4B
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 4 instr [0x6b] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] supported
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] will be used
[00:00:00.000,000] <inf> flash_stm32_qspi: QE requirement mode: 4
[00:00:00.000,000] <inf> flash_stm32_qspi: Quad mode enabled
[00:00:00.000,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x2000000 bytes)


回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-29 09:37:31 | 显示全部楼层
tovinz 发表于 2025-8-29 09:26
不知道是不是flash型号的问题

这是上面你的输出

有可能,我是JV系列的W25Q,不知道你的板子上是什么系列的?
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-29 10:01:24 | 显示全部楼层
Ljiangwei 发表于 2025-8-29 09:37
有可能,我是JV系列的W25Q,不知道你的板子上是什么系列的?

实际上可以看到单片机和 flash 应该是通信成功了,读取到了 SFDP 标准的相关信息
但是你的日志显示擦除后读取出来的不是 0xFF (Flash erase failed at offset 0x1000 got 0x6afe4d88),很难不怀疑写保护了
试试不插底板只使用核心板看看

微信图片_20250829095406_2_10.jpg
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-29 10:19:09 | 显示全部楼层
tovinz 发表于 2025-8-29 10:01
实际上可以看到单片机和 flash 应该是通信成功了,读取到了 SFDP 标准的相关信息
但是你的日志显示擦除 ...

好的,晚上回去测试一下
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-8-29 15:22:52 | 显示全部楼层
配置 qspi flash 部分的 log 输出等级为 debug,查看完整日志
[C] 纯文本查看 复制代码
CONFIG_LOG=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_FLASH_LOG_LEVEL_DBG=y


这是我这边的 spi_flash 全部日志内容,测试位置改为了 0x1000

[C] 纯文本查看 复制代码
[00:00:00.000,000] <dbg> flash_stm32h7: stm32h7_flash_init: Flash initialized. BS: 32
[00:00:00.008,000] <dbg> flash_stm32h7: stm32h7_flash_init: Block 0: bs: 131072 count: 32
[00:00:00.016,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.022,000] <inf> flash_stm32_qspi: W25Q256: SFDP v 1.5 AP ff with 1 PH
[00:00:00.030,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.5: 16 DW @ 80
[00:00:00.037,000] <inf> flash_stm32_qspi: Reading SFDP
[00:00:00.042,000] <inf> flash_stm32_qspi: W25Q256: 32 MiBy flash
[00:00:00.049,000] <dbg> flash_stm32_qspi: spi_nor_process_bfp: Erase 4096 with 20
[00:00:00.057,000] <dbg> flash_stm32_qspi: spi_nor_process_bfp: Erase 32768 with 52
[00:00:00.065,000] <dbg> flash_stm32_qspi: spi_nor_process_bfp: Erase 65536 with d8
[00:00:00.073,000] <dbg> flash_stm32_qspi: spi_nor_process_bfp: Page size 256 bytes
[00:00:00.081,000] <dbg> flash_stm32_qspi: spi_nor_process_bfp: Flash size 33554432 bytes
[00:00:00.090,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0xb7
[00:00:00.097,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x1b7
[00:00:00.104,000] <inf> flash_stm32_qspi: Flash - address mode: 4B
[00:00:00.110,000] <inf> flash_stm32_qspi: Quad read mode 4 instr [0x6b] supported
[00:00:00.118,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] supported
[00:00:00.126,000] <inf> flash_stm32_qspi: Quad read mode 7 instr [0xeb] will be used
[00:00:00.134,000] <inf> flash_stm32_qspi: QE requirement mode: 4
[00:00:00.141,000] <inf> flash_stm32_qspi: Quad mode enabled
[00:00:00.147,000] <dbg> flash_stm32_qspi: setup_pages_layout: layout page 256 not compatible with erase size 4096
[00:00:00.158,000] <dbg> flash_stm32_qspi: setup_pages_layout: erase size will be used as layout page size
[00:00:00.168,000] <dbg> flash_stm32_qspi: setup_pages_layout: layout 8192 x 4096 By pages
[00:00:00.177,000] <dbg> flash_stm32_qspi: flash_stm32_qspi_init: Write Un-protected
[00:00:00.185,000] <inf> flash_stm32_qspi: NOR quad-flash at 0x90000000 (0x2000000 bytes)
*** Booting Zephyr OS build v4.2.0-2084-g0fe091bc4691 ***

W25Q256 SPI flash testing
==========================
SPI_FLASH_TEST_REGION_OFFSET = 0x1000, 4096
SPI_FLASH_SECTOR_SIZE = 0x1000, 4096

Perform test on single sector
Test 1: Flash erase
[00:00:00.215,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.222,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.229,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x20
[00:00:00.236,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x3520
Flash erase succeeded!

Test 2: Flash write
Attempting to write 4 bytes
[00:00:00.280,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.287,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.294,000] <dbg> flash_stm32_qspi: qspi_write_access: Instruction 0x32
[00:00:00.302,000] <dbg> flash_stm32_qspi: qspi_write_access: CCR 0x3003532
Data read matches data written. Good!!

Perform test on multiple consecutive sectors
Test 1: Flash erase
[00:00:00.318,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.326,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.332,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x20
[00:00:00.340,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x3520
[00:00:00.378,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.385,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.392,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x20
[00:00:00.399,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x3520
Flash erase succeeded!

Test 2: Flash write
Attempting to write 4 bytes at offset 0x1000
[00:00:00.444,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.451,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.457,000] <dbg> flash_stm32_qspi: qspi_write_access: Instruction 0x32
[00:00:00.465,000] <dbg> flash_stm32_qspi: qspi_write_access: CCR 0x3003532
Data read matches data written. Good!!
Attempting to write 4 bytes at offset 0x2000
[00:00:00.480,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.487,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.494,000] <dbg> flash_stm32_qspi: qspi_write_access: Instruction 0x32
[00:00:00.501,000] <dbg> flash_stm32_qspi: qspi_write_access: CCR 0x3003532
Data read matches data written. Good!!







尝试读取状态寄存器来判断是否存在部分写保护的情况
WPS bit 位于状态寄存器3中,CMP bit 位于状态寄存器2中,TB、 BP3、 BP2、 BP1、 BP0 位于状态寄存器1中。
你的日志显示是在 0x1000 处发现擦除失败,也就是靠前的位置。
wechat_2025-08-29_145322_462.png

使用非易失性存储器的应用程序必须考虑到噪声和其他可能影响数据完整性的不利系统条件。为解决这一问题,W25Q256JV提供了多种方式来保护数据免受意外写入的影响。
&#61623; 当VCC低于阈值时,器件复位
&#61623; 上电后有延时写禁止功能
&#61623; 写使能/禁止指令,以及擦除或编程后自动写禁止
&#61623; 使用状态寄存器实现软件和硬件(/WP引脚)写保护
&#61623; 用于阵列保护的额外独立块/扇区锁定
&#61623; 使用掉电指令实现写保护
&#61623; 状态寄存器的写保护锁定,直至下一次上电
&#61623; 使用状态寄存器对阵列和安全寄存器进行一次性编程(OTP)写保护*
*注:此功能需特殊订购。详情请联系华邦电子。

在上电或掉电过程中,当VCC低于VWI的阈值时,W25Q256JV将保持复位状态(参见上电时序和电压电平以及图43)。在复位状态下,所有操作均被禁用,且不识别任何指令。上电期间,当VCC电压超过VWI后,所有与编程和擦除相关的指令会再被禁用一段延时tPUW。这包括写使能、页编程、扇区擦除、块擦除、芯片擦除和写状态寄存器指令。请注意,在电源上电期间,直到达到VCC最小值和tVSL延时之前,片选引脚(/CS)必须跟随VCC电源电平变化;在掉电时,它也必须跟随VCC电源电平变化,以防止出现不利的命令序列。如有需要,可在/CS引脚上使用上拉电阻来实现这一点。

上电后,器件会自动进入写禁止状态,状态寄存器的写使能锁存器(WEL)被设置为0。在页编程、扇区擦除、块擦除、芯片擦除或写状态寄存器指令被接受之前,必须先发出写使能指令。完成编程、擦除或写指令后,写使能锁存器(WEL)会自动清零,回到写禁止状态(0)。

通过写状态寄存器指令并设置状态寄存器保护(SRP、SRL)和块保护(CMP、TB、BP[3:0])位,可以实现软件控制的写保护。这些设置可将部分或整个存储阵列配置为只读模式。与写保护(/WP)引脚配合使用时,可在硬件控制下启用或禁用对状态寄存器的更改。有关更多信息,请参见状态寄存器部分。此外,掉电指令提供了额外级别的写保护,因为除释放掉电指令外,所有指令都将被忽略。

W25Q256JV还提供了另一种使用独立块锁定的写保护方法。每个64KB块(顶部和底部块除外,共510个块)以及顶部/底部块内的每个4KB扇区(共32个扇区)都配备有一个独立块锁定位。当锁定位为0时,相应的扇区或块可以被擦除或编程;当锁定位设置为1时,对相应扇区或块发出的擦除或编程命令将被忽略。器件上电时,所有独立块锁定位均为1,因此整个存储阵列都受到保护,防止被擦除/编程。必须发出“独立块解锁(39h)”指令才能解锁任何特定的扇区或块。

状态寄存器3中的WPS位用于决定应使用哪种写保护方案。当WPS=0(出厂默认值)时,器件仅使用CMP、TB、BP[3:0]位来保护阵列的特定区域;当WPS=1时,器件使用独立块锁定进行写保护。

不知道你是不是用的正点原子的这个 QSPI 例程,这个程序只是测试了存储空间的末尾的一小段,因为你的日志显示 0x1000 处发现擦除出问题了。因此也就需要通过检查状态寄存器来判断是否存在部分写保护的问题。
可以尝试更改这个程序进行全片或者部分的(至少是 0x1000 这个位置)的擦写读测试。而且一定要判断擦完后是否是 0xFF
wechat_2025-08-29_151140_992.png





最后还是没有办法的话,尝试更换一片新的 Flash









回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-8-29 21:37:29 | 显示全部楼层
tovinz 发表于 2025-8-29 15:22
配置 qspi flash 部分的 log 输出等级为 debug,查看完整日志
[mw_shl_code=c,true]CONFIG_LOG=y
CONFIG_ ...

是的,我是用的这个例程。我有测试了下这个例程,换了几个地址进行读写测试,发现都是正常的。我决定把原子的这个例程移植到zephyr上试试。看看到底哪里出了问题。
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-9-1 09:04:14 | 显示全部楼层
tovinz 发表于 2025-8-29 15:22
配置 qspi flash 部分的 log 输出等级为 debug,查看完整日志
[C] 纯文本查看 复制代码
CONFIG_LOG=y
CONFIG_ ...[/quote]

从dbg数据看,在我的配置下,erase命令使用是24bit address(CCR为0x2520)。而从你的dbg数据看,erase命令使用的是32bit address(CCR为0x3520)。我看了下正点的代码,他也是32bit address。所以我应该查查为啥我的配置erase命令使用的是24bit address。:L
[mw_shl_code=c,true]Perform test on single sector
Test 1: Flash erase
[00:00:00.259,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x6
[00:00:00.267,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x106
[00:00:00.273,000] <dbg> flash_stm32_qspi: qspi_send_cmd: Instruction 0x20
[00:00:00.280,000] <dbg> flash_stm32_qspi: qspi_send_cmd: CCR 0x2520
Flash erase failed at offset 0xff000 got 0x88
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-9-1 18:47:54 | 显示全部楼层
tovinz 发表于 2025-8-29 15:22
配置 qspi flash 部分的 log 输出等级为 debug,查看完整日志
[C] 纯文本查看 复制代码
CONFIG_LOG=y
CONFIG_ ...[/quote]

确认是这个问题了,地址不是用的32bit导致的。我在init函数里面加上[mw_shl_code=c,true]dev_data->flag_access_32bit = true;

flash测试就通过了
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-9-2 08:51:44 | 显示全部楼层
Ljiangwei 发表于 2025-9-1 18:47
确认是这个问题了,地址不是用的32bit导致的。我在init函数里面加上[mw_shl_code=c,true]dev_data->flag_ ...



这么说,从程序来看,zephyr/drivers/flash/flash_stm32_qspi.c 中的 spi_nor_process_bfp() 函数从 Flash 中读取  JESD216 标准信息,进而确定是否使用 32位地址模式。
而你的日志显示这一段中三个打印一个都没有,感觉是 JESD216 信息读出来驱动没有处理你的这片 Flash 的这一部分的逻辑,可以看一下读取到的 addr_mode 值是多少。
PixPin_2025-09-02_08-46-26.png
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-9-2 09:03:58 | 显示全部楼层
tovinz 发表于 2025-9-2 08:51
这么说,从程序来看,zephyr/drivers/flash/flash_stm32_qspi.c 中的 spi_nor_proces ...

是的。昨晚本来想进调试看看到底是啥。但是vscode的调试配置抽风死活进不了debug。今天晚上再研究研究。
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-9-2 22:13:17 | 显示全部楼层
tovinz 发表于 2025-9-2 08:51
这么说,从程序来看,zephyr/drivers/flash/flash_stm32_qspi.c 中的 spi_nor_proces ...

基本发现问题了。

从你的dbg信息看[00:00:00.030,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.5: 16 DW @ 80。你的w25q256有16个dw,而我的dbg信息看[00:00:00.094,000] <inf> flash_stm32_qspi: PH0: ff00 rev 1.0: 9 DW @ 80,我的w25q256只有9个dw。
这就导致在调用jesd216_bfp_decode_dw16这个函数时,我的直接就返回错误了,因为我的就没有dw16。所以也就没有后面的发送0xB7命令进入32bit address。
我现在不知道这是软件的bug,还是我的w25q256的bug
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-9-2 23:19:26 | 显示全部楼层
Ljiangwei 发表于 2025-9-2 22:13
基本发现问题了。

从你的dbg信息看[00:00:00.030,000]  flash_stm32_qspi: PH0: ff00 rev 1.5: 16 DW  ...

拍一下板子上的flash,看看能不能去GitHub提一个issue
回复

使用道具 举报

2

主题

20

回帖

26

积分

新手上路

积分
26
 楼主| 发表于 2025-9-3 11:34:48 | 显示全部楼层
tovinz 发表于 2025-9-2 23:19
拍一下板子上的flash,看看能不能去GitHub提一个issue

可以尝试一下,感觉这种flash就只能通过读jedec id判断他是哪个型号的flash,然后再初始化了。
回复

使用道具 举报

25

主题

379

回帖

454

积分

高级会员

积分
454
发表于 2025-9-3 14:16:39 | 显示全部楼层
Ljiangwei 发表于 2025-9-3 11:34
可以尝试一下,感觉这种flash就只能通过读jedec id判断他是哪个型号的flash,然后再初始化了。

从我搜索到的资料来看,SDFP 早期确实只有 9个 DW,你的版本号是 1.0,我的是 1.5 的。JESD216 后来也有更新拓展,参数表加长了。

只能说你的 Flash 是早期的库存
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-9-27 05:34 , Processed in 0.063671 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表