加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • U-boot代碼層次
    • 如何添加board
    • test board添加示例
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

為U-boot 添加新的board

2022/12/30
1298
閱讀需 32 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

U-boot代碼層次

如何添加board

添加board的基本步驟

test board添加示例

添加target配置選項

添加config頭文件

添加dtb文件

添加board文件

創(chuàng)建defconfig配置文件

spl支持semihost啟動

U-boot代碼層次

uboot需要支持眾多的硬件,并且具有良好的可擴(kuò)展性、可移植性和可維護(hù)性,因此必須要有一個設(shè)計良好的代碼架構(gòu)。代碼架構(gòu)的設(shè)計總是與軟硬件架構(gòu)密不可分的,在硬件層面嵌入式系統(tǒng)的核心一般包括以下層次:

(1)目標(biāo)板:它包含了系統(tǒng)運行所需的所有組件,如SOC芯片、DDR、flash/emmc存儲器、各種外設(shè)以及時鐘源、電源管理芯片

(2)SOC:它包含了cpu、總線控制器、集成在片內(nèi)的rom、sram、dma控制器、硬件加速器、異構(gòu)核,以及片內(nèi)時鐘、電源控制模塊等

(3)處理器架構(gòu):它一般指處理器體系結(jié)構(gòu)的大版本,不同的體系結(jié)構(gòu)之間可能存在不同的指令集、異常模型以及內(nèi)存模型等。例如對于arm系列架構(gòu),armv8和armv7就屬于不同的處理器架構(gòu)

(4)cpu型號:它是指處理器的具體型號,如cortex-a53或cortex-a72等

一般cpu型號和處理器架構(gòu)數(shù)量相對較少,如對于arm架構(gòu)來說一般就是arm官方發(fā)布的這些型號。而soc型號就要多一些,它主要是各芯片公司基于特定cpu架構(gòu)以及其它ip模塊,設(shè)計的專用或通用芯片,如高通海思設(shè)計的手機芯片。最后就是以soc芯片為核心設(shè)計的目標(biāo)板了,在目標(biāo)板上基本上集成了一款產(chǎn)品所需的所有組件,如一款手機的電路板。它們之間的簡單關(guān)系如下圖:

Uboot的代碼設(shè)計也遵循以上層次,arch目錄包含了處理器架構(gòu)相關(guān)代碼,arch/cpu目錄包含了特定cpu代碼,而board目錄則包含了特定目標(biāo)板的代碼。因此當(dāng)我們新增加一款目標(biāo)板時,主要的工作就可以集中在board相關(guān)的代碼,只要不是太新的cpu型號,arch和cpu相關(guān)代碼在uboot官方版本中都已經(jīng)被支持。因此可以直接復(fù)用這部分實現(xiàn),我們唯一要做的就是選擇正確的配置選項。

如何添加board

添加board的基本步驟

當(dāng)我們開始一個全新的項目時,總是希望能先讓系統(tǒng)能運行起來,然后再在此基礎(chǔ)上為其添加更多的feature,這個只包含能讓系統(tǒng)運行所需模塊的系統(tǒng),叫做最小系統(tǒng)。cpu能正常運行包含以下幾個條件:

(1)具有合適的電源和時鐘

(2)程序代碼被加載到合適的位置,cpu能夠正常獲取指令

(3)具有cpu用于數(shù)據(jù)操作的可讀寫內(nèi)存

(4)cpu被release reset
當(dāng)然對于需要支持中斷的系統(tǒng),則還需要包含中斷控制器,而對于像操作系統(tǒng)這種需要通過定時器驅(qū)動進(jìn)程切換的系統(tǒng),則顯然還需要timer定時器。為了達(dá)到以上目的,我們添加board的基本步驟大概如下:
(1)在board目錄下為新board添加一個目錄,用于存放board特定的代碼

(2)為新目錄添加Kconfig配置選項和Makefile編譯選項,將其添加到編譯系統(tǒng)中

(3)在Kconfig中為該board定義一個配置項,并為該配置項添加其所支持的特性,如cpu架構(gòu)、cpu型號等

(4)為新board增加一個配置相關(guān)的頭文件和編譯所需的defconfig文件,用于該board相關(guān)的選項配置

(5)在board目錄下添加適當(dāng)?shù)奈募?,并實現(xiàn)必要的接口

test board添加示例

