支持 #8 » ArmLite_MCU_Development_Guide.md
ArmLite MCU 開發與測試簡易指南
1. 文件目的
本文件說明 IT9860 SDK 中 ArmLite MCU 測試專案的架構、設定、建置、執行與除錯方式,主要對應以下目錄:
project/test_armliteMcu:Host CPU 測試程式、Kconfig 與測試判定。sdk/arm_lite_dev/armliteMcu:ArmLite MCU firmware 與各周邊模組。tool/bin/PrintArmLiteMcuDump:讀取 ArmLite MCU memory log 與 exception backtrace 的工具。
2. 系統架構
Host CPU 啟動 OpenRTOS 後,由 test_openrtos.c 建立測試 thread,進入 test_armlite_mcu.c 的 TestFunc()。Host 先設定 ArmLite 專用 GPIO,再切換 ArmLite engine、載入 firmware,並透過 shared memory telemetry 監看執行狀態。
ArmLite MCU 從 sdk/arm_lite_dev/armliteMcu/main.c 啟動,初始化啟用的周邊模組,並以 1 ms tick 驅動 scheduler。GPIO 與 SARADC task 預設每 10 ms 執行;UART、frequency 與 interrupt test 使用 polling 或 interrupt 處理。
Telemetry 將 heartbeat、各測試 counter、最後測量值與 error count 發佈到 shared memory1。Host 預設每秒取得 snapshot,連續三次健康後顯示 PASS;已經 PASS 的測試如果之後失去訊號,會改為 FAIL。
3. 核心開發流程
本專案最重要的關係如下:
project/test_armliteMcu/Kconfig
|
| qconf 存檔
v
build/openrtos/test_armliteMcu/config.cmake
|
| ArmLite nested build 讀取同一份設定
v
sdk/arm_lite_dev/armliteMcu/CMakeLists.txt
|
| 選擇 source + 產生 compile definitions
v
armliteMcu.plugin -> armliteMcu.raw -> armliteMcu.hex
|
| #include "armliteMcu.hex"
v
Host library 內的 gArmLiteMcuImage[]
|
| test_armlite_mcu.c: ITP_IOCTL_INIT
v
iteRiscLoadData() -> iteRiscFireCpu()
|
v
sdk/arm_lite_dev/armliteMcu/main.c
3.1 Kconfig 如何使用
project/test_armliteMcu/Kconfig 是整個 Host 與 ArmLite firmware 的共用設定入口。開發者先在 MCU Function Test -> Test Case 選擇一個測試:
GPIOTEST:啟用ARMLITE_GPIO_ENABLE與ARMLITE_GPIO_DEMO_ENABLE。UARTTEST:啟用ARMLITE_UART_ENABLE與選定 UART port。PWMTEST:啟用ARMLITE_PWM_ENABLE。FREQUENCYTEST:啟用 frequency capture 與所需 interrupt support。INTERRUPTTEST:啟用 ArmLite software interrupt self-test。I2CTEST:啟用 ArmLite I2C 與 Host loopback。SARADCTEST:啟用 SARADC。ALLTEST:同時啟用多個周邊,但不啟用 GPIO demo。
ARMLITE_ENABLE 與 ARMLITE_MCU 在此 project 為必要設定。ArmLite 與 ALT CPU 是不同的 core,不應因此測試額外啟用 ALT CPU。
Kconfig 的一般設定方式是由 test case 控制上層 enable,再由周邊設定指定腳位與參數。例如 GPIO TEST:
GPIOTEST=y
-> CFG_ARMLITE_GPIO_ENABLE=y
-> CFG_ARMLITE_GPIO_DEMO_ENABLE=y
-> CFG_ARMLITE_GPIO_PINS="42,43"
-> CFG_ARMLITE_GPIO_DIR_PINS="42"
CFG_ARMLITE_GPIO_PINS 是 ArmLite 擁有的 GPIO,CFG_ARMLITE_GPIO_DIR_PINS 是其中的 output。以上例子表示 GPIO42 為 output、GPIO43 為 input。
qconf 存檔後,SDK 會產生:
Host build 使用這些 CFG_* 宏;ArmLite nested build 也會在 sdk/arm_lite_dev/armliteMcu/CMakeLists.txt include Host 的 config.cmake,因此兩邊使用同一份設定。
ArmLite CMake 不只是直接傳遞設定,還會:
- 檢查 UART baud rate、GPIO 範圍與 RX/TX 衝突。
- 將 UART0–UART5 與 PWM1–PWM8 轉成 bit mask。
- 把 UART、PWM、frequency、SARADC 使用的 GPIO 自動加入 ArmLite ownership mask。
- 檢查 output pin 必須同時存在於 owner pin 清單。
- 依
CFG_ARMLITE_*_ENABLE決定要編譯哪些mcu_*_test.c與周邊 driver。 - 將計算後的值以 compile definition 傳入 firmware。
因此修改 Kconfig 後,必須重新建置 ArmLite firmware 與 Host image,不能只重新編譯 test_armlite_mcu.c。
3.2 Firmware 如何被建置與嵌入 Host
sdk/arm_lite_dev/armliteMcu/CMakeLists.txt 建置出 armliteMcu.plugin ELF,後續依序產生:
Host driver sdk/driver/arm_lite_dev/armliteMcu/armliteMcuDevice.c 以下列方式把 firmware 編譯進 Host image:
這表示上板時不是從 filesystem 動態開啟 .hex 檔;firmware bytes 已經在建置期間嵌入 Host executable。
3.3 test_armlite_mcu.c 如何 load firmware
Host 的 TestFunc() 執行順序如下:
ithGpioInitArmLitePins():在 ArmLite 啟動前,由 Host 設定專用 GPIO 的 mux、direction、initial level 與 pull。itpInit():初始化 ITP devices。armliteMcuReportWiring():列印當前 test case 的實際接線。ITP_IOCTL_ARMLITE_SWITCH_ENG:將 ArmLite framework 切換到ARMLITE_MCUdevice。如果原本是其他 engine,driver 會先 reset ArmLite CPU,再將後續 ioctl 指向itpDeviceArmLiteMcu。ITP_IOCTL_INIT:真正進行 firmware load 與 CPU start。- 啟用 memory dump 時,顯示 debug memory 與 backtrace address。
- 進入 I2C loopback 或
armliteMcuMonitor()讀取 telemetry。
ITP_IOCTL_INIT 會轉到 armliteMcuDevice.c 的 armliteMcuIoctl(),其實際流程是:
iteRiscResetCpu(ARMLITE_CPU)
|
+-- 清理前一次的 UART/PWM/frequency/SARADC 狀態
+-- 清除 telemetry shared memory
+-- 保留 UART DMA channel 6/7(如有啟用)
|
loadDeviceFirmware()
|
+-- iteRiscLoadData(ARMLITE_CPU_IMAGE_MEM_TARGET,
| gArmLiteMcuImage, image_size)
+-- 驗證 firmware header magic/target/API/load/end address
+-- 寫入 cmdExchangeAddress
+-- flush data cache/memory buffer
|
清除 command request/response registers
|
寫入 I2C/DMA boot resource(如有啟用)
|
iteRiscFireCpu(ARMLITE_CPU)
iteRiscLoadData() 只負責將嵌入的 image 複製到 ARMLITE_CPU_IMAGE_MEM_TARGET;iteRiscFireCpu() 才是解除 reset 並讓 ArmLite 從 firmware entry point 開始執行。
3.4 ArmLite main.c 執行流程
ArmLite firmware 進入 main() 後依序執行:
- Debug 初始化:如有
CFG_ARMLITE_MCU_LOG_DUMP,初始化 memory ring log;如有 backtrace,再初始化 exception dump area。 - Scheduler timer:
startTimer(CFG_ARMLITE_SCHEDULER_TIMER),並以ARMLite_GetBusClock()取得 bus clock。 - Telemetry:
armliteMcuTelemetryInit()寫入 active peripheral mask 與 bus clock。Host 會使用這個 mask 確認載入的 firmware 與 Host test case 一致。 - UART direct log:依 Kconfig 設定初始化 log UART。
- Interrupt:初始化 interrupt controller、探測可用 route,但此時還未開始 dispatch。
- Peripheral init:
armliteMcuInit()依ARMLITE_MCU_PERIPHERALenum 逐一呼叫已編譯進來的 GPIO/I2C/UART/PWM/frequency/interrupt/SARADC/CAN init。 - Interrupt start:所有周邊初始化完成後才啟用 interrupt dispatch。
- 計算 1 ms tick:由 bus clock 計算
ticksPerUs與ticksPerMs。 - 進入永久迴圈:等待下一個 tick,再呼叫
armliteMcuOnTick()。
armliteMcuWaitForNextTick() 在等待 1 ms 時不是單純 idle,它持續呼叫 armliteMcuPoll(),讓 UART 與 interrupt self-test 可以使用較細的時序。
armliteMcuOnTick() 每 1 ms 進行:
- frequency polling。
armliteMcuTask()週期排程。- telemetry 內容與 heartbeat 更新。
- 每秒輸出 direct UART status(如有啟用)。
- 每 10 ms publish memory log(如有啟用)。
Task table 在編譯時由 #ifdef 決定內容:
| Peripheral task | 週期 |
|---|---|
| GPIO demo | 10 ms |
| SARADC | 10 ms |
| I2C | 1 ms |
| CAN | 1 ms |
UART、frequency 與 interrupt test 不完全依賴這個 task table,它們有各自的 poll 或 interrupt 路徑。
4. 主要程式檔
Host 端
project/test_armliteMcu/Kconfig:測試項目、GPIO、UART、PWM、frequency、SARADC 與 debug 設定。project/test_armliteMcu/test_armlite_mcu.c:載入 firmware、報告接線、讀取 telemetry 與 PASS/FAIL 判定。project/test_armliteMcu/test_armlite_i2c.c:I2C loopback 測試。project/test_armliteMcu/test_openrtos.c:OpenRTOS 入口與測試 thread。
ArmLite MCU 端
main.c:Firmware 入口、scheduler 與周邊初始化。mcu_*_test.c:各測試的流程與 telemetry counter 更新。gpio/、uart/、pwm/、frequency/、i2c/、saradc/、canbus/:各周邊驅動實作。telemetry/:Host/MCU 共用的狀態發佈機制。debug/:memory ring log 與 exception backtrace。log/:ArmLite 直接 UART log。
5. 測試項目與接線
| Test Case | 功能 | 預設接線/操作 |
|---|---|---|
| GPIO TEST | GPIO output/input loopback | GPIO42 output 接 GPIO43 input |
| UART TEST | UART loopback | GPIO45 TX 接 GPIO44 RX |
| PWM TEST | PWM output | 以示波器量測選定的 PWM GPIO |
| GPIO FREQUENCY TEST | GPIO frequency capture | 訊號源接 GPIO43 |
| INTERRUPT TEST | ArmLite software interrupt | 無需外部接線 |
| SARADC TEST | XAIN0–XAIN7 | 類比輸入預設使用 GPIO19–GPIO26 |
| ALL TEST | UART + PWM + frequency + SARADC | UART loopback、PWM-to-frequency loopback 與 SARADC 輸入 |
ALL TEST 不包含 GPIO demo,避免 demo 切換已經由其他周邊佔用的 GPIO。實際 GPIO 號碼以當前 Kconfig 為準,不一定是上表的預設值。
6. Kconfig 設定快速參考
本節以 sdk/Kconfig 的 ArmLite MCU 設定為主,project/test_armliteMcu/Kconfig 則負責依 test case 提供 project default。在 qconf 的 MCU Function Test -> Test Case 選擇測試後,再到 ArmLite 周邊選單確認對應參數。
以下表格使用 Kconfig 原始 symbol 名稱,例如 ARMLITE_UART_ENABLE;它在 C/C++ compile definition 與產生的 .config 中會以 CFG_ARMLITE_UART_ENABLE 形式出現。
6.1 核心與共用設定
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_ENABLE |
n |
啟用 ArmLite core;與 ALT CPU 無關,兩者是不同 core。 |
ARMLITE_MCU |
n |
建置並載入基本 ArmLite MCU firmware,依賴 ARMLITE_ENABLE。 |
ARMLITE_MCU_LOG_DUMP |
n |
將 ring log 寫入 shared debug memory,可由 glamomem 讀取。 |
ARMLITE_MCU_BACKTRACE_DUMP |
n |
依賴 log dump;將 exception registers/backtrace 放在 8 KiB debug region 的最後 1 KiB。 |
ARMLITE_TELEMETRY_ENABLE |
內部值 | 無 qconf prompt,由需要回報結果的周邊自動 select。 |
ARMLITE_INTERRUPT_ENABLE |
內部值 | 無 qconf prompt,由 UART interrupt mode、frequency detect 或 interrupt test 自動 select。 |
ARMLITE_INTERRUPT_ENABLE 會啟用 FA626TE IRQ entry 與 ArmLite ITINT dispatcher。Firmware 會探測 controller-1 +0x080 與 controller-2 +0x140 路徑;探測與 UART interrupt mode 運作時,ALT CPU 必須保持停用。
6.2 GPIO ownership 與初始化
| Config | 預設 | 用途 |
|---|---|---|
ARMLITE_GPIO_ENABLE |
n |
啟用 ArmLite GPIO reservation 與 Host 預先初始化。 |
ARMLITE_GPIO_DEMO_ENABLE |
n |
切換第一個 owned output,取樣第一個 owned input,並自動啟用 telemetry。 |
ARMLITE_GPIO_PINS |
"" |
以逗號分隔的 ArmLite owner pin,例如 "42,43"。 |
ARMLITE_GPIO_DIR_PINS |
"" |
owner pins 中的 output;必須是 GPIO_PINS 子集。 |
ARMLITE_GPIO_INIT_HIGH_PINS |
"" |
output pins 中初始為 high 的腳位;其餘初始為 low。 |
ARMLITE_GPIO_PULL_ENABLE_PINS |
"" |
啟用 internal pull resistor 的 owned pins。 |
ARMLITE_GPIO_PULL_UP_PINS |
"" |
pull-enabled pins 中使用 pull-up 者;其餘為 pull-down。 |
Host 在 firmware load 前的 ithGpioInitArmLitePins() 會對最終 ownership mask 中的 GPIO 進行:
- 將 pin mux 設為 GPIO mode 0。
- 依 direction mask 設為 input/output。
- output 先寫入 initial level,再開啟 output direction,避免不必要的 glitch。
- input 依 pull-enable 與 pull-up mask 設定電阻。
最終 ownership 不只包含 ARMLITE_GPIO_PINS。ArmLite CMake 會自動加入:
- 已啟用 UART 的 RX/TX;TX 同時加入 output mask。
- direct UART log 的 TX;同時加入 output mask。
- 已啟用 PWM channel 的 GPIO;同時加入 output mask。
- frequency detect GPIO;作為 input。
- SARADC XAIN0–XAIN7 GPIO;作為 input。
上述 pin 會被轉成 bank0–bank3 的 CFG_ARMLITE_GPIO_BANKx_MASK 與 DIR_MASK,同時傳給 Host GPIO driver 與 ArmLite firmware。Firmware 啟動後,Host 不應再設定或驅動這些腳位。
6.3 I2C
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_I2C_ENABLE |
n |
將 ArmLite I2C 功能編譯進 firmware。 |
ARMLITE_I2C_PORT |
2 |
ArmLite 使用的 I2C controller port。 |
GPIO_ARMLITE_I2C_SCL |
40 |
SCL GPIO。 |
GPIO_ARMLITE_I2C_SDA |
41 |
SDA GPIO。 |
ARMLITE_I2C_CLOCK_HZ |
400000 |
I2C bus clock,單位 Hz。 |
ARMLITE_I2C_DELAY |
0 |
SDA hold time/TSR 設定。 |
I2C 的 SCL/SDA 有專用 config,不是 GPIO demo 的 input/output pin。泛用 sdk/Kconfig 的 ARMLITE_I2C_ENABLE 本身不會 select ARMLITE_GPIO_ENABLE,也不會由 GPIO ownership CMake 自動併入 ARMLITE_GPIO_PINS;使用時仍必須確認 Host 沒有同時使用該 I2C controller 與 pin mux。test_armliteMcu 的 I2C loopback 還會設定 Host 端對應 I2C 接口,實際接線以 project Kconfig 為準。
6.4 UART0–UART5
ARMLITE_UART_ENABLE 是總開關,會自動啟用 telemetry 與 GPIO reservation。再以 ARMLITE_UARTn_ENABLE 選擇一個或多個 controller;UART0 預設啟用,UART1–UART5 預設停用。Host CPU 不可同時使用 ArmLite 已 claim 的 UART controller。
每個 UART 都有相同三組設定:
| Config pattern | 說明 |
|---|---|
ARMLITE_UARTn_ENABLE |
將 UARTn 交給 ArmLite。 |
ARMLITE_UARTn_FIFO |
預設 mode,firmware polling UART FIFO。 |
ARMLITE_UARTn_INTR |
Interrupt mode,自動 select ARMLITE_INTERRUPT_ENABLE。 |
ARMLITE_UARTn_DMA |
DMA mode,固定使用 DMA channel 6/7。 |
ARMLITE_UARTn_IO_MODE |
內部整數:FIFO=0、interrupt=1、DMA=2。 |
ARMLITE_UARTn_BAUDRATE |
預設 115200,建置檢查範圍 1200–3000000。 |
GPIO_ARMLITE_UARTn_RX |
UARTn RX input GPIO。 |
GPIO_ARMLITE_UARTn_TX |
UARTn TX output GPIO;也可單獨供 direct log 使用。 |
UART GPIO 預設值:
| UART | RX | TX |
|---|---|---|
| UART0 | GPIO44 | GPIO45 |
| UART1 | -1 |
-1 |
| UART2 | -1 |
-1 |
| UART3 | -1 |
-1 |
| UART4 | -1 |
-1 |
| UART5 | -1 |
-1 |
UART1–UART5 的 -1 是「尚未設定」,啟用前必須改為 0–127 的有效 GPIO,且 RX/TX 不可相同。同一時間最多只允許一個 ArmLite UART 使用 DMA mode。UART0 interrupt mode 會實驗性地探測 controller-2 source 38;硬體路徑未被證實時會安全地初始化失敗。
6.5 ArmLite direct UART log
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_MCU_UART_LOG_ENABLE |
n |
ArmLite 直接從專用 UART TX 輸出 log,不經 Host CPU。 |
ARMLITE_MCU_UART_LOG_UART0–UART5 |
choice | 只能選擇一個未被 ArmLite UART test 佔用的 controller。 |
ARMLITE_MCU_UART_LOG_UART_PORT |
內部值 | 依 choice 轉成 port 0–5。 |
ARMLITE_MCU_UART_LOG_BAUDRATE |
115200 |
有效範圍 1200–3000000。 |
Direct log 會自動啟用 GPIO reservation,並將選定 UART 的 GPIO_ARMLITE_UARTn_TX 加入 owner/output mask。該 UART 不可同時用於 ArmLite UART loopback 或 Host console。ARMLITE_UART_CLAIM_UART0–UART5 為內部組合值,用來隱藏或阻止 Host 端重複使用同一 controller。
6.6 PWM
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_PWM_ENABLE |
n |
PWM 總開關,自動啟用 telemetry 與 GPIO reservation。 |
ARMLITE_PWM1_ENABLE |
y |
保留 PWM1 timer channel。 |
ARMLITE_PWM2_ENABLE–PWM8_ENABLE |
n |
保留額外 PWM channel。 |
ARMLITE_PWM_CHANNEL |
1 |
真正輸出測試波形的 channel,必須是已啟用 channel,且不可與 HW_TIMER 相同。 |
ARMLITE_PWM_FREQUENCY |
1000 |
PWM output frequency,單位 Hz。 |
ARMLITE_PWM_DUTY |
50 |
Duty cycle,有效範圍 1–99%。 |
GPIO_ARMLITE_PWM1 |
42 |
PWM1 output GPIO。 |
GPIO_ARMLITE_PWM2–PWM8 |
-1 |
啟用對應 channel 前必須設為有效 GPIO。 |
啟用某個 PWM channel 會保留它的 timer 與 GPIO,但只有 ARMLITE_PWM_CHANNEL 指定的單一 channel 會由 test firmware 輸出波形。所有已啟用 PWM GPIO 都會自動加入 owner/output mask。
6.7 GPIO frequency detect
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_FREQUENCY_ENABLE |
n |
啟用 GPIO rising-edge frequency measurement,並自動啟用 telemetry、GPIO 與 interrupt。 |
ARMLITE_FREQUENCY_EXPECTED_HZ |
1000 |
Host PASS/FAIL 的預期值,範圍 1–3000 Hz,Host 容許 5% 誤差。 |
ARMLITE_FREQUENCY_MAX_HZ |
3000 |
高於此頻率的 edge period 會被拒絕。 |
ARMLITE_FREQUENCY_TIMEOUT_MS |
2000 |
超過此時間沒有 rising edge 時判為 no signal。 |
GPIO_ARMLITE_FREQUENCY |
43 |
rising-edge input GPIO,自動加入 owner mask,方向為 input。 |
與 PWM 一起使用時,可將選定 PWM GPIO 接到 frequency GPIO。PWM frequency 必須與 expected frequency 一致,而 output GPIO 與 frequency input GPIO 不可使用同一支 pin。
6.8 Interrupt self-test
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_INTERRUPT_TEST_ENABLE |
n |
自動 select ARMLITE_INTERRUPT_ENABLE,週期觸發已探測到的 software interrupt bank。 |
此測試無需 GPIO。Telemetry 會報告 pass/fail、dispatch、unexpected interrupt 與 budget-exhaust counter。建議在啟用 UART interrupt mode 前,先單獨執行此測試確認 interrupt route。
6.9 SARADC
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_SARADC_ENABLE |
n |
僅限 IT9860 family;將 SARADC controller 交給 ArmLite,自動啟用 telemetry 與 GPIO reservation。 |
ARMLITE_SARADC_VALID_XAIN |
0xff |
XAIN0–XAIN7 有效 bit mask;bit0 對應 XAIN0。 |
ARMLITE_SARADC_CLOCK_DIVIDER |
9 |
SARADC clock divider,有效範圍 0–31。 |
XAIN GPIO 預設如下:
| XAIN | GPIO | XAIN | GPIO |
|---|---|---|---|
| XAIN0 | 19 | XAIN4 | 23 |
| XAIN1 | 20 | XAIN5 | 24 |
| XAIN2 | 21 | XAIN6 | 25 |
| XAIN3 | 22 | XAIN7 | 26 |
對應 config 為 GPIO_ARMLITE_XAIN_0–GPIO_ARMLITE_XAIN_7。這些 pin 會自動加入 owner mask,方向視為 input。ArmLite 使用 SARADC 時,Host CPU 不可同時啟用或存取正常 SARADC driver。
6.10 CAN bus
| Config | 預設 | 說明 |
|---|---|---|
ARMLITE_CANBUS_ENABLE |
n |
將 CANBUS1 交給 ArmLite;Host 不可同時使用 CANBUS1。 |
ARMLITE_CANBUS_FD_ENABLE |
n |
僅支援 IT9866_AT/9867_AT/9868_AT/9869_AT package。 |
GPIO_ARMLITE_CANBUS_RX |
-1 |
CAN RX GPIO,啟用前應設為有效腳位。 |
GPIO_ARMLITE_CANBUS_TX |
-1 |
CAN TX GPIO,啟用前應設為有效腳位。 |
CAN config 本身不會在 sdk/Kconfig 自動 select ARMLITE_GPIO_ENABLE,而目前 ArmLite GPIO ownership CMake 也沒有像 UART/PWM 一樣自動併入 CAN RX/TX。因此開發者必須額外確認 Host pin mux/driver 不會跟 CAN1 及這兩支 GPIO 衝突。若 project 要以通用 ownership 機制保護它們,可同時啟用 ARMLITE_GPIO_ENABLE 並將 RX/TX 列入 ARMLITE_GPIO_PINS,其中 TX 列入 ARMLITE_GPIO_DIR_PINS;但要確認這與 CAN driver 所需 mux 初始化順序一致。
6.11 存檔與建置檢查
存檔後應確認:
已更新為新設定。新增或修改 Kconfig symbol 後,必須重新開啟 qconf 並存檔,然後重新建置 ArmLite firmware 與 Host image。只有需要完全重置設定時,才刪除 .config 與 config.cmake。
建置期間會檢查常見錯誤,包含無效 GPIO、UART RX/TX 相同、多個 UART 同時使用 DMA、PWM test channel 未保留、PWM 與 scheduler timer 衝突、frequency input 與 PWM output 同 pin,以及 direction pin 不屬於 owner pin 等問題。
7. 建置與執行
在 SDK 的 build/openrtos 目錄執行:
建置會先以 Host project 的 config.cmake 建置 ArmLite firmware,產生 armliteMcu.plugin、armliteMcu.raw、armliteMcu.hex、disassembly 與 symbol 檔,再將 firmware 嵌入 Host image。
建置完成後執行:
run.cmd 會透過 glamomem 將 RAM image 載入開發板。若更換不同 DDR clock 的板子,必須在 Kconfig 同時調整 RAM_INIT_SCRIPT 與 DBG_INIT_SCRIPT。
8. 正常執行確認
Host console 應顯示測試名稱、實際接線、firmware bus clock、active peripheral mask 與各項 counter。檢查重點:
heartbeat持續增加,表示 ArmLite scheduler 正常運作。- Firmware active mask 與 Host 編譯的 test case 相同。
- 對應測試的 toggle/read/edge/UART/SARADC counter 持續增加。
- error、mismatch、unexpected interrupt 與 budget-exhaust counter 沒有異常增加。
- 連續三次健康 snapshot 後,Host 顯示 PASS。
9. GPIO demo 注意事項
GPIO demo 會找到第一個 owned output pin 作為輸出,並找到第一個 owned input pin 作為輸入,每 10 ms 切換輸出並取樣輸入。必須將 output 實體接到 input,loopback match count 才會增加。
ithGpioGet(pin) 回傳的是所在 bank 的 bit mask,不是固定的 0/1。顯示單一 GPIO level 時應寫成:
請避免以 GPIO 切換週期的整數倍進行輪詢。例如 MCU 每 10 ms 切換,Host 固定每 100 ms 讀取,可能每次都取到相同相位而誤以為 GPIO 沒有變化。可改為 17 ms 等非同步週期,或以 telemetry toggle/match counter 進行驗證。
10. UART log
啟用 CFG_ARMLITE_MCU_UART_LOG_ENABLE 後,ArmLite 可直接從選定 UART TX 輸出啟動設定與每秒狀態。預設為 UART0 TX GPIO45、115200 8N1。
該 UART controller 與 TX pin 不可同時由 Host console、UART loopback 或其他功能使用。UART TEST 或 ALL TEST 佔用 UART0 時,應將 direct log 移至其他未使用 UART,並正確設定其 TX GPIO。
11. Memory log 讀取
需先在 Kconfig 啟用 CFG_ARMLITE_MCU_LOG_DUMP。Host 啟動時會顯示類似:
進入 tool/bin/PrintArmLiteMcuDump 後執行:
--target 必須使用目前 project 對應的 glamomem.dat。常用選項:
# 顯示 ring buffer 現有內容後持續監看
python .\print_armlite_mcu_log.py --addr 0xXXXXXXXX `
--target .\glamomem.dat --print-initial
# 只顯示現有內容後結束
python .\print_armlite_mcu_log.py --addr 0xXXXXXXXX `
--target .\glamomem.dat --print-initial --no-loop
預設每 100 ms 輪詢。若每兩個字元的順序互換,加入 --word-endian big。
12. Exception backtrace
啟用 CFG_ARMLITE_MCU_BACKTRACE_DUMP 後,8 KB debug region 的前 7 KB 為 log,最後 1 KB 為 exception backtrace。Host 會另外顯示:
先將 Arm GNU toolchain 加入當前 PowerShell 的 PATH:
發生 Undefined instruction、Prefetch abort 或 Data abort 後執行:
python .\print_armlite_mcu_backtrace.py `
--addr 0xYYYYYYYY `
--target D:\path\to\glamomem.dat `
--elf D:\path\to\armliteMcu.plugin
--addr 必須是 backtrace address,不是 log address。armliteMcu.plugin 必須與板上執行的 firmware 完全相同,否則 function 與 source line 會解析錯誤。加入 --loop 可持續等待新的 exception dump。
13. 常見問題
Heartbeat 不增加
- 確認 firmware load 沒有失敗。
- 確認 DDR init script 與板子 clock 一致。
- 用 memory log 檢查 firmware 是否已啟動。
- 啟用 backtrace,檢查是否發生 exception。
GPIO 有 toggle count,但測試不 PASS
- 確認實體連接的是輸出與輸入腳,而非兩個 output。
- 確認
CFG_ARMLITE_GPIO_DIR_PINS與實際接線一致。 - 確認 pin mux 是 GPIO mode 0,沒有被其他周邊重複佔用。
- 檢查 loopback match/mismatch counter,不要只看單次 GPIO 輪詢值。
UART loopback 失敗
- 確認 TX/RX 交叉接線、baud rate 與 8N1 設定。
- 確認 UART controller/GPIO 沒有被 Host console 或 direct log 佔用。
- Interrupt mode 需先確認 ArmLite interrupt route,且 ALT CPU 必須停用。
- DMA mode 固定使用 DMA channel 6/7,同一時間只能有一個 ArmLite UART 使用 DMA。
Dump 工具報 invalid magic 或無法讀取
- 使用 Host console 當次顯示的實際 address。
- 確認
--target不是其他 project 的glamomem.dat。 - 確認
CFG_ARMLITE_MCU_LOG_DUMP已啟用,且 firmware 已執行armliteMcuLogInit()。 - Backtrace 只會在 exception 發生後出現,並必須使用相同 build 的 ELF。
14. 開發建議
- 一次先啟用一個 test case,確認基本功能後再使用 ALL TEST。
- 修改周邊腳位時,同時檢查 GPIO ownership、direction、pin mux 與 Host console。
- 保留每次上板 image 對應的
armliteMcu.plugin,以便之後解析 backtrace。 - 判斷系統健康時,優先使用 telemetry counter,單次的 GPIO 或 register 讀值只作為輔助資訊。
- « Previous
- 1
- 2
- Next »