image.png

  1. 作为SoC厂家会做一个基础底板,基于开源Uboot官方版本中找到一个最相近的板子配置进行移植,去适配自己的芯片和底板。这就是芯片原厂BSP包。
  2. 买别人SoC自己做底板的一般厂家,会拿到SoC的直接提供 u-boot 源码,做查看、修改(增加新功能) 或 u-boot 版本升级这三大块的用处;后两种都需要对新板子做适配/移植。
  3. 如果SoC和板子都不是自己的,只需要改功能,那就更容易了,例如加一个命令行。

一般厂家是我们最经常遇到的场景,芯片是别人的,跟业务相关的底板是自己的。这就需要进行移植

1. u-boot 移植要点

image.png

芯片公司、开发板厂家和用户三者之间的联系:

  • 芯片公司移植的 u-boot 从一开始是基于官方的 u-boot 拿来修改,添加/修改自家的 EVK 评估版的板子型号、相关外设初始化文件,并修改 u-boot 的 Makefile 配置,然后把自家芯片的 EVK 评估版的硬件原理图、u-boot、Linux 和 根文件系统以及使用说明文档等等全部开源,以供下游做应用的公司/厂家和做开发板的公司拿来做修改或直接应用;
  • 做开发板的厂家在拿到了芯片公司提供的芯片评估版 EVK 板子的原理图后,与 SoC 直接相关的比如 PMIC、DDR、FLASH、以太网 PHY 芯片等等不会做大改,一般直接照搬过来画自己的开发板。因为在移植 u-boot 的时候就不用再为新选型的芯片做代码适配,一般没必要做这种费力但效果不大的事情,能直接用的就尽量直接用,能不用改的就尽量不改。然后再拿到芯片公司提供的芯片评估版 EVK 板子对应的 u-boot 源码之后,同样的再添加/修改为自家开发板的型号、添加一点点自己板子的外设初始化代码(这个要求比较高)并修改 Makefile,便得到自家开发板适配的又一个 u-boot;
  • 当用户(比如现在的我)拿到了开发板厂家 或者 芯片公司提供的 u-boot 源码,即所有相关文件和初始化代码都写好了,便可以直接编译进而使用,或者自己再进一步定制化。

一般把 u-boot 做成对应平台通用的和最小化的,即只保留必要的板级外设初始化代码(如串口、网口和 FLASH 等需要主要做适配,都尽量找能现成使用的),其他更多板级外设初始化在 Linux 移植部分中完成。 如果要深入学习,有以下要点可以参考:

  1. 如果芯片公司或者单位提供了移植好的 u-boot,可以用 beyong 软件把移植好的 u-boot 文件夹与 官方原版(版本要一致)进行对比,看一看改动了哪些文件夹和哪些文件,帮助学习。
  2. uboot移植新手入门实践_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili。版本比较新。
  3. 韦东山 嵌入式Linux 第1期与2期间的衔接课程 u-boot编译体验和源码深度分析 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 老版本。
  4. 【韦东山 】移植U-boot 2012 04 01 到JZ2440_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 老版本。
  5. linux-----uboot和kernel移植 - 灰信网(软件开发博客聚合) (freesion.com)

2. 移植修改

image.png

2.1 uboot代码框架

移植uboot前需要了解下uboot的代码框架,好知道修改那些代码。

image.png

在硬件层面嵌入式系统的核心一般包括以下层次:
(1)目标板:它包含了系统运行所需的所有组件,如SOC芯片、DDR、flash/emmc存储器、各种外设以及时钟源、电源管理芯片等
(2)SOC:它包含了cpu、总线控制器、集成在片内的rom、sram、dma控制器、硬件加速器、异构核,以及片内时钟、电源控制模块等
(3)处理器架构:它一般指处理器体系结构的大版本,不同的体系结构之间可能存在不同的指令集、异常模型以及内存模型等。例如对于arm系列架构,armv8和armv7就属于不同的处理器架构
(4)cpu型号:它是指处理器的具体型号,如cortex-a53或cortex-a72等

arch目录包含了处理器架构相关代码,arch/cpu目录包含了特定cpu代码,而board目录则包含了特定目标板的代码。因此当我们新增加一款目标板时,主要的工作就可以集中在board相关的代码,只要不是太新的cpu型号,arch和cpu相关代码在uboot官方版本中都已经被支持。

2.2 添加board的基本步骤

当我们开始一个全新的项目时,总是希望能先让系统能运行起来,然后再在此基础上为其添加更多的feature,这个只包含能让系统运行所需模块的系统,叫做最小系统。cpu能正常运行包含以下几个条件:
(1)具有合适的电源和时钟
(2)程序代码被加载到合适的位置,cpu能够正常获取指令
(3)具有cpu用于数据操作的可读写内存
(4)cpu被release reset

当然对于需要支持中断的系统,则还需要包含中断控制器,而对于像操作系统这种需要通过定时器驱动进程切换的系统,则显然还需要timer定时器。为了达到以上目的,我们添加board的基本步骤大概如下:
(1)在board目录下为新board添加一个目录,用于存放board特定的代码
(2)为新目录添加Kconfig配置选项和Makefile编译选项,将其添加到编译系统中
(3)在Kconfig中为该board定义一个配置项,并为该配置项添加其所支持的特性,如cpu架构、cpu型号等
(4)为新board增加一个配置相关的头文件和编译所需的defconfig文件,用于该board相关的选项配置
(5)在board目录下添加适当的文件,并实现必要的接口

2.3 添加自己的开发板

2.3.1 新增config文件

那必须能抄就抄啊。先在 configs 目录下创建默认配置文件,复制 mx6ull_14x14_evk_emmc_defconfig,然后重命名为 mx6ull_alientek_emmc_defconfig,命令如下:

