兩年前我寫(xiě)過(guò)一篇《雙核i.MXRT1170之Cortex-M7與Cortex-M4互相激活之道》,那篇文章從離線啟動(dòng)的角度介紹了跑雙核應(yīng)用的基本方法,基本上把雙核啟動(dòng)的細(xì)節(jié)都介紹到了。 在應(yīng)用開(kāi)發(fā)的階段,很多時(shí)候我們還是需要在線調(diào)試的,主核的調(diào)試沒(méi)什么特別要注意的地方,從核的調(diào)試大家估計(jì)就有點(diǎn)陌生了,今天就給大家介紹下 IAR 開(kāi)發(fā)環(huán)境下調(diào)試從核工程的方法。
一、測(cè)試準(zhǔn)備
首先需要準(zhǔn)備好測(cè)試環(huán)境,包含必要的軟件和硬件,我的環(huán)境如下:
集成開(kāi)發(fā)環(huán)境:IAR EW for Arm v9.10.2,(https://www.iar.com/products/architectures/
軟件開(kāi)發(fā)包:SDK_2.11.0_MIMXRT1170-EVK(Toolchain要包含IAR),點(diǎn)此下載
軟件驅(qū)動(dòng):J-Link driver v7.56b,點(diǎn)此下載
硬件工具:J-Link Plus調(diào)試器
硬件開(kāi)發(fā)板:MIMXRT1170-EVK (Rev.C),含板載 DAP-Link 調(diào)試器
我們知道i.MX RT1170 其實(shí)主從核是在 Fuse 里可配的,我們就以默認(rèn)配置(Cortex-M7 為主,Cortex-M4 為從)為例來(lái)介紹,選取的測(cè)試工程是SDK_2.11.0_MIMXRT1170-EVKoardsevkmimxrt1170demo_appshello_worldcm4。
二、在IAR下調(diào)試
使用IAR 打開(kāi)hello_world_demo_cm4.eww 工程,切換到 debug build (就是在 RAM 中執(zhí)行)。
2.1 工程選項(xiàng)處理器選 Cortex-M4 核調(diào)試情況
我們先來(lái)看一下工程選項(xiàng)里處理器選擇 Cortex-M4,并且不使能任何額外腳本時(shí)調(diào)試情況。也就是說(shuō)在明知主核Cortex-M7 處于激活狀態(tài)而 Cortex-M4 處于未激活狀態(tài)時(shí),IAR C-SPY 調(diào)試組件能否工作。
分別測(cè)試了板載 DAP-Link 調(diào)試器以及外接 J-Link 調(diào)試器,測(cè)試結(jié)果均是不能直接調(diào)試,DAP-Link 下提示 "Failed to connect toCPU",J-Link 下提示"Select core is not same as the target core"。
2.2 工程選項(xiàng)處理器選 NXP MIMXRT1176xxxA_M4 調(diào)試情況
再來(lái)看一下工程選項(xiàng)里處理器選擇 NXP MIMXRT1176xxxA_M4 時(shí)調(diào)試情況(會(huì)調(diào)用相關(guān)腳本,在IAR/J-Link 里已經(jīng)做好)。也就是雖然 Cortex-M4 處于未激活狀態(tài),但是有配套腳本會(huì)負(fù)責(zé)激活工作。
J-Link下是可以直接調(diào)試的,在 Debug Log 窗口,我們可以看到有 .jlinkscript 腳本執(zhí)行的痕跡,腳本打印信息里顯示其識(shí)別到Cortex-M4 未激活,并且會(huì)做激活相關(guān)工作。
Note: 這個(gè)跟 NXP MIMXRT1176xxxA_M4 選擇相關(guān)的 .jlinkscript 腳本在 JLink 驅(qū)動(dòng)安裝目錄下,由于 log 里沒(méi)有直接顯示路徑,那大概率已經(jīng)被打包進(jìn) DLL 文件里了,我們看不到具體腳本代碼實(shí)現(xiàn)。
DAP-Link下也是可以直接調(diào)試的,在 Debug Log 窗口,我們可以看到 iMXRT_1170.dmac 腳本被執(zhí)行了,腳本打印信息里顯示其識(shí)別到 Cortex-M4未激活,并且會(huì)做激活相關(guān)工作。
Note: 這個(gè)跟 NXP MIMXRT1176xxxA_M4 選擇相關(guān)的 iMXRT_1170.dmac 腳本在 IAR 安裝目錄下,具體路徑已經(jīng)在 log 里顯示出來(lái)了,我們可以看到其具體腳本代碼實(shí)現(xiàn)。
如果你細(xì)心觀察,你會(huì)發(fā)現(xiàn) DAP-Link 下必須要在工程選項(xiàng) Debugger / ExtraOptions里加 “--macro_paramenable_core=1” 語(yǔ)句才能正常調(diào)試,這是因?yàn)?iMXRT_1170.dmac 腳本需要接受這個(gè)參數(shù)才能正常激活從核 Cortex-M4。
2.3 自己實(shí)現(xiàn)用于從核調(diào)試的腳本
現(xiàn)在我們知道了調(diào)試從核 Cortex-M4 工程必須要有專門腳本來(lái)負(fù)責(zé)激活從核才行,雖然 IAR/J-Link里已經(jīng)做好這個(gè)腳本,但是兩者行為是否統(tǒng)一我們不清楚(畢竟看不見(jiàn) J-Link 下腳本源碼),而且這個(gè)腳本是隨著 IAR/J-Link 版本而變化的,具有一定的不可控性。
為了完全掌控從核調(diào)試的主動(dòng)性與確定性,最好我們自己重新實(shí)現(xiàn) IAR/J-Link 下的調(diào)試腳本,在線調(diào)試時(shí)直接指定使用我們自己寫(xiě)的腳本,這樣即使工程選項(xiàng)里處理器選擇 Cortex-M4 我們也能正常調(diào)試。
對(duì)于DAP-Link,我們新建一個(gè) mimxrt1170_connect_cm4_user.mac 文件(具體內(nèi)容見(jiàn)附錄一)放到工程目錄下,并且在 IAR 選項(xiàng)里指定使用這個(gè) mac 文件。這個(gè) mac 文件語(yǔ)法詳見(jiàn) 《IAR內(nèi)部C-SPY調(diào)試組件配套宏文件(.mac)用法介紹》,其中最重要的是 execUserCoreConnect() 保留宏函數(shù)里要做激活 Cortex-M4 工作。
Note: 如果希望調(diào)試從核 Cortex-M4 時(shí),主核 Cortex-M7 依然在跑,可以注釋掉mimxrt1170_connect_cm4_user.mac 文件里的 execUserSetup() 函數(shù)。
對(duì)于J-Link,我們新建一個(gè) mimxrt1170_connect_cm4_user.jlinkscript 文件(具體內(nèi)容見(jiàn)附錄二)放到工程目錄下,并且在 IAR 選項(xiàng)里指定使用這個(gè) jlinkscript 文件。這個(gè) jlinkscript 文件語(yǔ)法詳見(jiàn) 《JLink Script文件基礎(chǔ)及其在IAR下調(diào)用方法》,其中最重要的是 InitTarget() 用戶自定義動(dòng)作函數(shù)里要做激活 Cortex-M4 工作。
Note: 如果希望調(diào)試從核 Cortex-M4 時(shí),主核 Cortex-M7 依然在跑,可以注釋掉mimxrt1170_connect_cm4_user.jlinkscript 文件里的AfterResetTarget() 函數(shù)。
附錄一、IAR腳本(用于DAP-Link)
prepare_core_spin_code(cmVersion) { __var start; if (cmVersion == 7) { start = 0x2021FF00; __writeMemory32(start >> 7, 0x40c0c068, "AP0_Memory"); } if (cmVersion == 4) { start = 0x20200000; __writeMemory32(start & 0xFFFF, 0x40c0c000, "AP0_Memory"); __writeMemory32(start >> 16, 0x40c0c004, "AP0_Memory"); } __writeMemory32(start + 0x20, start, "AP0_Memory"); __writeMemory32(0x223105, start + 0x4, "AP0_Memory"); } release_core(cmVersion) { if (cmVersion == 7) { __writeMemory32(0x2, 0x40c04000, "AP0_Memory"); } if (cmVersion == 4) { __writeMemory32(0x1, 0x40c04000, "AP0_Memory"); } } reset_core(cmVersion) { __var reg; __var ctrlAddr; __var statAddr; if (cmVersion == 7) { ctrlAddr = 0x40c042a4; statAddr = 0x40c042b0; } if (cmVersion == 4) { ctrlAddr = 0x40c04284; statAddr = 0x40c04290; } __writeMemory32(0x1, ctrlAddr, "AP0_Memory"); do { reg = __readMemory32(statAddr, "AP0_Memory"); __delay(10); }while(reg & 0x1); } //_ExecDeviceCoreConnect() execUserCoreConnect() { __probeCmd("j.i swd /force"); // dummy read __readAPReg(2); __delay(10); // Disable system reset caused by sysrstreq from each core __writeMemory32(0x3c00, 0x40C04004, "AP0_Memory"); prepare_core_spin_code(4); release_core(4); // switch to AP1 __writeDPReg(1<<24, 2); } execUserPreReset() { reset_core(4); release_core(4); __writeDPReg(1<<24, 2); } execUserSetup() { __var reg; reg = __readMemory32(0x40c04000, "AP0_Memory"); if((reg & 0x2) == 0) { prepare_core_spin_code(7); reset_core(7); } }
附錄二、J-Link 腳本
void prepare_core_spin_code(unsigned int cmVersion) { unsigned int start; if (cmVersion == 7) { start = 0x2021FF00; MEM_WriteU32(0x40c0c068, start >> 7); } if (cmVersion == 4) { start = 0x20200000; MEM_WriteU32(0x40c0c000, start & 0xFFFF); MEM_WriteU32(0x40C0c004, start >> 16); } MEM_WriteU32(start, start + 0x20); // BootROM go_fatal_mode() MEM_WriteU32(start + 0x4, 0x223105); } void release_core(unsigned int cmVersion) { if (cmVersion == 7) { MEM_WriteU32(0x40C04000, 0x2); } if (cmVersion == 4) { MEM_WriteU32(0x40C04000, 0x1); } } void reset_core(unsigned int cmVersion) { unsigned int reg; unsigned int ctrlAddr; unsigned int statAddr; if (cmVersion == 7) { ctrlAddr = 0x40c042a4; statAddr = 0x40c042b0; } if (cmVersion == 4) { ctrlAddr = 0x40c04284; statAddr = 0x40c04290; } MEM_WriteU32(ctrlAddr, 1); do { reg = MEM_ReadU32(statAddr); SYS_Sleep(10); }while (reg & 0x1); } void InitTarget(void) { CPU = CORTEX_M7; // Manually configure AP JLINK_CORESIGHT_AddAP(0, CORESIGHT_AHB_AP); JLINK_CORESIGHT_AddAP(1, CORESIGHT_AHB_AP); JLINK_CORESIGHT_AddAP(2, CORESIGHT_APB_AP); // Dummy read JLINK_CORESIGHT_ReadAP(JLINK_CORESIGHT_AP_REG_IDR); SYS_Sleep(10); // Disable system reset caused by sysrstreq from each core MEM_WriteU32(0x40C04004, 0x3c00); prepare_core_spin_code(4); release_core(4); // Switch to AP1 CPU = CORTEX_M4; CORESIGHT_IndexAHBAPToUse = 1; } void ResetTarget(void) { CORESIGHT_IndexAHBAPToUse = 0; reset_core(4); release_core(4); CORESIGHT_IndexAHBAPToUse = 1; } void AfterResetTarget(void) { unsigned int reg; reg = MEM_ReadU32(0x40c04000); if((reg & 0x2) == 0) { prepare_core_spin_code(7); reset_core(7); } }
編輯:黃飛
-
處理器
+關(guān)注
關(guān)注
68文章
19044瀏覽量
228503 -
IAR
+關(guān)注
關(guān)注
5文章
344瀏覽量
36563 -
調(diào)試器
+關(guān)注
關(guān)注
1文章
297瀏覽量
23632
原文標(biāo)題:雙核i.MX RT1170之單獨(dú)在線調(diào)試從核工程的方法(IAR篇)
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論