UBoot实验3、u-boot源码分析
- 格式:pdf
- 大小:96.93 KB
- 文档页数:33
刷入uboot和大分区的方法一、概念解释1.1 uboot是什么U-boot是一种开源的引导加载程序,它通常用于嵌入式系统的启动过程中,负责引导操作系统的启动和初始化硬件设备。
在嵌入式系统中,uboot扮演着非常重要的角色,它的稳定性和可靠性直接影响整个系统的稳定性。
1.2 分区的作用分区是将存储设备按照一定的规则划分成多个逻辑部分的过程。
对于嵌入式系统而言,合理的分区管理可以提高存储设备的利用率,同时也方便系统的管理和维护。
二、刷入uboot的步骤2.1 确定目标设备我们需要明确要刷入uboot的目标设备是什么,是一个嵌入式开发板还是其他类型的设备。
不同的设备可能需要不同的uboot版本和刷入方法。
2.2 获取uboot源码接下来,我们需要从冠方或者其他可靠渠道获取uboot的源码。
一般来说,冠方的源码是最稳定和可靠的选择,我们可以从冠方的仓库或者全球信息站上下载源码。
2.3 编译uboot获取源码之后,我们需要根据目标设备的硬件配置,对源码进行编译。
在编译之前,我们需要配置好交叉编译工具链和相关的环境变量,确保编译过程顺利进行。
2.4 刷入uboot当uboot源码编译完成之后,我们需要将编译生成的二进制文件刷入目标设备的存储设备中。
这个过程可能涉及到串口或者其他调试工具的使用,需要特别注意刷入过程中的各项参数和配置。
2.5 测试uboot刷入完成后,我们需要对uboot进行测试,确保它能够正常启动,并且能够正确识别硬件设备。
三、创建大分区的步骤3.1 确定分区方案在创建大分区之前,我们需要确定硬盘或者TF卡的分区方案,包括分区的数量、大小和格式等。
3.2 使用分区工具常用的分区工具有fdisk、parted等,我们可以使用这些工具来创建和调整分区。
在使用分区工具时,需要特别注意当前存储设备上是否有重要的数据,避免误操作导致数据丢失。
3.3 格式化分区创建完分区之后,我们需要对分区进行格式化,以便后续的数据存储和管理。
AM335x uboot spl分析芯片到uboot启动流程ROM → SPL→ uboot.img简介在335x 中ROM code是第一级的bootlader。
mpu上电后将会自动执行这里的代码,完成部分初始化和引导第二级的bootlader,第二级的bootlader引导第三级bootader,在ti官方上对于第二级和第三级的bootlader由uboot提供。
SPLTo unify all existing implementations for a secondary program loader (SPL) and to allow simply adding of new implementations this generic SPL framework has been created. With this framework almost all source files for a board can be reused. No code duplication or symlinking is necessary anymore.1> Basic ARM initialization2> UART console initialization3> Clocks and DPLL locking (minimal)4> SDRAM initialization5> Mux (minimal)6> BootDevice initialization(based on where we are bootingfrom.MMC1/MMC2/Nand/Onenand)7> Bootloading real u-boot from the BootDevice and passing control to it.uboot spl源代码分析一、makefile分析打开spl文件夹只有一个makefile 可见spl都是复用uboot原先的代码。
移植笔记从Norflash启动的uboot uboot移植记录之一uboot整个移植过程我们可以分为三个阶段:一,移植可以从Nor flash启动的uboot这个阶段是移植一个最简单的uboot,可以烧在Nor flash内运行.二,移植支持Nand flash驱动的uboot加入Nand flash驱动的支持,可以在uboot命令行下操作Nand flash.但还未能从Nand flash启动,只能在Nor flash内运行.三,移植可以从Nor flash启动的uboot可以烧录在Nand flash,并设置从Nand flash启动运行uboot.分三个阶段进行移植,可以对整个uboot的移植过程及原理更加清晰明了,同时降低了发现问题时解决问题的困难度和解决范围.首先介绍移植可以从Nor flash启动的uboot. 这个阶段相对简单一点,是移植一个最简单的uboot,可以烧在Nor flash内运行.不需要修改太多的东西。
步骤如下: 测试一下默认的smdk2410_config配置能否在你的板子上正常运行 1.编译uboot1.1.4#make smdk2410_config#make ARCH=arm注:编译针对arm的平台时,uboot默认使用arm-linux-gcc编译,若交叉编译器名字不一样,需要自行在Makefile里修改。
会出现两个错误.错误信息一:cc1: Invalid option `abi=apcs-gnu'make[1]: *** [hello_world.o] Error 1make[1]: Leaving directory `/root/u-boot-1.1.4/examples'make: *** [examples] Error 2解决办法:出错的文件是/cpu/arm920t/下的config.mk:将PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) 改成: PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,$(callcc-option,-mabi=apcs-gnu,))错误信息二:make[1]: *** No rule to make target `hello_world.srec', needed by`all'. Stop. make[1]: Leaving directory `/work/src/u-boot-1.1.4/examples' 解决方法:打开 examples/Makefile把example文件夹下的Makefile中的第126行%.srec: % 改成 %.srec: %.o第129行的%.bin: % 改成 %.bin: %.o2.若编译成功,则会在uboot源码下产生u-boot.bin文件。
csvM X28_DDR2_regis…1.xlsx101.25KB16100: 1*16 32200: 2*32 16400: 4*16 16800: 8*16 32400: 4*32 16160: 16*16表格信息:*上面需要准确填写的是行列地址总线宽度,bank数,CS数,数据总线宽度,时钟频率。
*tFAW不小于tRRD4倍,所以设置40ns。
*tRPA:如果数据手册不能找到tRPA,那么这么位置填入tRP。
*CASLAT:设置CAS LATCH周期,这个周期在ddr初始化时由ddr控制器对ddr设置。
*根据信号线计算ram大小,如下2 ^ (1cs + 3bank + 15row + 12col + 1datapath width) = 4GB:2、下载源码与建立baseline:2.1 源码下载略。
2.2 选择一个相近的平台,编写试编译通过:./setenv.shmake mx28evk_defconfigmake u-boot.sb*这里的sb文件是加密文件,而elftosb工具生成的可以通过-z参数选择是否加密。
*如果编译器是32位,但是系统是64位,那么安装32位兼容库即可:sudo apt install libc6-dev-i386 lib32z12.3 复制文件与修改配置:cp configs/mx28evk_defconfig configs/imx280a_defconfigcp configs/mx28evk_defconfig configs/imx280a_mmc_defconfigmkdir board/zlg/ && cp -rf board/freescale/mx28evk/ board/zlg/imx280a/ mv board/zlg/imx280a/mx28evk.c board/zlg/imx280a/imx280a.cvim board/zlg/imx280a/Kconfigvim board/zlg/imx280a/Makefilecp include/configs/mx28evk.h include/configs/imx280a.hvim include/configs/imx280a.h*vim ./arch/arm/include/asm/mach-types.h*从mx28手册可以得到内存起始物理地址:*删掉FEC,USB,SPI,LCD及额外环境变量的配置。
烧写U-BOOT该部分内容在Windows 7上测试通过。
1-1-1固化启动代码到SD卡中插SD卡到PC机中,打开SD_Writer,如下图,依次点Scan、Format,Select Boot选mmc。
再点击Program。
成功后把由Uboot源码生成的u-boot.bin文件拷到SD卡中。
1-1-2设置开发板从SD卡启动1.将SD卡插入到TE6410开发板的SD插座中;2.设置开发板的拨码开关SW2,让开发板从SD 卡启动:SW2引脚号Pin 8 Pin 7 Pin 6 Pin 5 Pin 4 Pin 3 Pin 2 Pin 1 引脚定义SELNAND OM4 OM3 OM2 OM1 GPN15 GPN14 GPN13 Nandflash启动 1 0 0 1 1 X X X Norflash启动X 0 1 0 1 X X XSD卡启动 1 1 1 1 1 0 0 0 拨码开关拨到“OFF”位置上表示“0”,另一侧表示“1”。
3.连接好开发板的串口线,USB线,电源线,打开dnw软件(位于用户基础资料光盘的“实用工具”文件夹中,将其拷贝到硬盘上运行)。
点击菜单“Serial Port Connect”,显示连上串口。
连接成功后,标题栏会显示[COM1,115200bps]图表错误!未找到引用源。
.14.打开开发板电源开关,可在DNW窗体上看到SDboot启动信息:图表错误!未找到引用源。
.21-1-3通过设置SW2引脚号Pin 8 Pin 7 Pin 6 Pin 5 Pin 4 Pin 3 Pin 2 Pin 1 引脚定义SELNAND OM4 OM3 OM2 OM1 GPN15 GPN14 GPN13 Nandflash启动 1 0 0 1 1 X X XNorflash启动X 0 1 0 1 X X XSD卡启动 1 1 1 1 1 0 0 0恢复nand启动,在提示时,按下空格键(其他键也可),即可看到所期待的页面:。
UBOOTPHY驱动分析及调试⽅法UBOOT版本:2017.11⼀、PHY 简介M edia I ndependent I nterface ( MII ),介质独⽴接⼝,起初是定义 100M 以太⽹(Fast Ethernet)的MAC层与PHY 芯⽚之间的传输标准。
MAC 与 PHY 之间的 MII 连接可以是可插拔的连接器,或者是同⼀块 PCB 上 MAC 与 PHY 之间的⾛线。
MDIO与MDCLK是 MII 接⼝的⼀部分,⼆者可称为SMI (Serial Management Interface) 串⾏管理接⼝,⽤于在 MAC 和 PHY 之间传递配置信息。
在 MDIO 规范中定义 PHY 地址为5 bit,即同⼀组MDIO最多可配置 2^5 = 32个 PHY。
MII 接⼝图如下所⽰:能够和MII相提并论的还有RMII(精简MII)、SMII(串⾏MII)、GMII(千兆MII)、RGMII(精简GMII)等接⼝,它们与普通MII相⽐较,仅是传输速率与数据传输⽅式不同等,这⾥不做过多的介绍。
⼆、PHY 设备创建及驱动匹配以 rockchip 为例,当它的 mac 驱动 gmac_rockchip 成功的被匹配时,会调⽤到 gmac_rockchip_probe ,mac 相关我们不做分析,直接进⼊主题 designware_eth_probe 函数中。
⾸先会获取到对应的 regulator ,并会做⼀些电源配置,1 device_get_supply_regulator(dev, "phy-supply",2 &phy_supply);3 regulator_set_enable(phy_supply, true);UBOOT 中引⼊了 DM 驱动模型,相关的设备与驱动事先已经绑定过,如这⾥通过 phandle 进⽽找出其对应的,驱动在 rk8xx.c 中定义:1 U_BOOT_DRIVER(rk8xx_switch) = {2 .name = "rk8xx_switch",3 .id = UCLASS_REGULATOR,4 .ops = &rk8xx_switch_ops,5 .probe = rk8xx_switch_probe,6 };接下来要初始化 mdio 总线,并将其注册到系统的 mii_devs 中,在获取某个控制器时,即可通过 miiphy_get_dev_by_name 来获取:1 dw_mdio_init(dev->name, dev);2 priv->bus = miiphy_get_dev_by_name(dev->name);电源以及 MDIO 总线已初始化完毕,万事俱备,接下来就正式的对 phy 进⾏操作了,⼀起来看 dw_phy_init 函数:1static int dw_phy_init(struct dw_eth_dev *priv, void *dev)2 {3struct phy_device *phydev;4int mask = 0xffffffff, ret;56 #ifdef CONFIG_PHY_ADDR7 mask = 1 << CONFIG_PHY_ADDR;8#endif910 phydev = phy_find_by_mask(priv->bus, mask, priv->interface);11if (!phydev)12return -ENODEV;1314 phy_connect_dev(phydev, dev);1516 phydev->supported &= PHY_GBIT_FEATURES;17if (priv->max_speed) {18 ret = phy_set_supported(phydev, priv->max_speed);19if (ret)20return ret;21 }22 phydev->advertising = phydev->supported;2324 priv->phydev = phydev;25 phy_config(phydev);2627return0;28 }我们主要来看 phy_find_by_mask ,这⾥是核⼼,其它细节配置不去分析以免喧宾夺主。
uboot查看内存大小的函数-回复如何通过uboot查看内存大小的函数。
在嵌入式系统开发中,uboot是常用的引导加载程序。
它是运行在系统上电后首先加载的程序,用于初始化硬件,并加载操作系统或其他应用程序。
其中一个重要的功能是查看内存大小,从而确保系统能够正确地分配和管理内存资源。
要在uboot中查看内存大小,我们需要查看并了解uboot的源代码,并找到相应的函数或命令。
下面,让我们详细介绍一下如何通过uboot查看内存大小的函数。
第一步:了解uboot的源代码结构和配置文件uboot的源代码包含了许多不同的文件和目录。
我们需要了解uboot的源代码结构,并找到与内存相关的文件或函数。
在uboot源代码的根目录中,有一个名为config.mk的文件。
这个文件包含了uboot的配置信息,我们可以通过修改它来指定需要的功能和选项。
第二步:查找与内存相关的文件在uboot源代码的common目录下,有一个名为cmd_mem.c的文件,这个文件包含了与内存操作相关的命令和函数。
我们可以在这个文件中查找与内存大小相关的代码。
打开cmd_mem.c文件,我们可以看到许多与内存操作相关的命令和函数。
其中一个重要的函数是do_meminfo,它用于显示内存信息,包括内存的大小和布局。
第三步:分析do_meminfo函数的实现do_meminfo函数是一个uboot命令的实现函数,它接受一个命令参数,并执行相应的操作。
它的作用是显示内存信息,并通过调用其他函数来获取和计算内存大小。
在do_meminfo函数中,我们可以找到一些与内存大小相关的变量和函数调用。
例如,通过调用gd->bd->bi_dram[0].size来获取内存的大小,其中gd是全局数据结构,bd是启动设备的描述结构,bi_dram[0]表示第一个DRAM区域。
第四步:编译和运行uboot在完成对do_meminfo函数的分析后,我们需要编译并运行uboot,以验证我们的修改是否成功。
bootm命令在U-Boot 中是用来启动Linux 内核或者Flat Device Tree (FDT) 格式的设备树以及可能包含的根文件系统镜像的命令。
bootm命令执行的流程通常涉及以下步骤:1.加载内核与设备树:在bootm执行前,通常需要使用fatload、ext2load或其他加载命令将Linux 内核映像(例如zImage 或uImage)、设备树blob(dtb 文件)加载到内存中预定义的位置。
2.验证与解析镜像头:bootm命令首先会检查指定内存区域的内容是否符合Multi-Component Boot (MCB) 格式,该格式允许在一个单一的二进制块中包含多个可启动组件的信息。
如果找到合法的MCB 头,它会进一步解析内核镜像和其他组件的相关信息。
3.设置环境变量:U-Boot 会根据加载的内核类型设置必要的环境变量,如bootargs(传递给内核的启动参数),fdtcontroladdr(设备树的加载地址)等。
4.初始化板级硬件:在启动内核前,确保所有必要的外设和SOC 功能已经被正确初始化,以便内核能够顺利接管控制权。
5.调用启动例程:最后,bootm命令会调用相关的启动例程来启动内核。
这个过程通常涉及到跳转到特定的启动函数,该函数会配置CPU 进入特定模式以运行ARM Linux 内核,然后调用内核的入口点开始执行内核代码。
具体来说,bootm命令在U-Boot 源代码中对应的实现部分主要包括:•cmd_bootm.c文件中包含了do_bootm()函数,它是bootm命令的主要执行体。
•在do_bootm()函数内部,会按照不同类型的镜像(单内核、多组件)分别处理。
•如果内核支持flattened device tree,会加载并验证设备树数据,并将其地址写入适当的寄存器或内存位置供内核启动时获取。
•设置栈指针、CPU模式、以及重定位向量表等,为内核启动做准备。
•最终,bootm调用类似boot_jump_linux()函数来跳转到内核的入口点开始执行。
U-Boot的源码分析概述:文档详细介绍PC2440a实训包中所使用的BootLoader-U-Boot。
对其源码的目录结构、MakeFile文件、源码的主要数据结构、U-Boot 的启动过程、U-Boot与内核的关系等进行详细的分析。
名称:U-Boot的源码分析版本:1.0version修改:版本修改时间修正作者修正说明V1.0 2009/4/1 侯德振文件创建Note:任何修改操作请在上述表格备注说明目录U-Boot的源码分析 (1)1.1U-Boot源码分析 (3)1.1.1U-Boot工程简介 (3)1.1.2U-Boot源码结构 (3)1.1.3makefile简要分析 (5)1.1.4平台相关的文件分析 (7)1.1.5U-Boot主要的数据结构 (8)1.1.6U-Boot重定位后的内存分布 (12)1.2U-Boot启动过程 (12)1.3U-Boot与内核的关系 (18)1.4U-Boot的重要细节 (27)1.1U-Boot源码分析U-Boot作为通用的Bootloader,U-Boot可以方便地移植到其他硬件平台上,其源代码也值得开发者们研究学习。
1.1.1 U-Boot工程简介最早,DENX软件工程中心的Wolfgang Denk基于8xxrom的源码创建了PPCBOOT 工程,并且不断添加处理器的支持。
后来,Sysgo Gmbh 把ppcboot 移植到ARM 平台上,创建了ARMboot工程。
然后以ppcboot工程和armboot工程为基础,创建了U-Boot工程。
现在U-Boot已经能够支持PowerPC、ARM、X86、MIPS体系结构的上百种开发板,已经成为功能最多、灵活性最强并且开发最积极的开放源码Bootloader。
目前仍然由DENX 的Wolfgang Denk维护。
U-Boot 的源码包可以从sourceforge 网站下载,还可以订阅该网站活跃的U-Boot Users邮件论坛,这个邮件论坛对于U-Boot的开发和使用都很有帮助。
U-Boot软件包下载网站:/project/u-boot。
U-Boot 邮件列表网站:/lists/listinfo/u-boot-users/。
DENX 相关的网站:http://www.denx.de/re/DPLG.html。
1.1.2 U-Boot源码结构从网站上下载得到U-Boot源码包,例如:U-Boot-1.2.0.tar.bz2解压就可以得到全部U-Boot源程序。
在顶层目录下有18 个子目录,分别存放和管理不同的源程序。
这些目录中所要存放的文件有其规则,可以分为3类。
第1 类目录与处理器体系结构或者开发板硬件直接相关; 第2 类目录是一些通用的函数或者驱动程序; 第3 类目录是U-Boot的应用程序、工具或者文档。
表4.1 列出了U-Boot顶层目录下各级目录存放原则。
目 录 特 性 解 释 说 明board 平台依赖 存放电路板相关的目录文件,例如:RPXlite(mpc8xx)、smdk2410(arm920t)、sc520_cdp(x86) 等目录cpu 平台依赖 存放CPU相关的目录文件,例如:mpc8xx、ppc4xx、arm720t、arm920t、 xscale、i386等目录lib_ppc 平台依赖 存放对PowerPC体系结构通用的文件,主要用于实现PowerPC平台通用的函数lib_arm 平台依赖 存放对ARM体系结构通用的文件,主要用于实现ARM 平台通用的函数lib_i386 平台依赖 存放对X86体系结构通用的文件,主要用于实现X86平台通用的函数include 通用 头文件和开发板配置文件,所有开发板的配置文件都在configs目录下common 通用 通用的多功能函数实现lib_generic 通用 通用库函数的实现Net 通用 存放网络的程序Fs 通用 存放文件系统的程序Post 通用 存放上电自检程序drivers 通用 通用的设备驱动程序,主要有以太网接口的驱动 Disk 通用 硬盘接口程序Rtc 通用 RTC的驱动程序Dtt 通用 数字温度测量器或者传感器的驱动examples 应用例程 一些独立运行的应用程序的例子,例如helloworldtools 工具 存放制作S-Record 或者 U-Boot格式的映像等工具,例如mkimageDoc 文档 开发使用文档U-Boot的源代码包含对几十种处理器、数百种开发板的支持。
可是对于特定的开发板,配置编译过程只需要其中部分程序。
这里具体以S3C2440 arm920t 处理器为例,具体分析S3C2440处理器和开发板所依赖的程序,以及U-Boot的通用函数和工具。
1.1.3 makefile简要分析所有这些目录的编译连接都是由顶层目录的makefile来确定的。
在执行make之前,先要执行make $(board)_config 对工程进行配置,以确定特定于目标板的各个子目录和头文件。
$(board)_config:是makefile 中的一个伪目标,它传入指定的CPU,ARCH,BOARD,SOC参数去执行mkconfig脚本。
这个脚本的主要功能在于连接目标板平台相关的头文件夹,生成config.h 文件包含板子的配置头文件。
使得makefile能根据目标板的这些参数去编译正确的平台相关的子目录。
以smdk2410板为例,执行 make smdk2410_config,主要完成三个功能:@在include文件夹下建立相应的文件(夹)软连接,#如果是ARM体系将执行以下操作:#ln -s asm-arm asm#ln -s arch-s3c24x0 asm-arm/arch#ln -s proc-armv asm-arm/proc@生成Makefile包含文件include/config.mk,内容很简单,定义了四个变量:ARCH = armCPU = arm920tBOARD = smdk2410SOC = s3c24x0@生成include/config.h头文件,只有一行:/* Automatically generated - do not edit */#include “config/smdk2410.h”顶层makefile先调用各子目录的makefile,生成目标文件或者目标文件库。
然后再连接所有目标文件(库)生成最终的u-boot.bin。
连接的主要目标(库)如下:OBJS = cpu/$(CPU)/start.oLIBS = lib_generic/libgeneric.aLIBS += board/$(BOARDDIR)/lib$(BOARD).aLIBS += cpu/$(CPU)/lib$(CPU).aifdef SOCLIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).aendifLIBS += lib_$(ARCH)/lib$(ARCH).aLIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.aLIBS += net/libnet.aLIBS += disk/libdisk.aLIBS += rtc/librtc.aLIBS += dtt/libdtt.aLIBS += drivers/libdrivers.aLIBS += drivers/nand/libnand.aLIBS += drivers/nand_legacy/libnand_legacy.aLIBS += drivers/sk98lin/libsk98lin.aLIBS += post/libpost.a post/cpu/libcpu.aLIBS += common/libcommon.aLIBS += $(BOARDLIBS)显然跟平台相关的主要是:cpu/$(CPU)/start.oboard/$(BOARDDIR)/lib$(BOARD).acpu/$(CPU)/lib$(CPU).acpu/$(CPU)/$(SOC)/lib$(SOC).alib_$(ARCH)/lib$(ARCH).a这里面的四个变量定义在include/config.mk(见上述)。
其余的均与平台无关。
所以考虑移植的时候也主要考虑这几个目标文件(库)对应的目录。
1.1.4 平台相关的文件分析1、include/config/smdk2440.h这个头文件中主要定义了两类变量。
一类是选项,前缀是CONFIG_,用来选择处理器、设备接口、命令、属性等,主要用来 决定是否编译某些文件或者函数。
另一类是参数,前缀是CFG_,用来定义总线频率、串口波特率、Flash地址等参数。
这些常数参量主要用来支持通用目录中的代码,定义板子资源参数。
这两类宏定义对u-boot的移植性非常关键,比如drive/CS8900.c,对cs8900而言,很多操作都是通用的,但不是所有的板子上面都有这个芯片,即使有它在内存中映射的基地址也是平台相关的。
所以对于smdk2440板,在smdk2440.h 中定义了#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */#define CS8900_BASE 0x19000300 /*IO mode base address*/ CONFIG_DRIVER_CS8900 的定义使得cs8900.c可以被编译(当然还得定义CFG_CMD_NET才行),因为cs8900.c中在函数定义的前面就有编译条件判断: #ifdef CONFIG_DRIVER_CS8900如果这个选项没有定义,整个cs8900.c就不会被编译了。
而常数参量CS8900_BASE则用在cs8900.h头文件中定义各个功能寄存器的地址。
u-boot的CS8900工作在IO模式下,只要给定IO寄存器在内存中映射的基地址,其余代码就与平台无关了。
u-boot的命令也是通过目标板的配置头文件来配置的,比如要添加ping命令,就必须添加CFG_CMD_NET和CFG_CMD_PING才行。
不然common/cmd_net.c 就不会被编译了。
从这里我可以这么认为,u-boot工程可配置性和移植性可以分为两层: 一是由makefile来实现,配置工程要包含的文件和文件夹上,用什么编译器。
二是由目标板的配置头文件来实现源码级的可配置性,通用性。