精選文章
RTOS - Jserv IoT 作業系統 - 前置學習 - vector table - hard fault handler
收錄於 : 關於Ameba的一百篇
前篇: Ameba assembly-2
剛好 Jserv 要來打造一套 cortex-M3 上的 IoT 作業系統.
這邊 RTOS 介紹來跟著這個進度前進.
--- Jserv 的 議程介紹
從無到有打造 IoT 作業系統
https://www.facebook.com/events/645044348986795/
"[Event] 6 月 27 日晚間,Jserv與他愉快的小夥伴 首度在台北透過 YouTube進行網路直播,主題是「從無到有打造 IoT 作業系統核心」,將以 ARM Cortex-M3 為例,探討具體而微的作業系統核心的設計與實做,從 Hello World 等級的程式開始,逐步演化為原始程式碼 400
行內、支援多執行緒、搶佔式 (preemptive) 多工作業系統核心。
有興趣的朋友,記得先閱讀相關材料:https://embedded2016.hackpad.com/-IoT--VzsIQuEJcbo"
** 直播網址: https://www.youtube.com/c/ GUTS4tech/live **
無論人們對 Internet of Things (IoT) 抱持再大的幻想,IoT 本質上仍是嵌入式系統,自然高效率又富有彈性的作業系統 就是箇中重要議題。本次直播將以 ARM Cortex-M3 為例,探討具體而微的作業系統核心的設計與實做,從 Hello World 等級的程式開始,逐步演化為原始程式碼 400 行內、支援多執行緒、搶佔式 (preemptive) 多工作業系統核心。
注意須知:
(a) 本議程後續會持續更新,建議預習各項材料:
http://hackfoldr.org/ oscar/
(b) 聽眾需要 ARM 背景知識,直播過程中只會作重點提示
無論人們對 Internet of Things (IoT) 抱持再大的幻想,IoT 本質上仍是嵌入式系統,自然高效率又富有彈性的作業系統
注意須知:
(a) 本議程後續會持續更新,建議預習各項材料:
http://hackfoldr.org/
(b) 聽眾需要 ARM 背景知識,直播過程中只會作重點提示
---
如果這篇只有上面敘述, 大概就變成廣告文了, 這篇來介紹一下 vector table 好了.
上述筆記內提到的參考文件也有介紹 - http://wiki.csie.ncku.edu.tw/embedded/arm-exceptions.pdf
上述筆記內提到的參考文件也有介紹 - http://wiki.csie.ncku.edu.tw/embedded/arm-exceptions.pdf
之前 在 main function 有稍微介紹了一下, 這篇再補充一下.
- 有 general registers (R0~R12) 和 special registers
--
processor mode and privileged levels
operation mode : thread mode / handler mode
access level : privileged mode / non-privileged mode
access mode : 分成有權限和沒權限 狀態. 這邊權限指:
- CPS , MSR/MRS
- system timer, NVIC, system control block
- MPU : memory access
handler mode : 是 interrupt / system exception 系統自動進入, 此時是在 privileged mode .
reset 時 一開始是在 thread mode,
--
vector table : 一開始是指在 0x0000 0000 位置
可以 透過 vector table offset register (VTOR) 來做改變
system control block : VTOR register 位置 是在 0xE000ED08
4.3. System control block
The System control block (SCB) provides system implementation information, and system control. This includes configuration, control, and reporting of the system exceptions. The system control block registers are:
Table 4.12. Summary of the system control block registers
Address | Name | Type | Required privilege |
Reset value
| Description |
---|---|---|---|---|---|
0xE000E008 | ACTLR | RW | Privileged | 0x00000000 | Auxiliary Control Register |
0xE000ED00 | CPUID | RO | Privileged | 0x412FC230 | CPUID Base Register |
0xE000ED04 | ICSR | RW [a] | Privileged | 0x00000000 | Interrupt Control and State Register |
0xE000ED08 | VTOR | RW | Privileged | 0x00000000 | Vector Table Offset Register |
0xE000ED0C | AIRCR | RW [a] | Privileged | 0xFA050000 | Application Interrupt and Reset Control Register |
0xE000ED10 | SCR | RW | Privileged | 0x00000000 | System Control Register |
0xE000ED14 | CCR | RW | Privileged | 0x00000200 | Configuration and Control Register |
0xE000ED18 | SHPR1 | RW | Privileged | 0x00000000 | System Handler Priority Register 1 |
0xE000ED1C | SHPR2 | RW | Privileged | 0x00000000 | System Handler Priority Register 2 |
0xE000ED20 | SHPR3 | RW | Privileged | 0x00000000 | System Handler Priority Register 3 |
0xE000ED24 | SHCRS | RW | Privileged | 0x00000000 | System Handler Control and State Register |
0xE000ED28 | CFSR | RW | Privileged | 0x00000000 | Configurable Fault Status Register |
0xE000ED28 | MMSR [b] | RW | Privileged | 0x00 | MemManage Fault Status Register |
0xE000ED29 | BFSR [b] | RW | Privileged | 0x00 | BusFault Status Register |
0xE000ED2A | UFSR [b] | RW | Privileged | 0x0000 | UsageFault Status Register |
0xE000ED2C | HFSR | RW | Privileged | 0x00000000 | HardFault Status Register |
0xE000ED34 | MMAR | RW | Privileged | Unknown | |
0xE000ED38 | BFAR | RW | Privileged | Unknown | BusFault Address Register |
0xE000ED3C | AFSR | RW | Privileged | 0x00000000 | Auxiliary Fault Status Register |
---
我們可以寫一段 簡單的 程式, 看 VTOR 設定
// the setup function runs once when you press reset or power the board
void setup() {
uint32_t address;
// initialize digital pin 13 as an output.
Serial.begin(38400);
address = *(uint32_t*)(0xE000ED08);
Serial.print("VTOR address : ");
Serial.print(address, HEX);
while(1);
}
// the loop function runs over and over again forever
void loop() {
}
--
結果 在 Ameba 上顯示 0x1000 0000, 這是 Ameba RAM 一開始的位置.
vector table 長相如下 : 在前一篇 RTOS, 我們在 variant.cpp 置換 SVC / PendSV / SysTick 成 RTOS 用的.
在這篇, 我們簡單介紹一下 Hard Fault
Hard Fault 在向量表中位於 0xC 這個位置.
可以把它印出來,
void setup() {
volatile uint32_t *ptr;
...
ptr = (uint32_t*)(0x1000000C);
address = *ptr;
Serial.print("Hard fault function : ");
Serial.println(address, HEX);
...
}
可以發現位置是在 0x0000 010D. 屬於 ROM function code. 看不到
--
來寫一個 hard fault 處理程式, 並把函式位置填入 中斷向量表, 換成我們寫的處理程式
void test_hardfault(void)
{
Serial.print("My hard fault");
while(1);
}
void setup() {
...
ptr = (uint32_t*)(0x1000000C);
*ptr = (uint32_t)(&test_hardfault);
...
}
執行結果 :
Hard fault function : 10004ED
置換成功.
PS: 如果把 while(1) 去掉, 會發現一直進去, 這是因為我們 hard fault function 還沒寫清除 status
--
我們來製造一個 除0 產生的 hard fault.
b = 0;
a = 3/b;
Serial.println(a);
執行結果 : 印出 0, 奇怪怎麼沒有 hard fault.
The bit assignments are:
Table 4.20. CCR bit assignments
Bits | Name | Function |
---|---|---|
[31:10] | - | Reserved. |
[9] | STKALIGN |
Indicates stack alignment on exception entry:
0 = 4-byte aligned1 = 8-byte aligned.
On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment.
|
[8] | BFHFNMIGN |
Enables handlers with priority -1 or -2 to ignore data BusFaults caused by load and store instructions. This applies to the hard fault, NMI, and FAULTMASK escalated handlers:
0 = data bus faults caused by load and store instructions cause a lock-up
1 = handlers running at priority -1 and -2 ignore data bus faults caused by load and store instructions.
Set this bit to 1 only when the handler and its data are in absolutely safe memory. The normal use of this bit is to probe system devices and bridges to detect control path problems and fix them.
|
[7:5] | - | Reserved. |
[4] | DIV_0_TRP |
Enables faulting or halting when the processor executes an
SDIV or UDIV instruction with a divisor of 0:
0 = do not trap divide by 0
1 = trap divide by 0.
When this bit is set to 0, a divide by zero returns a quotient of 0.
|
[3] | UNALIGN_TRP |
Enables unaligned access traps:
0 = do not trap unaligned halfword and word accesses1 = trap unaligned halfword and word accesses.
If this bit is set to 1, an unaligned access generates a UsageFault.
Unaligned
LDM , STM , LDRD , and STRD instructions always fault irrespective of whether UNALIGN_TRP is set to 1. |
[2] | - | Reserved. |
[1] | USERSETMPEND |
Enables unprivileged software access to the STIR, see Software Trigger Interrupt Register:
0 = disable1 = enable.
|
[0] | NONBASETHRDENA |
Indicates how the processor enters Thread mode:
0 = processor can enter Thread mode only when no exception is active
1 = processor can enter Thread mode from any level under the control of an EXC_RETURN value, see Exception return.
|
程式加入 :
value = *(uint32_t*)(0xE000ED14);
Serial.print("CCR : ");
Serial.println(value, HEX);
值為 200 : 表示目前系統只有設定 stack alignment / 8-byte alignment
我們把 divide 0 trap 設定進去 : bit4
ptr = (uint32_t*)(0xE000ED14);
*ptr = *ptr | 0x10;
執行結果 :
印出 My hard fault
達成
PS: hard fault handler 製作 , 也是門學問,
這篇有介紹如何設定成 gdb 中斷, 和利用 ITM
https://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/
相關 register 介紹可以參考 ARM 這份文件
http://www.keil.com/appnotes/files/apnt209.pdf
留言
張貼留言