Openwrt读取spi-nand协议Flash芯片UniqueID(华邦为例)

这篇具有很好参考价值的文章主要介绍了Openwrt读取spi-nand协议Flash芯片UniqueID(华邦为例)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Flash芯片一般都有一个出厂时由制造商设定的Unique ID,唯一ID。获取到可以用来进行各类加密识别认证,作为设备唯一ID的一种。
本文以华邦品牌的flash芯片为例(W25N01GV、W25M02GV),如何在Linux下读取该ID。

阅读芯片手册,了解读取步骤

一般Unique ID信息都存放在otp区域里,otp区域是芯片上一块特殊的区域,读取前需要进行模式切换,具体切换流程需要阅读芯片手册,每个厂家都不一样。
flash uid,OpenWrt,嵌入式硬件,c语言,硬件工程,物联网
在目录里,找到读取的相关页面
flash uid,OpenWrt,嵌入式硬件,c语言,硬件工程,物联网
阅读文档可以得知,winbond这款芯片otp区域有十页,其中第一页就存放的Unique ID。
读取需要修改状态寄存器的OTP-E位,且读取完成后需要复位。否则会影响正常区域的读写。

下面给出patch

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
old mode 100644
new mode 100755
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -48,6 +48,33 @@ static int spinand_read_status(struct spinand_device *spinand, u8 *status)
 	return spinand_read_reg_op(spinand, REG_STATUS, status);
 }
 
+static int spinand_read_status_reg2(struct spinand_device *spinand, u8 *status)
+{
+	return spinand_read_reg_op(spinand, REG_CFG, status);
+}
+
+static int spinand_read_write_status_reg2(struct spinand_device *spinand, int otp_en_flag)
+{
+	u8 val = 0;
+
+	spinand_read_status_reg2(spinand, &val);
+
+	if (otp_en_flag == 0)
+		val &= CFG_OTP_DISABLE;
+	else
+		val |= CFG_OTP_ENABLE;
+
+	spinand_write_reg_op(spinand, REG_CFG, val);
+
+	// reset val
+	val = 0;
+	spinand_read_status_reg2(spinand, &val);
+
+	return 0;
+}
+
 static int spinand_get_cfg(struct spinand_device *spinand, u8 *cfg)
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
@@ -1048,6 +1075,105 @@ static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
 	.free = spinand_noecc_ooblayout_free,
 };
 
