如何移植 Linux 到晶心平台

Facebook
Twitter
LinkedIn

沈智明,資深技術經理,晶心科技股份有限公司

有鑑於越來越多使用者將 Linux 移植在晶心平台(Andes Embedded™)的上(AndesCore™ N12 或 N10),本文之目的在協助使用者快速、有效率的將 Linux 移植到自建的 FPGA 板子上(CPU 是 AndesCore™ 的 N12 或 N10)。筆者曾協助多家公司工程師進行 Linux 移植到晶心平台的工作,將 Linux 移植過程容易遭遇的問題與盲點進行實務說明,期望能對使用者有所助益,也希望讀者不吝指教提供您寶貴的意見。

在進行實務的 Linux 移植時會發現,使用者的晶心平台可能會有各式各樣的組合,除了 CPU 是使用 N12 或 N10 外,使用者對於其他的周邊(如 RAM,ROM, Timer…..)之搭配各有所好,為了有系統性說明 Linux 移植的要領,將選定一明確的硬體,軟體,與開發工具(toolchain)環境做演練說明,除了讓讀者可以實作明瞭文中之敘述,當使用者的周邊非原設計之硬體(使用者自己的 IP)時,可以運用移植的基本原則,更改希望移植 IP 的 Linux 驅動程式,其他原始碼不動,逐一的將使用者的周邊驅動程式移植到晶心的平台。

在 Linux 移植過程中,使用者須建立一基本觀念,那就是整個 Linux OS 可分為兩部分,第一部分是與硬體相關的 HW dependence code,這部分的程式碼會因對應不同的硬體而造成軟體部分需做不同程度的改寫;第二部份是與硬體無關的 generic code,這部分的程式碼與硬體無關,純軟體運作,不會因平台(Andes, X86, Arm..)的改變而有差別。移植 Linux 的工程師第一步需要能區分出哪一部分程式碼是 HW dependence code,另外部分的程式碼就是 generic code,如果在這階段對程式碼判斷錯誤(HW dependence code/generic code)會拖延 Linux 移植的時程與增加除錯時的困難。

Linux 移植到晶心平台過程中,首先須先做到 Linux 基礎架構移植成功。在除錯時,Linux 的基礎架構元件是 CPU,timer,interrupt 與 UART,當 CPU 與這 3 項周邊移植成功後,scheduler 可以運行了,printk 也可以運行了 Linux 系統已經可以正常的運作了。接下來的工作只需將需移植的驅動程式一個一個移植即可,基礎骨架移植完成後,除錯也有 printk 可用,接下來只需將肉 (需要加的device drivers) 填上即可。Linux 移植比較困難的地方是 Linux 基礎架構尚未完成之前(Linux 移植的初期階段)的除錯,所幸晶心提供的標準除錯工具與AndeShape™的除錯器 AICE,可以一步一步找出問題之所在,讓初期移植 Linux 的除錯也變得很簡單,具體得作法,後文會詳細說明。本文敘述著重在如何建立Linux 基礎架構在晶心平台,至於個別 Linux 驅動程式的移植,坊間有許多的書在介紹,本文就不多加贅述。

1. 開發環境與程序
  使用者開始進行 Linux 移植到晶心平台,首先須先選定一版晶心的 Linux 原始碼作為基準再進行軟體移植,修改原始碼以符合使用者的開發平台,經由工具列的compile 與 link 所產生的 Linux 的映像檔,再放上 FPGA 板子以驗證程式編寫的正確與否,依此開發程序:軟體編寫->FPGA 板子驗證,再回到軟體編寫程序直到所有周邊IP 在FPGA 板子驗證完全,Linux 移植才完成,如圖表 1 所示,Linux 移植過程中,AICE 除錯可以有效加快 Linux 移植的速度。

選定一組 Linux 原始碼,工具列,FPGA 板子與 netlist 作為晶心的平台(於1.1,1.2,1.3 中所述),作為使用者的平台的對照組,經由使用者的平台與晶心的平台比對可以有效縮短產品開發時程。

   1.1 晶心版 Linux 原始碼
  目前晶心最新版本的 Linux 原始碼在 AndeSoft™的 BSP310 中,Linux 原始碼放在 BSP310 套件位置: BSPv310/source/Linux/linux-2.6.tgz。使用BSP310 中的 ramdisk ”xc5_glibc_ramdisk.img”作為 filesystem。

   1.2 工具列
  此晶心平台選用的工具列是 AndeSoft™的 nds32le-linux-glibc-v2。

   1.3 FPGA 板子與 netlist
  FPGA 板子是晶心 AndeShape™的 XC5 開發板。Netlist 是選定晶心AndesCore™的 N10 production version.

