# [手機裡的 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) * [Introductionthe 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)