NXP iMX8QM 通過 SCFW 隔離 AP_M4 核資源
By Toradex 胡珊逢
簡介
Apalis iMX8QM 使用了 NXP 的 iMX8 Quad Max 處理器。該 CPU 提供 A72 和 A53 Application Processor 和 M4 MCU。文章將介紹如何在硬件層面上隔離 AP 和 MCU 的資源,從而提高系統(tǒng)的可靠性。
System Controller Unit (SCU)System Controller Unit 是 iMX8 Quad Max 處理器上的一個專用 M4 核,連接 PMIC 和控制處理器上的子系統(tǒng),為處理器的硬件功能提供抽象接口,供子系統(tǒng)使用。其主要管理以下功能和資源:
系統(tǒng)初始化與啟動系統(tǒng)控制器通信電源管理資源管理引腳配置定時器中斷處理
默認情況下,AP 核和 M4 核均能夠使用 Apalis iMX8QM 的所有資源,包括 DDR RAM。SCU 可以通過分區(qū) partition 的方式,將 AP 和 M4 之間,以及兩個 M4 核之間所使用的資源從硬件上隔離開。一個分區(qū)中除了處理器核心外,還可以有外設(shè)、引腳 Pads 和內(nèi)存區(qū)域。處理器核只能訪問位于同一個分區(qū)內(nèi)的資源。如果嘗試訪問其他分區(qū)的資源,則會返回總線錯誤。
當 AP 核和 M4 核在同一個分區(qū)時,AP 上的 Linux 雖然可以通過 reserved memory 方式不去使用相關(guān) RAM 區(qū)域,但是直接物理地址訪問的方式仍起作用。這對于 M4 端也是如此。使用 SCU 的分區(qū),可以從底層規(guī)避該問題。除此之外,AP 和 M4 使用獨立 Power Domain,在隔離分區(qū)情況下,對于 M4 的實時關(guān)鍵任務(wù)和 AP 上基于富操作系統(tǒng) Linux 的應(yīng)用獨立運行提供可能。
在剛啟動時,系統(tǒng)會劃分三個分區(qū)。
SCU:包含所有運行 SCFW 固件所需的 Pads、外設(shè)和內(nèi)存區(qū)域SECO:Security Controller 運行所需的相關(guān)資源Boot:系統(tǒng)剩余的所有資源如 Pads、外設(shè)和內(nèi)存區(qū)域都將會劃分到該分區(qū)
當系統(tǒng)繼續(xù)啟動時,如果不做進一步的分區(qū),默認情況下 AP 和 M4 核都將運行在 Boot 分區(qū)中,它們之間只能通過軟件的方式隔離各自的資源。為了實現(xiàn) AP 和 M4 之間的硬件隔離,可以采用下面分區(qū)。
AP0:擁有運行 U-boot,Linux 的分區(qū)MCU0 和 MCU1:兩個 Cortex-M4 核各自運行的分區(qū)Shared:共享資源的分區(qū),例如將一段用于 rpmsg 通信的 RAM 區(qū)域劃分到其中,AP 和 M4 就能夠相互發(fā)送消息
分區(qū)的創(chuàng)建和資源劃分在 SCU 的固件 SCFW 中調(diào)整。
SCU 固件 SCFW
SCFW 的下載和編譯方法參考Build Custom i.MX 8/8X System Controller Firmware (SCFW)。接下來將針對上面使用 AP0、MCU0、MCU1 和 Shared 分區(qū)案例進行說明。按照上面方法下載的 SCFW 源碼中,mx8qm_apalis/board.c 已經(jīng)包含上面分區(qū)的實現(xiàn)代碼,所以無需額外的修改。在組裝 Boot Container 時傳入特定的 Flags 值可以啟用。
在 platform/board/mx8qm_apalis/board.c 中配置分區(qū)和資源。宏定義 PARTITION_NAME 命令系統(tǒng)啟動時的設(shè)置三個分區(qū)名字。
PARTITION_NAME(SC_PT, "SCU");
PARTITION_NAME(SECO_PT, "SECO");
PARTITION_NAME(pt_boot, "BOOT");
檢測標志位判斷是否需要創(chuàng)建 AP0、MCU0、MCU1 和 Shared 分區(qū)。
if (alt_config != SC_FALSE)
{
在需要進行分區(qū)時,PARTITION_NAME 設(shè)置相應(yīng)分區(qū)的名稱。
PARTITION_NAME(pt_boot, "AP0");
...
PARTITION_NAME(pt_m4_0, "MCU0");
...
PARTITION_NAME(pt_m4_1, "MCU1");
...
PARTITION_NAME(pt, "Shared");
這里以 MCU0 分區(qū)為例,rsrc_list中包含了劃分到 MCU0 分區(qū)的資源,如 M4 中斷、Message Unit、定時器等。
static const sc_rsrc_t rsrc_list[7U] =
{
SC_R_SYSTEM,
SC_R_IRQSTR_M4_0,
SC_R_MU_5B,
SC_R_MU_7A,
SC_R_MU_8B,
SC_R_GPT_4,
SC_R_SECO_MU_4
};
pad_list 中包含 MCU0 分區(qū)所使用的引腳范圍。
static const sc_pad_t pad_list[2U] =
{
RM_RANGE(SC_P_M40_I2C0_SCL, SC_P_M40_GPIO0_01)
};
結(jié)合 sc_fw_api_qm_b0.pdf 文檔,index 7~10 的引腳都將在劃分到 MCU0 分區(qū)。
sc_rm_mem_list_t 配置了包括 RAM 在內(nèi)的可使用存儲空間。
static const sc_rm_mem_list_t mem_list[2U] =
{
{0x088000000ULL, 0x0887FFFFFULL},
{0x008081000ULL, 0x008180FFFULL}
};
rm_partition_create 使用上面配置的所有資源創(chuàng)建 MCU0 分區(qū)。
BRD_ERR(rm_partition_create(pt_boot, &pt_m4_0, SC_FALSE,
SC_TRUE, SC_FALSE, SC_TRUE, SC_FALSE, SC_R_M4_0_PID0,
rsrc_list, ARRAY_SIZE(rsrc_list),
pad_list, ARRAY_SIZE(pad_list),
mem_list, ARRAY_SIZE(mem_list)));
組裝 Boot Container
NXP i.MX 8QuadMax 處理器使用前面提到的 SCU 來啟動系統(tǒng)。啟動時除了加載 SCFW,它還可以加載 ATF 和 U-Boot,以及直接加載 M4 核的固件。Boot Container 組裝方法參考 Specifics: Build U-Boot for NXP i.MX 8/8X-based SoMs。默認情況下,如網(wǎng)頁描述,使用下面命令組裝 Boot Container。該方法生成的 flash.bin 文件中并不包含 M4 核的固件,并且 AP 和 M4 在同一個分區(qū)。M4 的固件在 U-Boot 啟動時,使用 bootaux 命令從 eMMC 上加載后運行。
make SOC=iMX8QM flash_b0
為了使用上面 SCFW 中劃分的分區(qū),使用下面命令組裝 Boot Container。
make SOC=iMX8QM flash_regression_linux_m4
編譯目標來自 imx-mkimage/iMX8QM/soc.mak 中的定義。flash_regression_linux_m4: $(MKIMG) $(AHAB_IMG) \
scfw_tcm.bin u-boot-atf.bin m4_image.bin m4_1_image.bin \
./$(MKIMG) -soc QM -rev B0 -append $(AHAB_IMG) \
-c -flags 0x00200000 -scfw scfw_tcm.bin \
-ap u-boot-atf.bin a53 0x80000000 \
-p3 -m4 m4_image.bin 0 0x34FE0000 \
-p4 -m4 m4_1_image.bin 1 0x38FE0000 \
-out flash.bin
-flags 0x00200000向 SCFW 的 board.c 傳遞,SCU 在啟動時將會創(chuàng)建 AP0、MCU0、MCU1 和 Shared 的分區(qū)。
if (alt_config != SC_FALSE)
{
sc_fw_port.pdf 中說明了 Bit 21 SCFW_SC_BD_FLAGS_ALT_CONFIG 為更改 SCFW 配置的位,對應(yīng) 0x00200000。
上面命令中 m4_image.bin 和 m4_1_image.bin 為兩個 M4 各自的固件,從各自的 TCML 運行。因此,在執(zhí)行上面命令前,需要把兩個 M4 的固件復制到 imx-mkimage/iMX8QM 目錄下。
如下修改 U-boot 源碼中 U-boot/cmd/booti.c,重新編譯后將 u-boot.bin 復制到 imx-mkimage/iMX8QM 目錄下。
if (dest < gd->ram_base || dest > gd->ram_top) {
puts("kernel_comp_addr_r is outside of DRAM range!\n");
//return -EINVAL;
}
Linux device tree 更新
接下來的演示中,我們在 M4 上使用 multicore_examples/rpmsg_lite_pingpong_rtos 作為演示,在 AP 上的 Linux 系統(tǒng)中也需要開啟 rpmsg 節(jié)點并加載驅(qū)動。針對 Apalis iMX8 BSP 7 的 imx8qm-apalis-v1.1-ixora-v1.2.dtb 需要打該補丁。
更新 Boot Container 文件
上面命令執(zhí)行成功后生成的 flash.bin,需要更新到 Apalis iMX8 模塊上的 eMMC 上。對于使用 Toradex Easy Installer 進行批量燒寫或者重裝系統(tǒng),可以將 flash.bin 重名為 imx-boot,替換原來的燒錄文件中 imx-boot。在開發(fā)期間,使用 U-Boot 直接更新 flash.bin 會更加方便,免于重裝整個系統(tǒng)鏡像。
將 flash.bin 復制到的一臺 TFTP 服務(wù)器的下載目錄中。然后在 U-Boot 中配置 Apalis iMX8 和 TFTP 服務(wù)器 IP 地址。
Apalis iMX8 # setenv ipaddr 192.168.3.181
Apalis iMX8 # setenv serverip 192.168.3.196
Apalis iMX8 # saveenv
使用 tftpboot 和 mmc 命令將 flash.bin 下載并寫入到 eMMC 上。mmc write $loadaddr 0 0x973中最后的數(shù)值是寫入的 block 數(shù)量。tftpboot 在下載時會顯示文件大小,例如這里為 1238016 字節(jié)。需要寫入的 block = (1238016+511)/512,計算結(jié)果向上取整,并轉(zhuǎn)為十六進制數(shù)值。
Apalis iMX8 # tftpboot $loadaddr flash.bin
Using ethernet@5b040000 device
TFTP from server 192.168.3.196; our IP address is 192.168.3.181
Filename 'flash.bin'.
Load address: 0x95400000
Loading: ################################################## 1.2 MiB
3.4 MiB/s
done
Bytes transferred = 1238016 (12e400 hex)
Apalis iMX8 # mmc dev 0 1
Apalis iMX8 # mmc write $loadaddr 0 0x973
測試
在 U-Boot 中配置啟動時加載的 device tree 文件。
Apalis iMX8 # setenv fdtfile imx8qm-apalis-v1.1-ixora-v1.2.dtb
Apalis iMX8 # saveenv
Apalis iMX8 # reset
啟動后可以在 Linux 和兩個 M4 的調(diào)試串口上看到啟動內(nèi)容。
Linux 中進入 kernel modules 驅(qū)動目錄 kernel/drivers/rpmsg,加載 imx_rpmsg_pingpong.ko。兩個 M4 上的固件在發(fā)現(xiàn) rpmsg 通道后,自動向 Linux 發(fā)送消息。# insmod imx_rpmsg_pingpong.ko
...
[ 67.386427] get 91 (src: 0x1f)
[ 67.389556] get 101 (src: 0x1e)
[ 67.392707] imx_rpmsg_pingpong virtio1.rpmsg-openamp-demo-channel.-1.30:
goodbye!
[ 67.401771] get 93 (src: 0x1f)
[ 67.406364] get 95 (src: 0x1f)
[ 67.410982] get 97 (src: 0x1f)
[ 67.415594] get 99 (src: 0x1f)
[ 67.420212] get 101 (src: 0x1f)
[ 67.423388] imx_rpmsg_pingpong virtio3.rpmsg-openamp-demo-channel-1.-1.31:
goodbye!
總結(jié)
文章介紹了如何使用 SCU 劃分不同的分區(qū),將 AP 和 M4 之間做硬件隔離,并使用 SCFW 直接加載 M4 的固件,不僅提高系統(tǒng)可靠性,也將 M4 運行提前到 U-Boot 之前,加快啟動速度。更多關(guān)于 SCU 的高級高級功能,可以參考 SCFW 的說明文檔。
*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。