加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

i.MXRTXXX系列OTP及其烧写方法

2019/12/16
355
阅读需 13 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

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-MCUBootUtilitytoolsblhost2_3win> .blhost.exe

usage: D:NXP-MCUBootUtilitytoolsblhost2_3winblhost.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-MCUBootUtilitytoolsblhost2_3win> .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-MCUBootUtilitytoolsblhost2_3win> .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,必须复位芯片。

相关推荐

电子产业图谱

硕士毕业于苏州大学电子信息学院,目前就职于恩智浦(NXP)半导体MCU系统部门,担任嵌入式系统应用工程师。痞子衡会定期分享嵌入式相关文章