移植平台是指使用者要移植 Linux 的平台,也就是移植 Linux 的目標平台。將移植平台與晶心平台的比較列表如下: (其中所列之軟體皆屬於 BSP310 中之套件)。

2. Boot loader
  如果使用者有自己慣用的 boot loader,可以使用慣用的 boot loader 以加快開發時程,如果沒有 boot loader 的開發經驗,可以選用 u-boot 作為系統的 boot loader.。u-boot 的 source ocde 位置在BSPv310/source/Standalone/u-boot/u-boot.tgz。

   2.1 U-boot
  AndeSoft™的 BSP310 中 u-boot source code 是需要 EBIOS boot up 後再執行的 u-boot 版本。直接 boot up 不需要其他軟體協助的 U-boot 版本(ROM 版) 是比較符合使用者的需要,晶心版的 u-boot 使用方法請參考 BSP310 User
Manua。l 如果要 ROM 版的 u-boot 需要在 BSP310 中的 u-boot 軟體做 patch,
其指令如下:
# patch -p1 <burn-mode.patch
   patching file arch/nds32/cpu/n1213/ag101/cpu.c
   patching file arch/nds32/cpu/n1213/start.S
   patching file arch/nds32/include/asm/u-boot-nds32.h
   patching file arch/nds32/lib/board.c
   patching file board/AndesTech/adp-ag101p/config.mk
   patching file include/configs/adp-ag101p.h

patch 完成的 u-boot source code 可以產生 ROM 版的 u-boot image,直接開機後的執行結果如圖表 3 所示。

3. 除錯環境
  在移植 Linux 到晶心平台之前,先架設好除錯的環境,尤其對底層 Linux 原始碼的移植,有莫大的助益,在 printk 尚未正常運作前,需依靠 AndeShape™的 AICE 與 AndeSoft™的 GDB 來進行除錯。

   3.1 設定 Linux kernel 除錯選項
  Linux Kernel 需要設定一些除錯選項,才能順利的運用 AndeSoft™的 GDB 進行除錯。晶心平台中 Linux kernel 除錯選項設定如圖表 4 所示,增加這些選項會增加 kernel 映像檔的空間,如果空間佔用過大以至於不符合設計需求時,可在除錯工作完畢後將除錯選項關閉以節約不必要的空間浪費。

   3.2 Linux kernel 除錯的程序
  Build 成 kernel bootpImage (含 kernel debug message 如圖表四選項) 後, Linux 的映像檔放到 FPGA 板子上,PC host 端的 AndeSoft™的 GDB 透過網路(socket)與 AICE 連接至 FPGA 板子,進行除錯的工作。

   3.2.1 編譯鏈結成映像檔
  設定好 AndeSoft™的 cross-compiler 路徑後,利用下列指令經由 compiler and linker 後可以得到 bootpImage,指令如下:

#CROSS_COMPILE=”nds32le-linux-” ARCH=”nds32″ make xc5_defconfig
#CROSS_COMPILE=”nds32le-linux-” ARCH=”nds32″ make menuconfig
# CROSS_COMPILE=”nds32le-linux-” ARCH=”nds32″ make bootpImage
INITRD=xc5_glibc_ramdisk.img

將生成的 bootpIamge 放到 FPGA 板子上,將 AICE 連接到 FPGA 板子啟動
ICEman,指令如下:

#C:\Andestech\AndeSight200MCU\ice>ICEman.exe –p 1234


PC host 端的 AndeSoft™的 GDB 透過網路(socket)與 AICE 連接至FPGA 板子,進行除錯的工作,示範指令如下:

#ddd –debugger nds32le-linux-gdb vmlinux
gdb>target remote 10.0.2.164:1234

其中IP 值 10.0.2.164 是一個應用範例,使用者可依環境實際 IP 值進行設定。環境設定完成後,可以開始進行除錯工程。

