混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT600中的Debug Mailbox实现对JLink调试的影响。

  事情缘起痞子衡的同事 - 喜欢打破砂锅问到底的Kerry小姐姐,她最近在研究i.MXRT600这款芯片,她发现在芯片ROM串行下载(ISP)模式下,连上芯片USB端口可以在设备管理器中正常看到枚举的HID设备(0x1fc9,0x0020),这个HID设备可配合上位机工具blhost.exe进行应用程序下载。但是当使用JLink正常连上芯片(选择的是MIMXRT685,不是CM33)后,之前的那个HID设备不见了,看起来芯片像是退出了ROM正常运行,这个体验跟i.MXRT1050上不太一样,这是为什么?这其实是Debug Mailbox在捣鬼,且听痞子衡细聊:

一、引出调试问题

  按照我们之前在i.MXRT1050上的调试经验,将芯片设为串行下载模式后,使用JLink连接上芯片,并halt住内核,此时芯片PC是正常停在ROM区域的(0x200000之后),让我们同样的过程在i.MXRT600上也操作一次:

混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)

  我们发现PC指向了0x1c04a,并且不管你如何reset再重新halt,它一直停在这个地方,更奇怪的是这个地方不在ROM区域(0x03000000或0x13000000之后)里,这是怎么回事?

二、什么是Debug Mailbox?

  与i.MXRT1050不同的是,i.MXRT600中引入了Debug Mailbox机制,这个机制由ROM负责实现,因此连接上JLink后的行为是由Debug Mailbox机制决定的。

  翻开i.MXRT600的User Manual,在Debug subsystem这一章节可以找到Debug Mailbox相关信息,Debug Mailbox其实最早是NXP LPC系列新推的一项功能,后来也用在了i.MXRT600上面。

  下图是i.MXRT600的SWD调试系统内部连接图,其中蓝框标出的DM AP便是Debug Mailbox。

混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)

  我们知道i.MXRT600是基于Cortex-M33内核的MCU,这款ARM内核主打特点是安全,因此NXP在设计芯片时也加入了很多安全方面的特性,Debug Mailbox便是其一,Debug Mailbox基于NXP debug authentication protocol version 1.0,主要作用是实现外部调试器与芯片内ROM的通信,从而赋予调试器擦写Flash、进入ROM ISP、调试认证等功能。

三、ROM中Debug Mailbox实现

  那么ROM中的Debug Mailbox机制到底是什么?简单理解就是如下一段代码插入了ROM的初始化流程。这个机制其实很简单,就是确保debug特性是正常开启的,然后根据芯片复位类型来初始化debug port并决定要不要进入Mailbox命令处理。

// 确认IFR里debug特性正常开启

if (kStatus_DBG_Success != debug_auth_evaluate_dcfg_socu())

{

__set_FAULTMASK(1);

__WFI();

}

volatile uint32_t reset_status = RSTCTRL0->SYSRSTSTAT;

// 根据复位类型设置初始debug port状态

if (kStatus_DBG_Success != debug_auth_hal_set_initial_debug_port_state(reset_status))

{

__set_FAULTMASK(1);

__WFI();

}

if (reset_status & 0x20)

{

// 处理mailbox收到的来自debugger的命令

debug_mailbox_GetRequest();

}

  RSTCTRL0->SYSRSTSTAT[5]位即ARM_APD_RESET,表明ARM内核是否发生了软复位(warm reset),正常芯片上电,这个位不会被置1,但是如果有调试器接入给内核发软复位,这个位就会被置位。一旦这个位被置起来,ROM初始化过程中便会进入Mailbox命令处理函数debug_mailbox_GetRequest(),不再往后执行正常的ROM串行下载/启动流程。

混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)

  debug_mailbox_GetRequest()函数是Debug Mailbox机制的核心,它借助的是如下三个Mailbox寄存器来实现调试器与ROM的互动。

  • CSW:命令状态寄存器,调试器操作这个寄存器指示ROM进入mailbox命令解析状态
  • REQUEST:请求寄存器,调试器将mailbox命令写入这个寄存器指示ROM去执行
  • RETURN:结果寄存器,调试器通过读这个寄存器获取ROM执行mailbox命令结果

混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)

  对于使用者来说,一般借助调试器先向CSW寄存器写入0x21申请re-sync同时reset device ,然后再按需写入如下具体的命令进REQUEST寄存器,便可实现Debug Mailbox相应功能。

#define ENTER_DEBUGGER_MAILBOX (0x0001)  // Start Mailbox debug

#define GET_CRP_LEVEL (0x0002) // Deprecated and retuen 3

#define DM_ERASE_FLASH (0x0003) // Mass erase flash

#define EXIT_DEBUGGER_MAILBOX (0x0004) // Exit Mailbox debug

#define ENTER_ISP_MODE (0x0005) // Enter specified ISP mode

#define SET_FA_MODE (0x0006) // Set to "Fault Analysis" mode

#define START_DEBUG_SESSION (0x0007) // Start Debug session

