close
         在移植一個 bootloader 或是新建一套 BSP(boot strap package) 到 target board 時 , 是很艱辛的. 因為在整個系統還沒穩定前 , 即使有更好的ICE , 也很難協助做debug的動作. 再加上 build 的image 要反覆的燒錄在板子上的 flash 中來驗證. 如果沒有一套輔助系統 , 我想光是拔 flash IC 起來到燒錄器的過程 , 大概就不下數十次吧.

        在 gl300 的平台中 , 雖然 cpu 廠商 faraday 有提供 ICE , 但並不能協助我們進行 image 燒錄的過程 , 所以在燒錄的程序上幫不上忙. 所幸 , 平台上有一個 USB Device 界面 , 這是當初在開發GL300這顆CHIP , 為了求便利 , 裏頭多埋了一顆 RISC 的 CPU , 直接 Driving USB Device 與 PC Host 相連接. 也正因為有其獨立性 , 所以在 fa526 還沒 work up 起來前 , 可以利用 USB 界面 , 將 image 由USB 傳輸到 gL300 平台 , 再透過 AHB 燒到指定的位置上. 來解決燒錄的一些狀況.


       如上述所說 , 因為系統還沒穩定 , 所以Debug tool , 目前還幫不上忙. 而 image 剛燒錄到 flash 上時 , 無法知到系統是否能成功的的運行 , 因此必須透過一些簡單的 I/O 行為 , 來確認 Program Counter , 倒底是跑到那去. 所以還是得用最古老的方法 , 像是monitor I/O Pin 的訊號 , 或是利用 LED的顯示. 而 gl300 很幸運的 , 在 system enginee r的協助下 , 已經配有一個七段顯示器. 所以透過多段的顯示功能 , 可以做一些比較動態的行為表示.
            
 
       理論上 , 在rearview的code 透過gcc 的編譯 , 然後移植到gccgl300平台上 , 該是沒問題的 , 但事實上卻大有不同. 經實驗發現 gcc compiler的跟 Code Warrior的compiler 的設計有些許不同. 所以單純的將Code po 過來 , 就會出現像是虛擬指令語法不對 , 或是image loader 配置失當等問題.  偏偏我對 gcc 並不熟 , 所以光是配置一些空間 , 或是間接位置的使用 , 都出了相當的障礙. 像是:

        1. Cord Warrior上的 label 不用加冒號 , gcc 的label 要加冒號.
     
       2. Code Warrior 的空間指定用 DCD , 但 gcc 可以用 .word 或是 .long

       3. 在gcc 使用  .word宣告一個Label空間時 , 如果要透過 LDR 來取位置所指的值時 , 必須是 ldr  r0 , Label , 而不是 ldr ro, =Label