4. 移植Linux至晶心平台關鍵點經驗傳承
     4.1 Kernel 載入程式除錯實作
      kernel 載入程式目的將 kernel 主程式進行解壓縮並載入正確位置,此程式與kernel 主程式是兩個不同程式,但會一起包在 zImage 中只是 kernel 載入程式會 attached 在 zImage 的前面。除錯時需 file 不同的 ELF file 才能進行正確的除錯工作,kernel 載入程式的位置在
arch/nds32/boot/compressed/vmlinux,指令如下所示。
#ddd –debugger nds32le-linux-gdb arch/nds32/boot/compressed/vmlinux

kernel 主程式的 ELF file “vmlinux”在 kernel source code 的根目錄下指令如下所示。
#ddd –debugger nds32le-linux-gdb vmlinux

   4.2 Linux kernel 除錯實作
  kernel 載入程式執行完畢後會跳到 kernel 主程式執行。進入點是arch/nds32/kernel/head.S 的 assembly code 執行完後會進入 kernel 的主要函數 “start_kernel”。

   4.2.1. RAM offset patch
  晶心版 Linux 原始碼搭配 XC5 平台,RAM 的起始位置(指的是 PA)是 0x0, 使用者 FPGA 開發板的 RAM 起始位置如果不是 0x0,必須要修改 FPGA 板子中 RAM 的起始位置,做法是在晶心版的 Linux 原始碼中進行 RAM address patch,將原始碼中 RAM 位置調整到 FPGA 開發板中 RAM 的真實位置。

   4.2.2. PA/VA remap table
  當 FPGA 板子 IO 的 PA 設定正確後,使用者需要設定 PA/VA remap table,作法可參考 arch/nds32/include/asm/spec-ag101.h,依照 apec-ag101.h 中PA/VA 對應的關係去增減使用者自己 IO device 的 PA/VA remap table。

   4.2.3. Kernel 解壓縮與 software breakpoint
  在進行 kernel 除錯時,如果在低位址處,例如:head.S 中進行除錯,當設定software breakpoint 時,會有 breakpoint 無法停下來與 AICE 斷線的情況發生。原因是當使用者設定 software breakpoint 時,breakpoint 處的 instruction 會修改並加入 break instruction。但 kernel 解壓縮時會將除錯的程式碼覆蓋造成與 GDB 除錯不一致性而產生錯誤。解決的方法就是原設定 software breakpoint 改為 hardware breakpoint,這樣就可以避免因 kernel 解壓縮所造成除錯的錯誤,降低除錯時的困難度。

   4.2.4. PA/VA 觀念說明與除錯要領
   在原始碼 arch/nds32/kernel/head.S 中
la      $lp,        mmap_switched
mtsr $lp, $IPC
iret

執行完 iret 後,系統就會從 PA 轉成 VA,MMU translation status 從translation off 轉為 translation on 在此分界處除錯規則如下所述,如果觀念不清楚及容易產生除錯時的錯誤,請務必牢記。

     4.2.4.1. MMU translation off 時期除錯
   在這個時期除錯,VA 是不存在的。所有的 IO address 與 memory 都是 PA 沒有 VA,如果除錯位址設成 VA,容易 hit illegal address 而造成 exception。

     4.2.4.2. MMU translation on 時期除錯
   在這個時期除錯,PA 是不存在的。所有的 IO address 與 memory 都是 VA 沒有 PA,如果除錯位址設成 PA,容易 hit illegal address 而造成 exception.

  4.2.5. 移植 Linux 的基礎元件
  MMU translation on 後,很快就會進入 start_kernel 函數,接下來移植的重點就是移植 Linux 基礎元件,那就是 interrupt,timer and UART。當這 3 個device 移植成功後,Linux 的架構就建立起來了,printk 也可以用了,Linux 已經可以正常的運作。如果沒有意外,可以執行完 kernel 甚至將 filesystem 帶起來。接下來使用者可以將自己的周邊元件一個一個的 device driver 移植入系統。當周邊元件移植完成後,Linux 系統移植到晶心平台就完成了。

5. 結語
Linux作業系統運作在晶心平台已有多年的時間。各式各樣的Linux軟體運作在晶心平台不計其數。皆可證明Linux作業系統運作結合晶心平台是一個穩定與成熟的產品,只要能明瞭熟悉Linux 移植的技巧與重點,使用晶心平台開發Linux的產品將是一件愉快與簡單的工作。