#define DEBUG_AUTH_START (0x0010) // Start Debug Authentication Protocol

#define DEBUG_AUTH_RESP (0x0011) // Debug Authentication response

  了解了Debug Mailbox机制原理,我们再来看JLink连接i.MXRT600时必须要加载执行的如下Script内容(开头痞子衡说了必须选择MIMXRT685,而不是CM33,因为在JLink DLL / JLinkDevices.xml里MIMXRT685才默认指定了配套Script脚本)。关于JLink Script知识,可以先看痞子衡之前文章 《JLink Script文件基础及其在IAR下调用方法》。

  这个脚本内容其实在i.MXRT600的User Manual中已经给出了相应伪代码,通过调用JLINK_CORESIGHT_WriteAP()来写Mailbox寄存器(index 0对应CSW,index 1对应REQUEST),基本是按照前面介绍的Debug Mailbox使用流程来的,最后通过写入START_DEBUG_SESSION命令进REQUEST寄存器开启芯片调试模式。

void InitTarget(void) {

int v;

JLINK_CORESIGHT_Configure("IRPre=0;DRPre=0;IRPost=0;DRPost=0;IRLenDevice=4");

// Pre-select that we have a Cortex-M33 connected

CPU = CORTEX_M33;

// J-Link is allowed to use a TAP reset for JTAG-chain auto-detection

JTAG_AllowTAPReset = 0;

JTAG_SetDeviceId(0, 0x6BA02477);

// Read AP ID register to identify DM AP at index 2

JLINK_CORESIGHT_WriteDP(2, 0x020000f0);

v = JLINK_CORESIGHT_ReadAP(3);

JLINK_SYS_Report1("DAP-IDCODE:", v);

// Select DM AP index 2

JLINK_CORESIGHT_WriteDP(2, 0x02000000);

JLINK_CORESIGHT_ReadDP(0);

// Active DebugMailbox

JLINK_CORESIGHT_WriteAP(0, 0x21);

JLINK_CORESIGHT_ReadAP(0);

// Enter Debug Session

JLINK_CORESIGHT_WriteAP(1, 0x07);

JLINK_CORESIGHT_ReadAP(0);

}

五、芯片调试模式(REQUEST = 0x07)下的状态

  前面讲了JLink Script会使芯片进入调试模式,那调试模式下芯片到底是什么状态?ROM其实是通过如下函数加载执行了0x1c040 - 0x1c04B处的一小段代码,并最终停在了0x1c04a处的while(1);,至此真相大白。

void go_debug_mode(void)

{

#define VECTOR_DUMMY_ROUTINE 0x0001c000u

#define APP_ENTRY (VECTOR_DUMMY_ROUTINE + 0x40 + 1)

uint32_t dummy_loop_routines[] = {

VECTOR_DUMMY_ROUTINE + 0x1000, // SP

APP_ENTRY, // Reset Handler

APP_ENTRY, // NMI Handler

APP_ENTRY, // HardFault_Handler

APP_ENTRY, // MemManage_Handler

APP_ENTRY, // BusFault_Handler

APP_ENTRY, // UsageFault_Handler

APP_ENTRY, // SecureFault_Handler

0, // Reserved

0, // Reserved

0, // Reserved

APP_ENTRY, // SVC_Handler

APP_ENTRY, // DebugMon_Handler

0, // Reserved

APP_ENTRY, // PendSV_Handler

APP_ENTRY, // SysTick_Handler

// Below are the binary codes for :

// register uint32_t dummy = SCB->CPUID;

// while(1);

0x5000f64eu,

0x0000f2ceu,

0xe7fe6801u,

};

{

uint32_t *dest = (uint32_t *)VECTOR_DUMMY_ROUTINE;

uint32_t *src = (uint32_t *)&dummy_loop_routines[0];

for (uint32_t i = 0u; i < ARRAY_SIZE(dummy_loop_routines); i++)

{

*dest++ = *src++;

}

jump_to_boot_image(VECTOR_DUMMY_ROUTINE);

}

}

六、Debug Mailbox对JLink调试的影响

  基于上面分析,最后痞子衡再总结一下Debug Mailbox对JLink调试的影响:

  1. 当芯片在ROM中执行(比如ISP模式,比如Flash中没有应用程序)时,JLink要想正常连接,必须加载使能芯片调试模式的Script才行,否则会连不上芯片。
  2. 通过加载执行JLink Script成功连接上芯片后,PC总是停在0x1c04a,这是Debug Mailbox机制决定的。
  3. 只有当芯片正常启动Flash里的应用程序后(即离开了ROM),用JLink连接芯片(选择CM33,不加载Script),halt住内核,PC指向的才是真实的应用程序位置。

  至此,i.MXRT600中的Debug Mailbox实现对JLink调试的影响痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox)

以上是 混混小说衡镶入:揭秘i.RDRB40a的ITD模式用下J-Link连接后PC总是停在0k6b04a的原因(De的漏洞 Mailbox) 的全部内容, 来源链接: utcz.com/a/67847.html

回到顶部