基于NXP iMX7 ARM處理器部署FreeRTOS實時操作系統(tǒng)
1). 簡介
本文引用地址:http://www.ex-cimer.com/article/201608/295503.htmFreeRTOS是廣泛使用的開源實時操作系統(tǒng), 被眾多芯片廠商包括NXP所支持, 本文就展示在NXP iMX7 ARM處理器上面的M4核心上面部署FreeRTOS.
NXP iMX7 ARM處理器是NXP最新推出的異構(gòu)雙核處理器, 主核心為單核或者雙核Cortex-A7,通常運行Linux/WinCE操作系統(tǒng)來作為嵌入式應用主程序界面環(huán)境; 副核心為Cortex-M4, 通常運行實時操作系統(tǒng)來為嵌入式應用提供高效可靠的實時應用處理. 一個簡略的iMX7芯片框圖如下所示.
由上圖可見, 多種類型的內(nèi)存可供使用, 包括M4專屬的內(nèi)存空間 (Tightly Coupled Memory, TCM), 雖然很小但是CPU可以無延遲訪問; 多個OCRAM區(qū)域 (On-Chip RAM, 通常是SRAM), 同樣訪問非??於姨峁┫鄬Υ蟮娜萘? 最后就是DRR3主內(nèi)存空間. 出于性能考慮, 請盡可能優(yōu)先使用片內(nèi)內(nèi)存資源.
另外, M4有兩個總線連接到AXI/AHB interconnect, 一個負責數(shù)據(jù)傳輸,另一個負責指令傳輸, 因此為了最好的性能優(yōu)化, 我們需要將數(shù)據(jù)放置與連接數(shù)據(jù)總線的區(qū)域,而指令代碼放置與連接指令總線的區(qū)域. 例如, 對于TCM,則放置代碼于TCML空間, 而放置數(shù)據(jù)于TCMU空間.
然后關于Resource Domain Controller (RDC), 對于iMX7,由于Cortex-A7和Cortex-M4核心內(nèi)存和外設的訪問都是共享且平等的,為了保證不產(chǎn)生資源沖突,通過這個控制器來從硬件層面對指定內(nèi)存和外設的訪問權限進行保護. RDC 允許定義最多4個resource domains, 并將不同的內(nèi)存和外設資源指定到這些resource domain中. 默認情況下, A7核心和相關外設被指定于domain 0, 當FreeRTOS firmware運行后, M4核心以及相關外設最初也是domain 0, 但馬上被重新指定到domain 1. 因此如果一個外設需要被M4使用, 但同時A7 Linux kernel也使用了, 就需要修改A7 Linux Device Tree來禁止這個外設 (詳細操作方法請見這里).
本文就基于Toradex Colibri iMX7 (基于NXP iMX7 SoC) ARM計算機模塊搭配Colibri Eva Board開發(fā)板來演示編譯和部署FreeRTOS應用. 區(qū)別與傳統(tǒng)的MCU處理器, firmware通常從內(nèi)置的NOR Flash加載, Colibri iMX7則并沒有這樣的配置, 而是將firmware存放于外部存儲設備中如SD卡或者模塊上的Nand Flash, 同時這些存儲并不是“memory mapped”, 因此CPU無法直接執(zhí)行存儲在這里的firmware, 而是要先被加載到內(nèi)存區(qū)域后才能被執(zhí)行.
對于Colibri iMX7, 系統(tǒng)總是由Cortex-A7核心來啟動, 先執(zhí)行內(nèi)部boot ROM后啟動如U-boot這樣的boot loader,然后由boot loader從上述的存儲設備加載firmware到內(nèi)存,最后在觸發(fā)Cortex-M4核心去執(zhí)行這個firmware. 而如果需要更新或者替換firmware,只需要更改存儲設備上面的firmware鏡像即可.
2). 準備
a). 硬件準備
./ Colibri iMX7計算機模塊和Colibri Eva Board開發(fā)板
./ Ubuntu Linux開發(fā)主機
b). 軟件準備
./ iMX7模塊Cortex-A7核心運行Toradex Embedded Linux release V2.6 Beta2
./ Ubuntu Linux開發(fā)主機
FreeRTOS source code
交叉編譯ToolChain - Linaro ARM Embedded, 4.9 2015-Q3 update - 從這里下載
3). 配置
a). 下載FreeRTOS for Colibri iMX7
------------------------
$ git clone -b master-1.0.1 git://git.toradex.com/freertos-toradex.git freertos-colibri-imx7/
$ cd freertos-colibri-imx7/
------------------------
b). 解壓縮交叉編譯工具
------------------------
$ tar xjf gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2
//如果開發(fā)主機是Ubuntu 64bit 操作系統(tǒng),則需要安裝下面32bit支持包
$ sudo dpkg --add-architecture i386
$ sudo apt-get update
$ sudo apt-get install libc6:i386 libncurses5:i386
//測試gcc運行
$ cd .../gcc-arm-none-eabi-4_9-2015q3/bin/
$./arm-none-eabi-gcc --version
//安裝 make 和 Cmake 工具
$ sudo apt-get install make cmake
------------------------
4). 編譯FreeRTOS
FreeRTOS 的 examples 目錄下提供了諸多例程,在編譯前需要先設置叉編譯工具路徑的環(huán)境變量ARMGCC_DIR,然后運行armgcc子目錄下準備好的編譯腳本即可進行編譯.
------------------------
$ export ARMGCC_DIR=.../gcc-arm-none-eabi-4_9-2015q3/
$ cd .../freertos-colibri-imx7/examples/imx7_colibri_m4/demo_apps/hello_world/armgcc
$ ./build_all.sh
------------------------
編譯好的可執(zhí)行文件位于armgcc下的release和debug子目錄下, 可以加載到M4核心上面運行了.
5). 在M4核心上面運行Firmware
a). M4的固件程序在Colibri iMX7 A7核心Linux系統(tǒng)U-Boot中進行加載, 將編譯好的 hello_world.bin程序放到SD卡根目錄 (FAT32格式) ,并連接到開發(fā)板上.
------------------------
Colibri iMX7 # fatload mmc 0:1 0x7F8000 hello_world.bin
...
Colibri iMX7 # dcache flush
Colibri iMX7 # bootaux 0x7F8000
## Starting auxiliary core at 0x007F8000 ...
------------------------
b). FreeRTOS 默認使用 UARTB 作為其調(diào)試輸出串口, 波特率設置115200 8N1。A7 Linux 默認device tree設置也會訪問UARTB, 為了防止出現(xiàn)沖突, 推薦在device tree 中禁用 UARTB(設置status參數(shù))。也可以在 U-Boot 中添加下面參數(shù),臨時禁用 UARTB。
------------------------
Colibri iMX7 # setenv fdt_fixup 'fdt addr ${fdt_addr_r} && fdt rm /soc/aips-bus@30800000/spba-bus@30800000/serial@30890000'
Colibri iMX7 # s**eenv
------------------------
c). Linux會自動關閉不使用設備的時鐘,但A7核心Linux無法知道哪些時鐘在M4核心上面被使用,因此需要添加下面內(nèi)核參數(shù)來保證M4相關時鐘正常。
------------------------
Colibri iMX7 # setenv defargs clk_ignore_unused
------------------------
d). 通過另外一個窗口連接UARTB, 可以收到hello world程序運行后的打印輸出
------------------------
$ sudo minicom -D /dev/ttyUSB1 -b 115200
Welcome to minicom 2.7
......
Port /dev/ttyUSB1, 11:52:46
Press CTRL-A Z for help on special keys
Hello World!
------------------------
e). 自動啟動加載 M4 上運行的程序
// 運行下面命令將SD卡上面的程序文件復制到系統(tǒng)為M4程序單獨提供的ubi分區(qū)空間
------------------------
Colibri iMX7 # ubi part ubi
...
Colibri iMX7 # fatload mmc 0:1 ${loadaddr} hello_world.bin
...
Colibri iMX7 # ubi write ${loadaddr} m4firmware ${filesize}
------------------------
// 設置啟動變量,之后U-Boot會在開機啟動Linux前先啟動M4程序
------------------------
Colibri iMX7 # setenv m4boot 'ubi read 0x7F8000 m4firmware && dcache flush && bootaux 0x7F8000'
Colibri iMX7 # s**eenv
------------------------
6). M4 程序示例
除了上面測試的hello world, 在examples目錄中還有很多示例程序.
a). GPIO示例
// 例程位置: .../examples/imx7_colibri_m4/driver_examples/gpio_imx/
// 同上述方法編譯后生成應用: gpio_imx_example.bin
// 例程中使用EXT_IO1作為按鍵輸入, EXT_IO0作為輸出控制LED; 在Colibri 評估板上面, 利用X21將對應Pin腳和組件相連:
------------------------
EXT_IO0 => X21-LED1
EXT_IO1 => X21-SW6
------------------------
// 在Uboot運行程序, 由于A7 Linux Device Tree也定義了這幾個GPIO, 因此測試只在U-Boot環(huán)境下進行.
------------------------
====================== GPIO Example ========================
=================== GPIO Interrupt =====================
The (EXT_IO1) button is configured to trigger GPIO interrupt
Press the (EXT_IO1) button 3 times to continue.
Button pressed 1 time.
Button pressed 2 time.
Button pressed 3 time.
================= GPIO Functionality==================
The button state is now polled.
Press the button to switch LED on or off
Button pressed 1 times
Button pressed 2 times
...
------------------------
b). RPMsg示例 - M4和A7通訊
// 例程位置: .../examples/imx7_colibri_m4/demo_apps/rpmsg/str_echo_freertos/
// 同上述方法編譯后生成應用: rpmsg_str_echo_freertos_example.bin
// A7 Linux kernel對應module 源文件: drivers/rpmsg/imx_rpmsg_tty.c
// U-Boot執(zhí)行如下命令
------------------------
fatload mmc 0:1 0x7F8000 rpmsg_str_echo_freertos_example.bin
reading rpmsg_str_echo_freertos_example.bin
20860 bytes read in 21 ms (969.7 KiB/s)
Colibri iMX7 # dcache flush
Colibri iMX7 # bootaux 0x7F8000
## Starting auxiliary core at 0x007F8000 ...
Colibri iMX7 # run ubiboot
------------------------
// M4 串口輸出
------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
RPMSG Init as Remote
------------------------
// A7 Linux下執(zhí)行下面命令
------------------------
$ modprobe imx_rpmsg_tty
[ 184.656763] imx_rpmsg_tty rpmsg0: new channel: 0x400 -> 0x0!
[ 184.663331] Install rpmsg tty driver!
$ stty -F /dev/ttyRPMSG -echo
$ exec 3<> /dev/ttyRPMSG
$ echo Test >&3
$ cat <&3
Test
^C
$ exec 3>&-
------------------------
// M4串口對應輸出
------------------------
RPMSG String Echo FreeRTOS RTOS API Demo...
RPMSG Init as Remote
Name service handshake is done, M4 has setup a rpmsg channel [0 ---> 1024]
Get Message From Master Side : "Test" [len : 4]
Get New Line From Master Side
------------------------
// 如需將Linux kernel module 設置為開機自動加載
------------------------
$ echo imx_rpmsg_tty > /etc/modules-load.d/rpmsg_tty.conf
------------------------
// 另外關于RPMsg還有其他如pingpong demo, 可以自行測試.
7). 總結(jié)
本文對iMX7 異構(gòu)雙核架構(gòu)進行了說明, 并基于Toradex Colibri iMX7 模塊演示了在M4核心上面運行FreeRTOS例程以及A7和M4核心通過RPMsg通信例程, 相信對NXP iMX7架構(gòu)以及應用有了一個初步的了解, 其非常適合用于同時有人機交互和實時控制的工業(yè)應用場景, 同時非常低的功耗也使得整個嵌入式系統(tǒng)的穩(wěn)定可靠性有了很好的保證.
評論