開發紀錄(A)
 
今天聽了同學的分享,當時的我雖然完全聽不太懂,但有聽到重點就夠了—查表
 
第一次接觸這類的東西,一開始感覺很抖,但其實補充教材提供許多有用的參考資料:
  • Reference manual:列出記憶體映射位置與各個 bit 所代表的意義
 
至於要如何提供一個 Shell 呢?
  • Busy-loop:感覺上比較沒效率,但做起來簡單。在 07-Thread 內輸出入是經由 USART2 控制 (感覺上是選用不是強制),memory map0x4000 4400,這裡主要有三個重要暫存器:
  • USART_SR (Status Register,address offset = 0x00):這個暫存器主要是由硬體自己設定,當有資料在 USART_DR Shift Register 之間傳輸時,會設定這個暫存器
 
  • 主要由兩個 flag 判斷寫入或輸出:
  • Bit 7 TXE:Transmit data register empty
  • Bit 5 RXNE:Read data register not empty
        *(USART2_SR) & 0x80 // Detects output
        *(USART2_SR) & 0x20 // Detects input
  •  
  • 接下來還需要對 USART_DR 進行位元運算,來對這個暫存器進行寫入或輸出的動作,然後才能夠清除上述 TXERXNE 位元。
 
  • USART_DR (Data Register,address offset = 0x04):Contains the Received or Transmitted data character, depending on whether it is read from or written to
 
  • USART_CR1 (Control Register,address offset = 0x0C):在這個暫存器內設定所要開啟的功能
  • Bit 13 UE:USART enable
  • Bit 3 TE:Transmitter enable
  • Bit 2 RE:Receiver enable
  • 所以在 user_init 初始設定成 0x0000200C
        *(USART2_CR1) = 0x0000200C;
 
  • Trigger:使用 external interrupt 方式觸發,這方法應該會比較省電,而且令人意外的,實作起來其實跟 busy -loop 差不了多少
  1. Iterrupt Service Routine(ISR) 的設置在 startup.c 裡,在 isr_vecrors[] 所對應的 USART2 中斷位置加入處理常式,中斷發生時 PC 就會跳到對應的 handler 內執行
  1. The Definitive Guide To ARM Cortex M3 內有提到如何致能與除能中斷向量的方法
  • 0xE000E100 位置內負責致能0–31 的外部中斷 (這是以外部中斷的編號決定)。就USART2的例子,它位在外部中斷的第 38 的位置,所以將 0xE000E104 所指向位置的 bit 6 開啟 (設為 1),致能 USART2 中斷
        #define NVIC_SETENA2 (volatile unsigned long*)(0xE000E104)
        *((volatile unsigned long*)(0xE000E104)) |= (1<<6);
       
  1. 最後,只要讓 USART2 在輸入時會丟出一個 interrupt,就完成 USART2 的觸發設置
  • USART_CR1:
  • Bit 5 RXNEIE:RXNE interrupt enable This bit is set and cleared by software
       *(USART2_CR1) |= 0x20;
       
 
Shell Implementation
拚了一整ˋ天,終於把只有 fibonacci 指令的 Shell 做好了,主要都參照 bash 運作方式,一定還有很多 bug 是我沒有考慮到的,但是乖乖測試是可以正常跑的。
雖然說按鍵輸入改成觸發了,但為了不讓執行緒結束,還是得讓它跑在一個 busy-loop 上。
 
整個實作分成三大部分:
  • 輸入處理:os.c 裡,宣告了一個全域、固定大小的 buffer ,這個部分是輸入指令時要處理的字串
  • 現階段能夠吃的按鍵主要分成三類,這部分用 switch 判斷: