• 痞子衡嵌入式:恩智浦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总地址空间有16Kbit(地址范围为0x000 - 0x7FF),分为64个BANK,每个BANK含8个word(1word = 4bytes)。下图中4、8、9(总范围是0x000 - 0x1FF)是OTP word索引地址(也叫index地址),其与OTP空间地址对应关系是:

    otp_address = otp_index * 0x4

      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	oolslhost2_3win> .lhost.exe
    usage: D:NXP-MCUBootUtility	oolslhost2_3winlhost.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 oolslhost2_3win> .lhost.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 oolslhost2_3win> .lhost.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痞子衡便介绍完毕了,掌声在哪里~~~

    欢迎订阅

    文章会同时发布到我的 博客园主页CSDN主页微信公众号 平台上。

    微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

  • 相关阅读:
    ruby -- 进阶学习(十三)解说ckeditor在production环境下如何完整显示
    ruby -- 进阶学习(十二)fragment cache
    ruby -- 进阶学习(十一)配置解决production环境下无法加载css或js
    ruby -- 问题解决(六)link_to to destroy not working
    ruby -- 基础学习(七)时间的内置函数和格式说明
    ruby -- 进阶学习(十)自定义路由中:new, :collection和:member的区别
    ruby -- 进阶学习(九)定制错误跳转404和500
    C++ -- STL泛型编程(二)之set
    SVN库文件上传操作步骤
    jmeter 正则表达式基础语法
  • 原文地址:https://www.cnblogs.com/henjay724/p/11995128.html
Copyright © 2020-2023  润新知