如何移植 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 移植的速度。

图表 1 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平台与晶心平台的比较表

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 u-boot 执行结果图

3. 除错环境
  在移植 Linux 到晶心平台之前,先架设好除错的环境,尤其对底层 Linux 原始码的移植,有莫大的助益,在 printk 尚未正常运作前,需依靠 AndeShape™的 AICE
与 AndeSoft™的 GDB 來进行除错。

  3.1 设定 Linux kernel 除错选项
  Linux Kernel 需要设定一些除错选项,才能顺利的运用 AndeSoft™的 GDB 进行除错。晶心平台中 Linux kernel 除错选项设定如图表 4 所示,增加这些选项会增加 kernel 映像档的空间,如果空间占用过大以至于不符合设计需求时,可在除错工作完毕后将除错选项关闭以节约不必要的空间浪费。

图表 4设定 Kernel hacking 中除错选项勾选

   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的产品将是一件愉快与简单的工作。