---
# System prepended metadata

title: M4周邊設定流程
tags: [MVMC-lab, M4]

---

# M4周邊設定流程
###### tags: `M4` `MVMC-lab`

## 通用設定步驟
### 1. 設定腳位多工
:::info
使用到的周邊硬體 `Chapter32.PORT`
暫存器 `PMUX` 、 `PINCFG`
:::

- 查看[M4 datasheet](https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM_D5x_E5x_Family_Data_Sheet_DS60001507G.pdf)第六章**I/O Multiplexing and Considerations** 取得目標周邊的分類 ![](https://i.imgur.com/BlyL1ls.png)

- 設定PORT->PMUX暫存器
此晶片為32-bit機器，I/O支援高達32個腳位，e.g. PORTA包含PORTA0、PORTA1、PORTA2...、PORTA31。各編號間的多工器可個別獨立，也就是PORTA8使用ADC周邊，同時PORTA9可提供為SERCOM周邊做使用；而PMUX暫存器即是設定指定PIN角要提供何種周邊驅動的區域。
:::warning
PMUX暫存器為了節省記憶體空間，將兩個相鄰腳位的多工選擇塞進同一個暫存器，如下圖。並且將奇數編號的腳位放至高位元，偶數至低位元。
![](https://i.imgur.com/5sQb8Ht.png)
e.g. 要設定 **PORTA9** 的多工器必須至 **PORTA->PMUX[4]** 的高四位bit做設定 ，要設定 **PORTB16** 的多工器則要到 **PORTB->PMUX[8]** 的低四位bit設定。
:::
bit欄位資料按照第六章查詢到的資訊填入即可
![](https://i.imgur.com/wQOavaC.png)

- 致能多工器(PORT->PINCFG)
:::warning
此暫存器與PMUX暫存器不同，各編號有屬於自己的暫存器做對應設定。e.g.要致能 **PORTA9** 的多工器必須至 **PORTA->PINCFG[9]** 執行 ；要致能 **PORTB16** 的多工器則要到 **PORTB->PINCFG[16]** 執行。
:::
將PMUXEN旗標寫入1即可
![](https://i.imgur.com/yWSr0xh.png)

### 2.設定通用時脈(非必要)
:::info
使用到的周邊硬體 `Chapter14.GCLK`
暫存器 `GENCTRL`
:::
此暫存器提供12個GENCTRL暫存器，編號由0,1,2...,11，在data sheet中個別代表GCLK0,GCLK1,...GCLK11，這些通用時脈(GCLK)為周邊硬體的時脈來源。
:::warning
GCLK0固定作為CPU時脈與BUS時脈
:::

下圖為GENCTRL暫存器的旗標分布圖，必要設定的旗標有 `DIV` `GENEN` `SRC` 
![](https://i.imgur.com/1yPYTaU.png)
- SRC : 通用時脈的時脈源，可作為通用時脈的SRC如下圖
![](https://i.imgur.com/oHdI41n.png)
:::info
XOSC為高速的外部震盪源(石英震盪器或主動震盪器)，此晶片最高可提供兩個高速外部震盪源。

GCLK_IN為自行產生時脈至GCLK腳位

GCLK_GEN1為使用GCLK1作為時脈源

XOSC32K為RTC震盪器訊號

DFLL為內部震盪器時脈，固定為48MHz

DPLL為鎖相閉路環時脈，此晶片提供兩個DPLL硬體
:::
- DIV : SRC時脈進入後的除頻值，假如SRC為DFLL，DIV選用2，則此GCLK最終生產時脈將為 48MGz / 2 = 24MHz。
- GENEN : 致能此GCLK

### 3.致能ARM Peripheral Bus
:::info
使用到的周邊硬體 `Chapter15.MCLK`
暫存器 `AHBMASK` or `APBAMASK` or `APBBMASK` or `APBCMASK`  or `APBDMASK`
:::
可配合[M4 datasheet](https://ww1.microchip.com/downloads/aemDocuments/documents/MCU32/ProductDocuments/DataSheets/SAM_D5x_E5x_Family_Data_Sheet_DS60001507G.pdf)第3章第一小節的Block Diagram圖片。
此小節要開啟的功能為圖中的APBA、APBB、APBC、APBD區塊，將此區塊設定開啟，才能使得CPU核心與周邊硬體的資料流通(如設定暫存器的動作或是Run-Time期間取得周邊硬體訊號等)


找出要使用的周邊硬體在哪個暫存器中並將該旗標寫入1即可
![](https://i.imgur.com/WWaeBHZ.png)

### 4.選定周邊硬體的時脈源
:::info
使用到的周邊硬體 `Chapter14.GCLK`
暫存器 `PCHCTRL`
:::

PCHCTRL暫存器總共提供48個，編號由0至47，各編號對應不同周邊硬體(如下圖)
![](https://i.imgur.com/aJSCrtf.png)
![](https://i.imgur.com/pwelOUT.png)
e.g.要設定ADC0要至GCLK->PCHCTRL[40]設定

暫存器的旗標有 : 
![](https://i.imgur.com/k7Fig15.png)
須設定的為`GEN`及`CHEN`
- GEN : 為時脈源，直接寫入的數字即為通用時脈源編號，例如在GEN旗標寫2即代表希望此周邊以GCLK2當作時脈源。
- CHEN : 致能此周邊的時脈源。

### 5.周邊硬體設定


## 範例 -- 使用UART2
### 1. 設定腳位多工
:::info
PA8、PA9分別當作RX及TX使用
:::
查閱datasheet第六章，PA8、PA9設作SERCOM2的分類為D，因此多工器的設定如下
```c=
PORTA->PMUX[4].reg |= 0x33; //PA8、PA9 switch to D cluster
PORTA->PINCFG[8].reg |= 1;  //Enable PA8 multiplexor
PORTA->PINCFG[9].reg |= 1;  //Enable PA9 multiplexor
```
### 3.致能ARM Peripheral Bus
:::warning
由於此範例將直接使用專案中預設的GCLK2當作SERCOM2時脈源因此略過步驟2。
:::
查閱MCLK暫存器表會發現SERCOM2位於APB的cluster B中，因此開啟步驟如下
```c=
MCLK->APBBMASK.reg |= 1 << 9;
```

### 4.選定周邊硬體的時脈源

查看編號對應周邊硬體的表格會看到SERCOM2 Core為編號23，因此設定SERCOM2的時脈方法為下
```c=
GCLK->PCHCTRL[23].reg |= 2; //select GCLK2 as SERCOM2 clock source
GCLK->PCHCTRL[23].reg |= 1 << 6; //enable this peripheral clock
```

### 5.SERCOM設定
:::info
翻開datasheet章節總覽會發現SERCOM章節總共佔了4個，由33~36章，原因為SERCOM可客製此周邊要以何種串列通訊模式輸出，如:SPI、UART、I2C等，而每種不同的模式下，此周邊占用的記憶體空間有不同的解讀，因此才出現了多個章節的現象。

其他的周邊如Timer也有類似現象請注意。

此周邊的閱讀方法為:假設如目前情況需要使用的功能為UART，則章節切換至UART閱讀(Chapter 34.)即可。
:::

以UART模式執行下的SERCOM周邊是以此方式解讀
![](https://i.imgur.com/FrU9tvF.png)

此範例將設定:
- UART非同步模式
- no parity
- TX/RX全雙工
- 鮑率38400

#### CTRLA
- DORD : 選擇bit先送高或低，通常UART都是低bit先送
- CPOL : Clock Polarity，為USART模式下的設定，規定何時取樣資料，何時改變資料
- CMODE : 設定是否為同步傳輸(通訊時有無Clock訊號)
- FORM : 設定UART通訊格式，可選的模式有:
![](https://i.imgur.com/pX4FtHJ.png)
![](https://i.imgur.com/g2Fw33U.png)

- SAMPA與SAMPAR : 超採樣倍率，通常用於非同步傳輸
- RXPO與TXPO : 
:::info
SERCOM由於有可任意變換選擇通訊方式的特性，因此PORT到對應通訊腳位之前，在SERCOM中多加入了一層SERCOM_PAD腳位增加變化性。

筆者推測，此作法的優點為：三種串列通訊模式下，需要用到的腳位數不同，如I2C僅需兩支，SPI需要4支。多了一層PAD能使的硬體對應功能不被受限之外，IC設計在走線上也較為方便(?
![](https://i.imgur.com/qqDstfr.png)
:::

RXPO設定Data in的腳位要選用哪個PAD
![](https://i.imgur.com/e0KAlAy.png)

TXPO就相對複雜，因為在UART模式中有許多種FROM，物理層的腳位就有所不同
![](https://i.imgur.com/gqA84GM.png)

- RXINV與TXINV : RX或TX輸出反相
- IBON : Buffer overflow通知
- RUNSTDBY : 跟sleep模式或是省電有關，實驗室可能永遠不會碰到這塊
- MODE : 此旗標即為設定SERCOM要以何種模式(UART、SPI、I2C)進行，在UART模式提供兩種變化

![](https://i.imgur.com/87LWorX.png)

- ENABLE : 致能SERCOM硬體
:::warning
ENABLE皆為最後設定，若一開始就開啟，暫存器property中包含Enable-protected的就無法再進行存取
![](https://i.imgur.com/o3SVJrt.png)

:::
- SWRST : Software reset，不用晶片重啟就能reset整個周邊的設定。

:::spoiler
總結設定

DORD要使用LSB first，CMODE使用非同步模式，FORM為USART without parity，使用PAD[0]當作TX、PAD[1]當作RX，USART使用內部震盪。

```c=
SERCOM2->USART.CTRLA.reg |= (1 << 30); //DORD
SERCOM2->USART.CTRLA.reg |= (2 << 16); //TXPO
SERCOM2->USART.CTRLA.reg |= (1 << 20); //RXPO
SERCOM2->USART.CTRLA.reg |= (1 << 2)); //MODE
```
:::

#### CTRLB
- LINCMD、CHSIZE、SFDE、COLDEN : 非UART模式的設定，跳過
- RXEN、TXEN : 致能RX功能及TX功能
- PMODE : parity mode
- ENC : IrDA模式下的設定，跳過
- SBMODE : Stop bit設定

:::warning
![](https://i.imgur.com/MmQzuGY.png)
CTRLB的Property中包含Write-Synchronized，意思是寫入此暫存器的動作執行當下並不保證能馬上與周邊的暫存同步。檢查同步是否完成的旗標通常會在暫存器SYNCBUSY中。
e.g.以開啟TX、RX為例
```c=
SERCOM2->USART.CTRLB.reg |= 3 << 16;
while (SERCOM2->USART.SYNCBUSY.reg & (1 << 2));
```
:::

#### BAUD
:::info
SERCOM的鮑率計算如下，同步與非同步的計算公式不同
![](https://i.imgur.com/Wep3Vr7.png)
![](https://i.imgur.com/LUkGizQ.png)
(From datasheet Table33-2)
:::
由於範例中設定的旗標SAMPR為0，因此BAUD中不會有小數訊息，
可以看計算公式的第一列
![](https://i.imgur.com/7c0w2fu.png)

$目標 f_{BAUD} = 38400, 已知f_{ref} = 12,000,000$
$BAUD = 65535 \times (1 - 16 \times \frac{38400}{12000000}) \sim 62180$

#### INTFLAG
- RXC與TXC or DRE : 實作UART時只需檢查此2旗標即可

#### DATA
UART TX與RX寫入時只需存取此暫存器即可。

#### 致能周邊硬體
```c=
SERCOM2->USART.CTRLA.reg |= 2;
while (SERCOM2->USART.SYNCBUSY.reg & 2);
```