添加target配置選項

    在arch/arm/Kconfig的board select菜單下新增如下的TARGET_TESTBOARD配置選項:
config?TARGET_TESTBOARD
????????bool?"Qemu?test?board"
????????select?ARM64
????????select?DM
????????select?DM_SERIAL
????????select?PL01X_SERIAL
????????select?SUPPORT_SPL
????????select?SPL?if?SUPPORT_SPL
????????select?SPL_FRAMEWORK_BOARD_INIT_F?if?SPL
????????select?SPL_SERIAL_SUPPORT
????????select?PL011_SERIAL?if?SPL
????????select?SPL_LIBGENERIC_SUPPORT?if?SPL
????????select?SPL_LIBCOMMON_SUPPORT?if?SPL

它將在后面的configs/testboard_defconfig中通過CONFIG_ TARGET_TESTBOARD =y選擇

    在arch/arm/Kconfig文件中添加以下內(nèi)容,以包含board的Kconfig文件
?source?"board/mars/test/Kconfig"

添加config頭文件

在include/configs目錄下添加config頭文件testboard.h,并添加以下內(nèi)容:

#ifndef?__CONFIG_H
#define?__CONFIG_H
#include?<linux/sizes.h>

#define?CONFIG_SYS_SDRAM_BASE???????????0x40000000

/*?The?DTB?generated?by?QEMU?is?placed?at?start?of?RAM,?stay?away?from?there?*/
#define?CONFIG_SYS_INIT_SP_ADDR?????????(CONFIG_SYS_SDRAM_BASE?+?SZ_2M)
#define?CONFIG_SYS_LOAD_ADDR????????????(CONFIG_SYS_SDRAM_BASE?+?SZ_2M)
#define?CONFIG_SYS_MALLOC_LEN???????????SZ_16M

#define?CONFIG_SYS_BOOTM_LEN????????????SZ_64M

#define?CONFIG_SYS_HZ???????????????????????1000

#define?CONFIG_PL01x_PORTS??????????????{(void?*)(0x9000000)}
#define?CONFIG_PL011_CLOCK??????1


#define?CONFIG_SYS_UBOOT_START?0x40300000
#define?BOOT_TARGET_DEVICES(func)?
????????func(VIRTIO,?virtio,?0)

#define?CONFIG_EXTRA_ENV_SETTINGS?
????????"fdt_addr=0x43000000"?
????????"kernel_addr_r=0x40000000"?
????????"bootargs=earlycon?root=/dev/vda"?
????????"bootcmd=smhload?/home/lgj/work/linux/arch/arm64/boot/Image?${kernel_addr_r};"?
????????"smhload?/home/lgj/work/linux/arch/arm64/boot/dts/qemu/test-board-smc.dtb?${fdt_addr};"?
????????"booti?${kernel_addr_r}?-?${fdt_addr}"

#define?CONFIG_SYS_CBSIZE?512
#define?CONFIG_SYS_MONITOR_BASE?????????CONFIG_SYS_TEXT_BASE
#define?CONFIG_SYS_MAX_FLASH_BANKS_DETECT???????2
#define?CONFIG_SYS_MAX_FLASH_SECT???????256?/*?Sector:?256K,?Bank:?64M?*/
#define?CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS

#define?CONFIG_SPL_MAX_SIZE?0x25000
#define?CONFIG_SPL_STACK?(CONFIG_SYS_SDRAM_BASE?+?SZ_1M)
#define?CONFIG_SPL_BSS_START_ADDR?(CONFIG_SYS_SDRAM_BASE?+?SZ_1M)

#define?CONFIG_SPL_BSS_MAX_SIZE?0x1000
#endif?

添加dtb文件

使用qemu模擬器啟動uboot時,模擬器會提供一個默認(rèn)的dtb文件,但是我們也可以使用自己自定義的dtb文件,以下是自定義dtb文件的方法:

    在arch/arm/dts/目錄下添加dts文件test-board-minimal.dts,并在目錄的Makefile中添加以下編譯選項
dtb-$(CONFIG_TARGET_TESTBOARD)?+=?test-board-minimal.dtb
    在配置文件configs/testboard_defconfig中指定該dtb為默認(rèn)dtb文件,并使能uboot的設(shè)備樹支持
CONFIG_DEFAULT_DEVICE_TREE="test-board-minimal"
CONFIG_OF_CONTROL=y
CONFIG_OF_SEPARATE=y

