ZHCAFK3 July   2025 AM625 , AM62P

 

  1.   1
  2.   摘要
  3.   商标
  4. 1简介
  5. 2访问 SPI NOR 闪存寄存器
    1. 2.1 修改 U-Boot 源代码,以在 U-Boot 控制台中访问 NOR 闪存寄存器
    2. 2.2 修改 MCU Plus 和 RTOS SDK 源代码,以访问 NOR 闪存寄存器
  6. 3调试 NOR 闪存的使用示例
    1. 3.1 在 U-Boot 控制台中读取和写入 NOR Flash 寄存器
    2. 3.2 在 MCU Plus SDK 中读写 NOR Flash 寄存器
  7. 4总结
  8. 5参考资料

修改 U-Boot 源代码,以在 U-Boot 控制台中访问 NOR 闪存寄存器

在 MTD 驱动程序中,添加用于寄存器访问的全局范围函数。在 linux sdk 的 /board-support/ti-u-boot/drivers/mtd/spi/spi/spi-nor-core.c 和 /board-support/ti-u-boot/include/linux/mtd/spi-nor.h 文件中,有两个文件作用域的函数 spansion_read_any_reg() 和 spansion_write_any_reg(),可以执行寄存器访问操作。添加用于包装局部函数的全局作用域函数,以便命令行工具可以使用这些函数。TI 建议将代码添加到源文件的底部。补丁如下代码所示。

diff --git a/drivers/mtd/spi/spi-nor-core.c 
b/drivers/mtd/spi/spi-nor-core.c
index 232a0ac3a9..b532ac6a08 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -4178,3 +4195,24 @@ int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
 
        return (sr >> 2) & 7;
 }
+
+
+#ifdef CONFIG_SPI_FLASH_SPANSION
+ int spi_nor_read_any_reg(struct spi_nor *nor, u32 addr,
+ u8 dummy, u8 *val)
+ {
+ return spansion_read_any_reg(nor, addr, dummy, val);
+ }
+
+ int spi_nor_write_any_reg(struct spi_nor *nor, u32 addr,
+ u8 val)
+ {
+ int ret;
+
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ return spansion_write_any_reg(nor, addr, val);
+ }
+ #endif
diff --git a/include/linux/mtd/spi-nor.h 
b/include/linux/mtd/spi-nor.h
index 2861b73edb..01a651ebeb 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -652,3 +652,10 @@ int spi_nor_remove(struct spi_nor *nor);
 #endif
 #endif
+
+#ifdef CONFIG_SPI_FLASH_SPANSION
+ int spi_nor_read_any_reg(struct spi_nor *nor, u32 addr,
+ u8 dummy, u8 *val);
+ int spi_nor_write_any_reg(struct spi_nor *nor, u32 addr,
+ u8 val);
+ #endif
\ No newline at end of file

使用以下代码,在 U-Boot 控制台中,添加提供寄存器访问的新命令。~/board-support/ti-u-boot/cmd/sf.c 定义可从 U-Boot 使用的 SPI 闪存访问命令,如读取、写入和擦除。do_spi_rdar() 函数响应 rdar 命令执行寄存器读取操作。将命令行参数解析为寄存器地址和虚拟周期数,然后将寄存器值打印到控制台。do_spi_wrar () 执行寄存器写入以响应 wrar 命令。将命令行参数解析为寄存器地址和要写入的新寄存器值。

若要调用这些函数,必须在现有的 do_spi_flash() 函数控制台中插入其他 else-if 块。

diff --git a/cmd/sf.c 
b/cmd/sf.c  
index 11b9c25896..465bf962ec 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -160,6 +160,59 @@ static int do_spi_flash_probe(int argc, char *const argv[])
         return 0;
 }
