在v2.1.5之前的SDK版本里,每个示例目录下都会按板子创建不同目录,放置对应的工程文件,比如hal_example/project下有eh-lb561、eh-lb563和eh-lb523的目录,分别对应三种板子 的工程,每个目录下都有一套类似的SCons脚本以及.config和rtconfig.h配置文件,如果需要编译板子eh-lb561的软件,就进到eh-lb561目录执行scons进行编译。 这种方式存在的问题是每增加 一块板子就要新建一个工程目录,示例一多就要增加很多工程,一旦某个示例有公共配置需要修改,又要修改所有的工程,维护工作量很大。 因此,从v2.1.5开始,SDK引入一种新工程构建方式,称为通用工程,每个示例只需要维护一个工程文件夹,工程目录下不再保存.config和rtconfig文件, 编译时根据选择的板子就可以生成对应板子的软件,.config和rtconfig.h也会生成在build目录下,可以同时编译多个板子,生成的文件不会相互覆盖。
在通用工程目录下,执行如下命令可以编译生成指定的板子的镜像文件,board_name是板子的名称,他后面仍旧可以跟其他scons参数,如-j8指定使用8个线程编译。 对于双核芯片的板子,board_name需要指定是哪个核,比如eh-lb523_hcpu,表示编译可运行在523 HDK的HCPU上的程序。 通用工程为了减少重复文件的维护工作量,很多文件都会在编译时生成,如.config、rtconfig和链接脚本等,具体的生成方法见3.3节。
以下命令编译可运行于板子eh-lb523_v2 HCPU上的程序
编译生成的文件存放在build_eh-lb523_v2_hcpu目录下,如下图所示
通用工程的创建分为板子和应用工程两部分,如果是在已有的板子上创建新的应用,可以跳过3.1节创建板子,直接新建一个应用工程
板子的目录结构如下图所示,一级目录下放板子相关的源文件,包括
二级目录则是每个核的配置文件,包括
有时同一个型号的HDK会贴不同的芯片,为了避免在不同的板子目录下放置相同的IO设置代码,可以将公共代码放到一个目录, 再由不同板子来引用,如下图所示,公共代码放在了eh-lb56xu_v2,开发板HDK561对应文件夹eh-lb561_v2,开发板HDK563对应文件夹eh-lb563_v2, 他们的一级目录可以简化,引用eh-lb56xu_v2下的文件,HCPU和LCPU的仍旧放在这两个开发板目录下。
在二级目录运行menuconfig打开配置窗口,这个配置界面会加载SDK中除应用之外的所有Kconfig, 修改配置后选择“[D] Save minimal config”即可保存最小的差异化配置(与Kconfig的默认配置相比有变化的部分), 文件名填写board.conf。选择“[S] Save”则会生成.config和rtconfig.h,方便下次打开时能显示正确的配置,如果不生成.config, 关闭menuconfig后再打开,并不会加载board.conf中的配置,看到的仍旧是所有的缺省配置,为了避免rtconfig.h被误引用, 建议删除生成的rtconfig.h。也可以执行gen_board_config.bat基于board.conf生成.config和config.h, 生成的文件内容与选择“[S] Save”相同。
建议用board.conf配置一个可用于一般应用开发的基本运行环境,比如保证console(选择合适的串口)和文件系统(选择合适的文件系统类型)可以工作, 应用相关的配置则留到应用工程的配置文件中设置。
rtconfig.py增加CORE和CHIP两个变量,CORE用于指示对应的核,可以是”HCPU”或者”LCPU”,CHIP为芯片系列名,如”SF32LB56X”、”SF32LB52X”
对于要用到双核的应用,工程目录也分为hcpu和lcpu,如下图
对于SF32LB52X,如果只需要开发HCPU上的程序,不使用LCPU或者使用预生成好的LCPU镜像文件,应用工程就只需要创建一个目录放置HCPU的工程文件,例如下图的hal_example示例工程
目录下的文件有:
区别于以前的工程,需要在SConstruct脚本的开始调用PrepareEnv(), 准备板子的编译环境,如下图
由于子工程可能运行在不同的核上,需要在SConstruct脚本添加子工程的时候增加参数指定子工程运行在哪个核上,不指定则与主工程相同,例如下图添加了LCPU子工程
类似board.conf的生成,在工程目录下运行menuconfig可以保存最小配置到proj.conf,如果保存了全部配置,同样要删除rtconfig.h。 可以执行gen_proj_config.bat基于proj.conf生成.config和config.h,生成的文件内容与选择“[S] Save”相同。 build目录下也会生成一个Kconfig,内容类似下面,相比应用工程目录下的Kconfig,会多加载一个板子的Kconfig文件,以便生成完整的配置文件。
以下为proj.conf的示例,如果要将某个选项关闭,则以#开始,跟着选项名(加上CONFIG_前缀),然后写上“is not set”,例如下面的配置关闭了ULOG_USING_COLOR。
为了减少重复文件,以下几个文件在编译时会根据选择的板子动态生成在build目录下
生成的一般原则是按照优先级选择相应目录下的文件作为最终使用的文件或者覆盖低优先级的配置,优先级由高到低依次是:
比如,在应用工程目录data_service/common/hcpu下有个eh-lb561_v2_hcpu的板子目录,放了custom_mem_map.h, 那么build目录下的custom_mem_map.h就拷贝自data_service/common/hcpu/eh-lb561_v2_hcpu/custom_mem_map.h,如果应用的板子目录下没有custom_mem_map.h, 但应用工程目录下有,那么build目录下的custom_mem_map.h就拷贝自data_service/common/hcpu/custom_mem_map.h,只有在应用工程目录下也没有该文件时, 才会把customer/boards/eh-lb561_v2/hcpu/custom_mem_map.h拷贝到builld目录下。
按以下顺序选择靠前目录下的ptab.json作为编译使用的文件
按以下顺序选择靠前目录下的link script文件(keil编译对应link.sct, gcc编译对应link.lds)作为编译使用的文件
rtconfig.h是由Kconfig的默认值、board.conf和proj.conf合并而成。board.conf和proj.conf中记录了需要修改的配置(与默认值相比), 如果相同的配置同时出现在board.conf和proj.conf中,则使用proj.conf定义的配置。还可以在应用录下添加板子目录,放置该板子专属的proj.conf, 比如不同板子大部分软件配置都一样,只有个别参数不同,可以在根目录的proj.conf定义所有板子都会用到的配置, 在个别需要使用不同参数值的板子目录下放置proj.conf,在其中只定义需要修改的参数值。归纳起来,rtconfig.h和.config中的参数取值来源, 按优先级由高到低依次如下,如果多个文件中都对同一个变量进行了设置,优先级高的将覆盖优先级低的:
多工程编译时,同样运行于HCPU的主工程和子工程可能都会使用同一个板子目录下的链接脚本,但他们的代码编译地址又不一样, 比如下图是link.sct的代码段部分,起始地址都是CODE_START_ADDR,大小为CODE_SIZE,但在编译主程序和二级bootloader时, 这两个宏的取值是不同的。
为此,ptab.h的生成脚本增加了一个功能,在ptab.json中使用属性”exec”定义该region是哪个工程的代码执行段, 属性值为工程名,主工程是“main”,子工程与AddChildProj时指定的名称一致。例如下面的ptab.json中, 二级bootloader的代码段以FLASH_BOOT_LOADER命名,主工程的以HCPU_FLASH_CODE命名。
加上了exec属性后,主工程生成的ptab.h会把CODE_START_ADDR定义为HCPU_FLASH_CODE_START_ADDR, 二级bootloader子工程则会把CODE_START_ADDR定义为FLASH_BOOT_LOADER_START_ADDR
按以下步骤将现有工程改造为支持任意板子编译的通用工程