查看: 2389|回复: 2

[分享] 快速定位i.MXRT600启动引脚上电时序问题

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3302

    主题

    6549

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32045
    最后登录
    2024-4-29
    发表于 2021-6-2 10:04:05 | 显示全部楼层 |阅读模式
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是一种快速定位i.MXRT600板级设计ISP[2-0]启动模式引脚上电时序问题的方法。

    我们知道恩智浦i.MXRT600是主打音频市场的MCU产品,其也是i.MXRT三位数平台的第一款型号。这颗MCU已被众多知名国际大厂客户选用,在项目中作为协处理器负责音频相关子功能。不少客户都已经到了量产阶段,最近痞子衡在支持其中一个量产客户,客户遇到了同一批次某几个板卡无法正常启动的问题。痞子衡和同事一起排查,最终发现是ISP[2:0]启动引脚电平上电时序问题。这其实是个典型问题,痞子衡今天教你一招快速定位此类问题的方法:

    一、引出上电时序问题
    我们先来看看客户的问题,下面是客户板卡简图,i.MXRT600是负责音频功能的协处理器,它的启动引脚ISP[2:0]与主应用处理器(AP)连接了起来(客户项目设计里,AP并不负责控制i.MXRT600的启动模式),为了防止对i.MXRT600上电ISP引脚采样有影响,客户还特地在中间加了一层反向隔离电路。

    注:其实i.MXRT600支持Serial Boot模式,这种模式下i.MXRT600作为协处理器,其应用程序数据可直接由AP通过指定的UART/I2C/SPI/USB下载进i.MXRT600的内部RAM运行,能省去一颗外部Flash。
    1.png
    客户量产过程中,同一批次几百块板卡,有一两块板卡上i.MXRT600无法启动。客户做了少量ABA实验:将无法启动板卡上的i.MXRT600芯片吹下来,换到能正常启动板卡上,依然无法启动。反过来,能正常启动板卡上的i.MXRT600芯片换到无法正常启动的板卡上,这块板卡就能正常启动了。

    从上面ABA实验来看,似乎不是板级设计问题,像是出问题的板卡上i.MXRT600芯片自身问题。痞子衡拿到一块出问题的板子,上电后测量了ISP[2:0]引脚电平,其值是3'b011 - FlexSPI Boot from Port A,上电稳定后ISP设置是没问题的,但刚上电时i.MXRT600 BootROM到底采样到的是什么ISP电平值没人知道。

    下面是客户板卡上ISP部分反向隔离设计,为了验证是ISP采样时机问题,我们特意对电路进行改造将RT600_BOOT0和RT600_BOOT2分别强行拉高和拉低,然后给板卡重新上电,终于板卡能正常启动了。

    所以我们可以得出初步结论,对于i.MXRT600从上电到BootROM进行ISP采样,这段时间不是一个严格固定值,因芯片制造差异,这个时间应该是在一定范围内,板级供电设计时上电时间应留有足够余量。客户这个项目里上电时间余量留得不足,导致无法满足个别i.MXRT600芯片ISP采样时间要求。
    2.png
    二、BootROM中对于启动模式的处理
    在介绍快速定位ISP采样时机问题方法前,痞子衡先带大家了解下i.MXRT600 BootROM中关于启动模式的处理流程。


    咱们先回顾下痞子衡的旧文 《Boot配置(ISP_Pin/OTP)》,每次i.MXRT600芯片硬复位,OTP中的部分关于系统配置的值会被自动加载到OCOTP模块相应Shadow Register里(关于OCOTP外设基础知识可参考 《OTP及其烧写方法》),BootROM中主要用如下 get_runtime_boot_device_info() 函数来获取最终启动模式,并将其存在全局变量 s_bootDeviceInfo 中。
    注:代码中 OCOTP->OTP_SHADOW[0x60] 寄存器低四位即芯片参考手册里提及的 PRIMARY_BOOT_SRC[3:0]
    1. static boot_device_info_t s_bootDeviceInfo;

    2. void get_runtime_boot_device_info(void)
    3. {
    4.     // 从OTP Shadow Register获取启动模式
    5.     uint32_t bootSrc = OCOTP->OTP_SHADOW[0x60] & 0x0f;
    6.     boot_device_info_t bootDeviceInfo = { 0 };

    7.     if (bootSrc == 0) // Isp Pin
    8.     {
    9.         // 从ISP[2:0]引脚获取启动模式
    10.         bootSrc = get_bootpin_mode();
    11.         // 对 bootDeviceInfo 成员进一步赋值
    12.     }
    13.     else
    14.     {
    15.         // 对 bootDeviceInfo 成员进一步赋值
    16.     }
    17.     s_bootDeviceInfo = bootDeviceInfo;
    18. }
    复制代码
    每一次i.MXRT600系统软复位去重新执行BootROM时,ISP[2:0]引脚状态都会被重新采样,这完全是软件采样。ROM中ISP采样功能函数如下面 get_bootpin_mode() 所示,代码中做了IO电平去抖处理:
    1. #define BOOT_PIN_DEBOUNCE_READ_COUNT 500

    2. uint32_t get_bootpin_mode(void)
    3. {
    4.     uint32_t bootSrc = 0;

    5.     // 使能GPIO外设
    6.     CLOCK_EnableClock(kCLOCK_HsGpio1);
    7.     RESET_PeripheralReset(kHSGPIO1_RST_SHIFT_RSTn);

    8.     // 设置ISP引脚为GPIO模式,并使能上拉.
    9.     IOPCTL->PIO[1][15] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);
    10.     IOPCTL->PIO[1][16] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);
    11.     IOPCTL->PIO[1][17] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);

    12.     // 配置ISP引脚GPIO属性为数字输入模式.
    13.     GPIO->DIR[1] &= ~((1U << 15) | (1U << 16) | (1U << 17));

    14.     // Note1: 管脚默认上拉是disable的,ROM需要使能管脚上拉.
    15.     // Note2: 从使能管脚上拉到读取管脚值之间应间隔10us以上.
    16.     sw_delay_us(10);

    17.     // 采样ISP引脚值
    18.     for (uint32_t pin = 17; pin >= 15; pin--)
    19.     {
    20.         uint32_t readCount = 0;
    21.         for (uint32_t i = 0; i < BOOT_PIN_DEBOUNCE_READ_COUNT; i++)
    22.         {
    23.             readCount += GPIO->B[1][pin] & 0x1;
    24.         }
    25.         if (readCount >= BOOT_PIN_DEBOUNCE_READ_COUNT / 2)
    26.         {
    27.             bootSrc |= 0x1;
    28.         }
    29.         if (pin != 15)
    30.         {
    31.             bootSrc <<= 1;
    32.         }
    33.     }

    34.     return bootSrc;
    35. }
    复制代码
    上面就是BootROM中关于启动模式的处理代码。那么有没有方法挂上调试器通过查后门方式直接读取到 s_bootDeviceInfo 变量值呢?很抱歉,不可以!即使痞子衡也做不到,虽然痞子衡能通过查BootROM map文件得知这个变量放在 0x10012d38 地址处。但是i.MXRT600 BootROM中集成了 《Debug Mailbox机制》,我们无法通过调试器读取正常运行后的ROM状态,这条路行不通。


    三、快速定位ISP[2:0]电平采样问题
    第一小节介绍的客户项目启动问题,其实还算比较好定位,因为有ABA实验在先,基本可以明确问题就出在ISP采样时机上。但更多时候,在客户项目研发阶段,没有ABA实验的条件,可能仅有一块板卡,并且Flash配置以及App里启动头是否正确都尚待验证。这种情况下,我们就需要一种快速甄别是否是ISP采样时机因素导致的启动问题。


    当芯片无法启动时,我们第一想法肯定是要得知第二小节介绍里 s_bootDeviceInfo 到底是什么值,这样我们就能反推ISP引脚到底在ROM里是什么采样值,但这条路行不通。换个角度想,我们能不能不让BootROM去采样ISP引脚,换一种替代方式来决定启动模式,如果这种情况下能按替代设置去启动,就也可以反证ISP引脚采样时机有问题。


    这种启动模式替代设置方法就是痞子衡今天要教大家的方法,利用调试器临时改写OCOTP->OTP_SHADOW[0x60]值(对的,我们可以不烧写OTP),改写完成后对芯片做一次软复位即可。OCOTP->OTP_SHADOW寄存器组仅芯片硬件复位或者执行OCOTP更新命令其值才会被重新加载,软复位不会影响其值。


    四、在MIMXRT685-EVK上做一次实验
    让我们在MIMXRT685-EVK上做一次实验,这块板卡上Flash连到了FlexSPI0 Port B上,我们随意下载一个SDK XIP工程,并将ISP引脚拨码设为3'b010 - FlexSPI Boot from Port B,复位后芯片能正常启动,工程运行正常。


    现在我们将ISP引脚拨码设为3'b110 - Serial ISP,软复位后芯片进入了ISP下载模式,不会从Flash启动。查芯片头文件得知 OCOTP->OTP_SHADOW[0x60] 寄存器地址是 0x50130180,我们现在尝试改写这个寄存器。
    1. /** OCOTP - Register Layout Typedef */
    2. typedef struct {
    3.   __IO uint32_t OTP_SHADOW[496];                   /**< OTP shadow register N, array offset: 0x0, array step: 0x4 */
    4.        uint8_t RESERVED_0[64];
    5.   __IO uint32_t OTP_CTRL;                          /**< Control/address register, offset: 0x800 */
    6.   // 省略...
    7. } OCOTP_Type;

    8. /** Peripheral OCOTP base address */
    9. #define OCOTP_BASE                               (0x50130000u)
    10. /** Peripheral OCOTP base address */
    11. #define OCOTP_BASE_NS                            (0x40130000u)
    12. /** Peripheral OCOTP base pointer */
    13. #define OCOTP                                    ((OCOTP_Type *)OCOTP_BASE)
    14. /** Peripheral OCOTP base pointer */
    15. #define OCOTP_NS                                 ((OCOTP_Type *)OCOTP_BASE_NS)
    复制代码
    挂上J-Link调试器,打开J-Link Commander,连接芯片,注意选择"MIMXRT685_M33",然后使用w4命令在0x50130180地址处写入0x00000005(在PRIMARY_BOOT_SRC[3:0]定义里,4'b0101是QSPI_B_BOOT)。
    3.png
    继续执行reset和go命令(或者按一下板载软复位按钮RESET BUTTON SW3),这时候你可以看到芯片从Flash正常启动了,SDK XIP工程又运行起来了,显然这时候ISP引脚电平设置被忽略了,因此我们找到了有效的启动模式替代设置方法。
    4.png
    最后有一点要注意,在使用J-Link软复位时,如果看到如下log,得检查下配套JLinkScript里的ResetTarget()函数具体功能,要确保内核真的被复位了。
    5.png
    至此,快速定位i.MXRT600板级设计ISP[2-0]启动模式引脚上电时序问题的方法痞子衡便介绍完毕了,掌声在哪里~~~


    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:29
  • 签到天数: 485 天

    [LV.9]以坛为家II

    8

    主题

    1358

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    2920
    最后登录
    2024-4-28
    发表于 2021-6-2 10:55:19 | 显示全部楼层
    厉害,感觉非常的复杂,我都没到那个程序
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    20 小时前
  • 签到天数: 1299 天

    [LV.10]以坛为家III

    7

    主题

    6384

    帖子

    1

    金牌会员

    Rank: 6Rank: 6

    积分
    10610
    最后登录
    2024-4-29
    发表于 2021-6-8 18:18:07 | 显示全部楼层
    感谢分享!!
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-4-29 20:31 , Processed in 0.130647 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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