基于NXP iMX7 ARM處理器部署FreeRTOS實時操作系統(tǒng)
1). 簡介
本文引用地址:http://m.butianyuan.cn/article/201608/295503.htmFreeRTOS是廣泛使用的開源實時操作系統(tǒng), 被眾多芯片廠商包括NXP所支持, 本文就展示在NXP iMX7 ARM處理器上面的M4核心上面部署FreeRTOS.
NXP iMX7 ARM處理器是NXP最新推出的異構(gòu)雙核處理器, 主核心為單核或者雙核Cortex-A7,通常運行Linux/WinCE操作系統(tǒng)來作為嵌入式應(yīng)用主程序界面環(huán)境; 副核心為Cortex-M4, 通常運行實時操作系統(tǒng)來為嵌入式應(yīng)用提供高效可靠的實時應(yī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, 一個負責(zé)數(shù)據(jù)傳輸,另一個負責(zé)指令傳輸, 因此為了最好的性能優(yōu)化, 我們需要將數(shù)據(jù)放置與連接數(shù)據(jù)總線的區(qū)域,而指令代碼放置與連接指令總線的區(qū)域. 例如, 對于TCM,則放置代碼于TCML空間, 而放置數(shù)據(jù)于TCMU空間.
然后關(guān)于Resource Domain Controller (RDC), 對于iMX7,由于Cortex-A7和Cortex-M4核心內(nèi)存和外設(shè)的訪問都是共享且平等的,為了保證不產(chǎn)生資源沖突,通過這個控制器來從硬件層面對指定內(nèi)存和外設(shè)的訪問權(quán)限進行保護. RDC 允許定義最多4個resource domains, 并將不同的內(nèi)存和外設(shè)資源指定到這些resource domain中. 默認情況下, A7核心和相關(guān)外設(shè)被指定于domain 0, 當FreeRTOS firmware運行后, M4核心以及相關(guān)外設(shè)最初也是domain 0, 但馬上被重新指定到domain 1. 因此如果一個外設(shè)需要被M4使用, 但同時A7 Linux kernel也使用了, 就需要修改A7 Linux Device Tree來禁止這個外設(shè) (詳細操作方法請見這里).
本文就基于Toradex Colibri iMX7 (基于NXP iMX7 SoC) ARM計算機模塊搭配Colibri Eva Board開發(fā)板來演示編譯和部署FreeRTOS應(yīng)用. 區(qū)別與傳統(tǒng)的MCU處理器, firmware通常從內(nèi)置的NOR Flash加載, Colibri iMX7則并沒有這樣的配置, 而是將firmware存放于外部存儲設(shè)備中如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從上述的存儲設(shè)備加載firmware到內(nèi)存,最后在觸發(fā)Cortex-M4核心去執(zhí)行這個firmware. 而如果需要更新或者替換firmware,只需要更改存儲設(shè)備上面的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 目錄下提供了諸多例程,在編譯前需要先設(shè)置叉編譯工具路徑的環(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)試輸出串口, 波特率設(shè)置115200 8N1。A7 Linux 默認device tree設(shè)置也會訪問UARTB, 為了防止出現(xiàn)沖突, 推薦在device tree 中禁用 UARTB(設(shè)置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會自動關(guān)閉不使用設(shè)備的時鐘,但A7核心Linux無法知道哪些時鐘在M4核心上面被使用,因此需要添加下面內(nèi)核參數(shù)來保證M4相關(guān)時鐘正常。
------------------------
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卡上面的程序文件復(fù)制到系統(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}
------------------------
// 設(shè)置啟動變量,之后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/
// 同上述方法編譯后生成應(yīng)用: gpio_imx_example.bin
// 例程中使用EXT_IO1作為按鍵輸入, EXT_IO0作為輸出控制LED; 在Colibri 評估板上面, 利用X21將對應(yīng)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/
// 同上述方法編譯后生成應(yīng)用: rpmsg_str_echo_freertos_example.bin
// A7 Linux kernel對應(yīng)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串口對應(yīng)輸出
------------------------
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 設(shè)置為開機自動加載
------------------------
$ echo imx_rpmsg_tty > /etc/modules-load.d/rpmsg_tty.conf
------------------------
// 另外關(guān)于RPMsg還有其他如pingpong demo, 可以自行測試.
7). 總結(jié)
本文對iMX7 異構(gòu)雙核架構(gòu)進行了說明, 并基于Toradex Colibri iMX7 模塊演示了在M4核心上面運行FreeRTOS例程以及A7和M4核心通過RPMsg通信例程, 相信對NXP iMX7架構(gòu)以及應(yīng)用有了一個初步的了解, 其非常適合用于同時有人機交互和實時控制的工業(yè)應(yīng)用場景, 同時非常低的功耗也使得整個嵌入式系統(tǒng)的穩(wěn)定可靠性有了很好的保證.
評論