# [手機裡的 ARM 處理器](http://hackfoldr.org/arm): 隱藏的精靈 Cortex-M
**Copyright (C) 2017 Jim Huang (黃敬群) <jserv.tw @ gmail.com>**
:::warning
:warning: 注意
請透過 gitter (線上對話服務,可透過 GitHub 或 Twitter 帳號登入) 提交疑問和建議事項: [guts-general](https://gitter.im/embedded2015/guts-general) (按下去就對了)
:::
==[直播錄影](https://www.youtube.com/watch?v=v6kiSWCziDc)==
## 目標設定
我們將著重 Cortex-M,預計探討以下:
(3) 硬體特性: 指令集, 中斷處理, 運作模式, 電源管理, 除錯機制
(4) 一致的軟體介面 CMSIS
(5) 我們提出的系統軟體解決方案: F9 microkernel, Piko/RT, BitSec hypervisor
## 從 8 位元到 32 位元的 MCU 市場
* [為什麼 8 位元 MCU 歷久不衰?](http://archive.eettaiwan.com/www.eettaiwan.com/ART_8800715272_622964_NT_e4af5b0c.HTM)
* 1972 年,Intel 推出第一款 8 位元微處理器 [Intel 8008](https://en.wikipedia.org/wiki/Intel_8008)
* 同樣在 1972 年,Apollo 17 登陸月球。福斯金龜車(Volkswagen Beetle) 銷售量超過福特 T 系列(Ford Model T),成為有史以來最暢銷的車款。電影「教父」(The Godfather) 可說是當時全世界最賣座的電影
* 16-bit 與 32-bit 元件每年分別成長 7% 和 10%; 8-bit 的年成長率僅 0.7%
* 在汽車產業,大部份基於 CAN 與 Flexray 的應用對 8-bit 來說都太過先進
* 許多 IoT 裝置以及先進的馬達控制應用也超出 8-bit 的能力範圍
* 同場加映: [MCU 8位元市場 大廠不玩 台廠好樂](http://www.appledaily.com.tw/appledaily/article/finance/20131029/35398198/) ==真。台灣風格的新聞標題==
* [整併浪潮讓全球 MCU 供應商排名大風吹](http://www.eettaiwan.com/news/article/20170508NT03-NXP-Acquires-Freescale-Becomes-Top-MCU-Supplier-In-2016)
* 2016 年是 IC 產業劇烈整併的一年,全球前三大 MCU 供應商依序為 NXP、Microchip 以及Cypress,都是因為收購案而擴大了營收規模
* 反觀那些並沒有進行收購的 MCU 廠商,2016 年營收僅呈現個位數字成長甚至衰退
* NXP 在 2015 年 12 月完成對 Freescale 的收購 (以 116 億美元總價),並達到 116% 的 MCU 營收成長率
* Renesas 在 2015 年的 MCU 營收衰退 19% (有大部分原因是日圓貶值以及日本經濟景況不佳);在 2016 年,Renesas 的 MCU營收又衰退了 4%,來到約 25 億美元,全球市佔率為 16%。而在 2011 年,Renesas 在全球 MCU 市場的營收佔有率為 33%
* NXP 全球市佔率達 19% (年度營收 29 億美元);NXP 在 2015 年的 MCU 營收中,有四分之三是應用於智慧卡的 8 位元與 16 位元 MCU,在合併 Freescale 之後,智慧卡 MCU 營收僅佔據公司整體 MCU 營收的四分之一左右
* Cypress 年度營收成長 15%,來到約 6.22 億美元;Cypress 在 2015 年 3 月以 50 億美元的股票交換收購 Spansion,後者是 AMD 獨立而出的 NOR 快閃記憶體供應商,後來在 2013 年以 1.1 億美元收購了日商 Fujitsu Semiconductor 的 MCU 與類比業務部門,擴展記憶體以外業務
* 衰退最多的是 Samsung,2016 年銷售額衰退幅度達 14%,主要是因為智慧卡微控制器市場衰弱不振
* [32 位元 MCU 軟體的改變](https://wallace7914032.blogspot.tw/2013/10/32mcu.html) (2013 年)
* 32-bit MCU 突然在三年內劇降,直接壓縮了市場,價格直逼 8-bit
* 16-bit 變成沒有空間:比價格比省電,不如 8-bit
* 16-bit 比效能不如 32-bit
* 32-bit 不僅是核心快,週邊多到爆
* 32-bit 對 MCU 是一場革命,是一場軟體工程師對嵌入式系統主導設計的使用習慣變革
* 大部分硬體信號可以由 MCU 內部軟硬體結構出來
* ADC/DAC 精密度提高,使得濾波器可以使用軟體來做
* Flash 容量一下子到 1 MB 以上,多到可以做磁碟機來用
* 一但檔案系統出現,連資料庫都可以放進去
* 反觀 8-bit/16-bit 如果要達到相似效果,程式有得大改,且大部分 PC 上的軟體多以作業系統下做主,移到 8-bit/16-bit 會是大工程。32-bit 因有 RTOS,所以問題小很多
* 這波革命是新的,軟體工程師正在變成一般勞工。若不升級,難保工程師之名
* [微電網+區塊鏈=?Energo Labs 讓家家戶戶成為清潔微型電廠](https://www.xcnnews.com/kj/411065.html)
* 傳統的電力體系中由集中電廠發電,再運輸到各家各戶的網路中傳輸電力,終端用戶和工業用電用戶通過電錶核算,再由售電公司以及支付供應商支撐交易和結算網路
* 傳統供電體系電源傳輸過程長、損耗高、中心化採集交易成本高,而且由於電力體系市場競爭不充分,電廠掌握了能源的主導議價權,用戶面對高定價的電費毫無議價權
* 隨著太陽能電板成本價下跌、融資租賃方式普及,普通家庭也可以用太陽能電板自行生成電力,除了自給自足之外,剩餘電力還可以儲存、以及就近進行 P2P 交易,為個體戶帶來收益
* 請洽 [jserv 與他愉快的小夥伴](https://www.facebook.com/JservFans/),我們也在從事區塊鏈相關的應用和基礎研發工作,從 [證書區塊鏈](https://www.facebook.com/ncku.edu.tw/posts/1690201447680732) 著手,即將切入能源領域
* 2015 年第 2 季,ARM Holdings 公佈的[處理器出貨量比例](https://www.facebook.com/photo.php?fbid=10153487820517389&set=gm.745081762304978):
* Classic (ARM7/ARM9/ARM10/ARM11): 36%
* Cortex-A: 17%
* Cortex-R: 7%
* Cortex-M: 40%
* 第一項是台灣許多 IC 設計公司還採用的舊架構 (Classic),但我們可顯然看到 Cortex-M 在 2015 年第二季已超越 Classic。同時,Embedded 在市場產品分類佔了 43%,其次則是 Mobile and connectivity 佔 40%
## 為什麼要選 Cortex-M ?
* 簡單的回答
* low-latency
* deterministic
* code density
* SW reuability
* [ARM Roadmap 2017 Spring.pdf](http://wiki.csie.ncku.edu.tw/embedded/arm-roadmap-2017q1.)
* 市場需求區隔成 M0, M3, M4 與 M7 的等級
* Cortex-M0 主打初階 8/16 位元應用
* Cortex-M3 主打中階的 16/32 位元應用
* Cortex-M4 主打高階 32 位元與 DSP 應用
* Cortex-M7 主打旗艦級的高階自動化生產與 IoT 應用
* Cortex-M 系列 (從 ARMv6-M, ARMv7-M, 到 ARMv8-M; 32-bit)
* TrustZone
* [High-end security feature for low-end microcontrollers: Hardware-security acceleration on ARMv8-M systems](https://www.openpcd.org/dl/High-end%20security%20for%20low-end%20microcontrollers%20-%20Hardware-security%20acceleration%20on%20ARMv8-M%20system%20-%20Meriac%20Yiu.pdf)
## Cortex-M 系列概述
* Cortex-M 的資料一定要找權威 (如 Arm 官方網站) 和更新夠快的材料如 Wikipedia [ARM Cortex-M](https://en.wikipedia.org/wiki/ARM_Cortex-M)
* [Introduction the ARM Cortex-M](http://wiki.csie.ncku.edu.tw/embedded/arm-exceptions.pdf)
* 簡報撰寫於 2012 年,部份資訊過時,請留意
* Cortex-M 都「沒有」MMU,但 M7 (6 stages pipeline!) 提供 cache
* 選擇性的 MPU
* ARMv6 支援 unaligned data,可加快處理速度,參見 [Take advantage of ARM unaligned memory access while writing clean C code](http://stackoverflow.com/questions/32062894/take-advantage-of-arm-unaligned-memory-access-while-writing-clean-c-code)
* ARM7TDMI 在市場具有幾十億的量
* Cortex-M 用來取代原本的 ARM7TDMI
* Cortex-M 只支援 Thumb-1 和 Thumb-2 指令,而 32-bit ARM 指令則==不支援==
* Cortex-M3 具有 2 種 operation mode
* thread-mode
* handler-mode
* Cortex-M3 具備 2 種 privilege level
* Cortex-M3 register: PSP, MSP (r13)
* 透過 MRC, MCR 存取 special register
* 早期的 ARM Interrupt controller 是獨立的,而 Cortex-M 將 interrupt controller 內建 (NVIC)
* Cortex-A: Generic Timer
* Cortex-M: System Timer
* CPU 開始運作會觸發 exception 叫做 `reset`
* reset 和 NMI 以外的中斷都可以被屏蔽(和「關閉」不同)
* 在 ARM Classsic 中的 CPSR->SPSR,已不復於 Cortex-M 存在
* Interrupt Pending( 重要!) p .31
* 注意從 interrupt request -> interrupt pending status -> processor mode 的變化
* 當收到 external interrupt 時,interrupt pending status會從 L -> H (由硬體觸發)
* 而 interrupt pending status 由 H -> L 是由軟體去清掉,稱作 software clear
* p.33 interrupt returned -> exception return
* 在 rising -> falling 轉換中是有時間成本的
* 如果這過程中有其他事件,怎麼辦 ?可見 p.34
* 一定要 request 發生,才會觸發 pending status 的改變
![](https://hackpad-attachments.s3.amazonaws.com/embedded2015.hackpad.com_PLZhxd8JpQ4_p.340774_1439799643923_undefined)
* Rising Edge 和 Falling Edge 的過程時間是 ns 級,還是會有時間成本的
* 重點回顧
* NVIC, pipeline, SysTick, AMBA lite, ETM/SWD, FPU
* power managemnt (WFI, WFE)
* operation mode & priviledge level
* MPU
* Register
* 延伸閱讀: [嵌入式系統建構:開發運作於STM32的韌體程式](https://docs.google.com/document/d/1Ygl6cEGPXUffhTJE0K6B8zEtGmIuIdCjlZBkFlijUaE/edit)
## SWV/SWO/ITM
- [ ] multichannel printf() redirection to a debugger console using SWV/ITM ([source](https://twitter.com/Atollic/status/899466211821588485))
![](https://pbs.twimg.com/media/DHuLvabXYAAalsZ.jpg)
- [ ] Real-time variable watch using SWV/SWO ([source](https://twitter.com/Atollic/status/898741518239883264))
![](https://i.imgur.com/yReOUYa.png)
- [ ] Performance optimization using #SWV statistical profiling ([source](https://twitter.com/Atollic/status/898379240076439552))
![](https://pbs.twimg.com/media/DHevJ8gW0AMTmy_.jpg)
- [ ] Measure execution time using SWV/ITM ([source](https://twitter.com/Atollic/status/895721692345106432))
![](https://pbs.twimg.com/media/DG4-H9GUQAAqnPg.jpg)
## ARM Cortex-M 機制
首先我們先看到 ARM Cortex-M3的架構圖,今天我們要來介紹 M系列的 Nested Vectored Interrupt Controller (NVIC)是什麼以及他如何達到 Deterministic 和 Low-Latency
![](https://i.imgur.com/rTas6qf.png)
首先什麼是 Nested Interrupt?
> Ans: Interruptible Interrupt with priority
> Ref: https://stackoverflow.com/questions/34527763/linux-nested-interrupts
Nested Interrupt 帶給我們什麼好處?
* Preemptive
* Deterministic
NVIC的特色之一就是硬體實現 Nested Interrupt
### 超有用連結
> [M系列資源總整理](https://community.arm.com/processors/b/blog/posts/cortex-m-resources)[name=Yen-Kuan Wu][color=#f99c95]
# ARM v7-M
> 主要參考 [Armv7-M Architecture Reference Manual](https://static.docs.arm.com/ddi0403/e/DDI0403E_c_armv7m_arm.pdf)
> Chapter B1 - System Level Programmers’ Model[name=Yen-Kuan Wu][color=#f99c95]
* Operating modes
* Thread mode
* Handler mode
* Privilege level
* Privileged
* Unprivileged
* Stack pointers: banking
* Main stack pointer
* Process stack pointer
![](https://i.imgur.com/LiOtvko.png)
## Registers
![](https://i.imgur.com/qPRzXkP.png)
* **==xPSR==** 由以下3個 Register組成
* Application Program Status Register (APSR)
* Interrupt Program Status Register (IPSR)
* Execution Program Status Register (EPSR)
![](https://i.imgur.com/jvl1X0n.png)
* **==PRIMASK, FAULTMASK, BASEPRI==**
![](https://i.imgur.com/oHu78mP.png)
* **==Control==**
![](https://i.imgur.com/V2llUQ2.png)
> Ref: [Definitive Guide To the ARM Cortex-M3.pdf](https://www.eecs.umich.edu/courses/eecs373/labs/refs/M3%20Guide.pdf#page=53)[name=Yen-Kuan Wu][color=#f99c95]
# Exception
Exception是改變了正常Program流程的一個條件觸發
他包含了兩個階段:
* Exception generatoin
* 產生 Exception event並交付給處理器
* Exception processing
* 他是一系列的流程,包含以下3個階段
* Exception entry
* Exception handle
* Exception return
> Ref: [rtenv - Cortex-M機制](http://wiki.csie.ncku.edu.tw/embedded/rtenv)
> Ref: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Babefdjc.html[name=Yen-Kuan Wu][color=#f99c95]
每一個 Exception 有以下:
* Exception number
* Priority level
* ISR
Exception state 有以下:
* Inactive
* Pending
* Active
* Active and pending
Priority levels
Execution priority
## Exception categories
* Reset
* Supervisor call (SVCall)
* Synchronous: 透過 `svc`指令所產生的 exception
* Asynchronous: Interrupt-driven Supervisor-calling mechanism, PendSV
> * Synchronous exception: 指 exception generation 發生在明確的 Instruction stream
> * Aasynchronous exception: 反之[name=Yen-Kuan Wu][color=#f99c95]
>
>> Ref: https://community.arm.com/processors/f/discussions/8569/armv7-m-question-about-syn-asynchronous-exception/28994#28994[name=Yen-Kuan Wu][color=#4d5daf]
* Fault
* 錯誤發生時產生的 exception
* Interrupt
* 上列三者以外的,都是歸類為 Interrupt,而且所有 Interrupt都是屬於 asynchronous exception
## Overview of exceptions
* Reset
* 分成兩種
* Power-on reset
* Local reset
* Non Maskable Interrupt (NMI)
* HardFault
* handle faults which can't handle by other exception mechanisms
* 永久 Enable
* MemManage
* handle memory proctection fault
* BusFault
* memory realted fault
* UsageFault
* Non-memory related fault
* Undefined Instruction
* Invalid state on instruction execution
* Error on exception return
* [Optional]: unalinged memory access
* [Optional]: Division by zero
> Optional 是指可以自己規範要不要接收這些錯誤[name=Yen-Kuan Wu][color=#f99c95]
* SVCall
* Interrupts
* 系統層級的包含
* PendSV
* SysTick
* Others: uart, i2c, ...
![](https://i.imgur.com/j1YCoHv.png)
## [SVC, PendSV的介紹](http://wiki.csie.ncku.edu.tw/embedded/arm-exceptions.pdf#page=39)
* SVC
* 使用`svc`這個 instruction所啟動的 Interrupt,SVC是屬於 Synchronous Exception
* impl syscall
> code:
https://github.com/Piko-RT/pikoRT/blob/master/libc/piko/syscalls.S#L8
* PendSV
* Interrupt-driven Supervisor-calling mechanism
> code:
https://github.com/Piko-RT/pikoRT/blob/master/drivers/timer/systick.c#L110
### HardFault, MemFault, UsageFault, BusFault
demo: hardfault for piko
code:
https://github.com/Piko-RT/pikoRT/blob/master/arch/v7m-faults.c#L32
![](https://i.imgur.com/xLoIu97.jpg)
### Tail-chaining
這是一個非常強大的機制,當現在處理的 Interrupt結束時,會去跟下一個 Interrupt的 Priority比較,如果沒有達到 Preemption的需求,他將會 trigger tail-chaining這個機制,核心概念就是當目前有其他的 interrupt pending,應該儘快處理下一個 interrupt而不必回去 user context。
![](https://i.imgur.com/a5bmpW1.png)
### Late-arrival
這個機制就如同字面上的解釋,處理哪個 Interrupt可以在 Stacking之後再決定,所以 IRQ1 雖然比較晚到(優先權更高),但他卻可以先被處理。
![](https://i.imgur.com/B2x9vpM.png)
Reference:
* [Introduction: the ARM Cortex-M3 Exception / Interrupt](http://wiki.csie.ncku.edu.tw/embedded/arm-exceptions.pdf)
* [A Beginner’s Guide on Interrupt Latency - and Interrupt Latency of the Arm Cortex-M processors](https://community.arm.com/processors/b/blog/posts/beginner-guide-on-interrupt-latency-and-interrupt-latency-of-the-arm-cortex-m-processors?CommentId=9cca204a-05eb-4ffb-8ead-dc4243e98f59)
* [Using Cortex-M3/M4/M7 Fault Exceptions](http://www.keil.com/appnotes/files/apnt209.pdf)
* [ARM® Cortex®‑M4 Processor Technical Reference Manual](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100166_0001_00_en/index.html)
## CMSIS
有使用過嵌入式系統的朋友都知道有一種痛,叫作查 Reference Manual,不外乎就是找我要寫入或讀取哪個記憶體位置才能設定 Timer,這邊要特別注意的是從 0xA0000000 - 0xEFFFFFFF 其實是定址空間的範圍中,硬體暫存器對應的位址,也就是所謂的 Peripheral Register Mapping,以下是 M系列的 Memory Map
![](https://i.imgur.com/GlfHPyD.png)
而 Cortex Microcontroller Software Interface Standard (CMSIS) 能幫我們省去這個麻煩,他有定義一系列的 Macro,讓我們使用,不僅如此,有了 CMSIS 還能讓我們很輕鬆的 Porting到其他 M 系列,以下是他的架構圖:
![](https://i.imgur.com/wt3pb34.png)
我們比較常使用的是 CMSIS-CORE 這部份,它讓我們能更容易的操作 Peripheral Register
code:
https://github.com/Piko-RT/pikoRT/blob/master/target/stm32p103/init.c#L136
Reference:
* [CMSIS-doc](http://www.keil.com/pack/doc/CMSIS/General/html/index.html)
## STM32Cube HAL
![](https://i.imgur.com/uJQtc8Y.png)
code:
https://github.com/Piko-RT/pikoRT/blob/master/target/stm32f429/init.c#L32
Reference:
* [STM32Cube-doc](http://www.keil.com/pack/doc/STM32Cube/General/html/index.html)
注意到上面寫到支援 Interrupts的上限,和可支援的 Priority區間,這邊注意到這是官方給定的,但還是要由平台製造商(STMicro, NXP ...)決定。
![](https://i.imgur.com/1t9HnZ8.png)
這邊特別補充一下 NVIC支援的 Priority,在即時系統裡,我們希望愈高 Priority的任務可以愈快得到回應或開始執行,這同理到 Interrupts上,照裡來說 Systick 的 Priority應該要比 UART RX還來得高,因為時間的更新是比較重要且這關係到任務的排程,所以高優先權的 Interrupt是可以 Preempt低優先權的 Interrupt。
介紹完 NVIC的特性之後我們可以開始介紹不同的 Exceptions了
![](https://i.imgur.com/j1YCoHv.png)
注意到幾個欄位,分別是 Priority 和 Vector address,有一些 Interrupt 的 Priority是固定的,也有一些是 Configurable,再來是 Vector address,也就是他們相對應的 Handler在 Vector Table的 offset。
![](https://i.imgur.com/2LZKZfw.png)