最近買了一塊 STM32F429IDISCOVERY 來玩玩
STM32應該算是想學embedded system的經典款,網路上資料也挺多
想說就從這一塊來入手吧
之後應該會陸續寫寫我玩這塊板子的心得
以下先簡單介紹一下這塊板子~
STM32F429IDISCOVERY overview
- ARM cortex-M4
- 2MB flash memory
- 64-MBIT DRAM
- 3-axis gyroscope
- LCD display 240x320 resolution touchscreen
今天先測試 STM3 的GPIO功能,做一個LED blink的demo
實作參考 jserv 的 嵌入式系統建構:開發運作於STM32的韌體程式
STM32 reset
首先我們想知道的是,當ARM cortex-M4 reset後,第一步會做什麼
這部份我們可以參考STM32F429的reference mananul
STM32F429有兩根pin : BOOT0, BOOT1, CPU reset後會從這兩根pin的狀態來決定哪一塊memory當boot space
從schematic可以看出來,STM32F429IDISCOVERY選用的default boot space是Main Flash memory
然後我們從 User manual中可以看出來,Flash memory的start address是0x08000000
等開機時,會自動將0x08000000-0x080FFFFF 映射到 0x00000000-0x000FFFFF,所以將bin檔燒在0x08000000,
STM32F429就可以從0x00000000開始執行
Reset後,STM32F429會從 0x00000000 得到 MSP(Main Stack Pointer)。 也就是說,如果你在 0x00000000填0x20001000,
那CPU reset 後 stack將是 0x20000000 - 0x20001000。
接下來 從0x00000001得到 Program Counter,及code第一個指令開始的位址
以上行為可以用C語言達成 :1
2asm(".word 0x20001000");
asm(".word main "); //指定起始 為main()的address
講完了reset flow,接下來來實作 LED blink吧!
LED blink demo
STM32F429IDISCOVERY 有兩顆可控制的LED
我們這次實作一個讓這兩顆LED交錯閃爍的demo,以下是 C code
blink.c
1 |
|
我們可以從User mananul查詢各個 register的memory map
GPIO的控制步驟如下 :
開啟 AHB1 peripheral clock for GPIO G
PG13 PG14初始化設定 ( GPIO output, push-pull, pull-down )
輪流閃爍 PG13, PG14
想要讓 GPIO 輸出HIGH,可以在 15:0 對應的bit set 1
想要讓 GPIO 輸出LOW, 可以在 31:16 對應的bit set 1
分開設定的理由是,當你只想控制某跟pin,可以直接寫value,而不用管其他的pin
做到 atomic的效果
Makefile and loader
Makefile
1 | CROSS_COMPILE ?= arm-none-eabi- |
blink.ld
1 | SECTIONS |
我們使用gcc-arm-none-eabi,這是一款適用於 ARM bare-metal的tool chain
blink.o由blink.c gcc compile後編譯而成
- -mcpu=cortex-m4:指定mcu為cortex-M4
- -mthumb: 指定產生Thumb指令,ARM Cortex-M3/M4只支援Thumb2指令
- -nostartfile: 因為我們自己處理了 ARM reset的動作,所以指定link階段不要使用startup file
blink.out 為 blink.o 經過blink.ld link之後生成的 ELF檔
因為我們的code沒有全域變數,所以 blink.ld中只需要 .text,不需要 .data .bss
最後生成的blink.bin,就是我們要燒進flash的bin file
燒錄
從schematic看的出來,STM32F429IDISCOVERY的電路已經包含ST-Link了,所以USB-mini插上去後就可以直接燒錄,不需要額外的燒錄器。
我們使用官網的 STM32 ST-LINK Utility
燒錄成功後就可以看到 紅、綠兩顆LED開始交替閃爍了
完整code放在 github