请选择 进入手机版 | 继续访问电脑版
查看: 1165|回复: 2

[分享] OTFAD加密启动失败?先去检查系统时钟配置

[复制链接]
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3297

    主题

    6542

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    31909
    最后登录
    2024-3-29
    发表于 2021-3-4 14:32:30 | 显示全部楼层 |阅读模式
    OTFAD加密启动失败?先去检查系统时钟配置


    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是系统时钟配置不当会导致i.MXRT1xxx系列下OTFAD加密启动失败问题。


    我们知道,i.MXRT1xxx家族早期型号(RT1050/RT0160/RT1020)的硬件解密外设名字叫BEE,这个外设主要是配合FlexSPI外设去实现外接串行NOR Flash在线解密XIP执行用的。而到了最近的i.MXRT1xxx新型号(RT1010/RT1170)上,BEE外设被替换成了OTFAD外设,功能不变,解密效率得到了很大提升,但客户在使能OTFAD加密启动时常常遇到App无法正常运行问题,这其实跟OTFAD自身的一个时钟小限制有关(这个限制在BEE上不存在),今天痞子衡就来好好聊一聊OTFAD的这个小限制:


    一、问题描述
    我们以i.MXRT1010为例,从恩智浦官网下载一个SDK包(痞子衡下的是v2.9.1),随便选择其中一个例程,就以最简单的 \SDK\boards\evkmimxrt1010\demo_apps\led_blinky 为例吧。编译这个 led_blinky 工程(选择 flexspi_nor_debug build,即XIP工程),得到可执行文件(实际bin文件大小为10KB左右),使用 NXP-MCUBootUtility 工具将可执行文件(led_blinky.out)下载进MIMXRT1010-EVK开发板中(下载时启动模式为2'b01,启动时切换到2'b10),可以看到板载绿色LED小灯(D25)会闪,例程是可以正常工作的。
    21.png
    现在让我们尝试使能OTFAD加密,回到芯片下载模式依然借助 NXP-MCUBootUtility 工具,将工具 Secure boot type 选项切换为 OTFAD Encrypted Image Boot,其他设置均默认(此时加密范围是 0x60001000 - 0x60001fff,仅加密IVT等启动头,不含app),再次下载可执行文件(led_blinky.out),换到芯片启动模式复位板子,例程依旧是正常工作的,看起来OTFAD加密启动似乎没有问题。

    让我们再进一步,将加密范围设置为0x60002000 - 0x60004fff,这时加密区域覆盖到了整个app,重新按上述流程操作一遍,发现例程没能正常工作,这时候OTFAD加密启动出了问题,难道app区域不能被加密?那OTFAD加密还有啥意义?
    22.png
    app区域当然可以被加密,跟着痞子衡再做一次实验,在 led_blinky.c 文件的 main() 函数中,我们将时钟配置函数 BOARD_BootClockRUN() 直接注释掉或者在链接文件里将其全部搞成 __ramfunc(即在芯片内部RAM里执行这部分时钟配置代码),这个例程仅是利用SysTick定时翻转GPIO,因此时钟配置代码去掉不影响正常运行,重新编译工程再按上面流程操作一遍,这时候例程又能正常工作了,说明加密后的app是能被OTFAD正常解密执行的。
    23.png
    现在的问题变成了为何OTFAD加密启动时,BOARD_BootClockRUN() 函数不能在Flash里执行,这就是问题所在。


    二、原因分析
    关于上述问题的原因,痞子衡先直接给答案,这是OTFAD外设本身的时钟小限制,当OTFAD被使能时,如果被加密的app代码是XIP执行,app里做系统时钟配置时要始终保证Core时钟高于FlexSPI外设时钟。如果Core时钟低于FlexSPI时钟,此时Core去访问加密Flash区域,OTFAD无法正常解密,会导致指令错乱,发生系统故障。
    24.png
    我们配合上面的i.MXRT1010系统时钟树来认真分析下OTFAD这个时钟限制问题。芯片上电总是从BootROM执行,BootROM会先将Core配置到396MHz,将FlexSPI时钟根据用户放置在Flash偏移0x400处的FDCB里的设定配到30MHz - 200MHz不等,再读取Flash偏移0地址处OTFAD DEK KeyBlob数据使能OTFAD,然后读取IVT等头信息去跳转到App。很显然只加密IVT部分根本不受OTFAD限制的影响,这部分解析是在BootROM里完成的,BootROM里时钟配置符合OTFAD时钟限制要求。
    1. // BootROM里对Core时钟配置
    2. CCM_ANALOG->PFD_528[PFD3_FRAC] = 24,   PLL2 PFD3输出 (528MHz * 18) / 24 = 396MHz
    3. CCM->CBCMR[PRE_PERIPH_CLK_SEL] = 2,    时钟来自PLL2 PFD3
    4. CCM->CBCDR[PERIPH_CLK_SEL]     = 0,   内核时钟来自CCM->CBCMR[PRE_PERIPH_CLK_SEL]
    5. CCM->CBCDR[AHB_PODF]           = 0,   内核时钟不分频

    6. // BootROM里对FlexSPI时钟配置
    7. CCM_ANALOG->PFD_480[PFD0_FRAC] = x,    PLL3 PFD0输出 (480MHz * 18) / x
    8. CCM->CSCMR1[FLEXSPI_CLK_SEL]   = 3,    时钟来自PLL3 PFD0
    9. CCM->CSCMR1[FLEXSPI_CLK_SRC]   = 0,   FlexSPI时钟来自CCM->CSCMR1[FLEXSPI_CLK_SEL]
    10. CCM->CSCMR1[FLEXSPI_PODF]      = y,   FlexSPI时钟做(y+1)分频
    复制代码
    当BootROM跳转到了App之后,我们再来看看App里对时钟是怎么配置的,就是BOARD_BootClockRUN()函数,可以看到这个函数里将内核频率从BootROM设置的396MHz切换到外部OSC 24MHz。无论此时用户FDCB里对FlexSPI时钟是多少配置,至少也会大于30MHz,那么此时24MHz内核频率一定会低于FlexSPI时钟频率,此时只要发生内核对Flash加密区域的访问(时钟配置代码就在Flash里执行),就触发了OTFAD时钟限制问题,App就会跑飞。
    25.png
    三、解决方案

    知道了原因,解决方案就简单了,在App时钟配置里,不要按照寻常套路去先将内核时钟源切换到外部OSC再切到PLL,而是直接切到PLL上。比如i.MXRT1010内部有个PLL6(也叫Audio PLL),固定500MHz,正好是App要的最终内核频率,我们在BOARD_BootClockRUN()里将Audio(Enet) PLL初始化设置代码提到前面,删掉原来的切换OSC设置代码即可。
    1. void BOARD_BootClockRUN(void)
    2. {
    3.     // 此处略去...
    4.     /* Set Oscillator ready counter value. */
    5.     CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127);
    6. -    /* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */
    7. -    CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */
    8. -    CLOCK_SetMux(kCLOCK_PeriphMux, 1);     /* Set PERIPH_CLK MUX to PERIPH_CLK2 */

    9.     // 此处略去...
    10.     /* Set IPG_PODF. */
    11.     CLOCK_SetDiv(kCLOCK_IpgDiv, 3);
    12. +     /* Init Enet PLL. */
    13. +    CLOCK_InitEnetPll(&enetPllConfig_BOARD_BootClockRUN);
    14. +    /* Set preperiph clock source. */
    15. +    CLOCK_SetMux(kCLOCK_PrePeriphMux, 3);

    16.     // 此处略去...
    17.     /* Enable Audio PLL output. */
    18.     CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK;
    19. -    /* Init Enet PLL. */
    20. -    CLOCK_InitEnetPll(&enetPllConfig_BOARD_BootClockRUN);
    21. -    /* Set preperiph clock source. */
    22. -    CLOCK_SetMux(kCLOCK_PrePeriphMux, 3);

    23.     // 此处略去...
    24.     /* Set SystemCoreClock variable. */
    25.     SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
    26. }
    复制代码
    最后再提一下,这个OTFAD时钟限制问题在i.MXRT1170上同样存在,解决思路与上面类似,痞子衡就不再赘述了。


    至此,系统时钟配置不当会导致i.MXRT1xxx系列下OTFAD加密启动失败问题痞子衡便介绍完毕了,掌声在哪里~~~



    签到签到
    回复

    使用道具 举报

    该用户从未签到

    10

    主题

    40

    帖子

    0

    注册会员

    Rank: 2

    积分
    147
    最后登录
    2023-7-27
    发表于 2021-3-15 16:49:16 | 显示全部楼层
    NXP的芯片就是要复杂一点,,,
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-5-28 05:36
  • 签到天数: 1 天

    [LV.1]初来乍到

    2

    主题

    36

    帖子

    0

    注册会员

    Rank: 2

    积分
    132
    最后登录
    2024-2-23
    发表于 2024-2-20 00:12:20 | 显示全部楼层
    这个在新版SD里已经没问题了
    干不完的事
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-29 21:49 , Processed in 0.128893 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表