cd configs

cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig

然后修改里面的一些标识字符串命名。

2.3.2 添加头文件

在目录 include/configs 下添加 I.MX6ULL-ALPHA 开 发 板 对 应 的 头 文 件 , 复 制

include/configs/mx6ullevk.h,并重命名为 mx6ull_alientek_emmc.h,命令如下:

cp include/configs/mx6ullevk.h mx6ull_alientek_emmc.

然后修改里面的一些标识字符串命名。

根据需求对.h头文件里面的宏进行修改和增减

  • 宏 PHYS_SDRAM_SIZE 就是板子上 DRAM 的大小
  • 宏 CONFIG_DISPLAY_CPUINFO,uboot 启动的时候可以输出 CPU 信息。
  • 宏 CONFIG_DISPLAY_BOARDINFO,uboot 启动的时候可以输出板子信息。
  • CONFIG_SYS_MALLOC_LEN 为 malloc 内存池大小
  • 宏 CONFIG_BOARD_EARLY_INIT_F,这样 board_init_f 函数就会调用board_early_init_f 函数
  • 宏 CONFIG_BOARD_LATE_INIT,这样 board_init_r 函数就会调用board_late_init 函数。
  • 宏 CONFIG_BOOTCOMMAND,此宏就是设置环境变量 bootcmd 的值。
  • 宏 CONFIG_SYS_LOAD_ADDR 表示 linux kernel 在 DRAM 中的加载地址
  • 宏 CONFIG_SYS_HZ 为系统时钟频率,这里为 1000Hz。
  • 宏 CONFIG_STACKSIZE 为栈大小,这里为 128KB。
  • 宏 CONFIG_NR_DRAM_BANKS 为 DRAM BANK 的数量

2.3.3 板级文件夹

uboot 中每个板子都有一个对应的文件夹来存放板级文件,比如开发板上外设驱动文件等等。NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 board/freescale 目录下,在这个目录下有个名为 mx6ullevk 的文件夹,这个文件夹就是 NXP 官方 I.MX6ULL EVK 开发板的板级文件夹。复制 mx6ullevk,将其重命名为 mx6ull_alientek_emmc,命令如下:

cd board/freescale/
cp mx6ullevk/ -r mx6ull_alientek_emmc

进 入 mx6ull_alientek_emmc 目 录 中 , 将 其 中 的 mx6ullevk.c 文 件 重 命 名 为mx6ull_alientek_emmc.c,命令如下:

cd mx6ull_alientek_emmc
mv mx6ullevk.c mx6ull_alientek_emmc.c

修改对应的Makefile文件、cfg文件、Kconfig文件

2.3.4 dts文件

以下是自定义dtb文件的方法:

(1)在arch/arm/dts/目录下添加dts文件test-board-minimal.dts,并在目录的Makefile中添加以下编译选项

dtb-$(CONFIG_TARGET_TESTBOARD) += test-board-minimal.dtb

(2)在配置文件configs/testboard_defconfig中指定该dtb为默认dtb文件,并使能uboot的设备树支持

CONFIG_DEFAULT_DEVICE_TREE="test-board-minimal"
CONFIG_OF_CONTROL=y
CONFIG_OF_SEPARATE=y

2.4 常见适配修改

2.4.1 LCD点灯修改

一般 uboot 中修改驱动基本都是在 xxx.h 和 xxx.c 这两个文件中进行的,xxx 为板子名称,

比如 mx6ull_alientek_emmc.h 和 mx6ull_alientek_emmc.c 这两个文件。

一般修改 LCD 驱动重点注意以下几点:

  1. LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确。
  2. LCD 背光引脚 GPIO 的配置。
  3. LCD 配置参数是否正确

2.4.2 驱动修改

例如网卡等跟目标板子有差异的硬件驱动。

2.4.3 打印信息和环境变量修改

一些启动时打印的板子信息如果不对需要进行修改

uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs,如果需要也应该修改

bootargs里面:

  • console设置linux终端和波特率
  • root设置根文件系统位置
  • rootfstype指定根文件系统类型

uboot 移植到此结束,简单总结一下 uboot 移植的过程:

  1. 不管是购买的开发板还是自己做的开发板,基本都是参考半导体厂商的 dmeo 板,而半导体厂商会在他们自己的开发板上移植好 uboot、linux kernel 和 rootfs 等,最终制作好 BSP包提供给用户。我们可以在官方提供的 BSP 包的基础上添加我们的板子,也就是俗称的移植。
  2. 我们购买的开发板或者自己做的板子一般都不会原封不动的照抄半导体厂商的 demo板,都会根据实际的情况来做修改,既然有修改就必然涉及到 uboot 下驱动的移植。
  3. 一般 uboot 中需要解决串口、NAND、EMMC 或 SD 卡、网络和 LCD 驱动,因为 uboot的主要目的就是启动 Linux 内核,所以不需要考虑太多的外设驱动。
  4. 在 uboot 中添加自己的板子信息,根据自己板子的实际情况来修改 uboot 中的驱动。

后记:

本篇作为uboot入门的结尾,写的比较空一些,也可能没做过实际的工作讲出来不知道难点和技巧在哪里,不过也写了这么多。我经常问人一个问题:怎么样才能提高技能?一个答案是领导给你一个能提高技能的活干。细想真是如果没做过,即便是学习了也是不能够太深入的理解,被内行一问便知。笔者也不是什么活都干过,很多方面也不是专家,但是作为uboot入门这个系列应该够用了。至少可以让干啥的时候能快速的学习找到对应的解决方案,在干中继续学习吧。

读书和思考: 最近看《认知觉醒》,分享给大家一些(3):

results matching ""

    No results matching ""