痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法

2023-12-21 11:18

本文主要是介绍痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的OTP

  在i.MXRTxxx启动系列第二篇文章 Boot配置(ISP Pin, OTP) 里痞子衡提到了OTP,部分Boot配置都存储在OTP memory里,但是对OTP的介绍仅仅浅尝辄止,没有深入,今天痞子衡就为大家再进一步介绍OTP。

  OTP是i.MXRTxxx里一块特殊的存储区域,用于存放全部芯片配置信息,其中有一部分配置信息和Boot相关。这块特殊存储区域并不在ARM的4G system address空间里,需要用特殊的方式去访问(读/写),如何访问OTP是本篇文章的重点。

一、OTP基本原理

1.1 OTP属性(OTP, Shadow Lock)

  OTP本质上就是i.MXRTxxx内嵌的一块One Time Programmable memory,仅可被烧写一次,但可以被多次读取。OTP memory的烧写大部分是按Word进行的(也有极少部分是按Bit进行的),初始状态下所有OTP bit均为0,通过特殊的烧写时序可以将bit从0改成1,一旦某bit被烧写成1后便再也无法被修改(可理解为硬件熔丝烧断了无法恢复)
  i.MXRT600的OTP memory总地址空间有2KB(word index范围为0x000 - 0x1FF),分为64个BANK,每个BANK含8个word(1word = 4bytes)。
  OTP memory空间除了OTP特性外,还有Shadow Lock控制特性,Shadow Lock控制是OTP memory的标配,Lock控制有二种:第一种是WP,即写保护,用于保护OTP区域对应的shadow register不能被改写;第二种是RP,即读保护,被保护的OTP区域对应的shadow register不能被读取。看到这里,你会发现i.MXRTyyyy的efuse里的LOCK控制是同时针对efuse本身和shadow register的;而i.MXRTxxx的OTP里的LOCK控制仅针对shadow register,那么对OTP本身的保护在哪里呢?先别急,后面会给你答案。
  Shadow Lock控制在OTP的BANK0_word4、BANK1_word8/9,如下是RT600具体Lock bit定义:

关于OTP空间所有bit定义详见Reference Manual里的otpmap Descriptions。

1.2 OCOTP控制器与Shadow Register

  i.MXRTxxx内部有一个硬件IP模块叫OCOTP_CTRL,即OCOTP控制器,对OTP memory的读写控制操作其实都是通过这个OCOTP控制器实现的,下图是OCOTP_CTRL模块图:

  OCOTP_CTRL模块寄存器一共分两类:一类是IP控制寄存器,用于实现对OTP memory的读写操作时序控制;一类是Shadow register,用于上电时自动从OTP memory获取数据并缓存,这样我们可以直接访问Shadow register而不用访问OTP memory也能获取OTP内容(注意:当芯片运行中烧写OTP,Shadow register的值并不会立刻更新,需要执行IP控制器的reload命令或者将芯片reset才能同步)。
  下图是RT600里的OCOTP_CTRL模块寄存器map,其中Shadow register寄存器偏移地址范围是0x000 - 0x7FF(注意并不是所有OTP Word都会被加载到Shadow register里,虽然Shadow register预留了全部的OTP位置。这点与i.MXRTyyyy efuse会全部加载到Shadow register不同,原因是i.MXRTxxx的OTP里会有很多Peripheral寄存器加载初值,如果这些OTP值目的是加载Peripheral,那就没有必要再加载到Shadow register里,而i.MXRTyyyy的efuse值没有加载Peripheral寄存器的用途)。IP控制寄存器偏移地址范围是0x800 - 0x82C:

  痞子衡写过关于i.MXRTyyyy的eFUSE烧写的文章 飞思卡尔i.MX RTyyyy系列MCU启动那些事(5)- 再聊eFUSE及其烧写方法 ,其实i.MXRTxxx的OCOTP控制器与i.MXRTyyyy里的OCOTP控制器非常相似,虽然两者在寄存器组织上有差异,但其共同点更多。不过提及差异,有一个地方痞子衡不得不提,那就是CTRL寄存器的bit15,在i.MXRTyyyy上这个bit是保留的,但是i.MXRTxxx上这个bit为WORDLOCK,顾名思义即提供对操作的OTP word区域进行保护(主要是写保护),下一节介绍的efuse-program-once命令第三个可选参数[nolock/lock]其实就是利用了这个bit

