---
title: '嵌入式系統 - 基礎概念'
disqus: kyleAlien
---
嵌入式系統 - 基礎概念
===
## OverView of Content
[TOC]
## 嵌入式 - 定義
嵌入式系統的定義較為模糊,依照 `嵌入式系統 - 實戰指南 面向 IoT 應用` 定義: 嵌入式系統面向各類具有,**++獨立功能++**、可完成特定任務的 **++低功號++**、**++低成本++** 微型設備
### 嵌入式 - 系統比較
:::success
* 用系統的角度來看:嵌入式系統往往不需要多餘的外部設備 (或很少),就可以跟外部通訊
> e.g:串口、藍芽
:::
* 下表示大部分 `嵌入式系統` & `AP/PC 系統` 的比較
| 比較項目 | 嵌入式系統 | AP/PC 系統 |
| -------- | -------- | -------- |
| CPU | 8/16/32 bit | 32/64 bit |
| 指令集 | RISC (精簡指令集) 為主,幾乎不使用 CISC (複雜指令集) | RISC/CISC |
| 主頻 (全速) | <= 200MHz | > 1GHz |
| 功耗 (全速) | < 100mA | >= 100mA |
| RAM | `SRAM` 為主,為單位 KB,大部分內嵌 | `SDRAM`/`DDR` 為主,單位為 MB/G,大部分外插 |
| Flash | `NOR - Flash` 為主,為單位 KB,大部分內嵌 | `NAND - Flash` 為主,單位為 MB/G,大部分外插 |
| 操作系統 | 無 / RTOS | Linux、Android、iOS、Window、Mac |
| 人機接口 | 簡單一般不設計 GUI | 支持 GUI |
:::info
手機的架構與 PC 越來越相似,所以不列入 嵌入式系統 範疇 (功耗大、更專注在用戶使用)
:::
* 嵌入式系統架構主要分為:硬體、軟體
* 硬體:決定了系統的複雜性、成本、軟體的實現邏輯
* 嵌入式系統 & 非嵌入式系統的差異,以最大的差異來說就是外置設備的要求不同,**AP 需要更多的外部設備** (綠色代表必要)
> MCU (`Micro Computor`) 代表了 Soc (`System on chip`)
>
> AP 是應用處理器 Application Processor
>
> 
### RAM & Flash
* RAM 是隨機訪問存储器的簡稱,**^1.^ ++隨機訪外++ 代表可以在 RAM 的任意存储單元讀寫**,**^2.^ 斷電後數據會遺失**
> RAM 還有細分為 SRAM、SDRAM、DDR ... 等等,如果沒有特別說明的話 RAM 一般是指 SRAM (`static Random-Access Memory`)
* Flash 程式存储器,**不能隨機訪問單個存储單元,只能 ^1.^ ++批量訪問++;最常見的是按照 Page、Block 來讀寫 Flash**,**^2.^ 斷電後數據不遺失**
> E.g. `NOR-Flash`、`NAND-Flash`
* 兩者還有一大差異為 **速度、價錢**,Flash 速度較慢但便宜,而 RAM 相反
> 
## 硬體架構
### MCU 架構 - [AT32F407](https://www.arterytek.com/cn/product/AT32F407.jsp)
* 單晶片機:把許多物件都集成到一個 Chip 上 (電源、時鐘、MCU) 這種簡單的最基礎集成就稱為單晶片機
:::success
* **與 SoC 的差異?**
SoC 可以集成更多的外部物件
:::
單晶片機: 8051 (51 系列 8 bit 機)、MSP430 (16 bit 機)、ARM (32 bit 機)
* 在這裡我們看 [**AT32F407**](https://www.arterytek.com/cn/product/AT32F407.jsp) MCU 系統框圖 (可下載 MCU Datasheet 查看),並說明幾個重點
> 
1. **核心 MCU**:這裡是使用 **ARM Cortex M4F** 內核,它是 MCU 的大腦,決定了 MUC 的性能
2. **總線**:ARM 系列的 CPU 最常見的總線有三種;^1.^ **AHB** (`Advanced High-performance Bus`)、^2.^ **APB** (`Advanced Peripheral Bus`)、^3.^ **AXI** (`Advanced eXtensible Interface`) AXI 這種高階總線通常出現在 AP 系統晶片中
* **AHB 總線**:AHB 是高性能、高速總線,在該總線上的元素都比較重要,AHB 總線上大部分有以下元素 (並非一定)
| 元素 | 補充 |
| - | - |
| RAM | 隨機訪問記憶體 |
| Flash | 區塊訪問記憶體,不流失數據 |
| DMA | Direct Memory Access,可以在不干涉內核的狀況下訪問 RAM,在吞吐量較高的情況下性能高 |
| 以太網 MAC | 有線網路的硬體接口 |
| GPIO | 一般像是螢幕顯示就需要這樣的高速 |
最後可以看到 AHB 下有接上兩個 APB 橋接器
> 
:::warning
* 為何不把所有設備掛在 AHB 總線上 ?
1. AHB 總線上的裝置,可直接與內核通訊,尋址方式複雜
2. AHB 自帶的 **硬體 ==仲裁== 機制**,如果過多的設備,其複雜度又會以指數型成長
:::
* **APB 總線**:APB (240MHz) 總線上的時鐘速度 **只有 AHB (120MHz) 總線速度的一半**
| 元素 | 補充 |
| - | - |
| SPI | `Serial Peripheral Interface`,串行外設接口,用於短距離的設備通信,例如感測器和閃存 |
| UART | `Universal Asynchronous Receiver/Transmitter`,通用異步收發器,常用於串行通信 |
| I^2^C | `Inter-Integrated Circuit`,集成電路之間的串行通信總線,用於連接低速設備如 EEPROM 和 ADC |
| USB | `Universal Serial Bus`,通用串行總線,用於連接外部設備,例如鼠標、鍵盤或存儲設備 |
* **RCC (Reset Clock Contorller) 復位與時鐘控制模塊**:該模塊的主要功能是,把時鐘源的時鐘分配到不同模塊 !
:::info
不同區塊的時鐘可以用軟體進行配置
:::
### 內核架構 - Cortex M4
* 使用 ARM Cortex M4 系列處理器架構圖
> 
1. **內核的主要工作**:
^1.^ `取地址 Fetch`、^2.^ `解碼 Decode`、^3.^ `執行 Execute`,具體來說程式的核心則是 **使用 ==馮.諾伊曼架構==**;取址就是從 Flash 中取得程式,經過翻譯後,最後執行
2. **內核 RAM**:
內核 RAM 的速度更快,內核可以直接訪問這裡的記憶體 (**但容量較小**),又將這個區塊稱為 **暫存器 (Register)**
:::success
ARM 最基礎的暫存器有 16 個,在這之後為了需求還有在擴展,不過這 16 個暫存器一值都在
:::
3. **NVIC (`Nested Vevtored Interrupt Controller`)**:
嵌套向量中斷控制器,由於中斷有很多種,所以單晶片使用類似於 Key/Value 的模式,一個號碼對應一個中斷
:::info
晶片設計者把特定的號碼稱為 **中斷向量**、**中斷矢量** (因為從來源到目標有方向性)
:::
### 晶片架構 - 馮.諾伊曼架構
* 馮.諾伊曼架構用運在 CPU 中
1. `CPU`:中央處理器,進行讀取、解碼、執行
2. `Register`:儲存器
3. `I/O 總線`:輸入輸出系統
* CPU 運作順序如下
1. **PC 讀取**:
將程式 (`RAM`、`Flash`) 從記憶體中讀取到 Register;**PC (`Program Counter`, 程式計數器) 是 16 的原祖 Register 其中一個,每次上電都會從一個特定數值開始累加**
> 
* 指令是通過 PC 內的值作為地址來訪問 RAM、Flash,再由儲存器返回該地址中保存的 **指令**。地址則是程式中的指令在 RAM、Flash 中保存的位置。
:::warning
* 指令 != 地址,指令組合語言,接下來會說明
:::
:::info
* 這些被讀取指令,會保存在特殊 Register 中 (不屬於 16 原祖 Register)
特殊 Register 則是,**為了提高 CPU 的執行效率 (可看作 Cache)**,一般會 **預先將 PC 所指向的地址 & 後面的一段程式** 同時緩存到一個特別的储存器中,**避免每次都要使用到總線讀取**
> 
:::
2. **解碼器**:
**CPU 將指令 Register 中的指令進行解碼**,所有指令都被定義為一串二進位程式;有的指令進行運算、讀寫、CPU 休眠 ... 等等
> 
3. **執行**:
CPU 的執行指令
4. **回寫**:
最終結果寫回 Register、Flash、RAM 中
> 
### 指令 - 組合語言
* 我們寫的 **程式最終會翻譯成一組一組的指令**,並存在 RAM、Flash 中,而 **CPU 要讀取的就是這些指令**;指令由 Binary 表達,不意了解,所以就誕生出了組合語言,**組合語言是指令的代號,只要看到這個代號就執行固定的事情**
:::info
* 指令集 ?
組合語言通常是短小精悍的一串英文單字,這些單字組合起來成為一個集合,**指令集合就稱為指令集,++每個 CPU 都會有不同的指令集++**
:::
* 這些組合語言可以透過 **==匯編器==** 幫我們轉換成二進位,**是編譯器的雛型**
* 假設要計算 `1 + 2 = ?` 彙編器會幫我們翻譯成以下指令
```shell=
## 偽指令
## 儲存器地址 ------ | 內容 ------------ | Register ----- |
0x00 0x1111
0x01 0x2222 C1
0x02 0x2222 C2
0x03 0x8888 C3
```
解釋如下
| 儲存器單元編號 (地址) | 內容 | 說明 |
| -------- | -------- | -------- |
| 0x00 | 0x1111 (`假設為加法指令`) | 準備對後面兩個位置的數值進行加法 |
| 0x01 | 0x2222 (`假設為操作數移動指令`) | 將 0x01 數值移動到 C1 |
| 0x02 | 0x2222 (`假設為加法指令`) | 將 0x02 數值移動到 C2 |
| 0x03 | 0x8888 (`假設為移動指令`) | 將結果保存到 C3 |
* CPU 的 **PC 暫存器就是控制用來訪問 `儲存器單元編號 (地址)`**,有關 PC 要注意如下
1. **PC 的大小**:為 32 bit,最多就是 2^32^ 也就是 4GB 的尋址空間,但真正的 **尋址寬度是由 `內核決定` (內核有手段可以拓展寬度),比較準的應該是看 ++總線數量++**
:::info
一般來說運算器的寬度會跟尋址寬度一樣,**為了最佳效能**
:::
2. **PC 滿**:從 0 開始,但基本上不會滿,因為程式往往會進入一個 while 迴圈中,再次回到指定位置
```c=
// 偽程式
int main(int argc, char** argv) { // 地址 0x11223344
while(1) { // 地址 0x11550000
// Do something,最終還是會回到 0x11550000
} // 地址 0x22002200
}
```
### I/O 設備
* MCU 要如何控制硬體 IO 設備呢 ? 主要有分為兩種方式 ^1.^ 存儲器映射、^2.^ 端口映射;而嵌入式系統多為第一種(存儲器映射)
* 前面有說到外圍設備都會掛載在 APB 總線上,只要掛載到該總線上,就會 **映射** 到記憶體中某個區塊,MCU 只要操控該區塊的記憶體,就可以操控那個 IO 設備
:::info
* 映射 ?
想成一個鍵值對即可,每個設備都對映射到記憶體中,概念如同 `Map<設備, 記憶體>`
:::
> 
### 傳輸線 - 總線
* CPU 和存储器、IO... 等等設備交換數據的通道,總線會將信號連接到多個設備上,**總線是共享的,如果出現衝突狀況,則透過仲裁器負責處理**
> 
* 一般總線有分為三種
1. **控制總線**:負責訪問控制,也就是控制 `讀`、`寫`
2. **數據總線**:負責數據交換
3. **地址總線**:用來指定要訪問的設備地址、設備內存储器、暫存器地址
:::info
* 總線協議:由於各個設備共享總線,所以會有信號的時序、數據交換的規則,這個規則就稱為 `總線協議`
:::
* 總線的傳輸分為 5 個大步驟:^1.^ 申請總線、^2.^ 許可總線、^3.^ 請求訪問、^4.^ 設備應答、^5.^ 釋放總線控制,如下圖
> 
:::warning
* **AHB 有總線仲裁機制**,APH 沒有仲裁機制
:::
### 數字電路 - 鎖存鎖
* 數字電路主要有分為兩大類:^1.^ **組合邏輯電路**、^2.^ **時序邏輯電路**;
* **時序邏輯電路**:與時間有關,電路存在於 CPU、DSP、FPGA ...等等,而 **體現時間則是透過共振電晶體 Clock**
:::danger
* **時間電路產生的問題**:
由於 **每個模塊、或是外部裝置使用的 Clock 共振時間不同,導致數據傳輸不同的的問題** (就像是不同的解碼器,對相同的數據會解析出不同結果)
:::info
解決方法是數字電路,有兩種:**存鎖器**、**D 觸發器** (配套使用)
:::
:::
* **==鎖存鎖==**:是一個 **存储單元**,簡單理解起來就是,**鎖住一個狀態 (狀態可能是 `0` or `1`)**
1. **AND 鎖存器**:以下是一個循環迴路 AND 鎖存器,如果 A 輸入 0 (低訊號),則輸出 Y 就會一值是 0
> 
2. **D 鎖存器**:使用 4 個 NAND (Not AND) 鎖存器,就可以達到鎖住任何訊號的功能;
* 兩個輸入引腳 ^1.^ `D` 輸入數據 、^2.^ `E` 控制運作;E 腳特別的是,E on 時會保持前一個數據持續輸出 (無論 D 如何改變)
* 兩個輸出引腳 ^1.^ `Q` 輸出數據 、^2.^ `^Q` 輸出 **反向** 數據 (NOT 數據);如果 E on,則 Q 會與 D 相同輸出
| E (Input) | D (Input) | Q (Output) | ^Q (Output) |
| - | - | - | - |
| 0 | 0 | 保持前一個數據的輸出 | 保持前一個數據的輸出 |
| 0 | 1 | 保持前一個數據的輸出 | 保持前一個數據的輸出 |
| 1 | 0 | 0 (與 D 相同) | 1 (D 反向) |
| 1 | 1 | 1 (與 D 相同) | 0 (D 反向) |
> 
* **D 觸發器**:用來觸發 D 鎖存數據的更新!它的改變是,將 E (Input) 腳換為 C 代替 E 控制電路,並串起兩個 D 存鎖器;
> 
C 引腳就是來接時鐘 Clock 用的,**用 C 引腳來 ++檢查 D 引腳的資料++,並 ++透過 C 引腳來控制數據輸出++**,其時序圖如下
* 請先回憶兩件事:^1.^ D、Q 是相同輸出、^2.^ C 代替 E 控制,只有當 C 上升時才能控制 D 輸出
* 下圖第一個 C 上升:檢查到 D 是下降的,準備將 Q 調降
* 在調整 Q 的輸出,這期間 D 必須保持一段時間的輸出數據 (`延遲`),也就是說數據建立是需要時間的 (下圖藍色區塊)
> 
## Appendix & FAQ
:::info
:::
###### tags: `嵌入式`