4. U-boot的修改与编译

借助LubanCat-SDK,我们可以很方便的进行U-boot的编译,但是有时候我们还要根据板卡的实际情况来修改U-boot,实现一些定制功能。 为此,我们必须对U-boot进行一个深入的了解。

下面的内容,我们将会了解LubanCat-SDK是如何实现对U-boot的一键构建,构建参数又与哪些文件有关

不同LubanCat板卡使用相同版本的U-Boot源码进行构建,仅少量配置不同, 下述文档以使用sg200x处理器的鲁班猫板卡为例进行说明,使用其他型号处理器的鲁班猫板卡内容基本相同, 仅在必要处指出不同点。

4.1. 获取U-boot

SDK中包含了U-boot源码,不做单独仓库存放,需要获取SDK从而获取u-boot。

可以参考: SDK源码获取 章节。

4.2. U-boot编译

在LubanCat-SDK中,自动编译脚本基本上都存放在cvisetup.sh中,这是SDK的主要功能入口

在cvisetup.sh中,U-boot的构建函数是function build_uboot() 具体内容如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function build_uboot()
{(
print_notice "Run ${FUNCNAME[0]}() function"
_build_uboot_env
_build_opensbi_env
_link_uboot_logo
cd "$BUILD_PATH" || return
make u-boot
)}

function _build_uboot_env()
{
_build_atf_env
_build_fsbl_env
export UBOOT_OUTPUT_FOLDER IMGTOOL_PATH FLASH_PARTITION_XML FIP_BIN_PATH
export UBOOT_VBOOT RELEASE_VERSION ENABLE_BOOTLOGO STORAGE_TYPE COMPRESSOR_UBOOT
export PANEL_TUNING_PARAM PANEL_LANE_NUM_TUNING_PARAM PANEL_LANE_SWAP_TUNING_PARAM
}

function _build_opensbi_env()
{
export OPENSBI_PATH
}

function _link_uboot_logo()
{(
print_notice "Run ${FUNCNAME[0]}() function"
cd "$BUILD_PATH" || return
if [[ x"${PANEL_TUNING_PARAM}" =~ x"I80" ]]; then
    ln -sf "$COMMON_TOOLS_PATH"/bootlogo/logo_320x240.BMP "$COMMON_TOOLS_PATH"/bootlogo/logo.jpg
fi
)}

build_uboot包括:

  • _build_uboot_env设置了构建 U-Boot 所需的环境变量。

  • _build_opensbi_env设置了构建 OpenSBI 所需的环境变量。

  • _link_uboot_logo设置 U-Boot 启动时的logo。

  • cd “$BUILD_PATH”进入sophon-image-build/build目录

  • make u-boot编译uboot。

可查看sophon-image-build/build/Makefile查看make uboot是如何进行的,此处不展开讲解。

借助SDK可以很方便地进行编译,进入SDK顶层目录,以sg2000_lubancat_riscv_ubuntu_emmc为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#初始化编译环境,输入当前用户的密码
source build/cvisetup.sh

#加载对应的板级配置文件
defconfig sg2000_lubancat_riscv_ubuntu_emmc

#清除uboot编译输出
clean_uboot

#构建uboot
build_uboot

构建生成的uboot在install/soc_sg200x_xxx/fw_payload_uboot.elf

4.3. U-boot修改

一般来说,要适配一块新的板卡,在U-boot中主要设计三部分的修改和添加,分别是board目录下涉及板卡初始化的部分、 configs目录下对应板卡的配置文件、arch目录下与板级外设相关的文件。

得益于算能对sg200x系列处理器的完善支持,在U-boot阶段,我们直接根据使用的处理器型号选择算能官方参考板的配置即可。 例如sg2000处理器使用sophon-image-build/u-boot-2021.10/board/cvitek/mars

野火仅在U-boot源码中修改了挂载的文件系统,官方默认使用的squashfs文件系统,而ubuntu和buildroot都需要ext4格式。

4.3.1. U-boot配置文件

我们编译使用的配置文件不是在uboot源码中,而是在板级配置文件中。 路径为sophon-image-build/build/boards/sg200x/sg200x_lubancat_xxx/u-boot/sg200x_xxx_defconfig, 这里以sg2000_lubancat_riscv_ubuntu_sd_defconfig为例,如果我们要修改的话,可以借助menuconfig工具。

首先我们要来到u-boot-2021.10根目录下,然后执行以下操作:

1
2
3
4
5
#进入u-boot-2021.10根目录
cd u-boot-2021.10

# 使用menuconfig来管理修改指定的配置文件
make menuconfig KCONFIG_CONFIG=../build/boards/sg200x/sg2000_lubancat_riscv_ubuntu_sd/u-boot/sg2000_lubancat_riscv_ubuntu_sd_defconfig

或者通过SDK通过的编译命令打开,在sdk顶层目录执行:

1
2
3
4
5
6
7
8
#初始化编译环境,输入当前用户的密码
source build/cvisetup.sh

#加载对应的板级配置文件
defconfig sg2000_lubancat_riscv_ubuntu_sd

#打开menuconfig图形化配置界面
menuconfig_uboot

修改完成之后按ESC按键退出,并保存。

如果是指定KCONFIG_CONFIG参数打开的界面默认保存到原路径即可,默认覆盖原来板级目录的配置文件。