+static int do_spi_rdar(int argc, char * const argv[])
+        {
+               int ret = 0;
+               loff_t ofs;
+               ulong dummy;
+               u8 val;
+                if (argc != 3)
+                return -1;
+                if (!str2off(argv[1], &ofs)) {
+                puts("register address is not a valid number\n");
+                return 1;
+               }
+               if (!str2long(argv[2], &dummy)) {
+                puts("register address is not a valid number\n");
+               return 1;
+                }
+                ret = spi_nor_read_any_reg(flash, ofs, (u8)dummy, &val);
+                if (ret == 0)
+                printf("%02X\n", val);
+                else
+                puts("failed to read register\n");
+                return ret == 0 ? 0 : 1;
+        }
+       static int do_spi_wrar(int argc, char * const argv[])
+       {
+               int ret = 0;
+               loff_t ofs;
+                ulong val;
+               if (argc != 3)
+                return -1;
+               if (!str2off(argv[1], &ofs)) {
+               puts("register address is not a valid number\n");
+               return 1;
+                }
+               if (!str2long(argv[2], &val)) {
+               puts("val is not a valid number\n");
+               return 1;
+                }
+                ret = spi_nor_write_any_reg(flash, ofs, (u8)val);
+
+               return ret == 0 ? 0 : 1;
+       }
 /**
  * Write a block of data to SPI flash, first checking if it is different from
@@ -603,6 +656,10 @@ static int do_spi_flash(struct cmd_tbl *cmdtp, int flag, int argc,
                ret = do_spi_protect(argc, argv);
        else if (IS_ENABLED(CONFIG_CMD_SF_TEST) && !strcmp(cmd, "test"))
                ret = do_spi_flash_test(argc, argv);
+       else if (strcmp(cmd, "rdar") == 0)
+  ret = do_spi_rdar(argc, argv);
+ else if (strcmp(cmd, "wrar") == 0)
+ ret = do_spi_wrar(argc, argv);
        else
                ret = CMD_RET_USAGE;

此外,要添加一些要打印到控制台的调试日志,请使用以下代码作为参考来打印 opcode、nbytes、buswidth、dtr,dummy.nbytes 参数,以实现更高效的调试。

diff --git a/drivers/mtd/spi/spi-nor-core.c 
b/drivers/mtd/spi/spi-nor-core.c
index 232a0ac3a9..b532ac6a08 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -335,6 +335,17 @@ static int spansion_read_any_reg(struct spi_nor *nor, u32 addr, u8 dummy,
                           SPI_MEM_OP_DUMMY(dummy / 8, 1),
                           SPI_MEM_OP_DATA_IN(1, NULL, 1));
 
+ printf("*** [%s] [%d] op.cmd.opcode= [%d]\n",__func__,__LINE__, op.cmd.opcode);
+        printf("*** [%s] [%d] op.cmd.nbytes= [%d]\n",__func__,__LINE__, op.cmd.nbytes);
+         printf("*** [%s] [%d] op.cmd.buswidth= [%d]\n",__func__,__LINE__, op.cmd.buswidth);
+          printf("*** [%s] [%d] op.cmd.dtr= [%d]\n",__func__,__LINE__, op.cmd.dtr);
+
+
+//        printf("*** [%s] [%d] op.addr.val= [%d]\n",__func__,__LINE__, op.addr.val);
+        printf("*** [%s] [%d] op.dummy.nbytes= [%d]\n",__func__,__LINE__, op.dummy.nbytes);
+
+
+
        return spi_nor_read_write_reg(nor, &op, val);
 }
 
@@ -414,6 +425,12 @@ static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
                op.data.buf.in += op.data.nbytes;
        }
 
+      printf("*** [%s] [%d] op.cmd.opcode= [%d]\n",__func__,__LINE__, op.cmd.opcode);
+          printf("*** [%s] [%d] op.cmd.nbytes= [%d]\n",__func__,__LINE__, op.cmd.nbytes);
+           printf("*** [%s] [%d] op.cmd.buswidth= [%d]\n",__func__,__LINE__, op.cmd.buswidth);
+            printf("*** [%s] [%d] op.cmd.dtr= [%d]\n",__func__,__LINE__, op.cmd.dtr);
+            printf("*** [%s] [%d] op.dummy.nbytes= [%d]\n",__func__,__LINE__, op.dummy.nbytes);
+
        return len;
 }

若要将模式更改为 1 行模式,请将闪存保持在尽可能低的设置值。可以应用以下代码;此项更改可选。以下代码是基于 AM64 SDK 的示例。

diff --git a/arch/arm/dts/k3-am642-evm.dts 
b/arch/arm/dts/k3-am642-evm.dts
index 7f82730736..76d660a561 100644
--- a/arch/arm/dts/k3-am642-evm.dts  
+++ b/arch/arm/dts/k3-am642-evm.dts
@@ -463,8 +463,8 @@
        flash@0 {
                compatible = "jedec,spi-nor";
                reg = <0x0>;
-               spi-tx-bus-width = <8>;
-               spi-rx-bus-width = <8>;
+               spi-tx-bus-width = <1>;
+               spi-rx-bus-width = <1>;
                spi-max-frequency = <25000000>;
                cdns,tshsl-ns = <60>;
                cdns,tsd2d-ns = <60>;
diff --git a/arch/arm/dts/k3-am642-r5-evm.dts 
b/arch/arm/dts/k3-am642-r5-evm.dts
index 6b32be1c4c..482f1ef639 100644
--- a/arch/arm/dts/k3-am642-r5-evm.dts  
+++ b/arch/arm/dts/k3-am642-r5-evm.dts
@@ -308,8 +308,8 @@
        flash@0{
                compatible = "jedec,spi-nor";
                reg = <0x0>;
-               spi-tx-bus-width = <8>;
-               spi-rx-bus-width = <8>;
+               spi-tx-bus-width = <1>;
+               spi-rx-bus-width = <1>;
                spi-max-frequency = <25000000>;
                cdns,tshsl-ns = <60>;
                cdns,tsd2d-ns = <60>;
diff --git a/arch/arm/dts/k3-am642-r5-sk.dts 
b/arch/arm/dts/k3-am642-r5-sk.dts
index 6701e754bb..815dd5cb9b 100644
--- a/arch/arm/dts/k3-am642-r5-sk.dts
+++ b/arch/arm/dts/k3-am642-r5-sk.dts
@@ -290,8 +290,8 @@
        flash@0{
                compatible = "jedec,spi-nor";
                reg = <0x0>;
-               spi-tx-bus-width = <8>;
-               spi-rx-bus-width = <8>;
+               spi-tx-bus-width = <1>;
+               spi-rx-bus-width = <1>;
                spi-max-frequency = <25000000>;
                cdns,tshsl-ns = <60>;
                cdns,tsd2d-ns = <60>;
diff --git a/arch/arm/dts/k3-am642-sk.dts 
b/arch/arm/dts/k3-am642-sk.dts
index cbb10a4964..b2ee7e6965 100644
--- a/arch/arm/dts/k3-am642-sk.dts
+++ b/arch/arm/dts/k3-am642-sk.dts
@@ -482,8 +482,8 @@
        flash@0 {
                compatible = "jedec,spi-nor";
                reg = <0x0>;
-               spi-tx-bus-width = <8>;
-               spi-rx-bus-width = <8>;
+               spi-tx-bus-width = <1>;
+               spi-rx-bus-width = <1>;
                spi-max-frequency = <25000000>;
                cdns,tshsl-ns = <60>;
                cdns,tsd2d-ns = <60>;