二、使用blhost烧写OTP

  OTP memory的烧写是通过OCOTP_CTRL模块来实现的,我们当然可以在Application中集成OCOTP_CTRL的驱动程序,然后在Application调用OCOTP_CTRL的驱动程序完成OTP的烧写,但这种方式并不是痞子衡要介绍的重点,痞子衡要介绍的是通过Serial ISP模式配套的blhost.exe上位机工具实现OTP的烧写。
  痞子衡在前面的文章里介绍过如何进入Serial ISP模式与BootROM通信,此处假设你已经使用blhost与BootROM建立了通信。让我们再来回顾一下blhost的命令help,可以得知efuse-program-once这个命令就是我们想要的命令。

PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe
usage: D:\NXP-MCUBootUtility\tools\blhost2_3\win\blhost.exe[-p|--port <name>[,<speed>]][-u|--usb [[[<vid>,]<pid>]]]-- command <args...>Command:efuse-program-once <addr> <data> [nolock/lock]Program one word of OCOTP Field<addr> is ADDR of OTP word, not the shadowed memory address.<data> is hex digits without prefix '0x'efuse-read-once <addr>Read one word of OCOTP Field<addr> is ADDR of OTP word, not the shadowed memory address.

  让我们试一下efuse-program-once这个命令,开始试之前要解决2个问题:
  addr参数到底是什么地址?帮助里说是OTP word address,其实这个地址就是1.1节里介绍的word index,index范围为0x000 - 0x1FF,对应512个可读写操作的OTP Word。
  data参数到底是什么格式?帮助里说是hex digits without prefix '0x',但是似乎没有指明长度,我们知道每一个index对应的是4byte,那就应该是8位16进制数据(实测下来必须要填8位,如果是非8位会返回Error: invalid command or arguments)。
  弄清了问题,那我们做一个小测试:要求将OTP里的REVOKE_IMG_KEY word的最低byte烧写成0x5A。翻看OTP Memory Footprint表,找到REVOKE_IMG_KEY的index地址是0x66(对应Shadow register地址是0x40130198),命令搞起来:

PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe -u -- efuse-program-once 0x66 0000005A

Inject command 'efuse-program-once'
Successful generic response to command 'efuse-program-once'
Response status = 0 (0x0) Success.

PS D:\NXP-MCUBootUtility\tools\blhost2_3\win> .\blhost.exe -u -- efuse-read-once 0x66

Inject command 'efuse-read-once'
Response status = 0 (0x0) Success.
Response word 1 = 4 (0x4)
Response word 2 = 90 (0x5a)

  看起来命令执行正常,如果此时你用J-Link去读取对应Shadow register的值,你会发现刚才烧写的OTP数据并没有自动同步更新到Shadow register里。与i.MXRTyyyy系列下Flashloader里efuse program操作有所不同的是,i.MXRTxxx Serial ISP模式下blhost里的efuse-program-once命令仅包含program命令,没有集成reload命令。因此想要刷新Shadow register,必须复位芯片

  至此,恩智浦i.MX RTxxx系列MCU的OTP痞子衡便介绍完毕了,掌声在哪里~~~

这篇关于痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU启动那些事(4)- OTP及其烧写方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/519769

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

Window Server2016加入AD域的方法步骤

《WindowServer2016加入AD域的方法步骤》:本文主要介绍WindowServer2016加入AD域的方法步骤,包括配置DNS、检测ping通、更改计算机域、输入账号密码、重启服务... 目录一、 准备条件二、配置ServerB加入ServerA的AD域(test.ly)三、查看加入AD域后的变

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python中使用defaultdict和Counter的方法

《Python中使用defaultdict和Counter的方法》本文深入探讨了Python中的两个强大工具——defaultdict和Counter,并详细介绍了它们的工作原理、应用场景以及在实际编... 目录引言defaultdict的深入应用什么是defaultdictdefaultdict的工作原理

使用Python进行文件读写操作的基本方法

《使用Python进行文件读写操作的基本方法》今天的内容来介绍Python中进行文件读写操作的方法,这在学习Python时是必不可少的技术点,希望可以帮助到正在学习python的小伙伴,以下是Pyth... 目录一、文件读取:二、文件写入:三、文件追加:四、文件读写的二进制模式:五、使用 json 模块读写

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,