如果是通过menuconfig_uboot打开的界面,保存到的.config具体是保存到了u-boot-2021.10/build/sg2000_lubancat_riscv_ubuntu_sd/.config,需要将.config覆盖到板级的配置文件中,这样才能下次编译时清除编译输出后再加载也能加载修改后的配置文件。

4.3.2. 引脚初始化

算能芯片的引脚复用和电气属性不是通过设备树进行配置的,没有使用Pinctrl子系统,初始化工作是在uboot下进行。

初始化配置文件为:sophon-image-build/build/boards/sg200x/sg200x_lubancat_xxx/u-boot/cvi_board_init.c

以sg2000_lubancat_riscv_ubuntu_sd为例,截取部分内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int cvi_board_init(void)
{
    /*Network indicator light*/
    PINMUX_CONFIG(PWR_WAKEUP0, EPHY_LNK_LED);
    PINMUX_CONFIG(PWR_GPIO2, EPHY_SPD_LED);

    /*HOST_PWR_EN*/
    PINMUX_CONFIG(IIC2_SDA, PWR_GPIO_13);

    /*UART1*/
    PINMUX_CONFIG(IIC0_SCL, UART1_TX);
    PINMUX_CONFIG(IIC0_SDA, UART1_RX);

    /*WIFI*/
    pinmux_config(PINMUX_SDIO1);
    PINMUX_CONFIG(CAM_PD1, XGPIOA_4);
    PINMUX_CONFIG(CAM_MCLK0, XGPIOA_0);

    PINMUX_CONFIG(UART2_RX, UART2_RX);
    PINMUX_CONFIG(UART2_TX, UART2_TX);
    PINMUX_CONFIG(UART2_RTS, UART2_RTS);
    PINMUX_CONFIG(UART2_CTS, UART2_CTS);

    /***adc***/
    mmio_write_32(0x03001810,0x40);
    mmio_write_32(0x0300180C,0x40);

    set_rtc_register_for_power();

    return 0;
}

在cvi_board_init函数中进行配置,通过PINMUX_CONFIG设置引脚复用功能,通过mmio_write_32函数可以设置寄存器值。

4.3.2.1. 配置引脚复用功能

引脚复用功能定义在sophon-image-build/u-boot-2021.10/board/cvitek/mars/mars_pinlist_swconfig.h

以引脚总称为IIC2_SDA的引脚为例:

../../_images/uboot_0.jpg

从上图可见引脚总称为IIC2_SDA的引脚可以复用为i2c、gpio、pwm等功能,如果需要配置引脚复用那么就需要修改cvi_board_init.c通过PINMUX_CONFIG函数进行设置。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#格式是PINMUX_CONFIG(引脚总称, 复用功能);

int cvi_board_init(void)
{
....

#复用为gpio功能
PINMUX_CONFIG(IIC2_SDA, PWR_GPIO_13);

#复用为i2c功能
PINMUX_CONFIG(IIC2_SDA, IIC2_SDA);

#复用为pwm功能
PINMUX_CONFIG(IIC2_SDA, PWM_15);
....
}

除了在uboot进行初始化,也可以在应用层通过cvi_pinmux工具进行初始化,可以参考: cvi_pinmux工具

4.3.2.2. 配置寄存器值

可以通过mmio_write_32函数设置寄存器值,例如在作者调试adc的时候发现adc读取的数据不准,原因在于adc引脚默认有下拉电阻,需要disable下拉,查阅trm手册可知相关寄存器值。

1
2
3
4
5
#格式是mmio_write_32(寄存器地址,寄存器值)

/***adc***/
mmio_write_32(0x03001810,0x40);
mmio_write_32(0x0300180C,0x40);

TRM手册可以从资料网盘/5-数据手册中获取或者访问 算能官方仓库

4.3.3. 设备树文件

设备树文件是板级设备的描述文件,系统通过设备树文件得知板卡上有哪些外设,从而加载相应的驱动使外设正常工作。

算能uboot的设备树和内核设备树是用的同一个文件,路径是sophon-image-build/build/boards/sg200x/sg2000_lubancat_riscv_ubuntu_sd/dts_riscv/sg2000_lubancat_riscv_ubuntu_sd.dts

编译的时候会拷贝一份到sophon-image-build/u-boot-2021.10/arch/riscv/dts目录下。

通常二者的作用:

  • U-Boot DTB:负责初始化存储、打印串口等设备;

  • Kernel DTB:负责初始化存储、打印串口以外的设备;

U-Boot初始化时先用U-Boot DTB完成存储、打印串口初始化, 然后从存储上加载Kernel DTB并转而使用这份DTB继续初始化其余外设。

启用kernel DTB机制后:编译阶段会把U-Boot DTS里带 u-boot,dm-pre-reloc 和 u-boot,dm-spl 属性的节点过滤出来, 在此基础上再剔除defconfig中 CONFIG_OF_SPL_REMOVE_PROPS 指定的property, 最终生成u-boot.dtb文件并且追加在u-boot.bin的末尾。

4.4. 参考资料

算能添加了很多自定义的功能,但其主体还是基于官方U-boot的,所以关于U-boot的操作都是基本相同的,我们可以参考以下wiki。

官方uboot下载链接: http://www.denx.de/wiki/uboot/WebHome

官方uboot GitHub: https://github.com/uboot/uboot

uboot wiki: http://www.denx.de/wiki/uboot/WebHome