# STM32F429 Discovery kit
## 1. GPIO (General Purpose Input / Output)
[TOC]
### (1) 參考 [成大資工wiki-GPIO介紹](http://wiki.csie.ncku.edu.tw/embedded/GPIO#stm32f4xx-gpio%E7%89%B9%E6%80%A7)
1. GPIO : 四種功能`input` `output` `alternate functions` `analog`
2. `alternate functions` : 週邊硬體功能 (e.g.`UART`,`I2C`)
3. STM32F4xx 每個 GPIO Port 有 **10** 個 **32-bit 暫存器 (Register)**
4. GPIOx : 共有**9個Ports** (從A到I)
<!-- 放截圖 -->

:::danger
**Push-Up / Push-Down** 是為了避免**電壓floating**導致**信號不明確**的問題。
* Push-Up : default 為 High
* Push-Down : default 為 Low
:::
> TLL Schmitt Trigger :
> 一種整流電路,目的為使**輸入的類比訊號**轉換為**數位方波**
>* 原理 :
>高於一個閾值的信號:設為 High
>小於: 設為 Low
### (2) Hardware Block Diagram (including Clock-tree)
* 使用週邊功能步驟:
1. 設定週邊 (UART,SPI,USB...etc.)
2. 設定GPIO 正確電路型態(AF mode)
3. 根據週邊、GPIO : 管理**時鐘** (正確設定)

* Bus : 大致分AHB和APB兩種
`AHB`:高速 (H : High speed高速的)
`APB`:較慢 (P : peripharal週邊的)
:::warning
若往後要用特殊功能(如**SPI**),先了解該功能工作**Clock頻率**,再確認對應system clock的頻率,決定要**除頻多少**。否則不能正常工作。
:::
#### 簡易電路區塊說明:

* 左上角JTAG & SW : 外部debug電路
* ARM Cortex-M4 : CPU
* DMA : Direct Memory Access
* 中間Flash, SRAM等記憶體
* RNG : Random Number Generator.
---

* GPIO PORT A~K
---

* SPI:
MOSI (Master-out, Slave-in)
MISO (Master-in, Slave-out)
* Voltage regulator: 穩壓功能
* XTAL OSC : 外部石英震盪器
XTAL 32kHz : **GPIO PC14, PC15**
XTAL 4-16kHz : **GPIO PH0, PH1
* RTC : Real-Time Clock
#### Clock Tree

:::info
**鎖相迴路(PLL: Phase-locked loops)** 是一種利用反饋(Feedback)控制原理實現的頻率及相位的同步技術,其作用是將電路輸出的時鐘與其外部的參考時鐘保持同步。
>引用自**維基百科**
:::
#### MMIO (Memory Mapped I/O)
* 在撰寫程式碼時,針對某個Register對應的Pin腳的設定,其實是**先對Memory寫入**,MCU內建的**Controller**再對Register寫入。

### (3) 範例程式碼
#### 1. 檔案格式說明

:::success
`.c` : C files.
`.h` : Header files.
`.s` : Assembly codes.
`.ld`: Linker Script.
`.o` : Object files.
Compiler 生成`目標檔`,再Link其他libraries.
`.elf` : UNIX OS下的執行黨
`.bin` : 燒錄到stm之檔案
:::
#### 2. 如何從eclipse編譯project,再使用ST-LINK Utility燒錄到開發版?
1. 從eclipse(luna)版,按下`Build`
2. 若`Build`成功,確認路徑:`Project/Debug/`是否生成一個`.hex`檔案
3. 將STM32開發版**插入電腦**,開啟**ST-LINK Utility**
4. 先點選`open/file`,放入剛剛的`.hex`檔案
5. 點選`connect`連接到開發版
6. 點選`Program & Verify`
::: danger
如果都沒有error訊息則大功告成
:::


#### 3. Import Exam1_LED
此範例程式為練習用GPIO控制LED的閃爍
:::success
如何知道LED對應到哪些**Port**和**Pin**?
:::
本開發版的LED對應之GPIO Port 為 GPIO**G**的
`PG13` `PG14`兩個腳位,可從Schematics找到

因此 `Blink_led.h`檔中的`Blink_Port_Number`和`Blink_Pin_Number`應該設為
6和13(6=G, 13)

