Common Project Build Method
1. Background
In SDK versions before v2.1.5, under each example directory, different directories were created for each board to store corresponding project files. For instance, under $SDK_ROOT/hal_example/project, directories for eh-lb561, eh-lb563, and eh-lb523 boards were present, each corresponding to a project for the respective boards. Each directory contained similar SCons scripts and .config and rtconfig.h configuration files. To compile software for the eh-lb561 board, users would enter the eh-lb561 directory and execute scons
to perform the compilation.
The problem with this approach was that every time a new board was added, a new project directory had to be created. As the number of examples increased, many new projects were added. If a common configuration needed modification for a certain example, it had to be updated in all the projects, leading to high maintenance overhead.
To address this issue, starting from v2.1.5, the SDK introduced a new project build method known as the “Common Project” approach. Under this method, only one project folder is required for each example, and it no longer stores the .config and rtconfig files. During compilation, the software for the selected board is generated, and .config and rtconfig.h are generated in the build directory. Multiple boards can be compiled simultaneously, and the generated files will not overwrite each other.
2. Compilation Method
In the common project directory, execute the following command to compile the image for a specified board. board_name
is the name of the board, and it can still be followed by other scons parameters, such as -j8
to specify the use of 8 threads for compilation.
For dual-core chip boards, the board_name
must specify which core is being used, for example, eh-lb523_hcpu
, indicating the program that can run on the HCPU of the 523 HDK board.
To reduce repetitive file maintenance work, many files are generated during compilation, such as .config, rtconfig, and linker scripts, etc. The specific generation method is described in section 3.3.
scons --board=board_name
The following command compiles a program that can run on the HCPU of the eh-lb523_v2 board.
scons --board=eh-lb523_v2_hcpu -j8
The generated files will be stored in the build_eh-lb523_v2_hcpu
directory, as shown below:
3. How to Create a Common Project
The creation of a common project involves two parts: the board and the application. If creating a new application on an existing board, you can skip section 3.1 and directly create an application project.
3.1 Board
The directory structure for the board is shown below. The top-level directory stores the source files related to the board, including:
IO-related code, such as
bsp_pinmux.c
,bsp_power.c
Initialization code,
bsp_init.c
ptab.json
, memory layoutSConscript
, build scriptKconfig.board
, the board’s Kconfig configuration file
The second-level directories contain configuration files for each core, including:
_board.conf_
, the minimal configuration file generated by Kconfig_Kconfig.board_
, the Kconfig configuration file for the core, which can source the top-level_Kconfig.board_
_link.sct_
, optional, Keil’s linker script_rtconfig.py_
, which can specify JLINK_DEVICE, optimization level, and other compilation parameters (it is recommended to use the newly added Kconfig configuration for optimization)_custom_mem_map.h_
, used whenCUSTOM_MEM_MAP
is enabled
Sometimes, different chips may be used on the same model of HDK. To avoid duplicating IO setup code in different board directories, common code can be placed in a shared directory, which is then referenced by the individual board directories.
3.1.1 board.conf
Run menuconfig
in the second-level directory to open the configuration window. This configuration interface loads all Kconfig files from the SDK except for the application-specific ones. After modifying the configuration, choose “[D] Save minimal config” to save the minimal differential configuration (the part that differs from the default Kconfig configuration), and name the file board.conf
. Choosing “[S] Save” will generate .config
and _rtconfig.h_
, allowing the correct configuration to be displayed the next time it is opened. If .config
is not generated, after closing menuconfig
, the configuration will revert to the default configuration, and the settings in board.conf
will not be loaded. It is recommended to delete the generated _rtconfig.h_
to avoid it being mistakenly referenced. Alternatively, you can run _gen_board_config.bat_
to generate .config
and config.h
based on board.conf
.
It is recommended to configure a basic runtime environment in board.conf
for general application development, such as ensuring the console (selecting the appropriate serial port) and file system (selecting the appropriate file system type) work. Application-specific configurations should be set in the application’s project configuration file.
3.1.2 rtconfig.py
The rtconfig.py
file introduces two new variables: CORE
and CHIP
. CORE
specifies the core type, which can be either “HCPU” or “LCPU,” and CHIP
represents the chip series, such as “SF32LB56X” or “SF32LB52X.”
3.2 Application Project
For applications that use dual-core chips, the project directory is split into hcpu
and lcpu
subdirectories.
For the SF32LB52X, if only the HCPU application is needed, and no LCPU is used, or a precompiled LCPU image is used, the application project only needs to create a directory for the HCPU project files, as shown in the following example project.
The files in the directory include:
_Kconfig.proj_
, the application’s Kconfig configuration file_proj.conf_
, the application’s minimal configuration file_rtconfig.py_
, custom compilation options for the application, which override any matching configurations in the board directorySconscript/Sconstruct
, build scriptsApplication-specific source code
3.2.1 SConstruct
Unlike the previous project setup, the SConstruct
script must call PrepareEnv()
at the beginning to prepare the board’s compilation environment.
Since sub-projects may run on different cores, parameters must be added in the SConstruct
script to specify which core the sub-project will run on. If not specified, it defaults to the main project. For instance, the following shows how an LCPU sub-project is added.
3.2.2 proj.conf
Similar to generating board.conf
, run menuconfig
in the project directory to save the minimal configuration to proj.conf
. If all configurations are saved, delete the generated _rtconfig.h_
. You can also execute _gen_proj_config.bat_
to generate .config
and config.h
based on proj.conf
. The generated files are equivalent to choosing “[S] Save” in menuconfig
.
In the build directory, a Kconfig file will also be generated. Compared to the Kconfig file in the application project directory, it will additionally load the board’s Kconfig file to generate a complete configuration file.
source "$SIFLI_SDK/Kconfig.v2"
source "$SIFLI_SDK/customer/boards/eh-lb56xu_v2/hcpu/Kconfig.board"
source "D:/Users/xiaomingxi/code/bt7/example/multicore/data_service/common/hcpu/Kconfig.proj"
Below is an example of proj.conf
. To disable a specific option, start with a #
and write “is not set” after the option name (with the CONFIG_
prefix). The configuration below disables ULOG_USING_COLOR
.
CONFIG_RT_MAIN_THREAD_STACK_SIZE=4096
CONFIG_RT_MAIN_THREAD_PRIORITY=15
CONFIG_RT_USING_ULOG=y
CONFIG_ULOG_USING_ISR_LOG=y
## CONFIG_ULOG_USING_COLOR is not set
CONFIG_ULOG_OUTPUT_THREAD_NAME=y
CONFIG_RT_TICK_PER_SECOND=1000
CONFIG_IDLE_THREAD_STACK_SIZE=512
CONFIG_RT_TIMER_THREAD_STACK_SIZE=1024
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_BSP_USING_TOUCHD=y
CONFIG_BSP_USING_LCPU_PATCH=y
CONFIG_BSP_USING_LCD=y
CONFIG_BLUETOOTH=y
CONFIG_BSP_USING_FULL_ASSERT=y
## CONFIG_BSP_USING_LOOP_ASSERT is not set
## CONFIG_BSP_USING_EMPTY_ASSERT is not set
3.3 File Generation Rules
To reduce repetitive file maintenance, the following files are dynamically generated during compilation based on the selected board in the build directory:
_rtconfig.h
(and.config
)_ptab.json/ptab.h_
_custom_mem_map.h_
_link.sct/link.lds_
(linker scripts)
The general rule for file generation is to select the highest-priority file from the relevant directories as the final used file or to override lower-priority configurations. The priority order from highest to lowest is:
The board directory in the application project directory
The chip directory in the application project directory (specified by
rtconfig.CHIP
for the chip series, e.g., sf32lb56x)The application project directory
The board directory
The chip series directory
3.3.1 custom_mem_map.h
For example, in the application project directory data_service/common/hcpu
, there is a board directory eh-lb561_v2_hcpu
that contains the _custom_mem_map.h_
. Therefore, the _custom_mem_map.h_
in the build directory is copied from data_service/common/hcpu/eh-lb561_v2_hcpu/custom_mem_map.h
. If the application’s board directory doesn’t have _custom_mem_map.h_
but the application project directory does, it will be copied from there. Only if the file is not present in both the application and the board directory will it be copied from _$SDK_ROOT/customer/boards/eh-lb561_v2/hcpu/custom_mem_map.h_
.
3.3.2 ptab.json
The following order is used to select the _ptab.json_
file for compilation:
The board directory in the application project directory
The chip directory in the application project directory
The application project directory
The board directory
The ptab.h
is generated from _ptab.json_
and stored in the build directory.
3.3.3 Link Script
The following order is used to select the linker script file (Keil’s _link.sct_
, GCC’s _link.lds_
) for compilation:
The board directory in the application project directory
The chip directory in the application project directory
The application project directory
The board directory
3.3.4 rtconfig.h
The _rtconfig.h_
is generated by merging the default values from Kconfig with _board.conf_
and _proj.conf_
. _board.conf_
and _proj.conf_
record the modified configurations (changes compared to the default values). If the same configuration appears in both _board.conf_
and _proj.conf_
, the configuration in _proj.conf_
takes precedence. You can also add a board directory to the application project to place a board-specific proj.conf
. For instance, if most configurations are the same across boards but only a few parameters differ, you can define the shared configurations in the root proj.conf
and place the specific ones in each board’s directory.
The order of parameter values in _rtconfig.h_
and .config
follows the priority from highest to lowest, as follows:
proj.conf
in the application’s board directoryproj.conf
in the application’s chip directoryproj.conf
in the application project directory_board.conf_
in the board directoryDefault values from Kconfig
3.4 Reusing Link Scripts
During multi-project compilation, both the main project and sub-projects may use the same board directory’s linker script, but their code compilation addresses may differ. For example, the code snippet from _link.sct_
below shows that the starting address is CODE_START_ADDR
, and the size is CODE_SIZE
, but the values of these macros may be different for the main program and the secondary bootloader.
To address this, the script for generating ptab.h
adds a feature to define the exec
property in the _ptab.json_
to indicate which project the region’s code belongs to. The property value for the main project is “main,” and for sub-projects, it corresponds to the name specified when adding the sub-project.
After adding the exec
property, the main project’s generated ptab.h
will define CODE_START_ADDR
as HCPU_FLASH_CODE_START_ADDR
, and the secondary bootloader sub-project will define CODE_START_ADDR
as FLASH_BOOT_LOADER_START_ADDR
.
4. Modifying Existing Projects
Follow these steps to convert an existing project into a common project supporting compilation for any board:
Create the board folder, extract board-related configurations from the original project’s
.config
, write them intoboard.conf
(skip this step if the board already exists), and copy the_ptab.json_
file from the original project to the newly created board folder.Create the application project folder, extract common configurations from the original project’s
.config
, write them into the rootproj.conf
of the application project, and place board-specific configurations in the corresponding board directory under the application.Copy the
Sconscript
andSConstruct
from the original project directory, and add thePrepareEnv()
call to theSConstruct
to support compiling for the specified board.