大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是一種快速定位i.MXRT600板級(jí)設(shè)計(jì)ISP[2-0]啟動(dòng)模式引腳上電時(shí)序問題的方法。
我們知道恩智浦i.MXRT600是主打音頻市場的MCU產(chǎn)品,其也是i.MXRT三位數(shù)平臺(tái)的第一款型號(hào)。這顆MCU已被眾多知名國際大廠客戶選用,在項(xiàng)目中作為協(xié)處理器負(fù)責(zé)音頻相關(guān)子功能。不少客戶都已經(jīng)到了量產(chǎn)階段,最近痞子衡在支持其中一個(gè)量產(chǎn)客戶,客戶遇到了同一批次某幾個(gè)板卡無法正常啟動(dòng)的問題。痞子衡和同事一起排查,最終發(fā)現(xiàn)是ISP[2:0]啟動(dòng)引腳電平上電時(shí)序問題。這其實(shí)是個(gè)典型問題,痞子衡今天教你一招快速定位此類問題的方法:
一、引出上電時(shí)序問題
我們先來看看客戶的問題,下面是客戶板卡簡圖,i.MXRT600是負(fù)責(zé)音頻功能的協(xié)處理器,它的啟動(dòng)引腳ISP[2:0]與主應(yīng)用處理器(AP)連接了起來(客戶項(xiàng)目設(shè)計(jì)里,AP并不負(fù)責(zé)控制i.MXRT600的啟動(dòng)模式),為了防止對(duì)i.MXRT600上電ISP引腳采樣有影響,客戶還特地在中間加了一層反向隔離電路。
- 注:其實(shí)i.MXRT600支持Serial Boot模式,這種模式下i.MXRT600作為協(xié)處理器,其應(yīng)用程序數(shù)據(jù)可直接由AP通過指定的UART/I2C/SPI/USB下載進(jìn)i.MXRT600的內(nèi)部RAM運(yùn)行,能省去一顆外部Flash。
客戶量產(chǎn)過程中,同一批次幾百塊板卡,有一兩塊板卡上i.MXRT600無法啟動(dòng)。客戶做了少量ABA實(shí)驗(yàn):將無法啟動(dòng)板卡上的i.MXRT600芯片吹下來,換到能正常啟動(dòng)板卡上,依然無法啟動(dòng)。反過來,能正常啟動(dòng)板卡上的i.MXRT600芯片換到無法正常啟動(dòng)的板卡上,這塊板卡就能正常啟動(dòng)了。
從上面ABA實(shí)驗(yàn)來看,似乎不是板級(jí)設(shè)計(jì)問題,像是出問題的板卡上i.MXRT600芯片自身問題。痞子衡拿到一塊出問題的板子,上電后測量了ISP[2:0]引腳電平,其值是3'b011 - FlexSPI Boot from Port A,上電穩(wěn)定后ISP設(shè)置是沒問題的,但剛上電時(shí)i.MXRT600 BootROM到底采樣到的是什么ISP電平值沒人知道。
下面是客戶板卡上ISP部分反向隔離設(shè)計(jì),為了驗(yàn)證是ISP采樣時(shí)機(jī)問題,我們特意對(duì)電路進(jìn)行改造將RT600_BOOT0和RT600_BOOT2分別強(qiáng)行拉高和拉低,然后給板卡重新上電,終于板卡能正常啟動(dòng)了。
所以我們可以得出初步結(jié)論,對(duì)于i.MXRT600從上電到BootROM進(jìn)行ISP采樣,這段時(shí)間不是一個(gè)嚴(yán)格固定值,因芯片制造差異,這個(gè)時(shí)間應(yīng)該是在一定范圍內(nèi),板級(jí)供電設(shè)計(jì)時(shí)上電時(shí)間應(yīng)留有足夠余量??蛻暨@個(gè)項(xiàng)目里上電時(shí)間余量留得不足,導(dǎo)致無法滿足個(gè)別i.MXRT600芯片ISP采樣時(shí)間要求。
二、BootROM中對(duì)于啟動(dòng)模式的處理
在介紹快速定位ISP采樣時(shí)機(jī)問題方法前,痞子衡先帶大家了解下i.MXRT600 BootROM中關(guān)于啟動(dòng)模式的處理流程。
咱們先回顧下痞子衡的舊文 《Boot配置(ISP_Pin/OTP)》,每次i.MXRT600芯片硬復(fù)位,OTP中的部分關(guān)于系統(tǒng)配置的值會(huì)被自動(dòng)加載到OCOTP模塊相應(yīng)Shadow Register里(關(guān)于OCOTP外設(shè)基礎(chǔ)知識(shí)可參考 《OTP及其燒寫方法》),BootROM中主要用如下 get_runtime_boot_device_info() 函數(shù)來獲取最終啟動(dòng)模式,并將其存在全局變量 s_bootDeviceInfo 中。
- 注:代碼中 OCOTP->OTP_SHADOW[0x60] 寄存器低四位即芯片參考手冊(cè)里提及的 PRIMARY_BOOT_SRC[3:0]
static boot_device_info_t s_bootDeviceInfo;
void get_runtime_boot_device_info(void)
{
// 從OTP Shadow Register獲取啟動(dòng)模式
uint32_t bootSrc = OCOTP->OTP_SHADOW[0x60] & 0x0f;
boot_device_info_t bootDeviceInfo = { 0 };
if (bootSrc == 0) // Isp Pin
{
// 從ISP[2:0]引腳獲取啟動(dòng)模式
bootSrc = get_bootpin_mode();
// 對(duì) bootDeviceInfo 成員進(jìn)一步賦值
}
else
{
// 對(duì) bootDeviceInfo 成員進(jìn)一步賦值
}
s_bootDeviceInfo = bootDeviceInfo;
}
每一次i.MXRT600系統(tǒng)軟復(fù)位去重新執(zhí)行BootROM時(shí),ISP[2:0]引腳狀態(tài)都會(huì)被重新采樣,這完全是軟件采樣。ROM中ISP采樣功能函數(shù)如下面 get_bootpin_mode() 所示,代碼中做了IO電平去抖處理:
#define BOOT_PIN_DEBOUNCE_READ_COUNT 500
uint32_t get_bootpin_mode(void)
{
uint32_t bootSrc = 0;
// 使能GPIO外設(shè)
CLOCK_EnableClock(kCLOCK_HsGpio1);
RESET_PeripheralReset(kHSGPIO1_RST_SHIFT_RSTn);
// 設(shè)置ISP引腳為GPIO模式,并使能上拉.
IOPCTL->PIO[1][15] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);
IOPCTL->PIO[1][16] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);
IOPCTL->PIO[1][17] = IOPCTL_PIO_FSEL(0) | IOPCTL_PIO_PUPDENA(1) | IOPCTL_PIO_PUPDSEL(1) | IOPCTL_PIO_IBENA(1);
// 配置ISP引腳GPIO屬性為數(shù)字輸入模式.
GPIO->DIR[1] &= ~((1U << 15) | (1U << 16) | (1U << 17));
// Note1: 管腳默認(rèn)上拉是disable的,ROM需要使能管腳上拉.
// Note2: 從使能管腳上拉到讀取管腳值之間應(yīng)間隔10us以上.
sw_delay_us(10);
// 采樣ISP引腳值
for (uint32_t pin = 17; pin >= 15; pin--)
{
uint32_t readCount = 0;
for (uint32_t i = 0; i < BOOT_PIN_DEBOUNCE_READ_COUNT; i++)
{
readCount += GPIO->B[1][pin] & 0x1;
}
if (readCount >= BOOT_PIN_DEBOUNCE_READ_COUNT / 2)
{
bootSrc |= 0x1;
}
if (pin != 15)
{
bootSrc <<= 1;
}
}
return bootSrc;
}
上面就是BootROM中關(guān)于啟動(dòng)模式的處理代碼。那么有沒有方法掛上調(diào)試器通過查后門方式直接讀取到 s_bootDeviceInfo 變量值呢?很抱歉,不可以!即使痞子衡也做不到,雖然痞子衡能通過查BootROM map文件得知這個(gè)變量放在 0x10012d38 地址處。但是i.MXRT600 BootROM中集成了 《Debug Mailbox機(jī)制》,我們無法通過調(diào)試器讀取正常運(yùn)行后的ROM狀態(tài),這條路行不通。
三、快速定位ISP[2:0]電平采樣問題
第一小節(jié)介紹的客戶項(xiàng)目啟動(dòng)問題,其實(shí)還算比較好定位,因?yàn)橛蠥BA實(shí)驗(yàn)在先,基本可以明確問題就出在ISP采樣時(shí)機(jī)上。但更多時(shí)候,在客戶項(xiàng)目研發(fā)階段,沒有ABA實(shí)驗(yàn)的條件,可能僅有一塊板卡,并且Flash配置以及App里啟動(dòng)頭是否正確都尚待驗(yàn)證。這種情況下,我們就需要一種快速甄別是否是ISP采樣時(shí)機(jī)因素導(dǎo)致的啟動(dòng)問題。
當(dāng)芯片無法啟動(dòng)時(shí),我們第一想法肯定是要得知第二小節(jié)介紹里 s_bootDeviceInfo 到底是什么值,這樣我們就能反推ISP引腳到底在ROM里是什么采樣值,但這條路行不通。換個(gè)角度想,我們能不能不讓BootROM去采樣ISP引腳,換一種替代方式來決定啟動(dòng)模式,如果這種情況下能按替代設(shè)置去啟動(dòng),就也可以反證ISP引腳采樣時(shí)機(jī)有問題。
這種啟動(dòng)模式替代設(shè)置方法就是痞子衡今天要教大家的方法,利用調(diào)試器臨時(shí)改寫OCOTP->OTP_SHADOW[0x60]值(對(duì)的,我們可以不燒寫OTP),改寫完成后對(duì)芯片做一次軟復(fù)位即可。OCOTP->OTP_SHADOW寄存器組僅芯片硬件復(fù)位或者執(zhí)行OCOTP更新命令其值才會(huì)被重新加載,軟復(fù)位不會(huì)影響其值。
四、在MIMXRT685-EVK上做一次實(shí)驗(yàn)
讓我們?cè)贛IMXRT685-EVK上做一次實(shí)驗(yàn),這塊板卡上Flash連到了FlexSPI0 Port B上,我們隨意下載一個(gè)SDK XIP工程,并將ISP引腳撥碼設(shè)為3'b010 - FlexSPI Boot from Port B,復(fù)位后芯片能正常啟動(dòng),工程運(yùn)行正常。
現(xiàn)在我們將ISP引腳撥碼設(shè)為3'b110 - Serial ISP,軟復(fù)位后芯片進(jìn)入了ISP下載模式,不會(huì)從Flash啟動(dòng)。查芯片頭文件得知 OCOTP->OTP_SHADOW[0x60] 寄存器地址是 0x50130180,我們現(xiàn)在嘗試改寫這個(gè)寄存器。
/** OCOTP - Register Layout Typedef */
typedef struct {
__IO uint32_t OTP_SHADOW[496]; /**< OTP shadow register N, array offset: 0x0, array step: 0x4 */
uint8_t RESERVED_0[64];
__IO uint32_t OTP_CTRL; /**< Control/address register, offset: 0x800 */
// 省略...
} OCOTP_Type;
/** Peripheral OCOTP base address */
#define OCOTP_BASE (0x50130000u)
/** Peripheral OCOTP base address */
#define OCOTP_BASE_NS (0x40130000u)
/** Peripheral OCOTP base pointer */
#define OCOTP ((OCOTP_Type *)OCOTP_BASE)
/** Peripheral OCOTP base pointer */
#define OCOTP_NS ((OCOTP_Type *)OCOTP_BASE_NS)
掛上J-Link調(diào)試器,打開J-Link Commander,連接芯片,注意選擇"MIMXRT685_M33",然后使用w4命令在0x50130180地址處寫入0x00000005(在PRIMARY_BOOT_SRC[3:0]定義里,4'b0101是QSPI_B_BOOT)。
繼續(xù)執(zhí)行reset和go命令(或者按一下板載軟復(fù)位按鈕RESET BUTTON SW3),這時(shí)候你可以看到芯片從Flash正常啟動(dòng)了,SDK XIP工程又運(yùn)行起來了,顯然這時(shí)候ISP引腳電平設(shè)置被忽略了,因此我們找到了有效的啟動(dòng)模式替代設(shè)置方法。
最后有一點(diǎn)要注意,在使用J-Link軟復(fù)位時(shí),如果看到如下log,得檢查下配套JLinkScript里的ResetTarget()函數(shù)具體功能,要確保內(nèi)核真的被復(fù)位了。
至此,快速定位i.MXRT600板級(jí)設(shè)計(jì)ISP[2-0]啟動(dòng)模式引腳上電時(shí)序問題的方法痞子衡便介紹完畢了,掌聲在哪里~~~