Lab1: Mini UART & Simple Shell
MMIO
rpi3透過MMIO(memory mapped io)方式存取周邊裝置的暫存器
在ARM CPU和pheripheral bus間坐落VideoCore/ARM MMU,MMU將周邊裝置映射到0x3f000000-0x7e000000。
GPIO
GPIO可設置為給LED或按鈕使用的input-output或UART、SPI使用的alternate functions兩種模式。使用alternate function時需額外設置pull up/down register來禁用GPIO pull up/down,透過設置GPPUD及GPPUDCLKn。
GPIO 14, 15腳位可用做於mini UART或PL011 UART。設置GPFSELn為ALT5來使用mini UART或ALT0來使用PL011 UART。
Setup
設置過程中多次參考BCM2835的文件,為什麼非BCM2837?
Unfortunately Broadcom (the manufacturer of the SoC chip) is legendary bad at documenting their products. The best we’ve got is the BCM2835 documentation, which is close enough. (REF: Bare Metal Programming on Raspberry Pi 3)
且BCM2837的peripherals映射地址以0x3F000000開頭而非BCM2835的0x7E000000。
Similarily, all peripherals communicates in memory with the CPU. Each has it’s dedicated memory address starting from 0x3F000000
Shell
由於沒有glibc可用,必須要自行實作格式化輸出函數vsprintf ,用在命令的顯示輸出上。
要曉得變數的大小能使用aarch64-linux-gnu-gcc -c -Q -mcpu=cortex-a72 --help=target顯示data model。
vsprintf
1 | unsigned int vsprintf(char *dst, char *fmt, __builtin_va_list args) { |
原理是逐字讀取,根據對應的字元從args讀取對應的參數:
1 | // char |
值得注意的是char和float並沒有使用原來的型態進行讀取,原因在於...對應的參數會被擴展為較大的型態,char、short擴展為int,float擴展為double。
6.5.2.2.7 The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
vsprintf目前只支援integer、char、float三種型態的格式化輸出,且float由兩個整數部份組成(整數18位+小數6位)無法自由調整。
1 | char dst[20]; |