rpi3 has 2 UARTs, mini UART and PL011 UART.
rpi3 透過 memory mapped io (MMIO) 來存取周邊裝置。
在 ARM CPU 與 peripheral bus 中間有 VideoCore/ARM MMU。MMU 會將周邊的記憶體位置 map 到 0x3f000000 - 0x7e000000
(Physical Address) 這個區段。
The register’s memory address in reference is bus address, you should translate into physical address.
rpi3 的一些 GPIO 腳位可以用作 UART 與 SPI。GPIO 14, 15 可以被用作 mini UART 或 PL011 UART。
在使用 UART 前,比須將特定的 GPIO 腳位設定到相應的模式,mini UART 必須將模式設定為 ALT5
,PL011 UART 則是 ALT0
。可以透過設定 GPFSELn
暫存器來更改 alternate function。
因為 GPIO 使用 alternate functions 而非 basic input-output,必須調整 pull up/down register 來關閉 GPIO pull up/down。可以透過設定 GPPUD
及 GPPUDCLKn
暫存器調整。
先定義一些 MMIO 的記憶體位置在 header
1
2
3
4
| #ifndef MMIO_H
#define MMIO_H
#define MMIO_BASE 0x3F000000
#endif
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| #include "mmio.h"
#define GPIO_BASE (MMIO_BASE + 0x200000)
#define GPFSEL0 ((volatile unsigned int*)(GPIO_BASE + 0x00))
#define GPFSEL1 ((volatile unsigned int*)(GPIO_BASE + 0x04))
#define GPFSEL2 ((volatile unsigned int*)(GPIO_BASE + 0x08))
#define GPFSEL3 ((volatile unsigned int*)(GPIO_BASE + 0x0C))
#define GPFSEL4 ((volatile unsigned int*)(GPIO_BASE + 0x10))
#define GPFSEL5 ((volatile unsigned int*)(GPIO_BASE + 0x14))
// 0x18 Reserved
#define GPSET0 ((volatile unsigned int*)(GPIO_BASE + 0x1C))
#define GPSET1 ((volatile unsigned int*)(GPIO_BASE + 0x20))
// 0x24 Reserved
#define GPCLR0 ((volatile unsigned int*)(GPIO_BASE + 0x28))
#define GPCLR1 ((volatile unsigned int*)(GPIO_BASE + 0x2C))
// 0x30 Reserved
#define GPLEV0 ((volatile unsigned int*)(GPIO_BASE + 0x34))
#define GPLEV1 ((volatile unsigned int*)(GPIO_BASE + 0x38))
// 0x3C Reserved
#define GPEDS0 ((volatile unsigned int*)(GPIO_BASE + 0x40))
#define GPEDS1 ((volatile unsigned int*)(GPIO_BASE + 0x44))
// 0x48 Reserved
#define GPREN0 ((volatile unsigned int*)(GPIO_BASE + 0x4C))
#define GPREN1 ((volatile unsigned int*)(GPIO_BASE + 0x50))
// 0x54 Reserved
#define GPFEN0 ((volatile unsigned int*)(GPIO_BASE + 0x58))
#define GPFEN1 ((volatile unsigned int*)(GPIO_BASE + 0x5C))
// 0x60 Reserved
#define GPHEN0 ((volatile unsigned int*)(GPIO_BASE + 0x64))
#define GPHEN1 ((volatile unsigned int*)(GPIO_BASE + 0x68))
// 0x6C Reserved
#define GPLEN0 ((volatile unsigned int*)(GPIO_BASE + 0x70))
#define GPLEN1 ((volatile unsigned int*)(GPIO_BASE + 0x74))
// 0x78 Reserved
#define GPAREN0 ((volatile unsigned int*)(GPIO_BASE + 0x7C))
#define GPAREN1 ((volatile unsigned int*)(GPIO_BASE + 0x80))
// 0x84 Reserved
#define GPAFEN0 ((volatile unsigned int*)(GPIO_BASE + 0x88))
#define GPAFEN1 ((volatile unsigned int*)(GPIO_BASE + 0x8C))
// 0x90 Reserved
#define GPPUD ((volatile unsigned int*)(GPIO_BASE + 0x94))
#define GPPUDCLK0 ((volatile unsigned int*)(GPIO_BASE + 0x98))
#define GPPUDCLK1 ((volatile unsigned int*)(GPIO_BASE + 0x9C))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| #include "mmio.h"
#define AUX_BASE (MMIO_BASE + 0x215000)
#define AUX_IRQ ((volatile unsigned int*)(AUX_BASE + 0x00))
#define AUX_ENABLES ((volatile unsigned int*)(AUX_BASE + 0x04))
#define AUX_MU_IO ((volatile unsigned int*)(AUX_BASE + 0x40))
#define AUX_MU_IER ((volatile unsigned int*)(AUX_BASE + 0x44))
#define AUX_MU_IIR ((volatile unsigned int*)(AUX_BASE + 0x48))
#define AUX_MU_LCR ((volatile unsigned int*)(AUX_BASE + 0x4C))
#define AUX_MU_MCR ((volatile unsigned int*)(AUX_BASE + 0x50))
#define AUX_MU_LSR ((volatile unsigned int*)(AUX_BASE + 0x54))
#define AUX_MU_MSR ((volatile unsigned int*)(AUX_BASE + 0x58))
#define AUX_MU_SCRATCH ((volatile unsigned int*)(AUX_BASE + 0x5C))
#define AUX_MU_CNTL ((volatile unsigned int*)(AUX_BASE + 0x60))
#define AUX_MU_STAT ((volatile unsigned int*)(AUX_BASE + 0x64))
#define AUX_MU_BAUD ((volatile unsigned int*)(AUX_BASE + 0x68))
#define AUX_SPI0_CNTL0 ((volatile unsigned int*)(AUX_BASE + 0x80))
#define AUX_SPI0_CNTL1 ((volatile unsigned int*)(AUX_BASE + 0x84))
#define AUX_SPI0_STAT ((volatile unsigned int*)(AUX_BASE + 0x88))
#define AUX_SPI0_IO ((volatile unsigned int*)(AUX_BASE + 0x90))
#define AUX_SPI0_PEEK ((volatile unsigned int*)(AUX_BASE + 0x94))
#define AUX_SPI1_CNTL0 ((volatile unsigned int*)(AUX_BASE + 0xC0))
#define AUX_SPI1_CNTL1 ((volatile unsigned int*)(AUX_BASE + 0xC4))
#define AUX_SPI1_STAT ((volatile unsigned int*)(AUX_BASE + 0xC8))
#define AUX_SPI1_IO ((volatile unsigned int*)(AUX_BASE + 0xD0))
#define AUX_SPI1_PEEK ((volatile unsigned int*)(AUX_BASE + 0xD4))
|
BCM2835 ARM Peripher - 6.1
BCM2835 ARM Peripher - 2.1
https://grasslab.github.io/osdi/en/hardware/uart.html#uart
http://wiki.csie.ncku.edu.tw/embedded/GPIO
https://youtu.be/5vnW4U5Vj0k (很好的解釋 pull-up / pull-down resister 的功用)