HW7 開發紀錄(A)
 

00 - HelloWorld

 
這裡主要是讓我們了解到如何將 STM32 開機,並執行程式,此程式為 bare-metal 方式,即是不建立 OS 來操作,雖然並不可靠,但能清楚的了解開機步驟,接下來我們就來探討程式部份。
 
__attribute((section(".isr_vector")))
uint32_t *isr_vectors[] = {
        0,
        (uint32_t *) reset_handler,        /* code entry point */
};
 
一開始我們必須設置 isr_vector  ( ISR -> interrupt service routine ),此為 Interrupt Vector Table 的內容, 而 index = 0為不使用, index = 1 為硬體reset event,以下有其他的事件名稱。(詳情可看規格書中的 9.1.2 )
 
 
 
很快的導入到 main function 中,這裡主要是要能輸出字串,而在開發版中若要能輸出結果,只能透過版子上的 LED 燈,不然就要使用 GPIO 來做輸出,而對於輸出字串我們需要搭配像 UART、USART 等序列傳輸方法,來跟其他周邊裝置溝通,因此在 code 中,我們使用了 USART,而 USART 的使用還要開啟 GPIO 來做 Tx、Rx 的傳輸,因此我們要先開啟 APB 中的設置來啟用 Port ,然後設置 GPIO 的 mode與 CNF ( General purpose output push-pull ),這裡的 GPIOA_CRL 與 GPIOA_CRH 是因為一個 GPIO 可控制 16 pin,32 bits register 無法裝載,因此用兩個 Register 來操作。最後設定 USART 的參數即可使用。
 

00 - Semihosting

 
這邊其實與上一個範例是同樣功能,但是這邊換另一種方式輸出,此方式稱為 Semihosting,其實就是軟體的中斷 ( System call ),其中就有關於 printf 以及 scanf event,透過此方式就能將結果輸出。
 
此為在不同 Instruction State 上的指令用法。
  SVC  0x12346 (in ARM state)
  SVC  0xAB (in thumb state)
  BKPT  0xAB (for ARMv7-M, Thumb2-only)
 
而當執行後 SVC_Handler 會去操作對應的事件,而可看到 "=r" (result) : "r" (r0), "r" (r1) 此一行描述,在此可參考另一篇部落格有詳細敘述,在此僅描述出現之程式碼, =r 代表在組合語言中的寫入對象 (如 add r0,r1,r2  之 r0),而後面兩個 r 則代表帶入的運算對象,而在 Semihosting 中,第一個參數為 Vector ,而第二個則是 Parameter。
 
register int r0 asm("r0") = service;//0x05
register void *r1 asm("r1") = opaque;//{ 1, (uint32_t) message, sizeof(message) }
register int result asm("r0");
asm volatile("bkpt 0xab"
            : "=r" (result) : "r" (r0), "r" (r1));
 
而這邊也有比較特殊的寫法,此寫法是一種強制轉型,代表可透過此方式來帶入不同的資料結構,可以不用因此而寫泛型,增加閱讀之困擾。
 
uint32_t param[] = { 1, (uint32_t) message, sizeof(message) };
semihost_call(SYS_WRITE, (void *) param);
static int semihost_call(int service, void *opaque){
    ...
}
 
而關於SVC的中段編號設置
 
  • 0x00 to 0x31 (提供ARM使用,其功能參考上表)
  • 0x32 to 0xFF (保留以後供ARM使用)
  • 0x100 to 0x1FF (保留供其他應用使用,此部份不會被ARM使用,若要開發自己的軟體中斷可以使用此部分)
  • 0x200 to 0xFFFFFFFF (未定義,強烈建議不要使用此部份).