+static int spinand_unique_id_read(void *priv, u8 *buf, int readlen) {
+	int ret;
+	u8 status;
+	struct spinand_device *spinand = (struct spinand_device *)priv;
+	struct device *dev = &spinand->spimem->spi->dev;
+	u32 addr[5]= {0x00,0x00,0x00,0x00,0x00};
+	int addrlen = 5;
+
+	typedef struct nand_pos my_pos;
+	my_pos pos;
+	typedef struct nand_page_io_req my_req;
+	my_req req;
+
+	if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) {
+		dev_err(dev, "Must provide correct addr(length) for spinand calibration\n");
+		return -EINVAL;
+	}
+
+
+	if (ret)
+		return ret;
+
+	/* We should store our golden data in first target because
+	 * we can't switch target at this moment.
+	 */
+	pos = (my_pos){
+		.target = 0,
+		.lun = *addr,
+		.plane = *(addr+1),
+		.eraseblock = *(addr+2),
+		.page = *(addr+3),
+	};
+
+	req = (my_req){
+		.type = NAND_PAGE_READ,
+		.pos = pos,
+		.dataoffs = *(addr+4),
+		.datalen = readlen,
+		.databuf.in = buf,
+		.mode = MTD_OPS_AUTO_OOB,
+	};
+
+	ret = spinand_load_page_op(spinand, &req);
+	if (ret)
+		return ret;
+
+	ret = spinand_wait(spinand, &status);
+	if (ret < 0)
+		return ret;
+
+	{
+		//struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen);
+		struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, buf, readlen);
+		ret = spi_mem_exec_op(spinand->spimem, &op);
+	}
+
+	return 0;
+}
+
+static int spi_nand_unique_id(struct spinand_device *spinand)
+{
+	int ret = 0;
+	u8 *buf;
+	int readlen = 32;
+
+	buf = kzalloc(readlen, GFP_KERNEL);
+	if(!buf){
+		printk("%s-%d; ERROR - kzalloc func: Insufficient memory allocation failed;\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	// set Status Register-2, open OTP mode
+	spinand_read_write_status_reg2(spinand, 1);
+
+	spinand_unique_id_read(spinand, buf, readlen);
+
+	// copy spinand->uid from buf
+	memcpy(spinand->uid, buf, sizeof(spinand->uid));
+
+	// reset Status Register-2, close OTP mode
+	spinand_read_write_status_reg2(spinand, 0);
+
+	kfree(buf);
+
+	return 0;
+}
+
 static int spinand_init(struct spinand_device *spinand)
 {
 	struct device *dev = &spinand->spimem->spi->dev;
@@ -1094,6 +1220,16 @@ static int spinand_init(struct spinand_device *spinand)
 	if (ret)
 		goto err_free_bufs;
 
+	// init spinand->uid
+	memset(spinand->uid, 0, sizeof(spinand->uid));
+	// try read flash-chip unique ID
+	if(spi_nand_unique_id(spinand) == 0){
+		// sync uniqiue id
+		mtd->chip_uid = spinand->uid;
+	}
+
 	ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0);
 	if (ret)
 		goto err_free_bufs;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
old mode 100644
new mode 100755
index fabd98fe69ad2eeeed2e0b4bec0c5f39a7534320..61531db9ae2c4cd886a1e5863ed7146b8ed48337
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -155,6 +155,7 @@
 #define CFG_OTP_ENABLE		BIT(6)
 #define CFG_ECC_ENABLE		BIT(4)
 #define CFG_QUAD_ENABLE		BIT(0)
+#define CFG_OTP_DISABLE		(~(BIT(6)))
 
 /* status register */
 #define REG_STATUS		0xc0
@@ -361,6 +362,14 @@ struct spinand_dirmap {
 	struct spi_mem_dirmap_desc *rdesc;
 };
 
+/*
+ * SPINAND unique ID length and number of repetitions. The full unique ID is the
+ * manufacturer ID (1B) plus the unique device ID (16B). Also count the '-'
+ * between both IDs and the '\0' at the end in the 'STRING_LEN'.
+ */
+#define SPINAND_UNIQUEID_LEN       16
+
 /**
  * struct spinand_device - SPI NAND device instance
  * @base: NAND device instance
@@ -386,6 +395,7 @@ struct spinand_dirmap {
  *		the stack
  * @manufacturer: SPI NAND manufacturer information
  * @priv: manufacturer private data
+ * @uid: Unique ID of the flash chip (add by IKUAI)
  */
 struct spinand_device {
 	struct nand_device base;
@@ -414,6 +424,9 @@ struct spinand_device {
 	u8 *scratchbuf;
 	const struct spinand_manufacturer *manufacturer;
 	void *priv;
+	u8 uid[SPINAND_UNIQUEID_LEN];
 };
 
 /**

代码存在优化空间,且可以使用linux内核原生的自带寄存器更新函数 spinand_upd_cfg 实现,只是该函数传参有坑,需要注意。文章来源地址https://www.toymoban.com/news/detail-687129.html

到了这里,关于Openwrt读取spi-nand协议Flash芯片UniqueID(华邦为例)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【小米路由器3】breed刷机救砖-nand flash硬改SPI flash-编程器救砖(解决ttl无法救砖问题)

    大家好,我是老子姓李!(gzh:楠瘦) 本博文带来 【小米路由器3】变砖,ttl无法救砖,硬改焊接一块SPI flash,使用编程器刷入小米路由器mini的breed最终成功救砖 。 1.引言 1.1 背景 个人嫌弃小米路由器的自带固件不够好用,觉得网速又慢、不够稳定,而且不能装插件。本着

    2024年02月09日
    浏览(218)
  • 【FLASH存储器系列五】SPI NOR FLASH芯片使用指导之一

    👉个人主页: highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容   目录 1芯片简介 2引脚定义 3功能框图 4器件操作 4.1操作框图 4.2标准SPI 4.3DaulSPI 4.4QaudSPI 4.5QPI 4.6DTR(W25Q128不支持) 4.73-字节/4-字节地址模式(W25Q128只支持3字节) 4.8保持

    2023年04月19日
    浏览(48)
  • FPGA模块——SPI协议(读写FLASH)

    芯片引脚图: 内部结构图: 存储区域总共分成了32块,每块64KB。每块又分成了16个部分,每个部分4KB。方便进行读取和局部操作。 电路设计 SPI的四种模式 这里使用这个模式: 主机和从机在时钟上升沿放入要输出的数据,在时钟下降沿读取要输入的数据。 8个时钟后交换一个

    2024年02月05日
    浏览(48)
  • FPGA实现基于SPI协议的Flash驱动控制(全擦除、页擦除、读数据、页写、连续写—地址写)

    本论文使用Verilog HDL硬件描述语言,结合野火可以FPGA征途Pro开发板,实现了SPI通信协议的全擦除,扇区擦除,读数据,页写,连续写的驱动设计。在 Altera Cyclone Ⅳ 芯片上采用“自顶向下”的模块化设计思想及 Verilog HDL 硬件描述语言,设计并实现串行外设接口(SPI)。在 Qu

    2024年02月12日
    浏览(50)
  • 【STM32学习】——SPI通信协议&SPI时序&W25Q64存储芯片&软件SPI读写

    目录 前言 一、SPI通信协议 1.概述​ 2.硬件电路  3.移位示意图 二、SPI时序 1.时序基本单元 2.完整时序波形 三、W25Q64存储芯片 1.芯片简介  2.硬件电路引脚定义  3.芯片框图 4.Flash操作注意事项 四、软件SPI读写W25Q64 五、SPI通信外设 总结 声明:学习笔记来自江科大自化协B站教

    2024年02月09日
    浏览(62)
  • [NAND Flash 6.4] NAND FLASH基本读操作及原理_NAND FLASH Read Operation源码实现

    依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 返回总目录 ​全文 6000 字 内容摘要 NAND Flash 引脚功能 读操作步骤 NAND Flash 中的特殊硬件结构 NAND Flash 读写时的数据流向 Read 操作时序 读时序操作过程的解释 Read 操作实战流程设计 NAND Read 源码 前言 上面

    2024年01月19日
    浏览(38)
  • DSP28335使用SPI从AD2S1210(旋变芯片)读取位置

    精准的转子位置对于电机精确控制来说至关重要,利用旋转变压器获取转子位置角度是一种常见方案。因此在电控程序中只需要通过主控芯片(以 DSP28335 为例)与旋变解码芯片(以 AD2S1210 为例)进行通信(以 SPI通信 为例)。 在实际操作中,通过SPI从旋变芯片读取绝对位置时,读取

    2024年02月13日
    浏览(42)
  • [NAND Flash 6.3] NAND FLASH基本编程(写)操作及原理_NAND FLASH Program Operation 源码实现

    依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 返回总目录 全文 3244 字 ​ 前言 使用的 NAND FLASH 的硬件原理图,面对这些引脚,很难明白他们是什么含义,下面先来个热身: 问1. 原理图上 NAND FLASH 只有数据线,怎么传输地址? 答1. 在 DATA0~DATA7 上既传

    2024年01月19日
    浏览(35)
  • 【SDN】普通路由器刷OpenWrt+OpenFlow教程完美版_搭建SDN OpenFlow1.3协议的路由器(Flash<16M)

    Email:louis.yyj.dev@foxmail.com 刷机前请确认你的路由器支持OpenWrt,并确定Flash大小,具体方法请进入下面的网址,在Model一栏中输入

    2024年02月09日
    浏览(44)
  • STM32模拟SPI时序配置读取双路24位模数转换(24bit ADC)芯片ADS1220采样数据

    TI公司的双路24位模数转换芯片ADS1220具有比较丰富的模式配置,双路差分输入采样也可以配置为4路单端输入信号采样。有多种参考电压源可选,内部增益(从1倍到128倍)和输出率(可达到2K/s)可配置,模拟电压和数字电路电压可单独设置等等。这里介绍STM32访问和读取ADS12

    2023年04月09日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包