#### In `BlinkLed.c`
``` C=
#include "BlinkLed.h"
// ----------------------------------------------------------------------------
// RCC : Reset and clock controL register.
void blink_led_init()
{
// Enable GPIO Peripheral clock
RCC->AHB1ENR |= BLINK_RCC_MASKx(BLINK_PORT_NUMBER);
// Use struct type definition.
GPIO_InitTypeDef GPIO_InitStructure;
// Configure pin in output push/pull mode
GPIO_InitStructure.Pin = BLINK_PIN_MASK(BLINK_PIN_NUMBER);
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(BLINK_GPIOx(BLINK_PORT_NUMBER), &GPIO_InitStructure);
// Start with led turned off
blink_led_off();
}
```
**Note:** 把Pin設好後,要先把該Port對應的**Clock** 設定好(打開)才會正常運作
此範例中的GPIO**G**對應之clock可從上**Clock tree**圖找出為 `AHB1`
所以才會有這行程式碼:
``` C=
RCC->AHB1ENR |= BLINK_RCC_MASKx(BLINK_PORT_NUMBER);
```
可以從`BlinkLed.h`檔案找出`BLINK_RCC_MASKx() `的定義:
```=
#define BLINK_RCC_MASKx(_N) (RCC_AHB1ENR_GPIOAEN << (_N))
```
可知function `BLINK_RCC_MASKx(_N)`會接收參數`PORT_NUMBER`並將Register `RCC_AHB1ENR_GPIOAEN` 的第 **_N** 個bit設為 1
表示將`AHB1`這條Bus連到的Port `GPIOG`的Enable打開。
#### In `BlinkLed.h`
``` C=
// ----- LED definitions ------------------------------------------------------
// Adjust these definitions for your own board.
#if defined(BOARD_OLIMEX_STM32_E407)
// STM32-E407 definitions (the GREEN led, C13, active low)
// Port numbers: 0=A, 1=B, 2=C, 3=D, 4=E, 5=F, 6=G, ...
#define BLINK_PORT_NUMBER (2)
#define BLINK_PIN_NUMBER (13)
#define BLINK_ACTIVE_LOW (1)
#else
// STM32F4DISCOVERY definitions (the GREEN led, D12, active high)
// (SEGGER J-Link device name: STM32F407VG).
#define BLINK_PORT_NUMBER (5)
#define BLINK_PIN_NUMBER (6)
#define BLINK_ACTIVE_LOW (1)
#endif
#define BLINK_GPIOx(_N) ((GPIO_TypeDef *)(GPIOA_BASE + (GPIOB_BASE-GPIOA_BASE)*(_N)))
#define BLINK_PIN_MASK(_N) (1 << (_N))
#define BLINK_RCC_MASKx(_N) (RCC_AHB1ENR_GPIOAEN << (_N))
```
#### 另一個範例:
下面為網路上參考一個範例程式
因為他們不是用我們的型號 `stm32f429`
所以他LED Port跟pin的設定不太依樣
他是 `GPIOD`的第`12 13 14 15`四個Pin
即 `PG12` `PG13` `PG14` `PG15` 四個針腳
``` C=
#include <stm32f4xx.h>
#include <stm32f4xx_gpio.h>
void delay(uint32_t count)
{
while(count--);
}
void init_GPIO()
{
GPIO_InitTypeDef GPIO_InitStruct = {
.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15,
.GPIO_Mode = GPIO_Mode_OUT,
.GPIO_Speed = GPIO_Speed_50MHz,
.GPIO_OType =GPIO_OType_PP,
.GPIO_PuPd = GPIO_PuPd_DOWN
};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_Init(GPIOD, &GPIO_InitStruct);
}
int main()
{
init_GPIO();
int digitStatus = 1;
while(1) {
GPIO_WriteBit(GPIOD, GPIO_Pin_12, digitStatus);
delay(1000000L);
GPIO_WriteBit(GPIOD, GPIO_Pin_13, digitStatus);
delay(1000000L);
GPIO_WriteBit(GPIOD, GPIO_Pin_14, digitStatus);
delay(1000000L);
GPIO_WriteBit(GPIOD, GPIO_Pin_15, digitStatus);
delay(1000000L);
digitStatus = (digitStatus + 1) % 2;
}
return 0;
}
```
### (4) 補充資料
**STM32_cube**
[STM32Cube](https://www.st.com/content/st_com/en/stm32cube-ecosystem.html)官方網站
###### tags: `STM32f429 Discovery kit`