添加board文件

    在board目錄下創(chuàng)建mars/test目錄在board/mars/test目錄下創(chuàng)建Kconfig文件,并添加如下內(nèi)容
if?TARGET_TESTBOARD
config?SYS_VENDOR
????????default?"mars"

config?SYS_BOARD
????????default?"test"

config?SYS_CONFIG_NAME
????????default?"testboard"
endif

其中:

SYS_VENDOR:用于指定該board的vendor名,它與SYS_BOARD一起確定會被編譯的board代碼路徑。即board/< SYS_VENDOR >/common和board/< SYS_VENDOR >/< SYS_BOARD >的路徑下的Makefile會被執(zhí)行,在我們的例子中該目錄為board/mars/common/和board/mars/test/SYS_BOARD:用于指定在board/< SYS_VENDOR >下需要編譯的board路徑,如當(dāng)前配置下該目錄為board/mars/test/

SYS_CONFIG_NAME用于指定include/configs目錄下的頭文件名,如當(dāng)前配置該文件即為include/configs/testboard.h

    在board/mars/test目錄下創(chuàng)建MAINTAINERS文件,并添加如下內(nèi)容
QEMU?QEMU?TEST?BOARD
M:??????xxx@yyy.com
S:??????Maintained
F:??????board/mars/test
F:??????include/configs/testboard.h
F:??????configs/testboard.h
    在board/mars/test目錄下創(chuàng)建Makefile文件,并添加如下內(nèi)容
????obj-y???+=?testboard.o
    創(chuàng)建board/mars/test目錄下創(chuàng)建testboard.c文件,并添加如下內(nèi)容
include?<common’s>
#include?<cpu_func.h>
#include?<fdtdec.h>
#include?<init.h>
#include?<spl.h>

#ifdef?CONFIG_ARM64
#include?<asm/armv8/mmu.h>
static?struct?mm_region?testboard_mem_map[]?=?{
????????{
????????????????/*?Flash?*/
????????????????.virt?=?0x00000000UL,
????????????????.phys?=?0x00000000UL,
????????????????.size?=?0x08000000UL,
????????????????.attrs?=?PTE_BLOCK_MEMTYPE(MT_NORMAL)?|
?????????????????????????PTE_BLOCK_INNER_SHARE
????????},?{
????????????????/*?Lowmem?peripherals?*/
????????????????.virt?=?0x08000000UL,
????????????????.phys?=?0x08000000UL,
????????????????.size?=?0x38000000,
????????????????.attrs?=?PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE)?|
?????????????????????????PTE_BLOCK_NON_SHARE?|
?????????????????????????PTE_BLOCK_PXN?|?PTE_BLOCK_UXN
????????},?{
????????????????/*?RAM?*/
????????????????.virt?=?0x40000000UL,
????????????????.phys?=?0x40000000UL,
????????????????.size?=?255UL?*?SZ_1G,
????????????????.attrs?=?PTE_BLOCK_MEMTYPE(MT_NORMAL)?|
?????????????????????????PTE_BLOCK_INNER_SHARE
????????},?{
????????????????/*?Highmem?PCI-E?ECAM?memory?area?*/
????????????????.virt?=?0x4010000000ULL,
????????????????.phys?=?0x4010000000ULL,
????????????????.size?=?0x10000000,
????????????????.attrs?=?PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE)?|
?????????????????????????PTE_BLOCK_NON_SHARE?|
?????????????????????????PTE_BLOCK_PXN?|?PTE_BLOCK_UXN
????????},?{
????????????????/*?Highmem?PCI-E?MMIO?memory?area?*/
????????????????.virt?=?0x8000000000ULL,
????????????????.phys?=?0x8000000000ULL,
????????????????.size?=?0x8000000000ULL,
????????????????.attrs?=?PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE)?|
?????????????????????????PTE_BLOCK_NON_SHARE?|
?????????????????????????PTE_BLOCK_PXN?|?PTE_BLOCK_UXN
????????},?{
????????????????/*?List?terminator?*/
????????????????0,
????????}
};

struct?mm_region?*mem_map?=?testboard_mem_map;
#endif

int?board_init(void)
{
????????return?0;
}

int?dram_init(void)
{
????????if?(fdtdec_setup_mem_size_base()?!=?0)
????????????????return?-EINVAL;

????????return?0;
}