諸如此類的問題 , 最後都是透過反組譯的解析 , 才弄清楚並解決了問題.  (反組譯的方法 , 可以下 # arm-linux-objdump -D u-boot >> t1 , 開啟 轉輸出檔 t1  , 就可以分析image 結構)


       了解了compile的問題後 , 再來要編排整個start.S 中 bootstarp的流程 . 因為u-boot的設定 , 這跟以前單純的bootstarp code 有所不同 , 所以大概可分列如下

       1. 設定ISR Table , 及_start entry point 以符合lds檔案中的 entry 入口點.
       
       2. 從reset 開始 , 必須先對系統做initialize , 包括cpu的初值設定 , SRAM or SDRAM 的BANK 及 Auto refresh 設定. 加上透過GPIO來控制七段顯示器的設定

       3. 現今bootstarp code 大多由ROM 載到SDRAM 的ram base來執行. 所以必須對系統做relocation  的動作. 所以必須copy 資料到 SDRAM 的啟始位置 , 或是由系統設定的指定位置.

       4. remap , 在fa526中 , 有一個便於系統使用的remap 功能 , 可以讓ROM 及 SDRAM 所處的Memory bank 做交換.

       5. 設定 Stack Pointer 及 bss area , 在Arm base 的mcu裏 , 有許多的mode  , 像是supervisor , user , undef , abort 等不同的mode . 當cpu working 在這不同的mode 時 , 必須使用到事前指定好的stack address . 除此之外 , 設定一個bss area , 這會在 C Area 的變數定義中使用到.

       6. 確保系統的狀態 , disable Interrupt
      
       7. Jump 到u-boot 的系統啟始點-- start_armboot

       會修改到的檔案 , 可分為下列幾個部份:
        
        1. /cpu/fa526/start.S 
            bootstrap code 的起點 , 包含ISR TABLE設定 ,  image的copy and relocation , cpu initialize  , stack and bss initialize , SDRAM auto refresh 設定. 最後跳到 u-boot 的start_armboot 啟始點

       2. /cpu/fa526/gl300/serial.c
           設定 gl300 平台上的serial port  , 包含 baudrate 設定 , uart port control

      3. /board/genesyslogic/gl300/config.mk
          設定 TextBase = 0x1f00000  , 為u-boot image relocation 的啟始點.


       如果po的過程 , 真如上列七項的快速 , 那就太棒了. 結果並不如預期.茲列出幾項po code 過程中所遇到的狀況.

       1.七段顯示器無法顯示 :
           無法正確的將數字參數由GPIO port匯出. 主要是因為label 定義的位址 , 在透過 ldr r0,=Label 時出錯了 , 正確應該是 ldr r0, Label
  
      2.SDRAM refresh 設定異常:
         如前言 , 在gcc的compile的結果 , 與code worrier有些許的不同. 在 SDRAM 的設定過程中 , 有些 branch 的條件命令 , gcc 必須 packing 成4個指令周期 , 要不 , program counter 在條件判斷式後 , 會一口氣跳到下一個符合 fetch 的指令長度 , 而lose了原本該在branch之後的指令. 這使得SDRAM 的 auto refres 設定的程序出了問題. 解決的方式 , 則是在branch 後多加了幾個 nop 來符合指令跳躍長度. 

      3. relocation : 
          在  u-boot中 , 我們透過 /board/genesyslogic/gl300/config.mk 下的 TextBase = 0x01f00000 來指定 u-boot.bin 的啟始位置. 這可以使的程式 working 在Memory 空間較高的位置端 , 而 0x00000000 的位置 , 則是保留給爾後系統真正的 system image 載入所使用. 但在開始的 start.S中, 七段顯示器的處理方式 , 是以取得數字顯示參數列的絕對位址 , 做為輸出索引 . 這使得燒入在由 ROM 起始所指訂的 0X00000000 與 TextBase 所設定的 0x1f00000 位置 , 起了差距. 這個錯誤也使的在顯示七段顯示器的過程 , program counter 亂掉  , 進而將系統 crash 掉. 解決的方法 , 則是由七段顯示的程序中, 算出參數列與實際程式起始位址的差距 , 這樣就可以避免上述的問題發生.

     4.remap : 
        我們設定 u-boot  的起始將由0x1f00000 開始 , 這也代表 bootstrap 必須將 u-boot image copy 到 0x11f00000的位置 (remap 前SDRAM 的BASE在0X10000000) , 這樣才能在系統 remap 後 , u-boot 的啟始落在 0x1f00000的位置上. 但問題是 , 當系統 reamp 完的當下 , program counter 仍停在留在 remap 的程序後的位址 , 大約是在0x0000xxxx 左右 , 這跟我們真正的 0x1f00000 有一段的差距 , 也造成 remap 後的 image  , 不是系統正確能運行的指令. 系統也因此crash掉.  所以 , 做了下列權宜的方法:

  1) 先copy image 到 0x10000000 , 然後進行remap , 以及stack bss  , 以及hardware_init設定

        2)再一次的u-boot image copy 到 0x1f00000 的位址上 , 然後在用 ldr pc, start_armboot 的方式 , 將 program counter 直接定址到 0x1f00000[ start_armboot ] 的地方.

這樣一來 , u-boot的整個系統運作 , 除了ISR table 仍在 0x0000000 的位址 , 以及 stack 是在 0x1f00000之前的設定空間 , 剩下的指令都運作在0x1f00000 的地方.

        解決了上面的幾項問題後 , 系統正常的 load 到 start_armboot 的位址 (在 / lib_arm/ board.c) , 並經由 puts( ) 的指令 , 將預先設定好的字串 , 透過rs232 port , 輸出到 PC 上頭的 Hyper terminal 上 ( baudrate : 38400 , 8 , n , 1)

        系統進行到這 , 並不代表 u-boot 已經完全的活起來了 , 但至少可以證明我們從 u-boot 的 compiler 以及 link 的過程中 , 能夠讓 image 順利的在 fa526 這顆 cpu來執行 , 並且能夠順利的運作重定位 , 以及rs232等層次運作. 但接下來才是要試驗 u-boo t的功能性. 這足以驗證一些功能在 gl300 的平台是否完沒沒有問題的運行.




arrow
arrow
    全站熱搜

    jslinux 發表在 痞客邦 留言(0) 人氣()