int?dram_init_banksize(void)
{
????????fdtdec_setup_memory_banksize();

????????return?0;
}

void?*board_fdt_blob_setup(void)
{
????????/*?QEMU?loads?a?generated?DTB?for?us?at?the?start?of?RAM.?*/
????????return?(void?*)CONFIG_SYS_SDRAM_BASE;
}

void?enable_caches(void)
{
?????????icache_enable();
?????????dcache_enable();
}

#ifdef?CONFIG_SPL
u32?spl_boot_device(void)
{
????????return?BOOT_DEVICE_SEMIHOSTING;
}
#endif

創(chuàng)建defconfig配置文件

在configs目錄下為testboard創(chuàng)建配置文件testboard_defconfig,并添加如下內(nèi)容

CONFIG_ARM=y
CONFIG_TARGET_TESTBOARD=y
CONFIG_POSITION_INDEPENDENT=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x40000
CONFIG_ENV_SECT_SIZE=0x40000
CONFIG_DEFAULT_DEVICE_TREE="test-board-minimal"
CONFIG_ENV_ADDR=0x4000000

CONFIG_OF_CONTROL=y
CONFIG_OF_SEPARATE=y

CONFIG_DM_SERIAL=y
CONFIG_DM_ETH=y
CONFIG_SYSRESET=y
CONFIG_SEMIHOSTING=y

#?add?boot?stage?info?to?fdt
CONFIG_OF_FDT=y

CONFIG_SPL_SYS_MALLOC_F_LEN=0x1000
CONFIG_SPL_TEXT_BASE=0x40000000
CONFIG_CONS_INDEX=0
CONFIG_SYS_TEXT_BASE=0x40300000
#?CONFIG_DISPLAY_CPUINFO?is?not?set

spl支持semihost啟動

    將arch/arm/lib/semihosting.c中smh_load_file導(dǎo)出,即去掉下面定義中的static
static?int?smh_load_file(const?char?*?const?name,?ulong?load_addr,??ulong?*end_addr)
{
????????…
}
    將arch/arm/lib/semihosting.c中的do_smhload文件修改為只有uboot編譯,即將其修改為:
#ifndef?CONFIG_SPL_BUILD
static?int?do_smhload(struct?cmd_tbl?*cmdtp,?int?flag,?int?argc,
??????????????????????char?*const?argv[])?{
}
#endif
    在arch/arm/include/asm/spl.h的BOOT DEVICE枚舉中添加對semihosting的支持
enum?{
????????…
????????BOOT_DEVICE_SEMIHOSTING,
????????BOOT_DEVICE_NONE
};??????
    在common/spl/目錄下添加文件spl_semihosting.c,并添加以下內(nèi)容:
#include?<image.h>
#include?<spl.h>
extern?int?smh_load_file(const?char?*?const?name,?ulong?load_addr,
?????????????????????????ulong?*end_addr);

static?int?spl_sh_load_image(struct?spl_image_info?*spl_image,
??????????????????????????????struct?spl_boot_device?*bootdev)
{
????????int?rc;
????????ulong?uboot_load_addr?=?0x40300000,?uboot_end_addr;

????????rc?=?smh_load_file("u-boot.bin",?uboot_load_addr,
?????????????????????????&uboot_end_addr);
????????if?(rc?<?0)?{
????????????????if?(CONFIG_IS_ENABLED(SHOW_ERRORS)?&&
????????????????????CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT))
????????????????????????printf(SPL_TPL_PROMPT?"load?file?u-boot.bin?failed?(err=%d)n",
???????????????????????????????rc);
????????????????else
????????????????????????puts(SPL_TPL_PROMPT?"load?file?u-boot.bin?failedn");
?
????????????????return?-1;
????????}
?
????????spl_image->load_addr?=?uboot_load_addr;
????????spl_image->entry_point?=?uboot_load_addr;
????????spl_image->os?=?IH_OS_U_BOOT;

????????return?0;
}
SPL_LOAD_IMAGE_METHOD("SEMIHOSTING",?0,?BOOT_DEVICE_SEMIHOSTING,?spl_sh_load_image);

 

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

針對嵌入式人工智能,物聯(lián)網(wǎng)等專業(yè)技術(shù)分享和交流平臺,內(nèi)容涉及arm,linux,android等各方面。

Arm64 ?;厮?>
				</a>
							</li>
						<li id= 查看更多