• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Mini-System Devices with Screens – Bestechnic SoC Porting Case
2
3This document exemplifies the porting procedure for a development board on a mini-system device with a screen – an intelligent switch panel. It uses the BES multi-modal V200Z-R development board powered by the Bestechnic BES2600W SoC as an example. Components such as `ace_engine_lite`, `graphic_ui`, `aafwk_lite`, `appexecfwk_lite`, and `HDF` are adapted based on the OpenHarmony LiteOS-M kernel. This example uses the board-SoC separation solution as the porting architecture, the Newlib C or Musl C library as the toolchain, and GN and Kconfig graphical configuration for LiteOS-M kernel compilation.
4
5## Compilation and Building
6
7### Directory Planning
8
9This example uses an improved SoC porting architecture. The original SoC adaptation directory is as follows:
10
11```
12device
13└── <device_company>
14    └── <device_name>
15```
16
17This adaptation directory has a downside: To use the Hi3861 SoC on the BearPi-HM Nano or HiSpark Pegasus development board, you need to place a copy of the code in the directory of both development boards. To solve this problem, the board vendor is decoupled from the SoC vendor in this example, by following the board-SoC decoupling design ideas. The SoC adaptation directory used in this example is as follows:
18
19```
20device
21├── board                                --- Board vendor directory
22│   └── fnlink                           --- Board vendor name: Fn-Link
23│       └── v200zr                       --- Board name: v200zr
24└── soc									 --- SoC vendor directory
25    └── bestechnic                       --- SoC vendor: Bestechnic
26        └── bes2600						 --- SoC Series: The bes2600 series includes bes2600w.
27```
28
29The planned product demo directory is as follows:
30
31```
32vendor
33└── bestechnic							 --- Vendor of the product demo.
34    └── display_demo         			 --- Product demo name.
35```
36
37### Precompilation Adaptation
38
39Before porting, you need to perform precompilation adaptation.
40
41To do so, use the `hb set` command to set environment variables such as the root directory, board directory, product directory, and board company name of the entire project.
42
43The specific procedure is as follows:
44
451. Add the `config.json` file to the `vendor/bestechnic/display_demo` directory to describe the board and kernel information used by the product demo. The following is an example of the description:
46
47```
48{
49  "product_name": "display_demo",       --- Product name to display in the hb set drop-down list.
50  Type of the "type": "mini", --- Build system type, which can mini, small, or standard.
51  Version of the "version": "3.0", --- Build system version, which can be 1.0, 2.0, or 3.0.
52  "device_company": "fnlink",           --- Board vendor name, which is used to find the /device/board/fnlink directory during compilation.
53  "board": "v200zr",                    --- Board name, which is used to find the /device/board/fnlink/v200zr directory during compilation.
54  "kernel_type": "liteos_m",            --- Kernel type. OpenHarmony supports multiple kernels, and one board may be adapted to multiple kernels. Therefore, you need to specify a kernel for compilation.
55  "kernel_version": "3.0.0",            --- Kernel version. A board may be adapted to multiple Linux kernel versions. Therefore, you need to specify a kernel version for compilation.
56  "subsystems": [ ]                     --- Subsystem to be compiled and built.
57}
58```
59
602. Add the `config.gni` file to the `device/board/fnlink/v200zr/liteos_m` directory to describe the board and kernel used in the product demo. The following is an example of the description:
61
62```
63# Kernel type, e.g. "linux", "liteos_a", "liteos_m".
64kernel_type = "liteos_m"                --- Kernel type, which corresponds to kernel_type in the config.json file.
65
66# Kernel version.
67kernel_version = "3.0.0"                --- Kernel version, which corresponds to kernel_version in the config.json file.
68```
69
703. Verify the `hb set` configuration:
71
72   Run the `hb set` command, enter the project root directory, and press `Enter`. The `hb` command traverses all `config.json` files in the `//vendor/<product_company>/<product_name>` directory and provides product compilation options. In the `config.json` file, `product_name` indicates the product name, `device_company` and `board` are used to locate the `//device/board/<device_company>/<board>` directory and find the matching `<any_dir_name>/config.gni` file. If multiple file matches are found, it indicates that the board has been adapted to multiple kernels. In this case, `kernel_type` and `kernel_version` in the `config.json` file can be used to uniquely match the `config.gni` file and thereby determine the board with which kernel needs to be compiled and adapted. If the information shown below is displayed, the `hb set` configuration is correct.
73
74   ![hb set](figures/bes2600_hb_set.png)
75
76			You can run the `hb env` command to view the selected precompilation environment variables.
77
78![hb env](figures/bes2600_hb_env.png)
79
80Before running the `hb build` command, complete the LiteOS-M kernel adaptation. For details, see [Kernel Porting](https://gitee.com/openharmony/docs/blob/master/en/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md#%E5%86%85%E6%A0%B8%E7%A7%BB%E6%A4%8D).
81
82## Kernel Porting
83
84To port the kernel, you need to complete the LiteOS-M Kconfig adaptation, GN compilation and building, and minimum adaptation for kernel startup.
85
86### LiteOS-M Kconfig Adaptation
87
88Run the `make menuconfig` command in the `//kernel/liteos_m` directory to select compilation configuration options. In the `Makefile` file, the `hb env` result is converted into environment variables, that is, `PRODUCT_PATH`, `DEVICE_PATH`, and `BOARD_COMPANY`. The sample code is as follows:
89
90```
91$(foreach line,$(shell hb env | sed 's/\[OHOS INFO\]/ohos/g;s/ /_/g;s/:_/=/g' || true),$(eval $(line)))
92ifneq ($(ohos_kernel),liteos_m)
93$(error The selected product ($(ohos_product)) is not a liteos_m kernel type product)
94endif
95--- Convert each line of hb env to a variable. For example, convert [OHOS INFO] device company: fnlink to ohos_device_company=fnlink.
96
97...
98
99ifeq ($(BOARD_COMPANY),)
100BOARD_COMPANY:=$(ohos_device_company)
101endif
102...
103export BOARD_COMPANY
104--- Convert ohos_device_company to the BOARD_COMPANY environment variable.
105```
106
107Use the exported environment variables in the `//kernel/liteos_m/Kconfig` file. `Kconfiglib` uses `ulfalizer` to develop the Python-based version. In the [source code](https://github.com/ulfalizer/Kconfiglib), as described in [function description](https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/kconfig/kconfiglib.py), the keyword `orsource` is used. In this keyword, `o` indicates `optional`, that is, the file is optional. `r` indicates `relative`, that is, the path of the file relative to the current file.
108
109```
110config SOC_COMPANY
111    string "SoC company name to locate soc build path"
112    help
113      This option specifies the SoC company name, used to locate the build path for soc. This option is set by the
114      SoC's Kconfig file, and should be exactly the same with SoC company path, and the user should generally avoid
115       modifying it via the menu configuration.
116
117orsource "../../device/board/*/Kconfig.liteos_m.shields"                                 --- Load the configurations of all extension boards. To allow the extension boards provided by board vendor A to be used by board vendor B, the asterisk (*) instead of BOARD_COMPANY is used. As OpenHarmony supports the multi-kernel design, the Kconfig file uses liteos_m as the suffix. During board adaptation, the actual kernel name can be used as the suffix for extension during kernel adaptation.
118
119orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.defconfig.boards"         --- Load all predefined board configurations of BOARD_COMPANY.
120
121choice
122    prompt "Board Selection"
123
124The orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.boards" --- Provide a list of available boards.
125
126endchoice
127
128orsource "../../device/soc/*/Kconfig.liteos_m.defconfig"                                 --- Load the default configuration definitions of all SoCs.
129
130choice
131    prompt "SoC Series Selection"
132
133orsource "../../device/soc/*/Kconfig.liteos_m.series"                                    --- Provide a list of available SoC series.
134
135endchoice
136
137orsource "../../device/soc/*/Kconfig.liteos_m.soc"                                       --- Load all SoC configurations.
138```
139
140According to the `//kernel/liteos_m/Kconfig` file, the following `Kconfig` files need to be added to the `//device/board/fnlink` directory for adaptation:
141
142```
143.
144├── v200zr                                       --- Configuration of the v200zr
145│   ├── Kconfig.liteos_m.board                   --- Configuration options of the v200zr board
146│   ├── Kconfig.liteos_m.defconfig.board         --- Default configuration items of the v200zr board
147│   └── liteos_m
148│       └── config.gni
149├── Kconfig.liteos_m.boards                      --- Board configuration of Fn-Link
150├── Kconfig.liteos_m.defconfig.boards			 --- Default board configuration of Fn-Link
151├── Kconfig.liteos_m.shields					 --- Extension board configuration of Fn-Link
152└── shields										 --- Extension board directory of Fn-Link
153    ├── v200zr-t0								 --- Expansion board v200zr-t0 of Fn-Link
154    │   ├── Kconfig.liteos_m.defconfig.shield	 --- Default configuration of the expansion board v200zr-t0
155    │   └── Kconfig.liteos_m.shield				 --- Configuration of the expansion board v200zr-t0
156    ├── v200zr-t1
157    │   ├── Kconfig.liteos_m.defconfig.shield
158    │   └── Kconfig.liteos_m.shield
159    └── Kconfig.liteos_m.shields
160```
161
162In `v200zr/Kconfig.liteos_m.board`, you need to set the board configuration options and the dependent `SoC` as follows:
163
164```
165config BOARD_v200zr
166    bool "select board v200zr"
167    depends on SOC_BES2600W		 --- The v200zr board uses the bes2600w SoC. Therefore, the v200zr board configuration options are available only when the bes2600w SoC is selected.
168```
169
170In `v200zr/Kconfig.liteos_m.defconfig.board`, the default name of `BOARD` is defined as `"v200zr"`.
171
172```
173if BOARD_v200zr
174config BOARD
175    string		 --- No content is defined for string. Therefore, it is not visible to users.
176    default "v200zr"
177
178endif # BOARD_v200zr
179```
180
181According to the `//kernel/liteos_m/Kconfig` file, the following `Kconfig` files need to be added to the `//device/soc/bestechnic` directory for adaptation:
182
183```
184.
185├── bes2600									 --- bes2600 SoC series
186│   ├── Kconfig.liteos_m.defconfig.bes2600w	 --- Configuration of the bes2600w SoC series provided by Bestechnic
187│   ├── Kconfig.liteos_m.defconfig.series	 --- Default configuration of the bes2600 provided by Bestechnic
188│   ├── Kconfig.liteos_m.series				 --- Configuration of the bes2600 SoC series provided by Bestechnic
189│   └── Kconfig.liteos_m.soc				 --- Configuration of the bes2600 SoC provided by Bestechnic
190├── Kconfig.liteos_m.defconfig				 --- Default SoC configuration of Bestechnic
191├── Kconfig.liteos_m.series					 --- Configuration of the SoC series provided by Bestechnic
192└── Kconfig.liteos_m.soc					 --- Configuration of the SoC provided by Bestechnic
193```
194
195In the `bes2600/Kconfig.liteos_m.series` file, configure the `bes2600 SoC series` and SoC architecture as follows:
196
197```
198config SOC_SERIES_BES2600			 --- bes2600 SoC series configuration options
199    bool "Bestechnic 2600 Series"
200    select ARM						 --- When bes2600 is selected, the ARM architecture is selected by default.
201    select SOC_COMPANY_BESTECHNIC    --- When bes2600 is selected, bestechnic is selected by default. The driver depends on the macro configuration. You can select the configuration to compile the driver of the corresponding vendor.
202    select CPU_CORTEX_M33			 --- When bes2600 is selected, cortex-m33 CPU is selected by default.
203    help
204        Enable support for Bestechnic 2600 series
205```
206
207In the `bes2600/Kconfig.liteos_m.soc` file, provide the number of specific SoCs under the `bes2600 SoC series` as follows:
208
209```
210choice
211    prompt "Bestechnic 2600 series SoC"
212    depends on SOC_SERIES_BES2600	 --- The following configuration options are displayed only when bes2600 Series is selected:
213
214config SOC_BES2600W					 --- Add the bes2600w SoC configuration option.
215    bool "SoC BES2600w"
216
217endchoice
218```
219
220In the `bes2600/Kconfig.liteos_m.defconfig.series` file, provide the following configuration that is used by default when the bes2600 SoC series is selected:
221
222```
223if SOC_SERIES_BES2600							 --- The following default configuration options are added only when the bes2600 series is selected:
224
225rsource "Kconfig.liteos_m.defconfig.bes2600w"	 --- Add the default configuration that is used by default when bes2600 SoC series is selected.
226
227config SOC_SERIES								 --- Add the configuration that is used by default when SOC_SERIES is selected:
228    string
229    default "bes2600"
230
231endif
232```
233
234When the configuration is complete, set the `defconfig` storage path of `make menuconfig` based on the `kernel/liteos_m/Makefile` file.
235
236```
237ifeq ($(TEE:1=y),y)
238tee = _tee
239endif
240ifeq ($(RELEASE:1=y),y)
241CONFIG ?= $(PRODUCT_PATH)/kernel_configs/release$(tee).config
242else
243CONFIG ?= $(PRODUCT_PATH)/kernel_configs/debug$(tee).config		 --- The configuration file is saved in $(CONFIG) and is defined by the product.
244endif
245
246...
247
248update_config menuconfig:
249	$(HIDE)test -f "$(CONFIG)" && cp -v "$(CONFIG)" .config && menuconfig $(args) && savedefconfig --out "$(CONFIG)"
250```
251
252In this example, the configuration file of `defconfig` is saved in `$(PRODUCT_PATH)/kernel_configs/debug.config`. It is empty by default upon creation. The directory and file structure of the product is as follows:
253
254```
255.
256└── display_demo
257    ├── config.json
258    └── kernel_configs
259        └── debug.config
260```
261
262When the configuration is complete, run the `make menuconfig` command in the `kernel/liteos_m` directory to select `SoC Series`/`SoC`/`Board`.
263
264![board make menuconfig](figures/bes2600_board_make_menuconfig.png)
265
266The result is automatically saved in `$(PRODUCT_PATH)/kernel_configs/debug.config` and will be exported when `make menuconfig` is executed.
267
268### GN Build Adaptation
269
270The graphical configuration result of `Kconfig` generated in the previous step can be used as the input of GN build to determine whether to build different modules. In addition, to solve the problem of arbitrary use of `include` during GN build, modular compilation is used for kernel compilation, streamlining the entire compilation logic. For details, see *LiteOS-M Kernel BUILD.gn Compilation Guide*.
271
272In the `kernel/liteos_m/BUILD.gn` file, the compilation entrances of `Board` and `SoC` are specified as `//device/board/fnlink` and `//device/soc/bestechnic`.
273
274```
275deps += [ "//device/board/$device_company" ]
276deps += [ "//device/soc/$LOSCFG_SOC_COMPANY" ]
277```
278
279Add the following content to `//device/board/fnlink/BUILD.gn`:
280
281```
282if (ohos_kernel_type == "liteos_m") {                    --- In the multi-kernel design, macros need to be used to isolate the adapted LiteOS-M kernel.
283  import("//kernel/liteos_m/liteos.gni")				 --- Import the kernel GN template.
284  module_name = get_path_info(rebase_path("."), "name")	 --- Dynamically obtain the current directory and use it as the module name, eliminating the need for manual synchronization between the directory and module name.
285  module_group(module_name) {							 --- Use the module_group template.
286    modules = [											 --- Add the modules to be built.
287    ]
288  }
289}
290```
291
292Modify the `//device/soc/bestechnic/BUILD.gn` file in a similar manner.
293
294### Kernel Boot Adaptation
295
296The system boot process consists of three phases:
297
298| Phase | Partitioning Planning                | Description                         |
299| --------- | ------------------------ | ----------------------------- |
300| BOOT1     | [0, 0x10000]             | The firmware is started.   |
301| BOOT2     | [0x2C010000, 0x2C020000] | The OTA update starts.|
302| RTOS_MAIN | [0x2C080000, 0x2C860000] | The kernel is started.   |
303
304In the third phase where the kernel is started, the file to be adapted is saved in `//device/soc/bestechnic/bes2600/liteos_m/sdk/bsp/rtos/liteos/liteos_m/board.c`.
305
306The general idea of kernel boot adaptation is as follows:
307
3081. `os_vector_init` is used to initialize interrupt vectors and interrupt processing functions.
3092. `osKernelInitialize` is used to initialize the kernel.
3103. The `board_main` thread is created to initialize the chip platform.
3114. The kernel starts up and schedules the `osKernelStart` thread.
312
313This section describes step 3 in detail. Other steps involve invoking of kernel functions and are not described here.
314
315In step 3, before starting `OHOS_SystemInit`, `board_main` needs to complete the necessary actions as follows:
316
317```
318...
319    if(!ret) {
320        ...
321        OhosSystemAdapterHooks();    --- Configure the hook during system boot and complete the printing and driver initialization before OHOS_SystemInit is started.
322        ...
323        OHOS_SystemInit(); 			 --- Start the OpenHarmony service and initialize components.
324    }
325....
326```
327
328The `OhosSystemAdapterHooks` function is in the `device/soc/bestechnic/bes2600/liteos_m/components/utils/src/hm_sys.c` file, as shown below:
329
330```
331int OhosSystemAdapterHooks(void)
332{
333    init_trace_system(); 	 --- Initialize the printing function.
334    DeviceManagerStart(); 	 --- Call the DeviceManagerStart function to initialize the HDF driver. This process is implemented by calling the driver configuration file hdf.hcs in the board code and implementing the drivers source code.
335    return 0;
336}
337
338```
339
340### littlefs File System Porting
341
342 The `V200Z-R` development board uses the `Nor Flash` that supports `XIP` and has a maximum size of `32 MB`. The `example` file system can be used. During the adaptation, place the file system configuration file in the specified path. The file system image is then automatically generated based on the configuration and packaged into the burning package.
343
3441. Specify the directory for storing the file system `config.json` by using `flash_partition_dir`.
345
346```
347  "flash_partition_dir": "fs" 	 --- Store the file system configuration file in the vendor/bestechnic/display_demo/fs directory.
348```
349
3502. Place the following items in the `vendor/bestechnic/display_demo/fs` directory:
351
352  - `wifi_Download_cfg.yaml`: configuration file for image burning. The partitions can be adjusted as required.
353  - `/data/data`: The first /`data` is the root directory to mount. The second `data` is the `data` directory in the root directory. You can place the configuration file in the second `data` directory or in any directory at the same level. During packaging, the whole root directory is packaged.
354
3553. Set the following items in the `config.json` file based on the `wifi_Download_cfg.yaml` file:
356
357  - `fs_src`: name under which the file system is mounted.
358  - `fs_name`: name of the generated file system.
359  - `block_size`: size of the read data block. Set it to `4K` alignment and do not change the value.
360  - `fs_size`: size of the generated file system.
361  - `burn_name`: size of the burnt `bin` name.
362  - `enable`: whether to generate the file system.
363
3644. In the `//device/soc/bestechnic/bes2600/liteos_m/components/hdf_config/hdf.hcs` file, configure the start address for burning the file system, size of the file system, and size of the read data block (`block_size`). The reference configuration is as follows:
365
366```
367    misc {
368        fs_config {
369            example_config {
370                match_attr = "littlefs_config";
371                mount_points = ["/data"];
372                partitions = [10];
373                block_size = [4096];
374                block_count = [1024];
375            }
376        }
377        storage_config {
378            flash_config {
379                match_attr = "flash_config";
380                partitions = [10];
381                owner = [0];
382                description = ["littlefs"];
383                start_addr = [0xB60000];
384                length = [0x400000];
385                options = [3];
386            }
387        }
388    }
389```
390
391In `device/soc/bestechnic/bes2600/liteos_m/components/fs/fs_init.c`, load data through `hdf` and read and write to `flash` as follows:
392
393```
394static int32_t FsDriverInit(struct HdfDeviceObject *object)
395{
396    if (object == NULL) {
397        return HDF_FAILURE;
398    }
399    if (object->property) {
400        if (FsGetResource(fs, object->property) != HDF_SUCCESS) {
401            HDF_LOGE("%s: FsGetResource failed", __func__);
402            return HDF_FAILURE;
403        }
404    }
405    for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
406        if (fs[i].mount_point == NULL)
407            continue;
408
409        fs[i].lfs_cfg.read = littlefs_block_read;
410        fs[i].lfs_cfg.prog = littlefs_block_write;
411        fs[i].lfs_cfg.erase = littlefs_block_erase;
412        fs[i].lfs_cfg.sync = littlefs_block_sync;
413
414        fs[i].lfs_cfg.read_size = 256;
415        fs[i].lfs_cfg.prog_size = 256;
416        fs[i].lfs_cfg.cache_size = 256;
417        fs[i].lfs_cfg.lookahead_size = 16;
418        fs[i].lfs_cfg.block_cycles = 1000;
419
420        int ret = mount(NULL, fs[i].mount_point, "littlefs", 0, &fs[i].lfs_cfg);
421        HDF_LOGI("%s: mount fs on '%s' %s\n", __func__, fs[i].mount_point, (ret == 0) ? "succeed" : "failed");
422    }
423    return HDF_SUCCESS;
424}
425```
426
427
428
429### C Library Adaptation
430
431In the mini system, adapting the C library is a complex process. For details, see *Solution to Smooth Switchover Between musl and newlib for LiteOS-M Kernel*. The toolchain uses the `newlib` C library of the [gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2](https://gitee.com/link?target=https%3A%2F%2Fdeveloper.arm.com%2F-%2Fmedia%2FFiles%2Fdownloads%2Fgnu-rm%2F10.3-2021.10%2Fgcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2). In light of this, the `newlib` C library is used for system porting. Select `newlib` in `make menuconfig` of the kernel, as shown below.
432
433![image-20211212191013553](figures/bes2600_newlib_make_menuconfig.png)
434
435#### malloc Adaptation
436
437For details, see [The Red Hat newlib C Library-malloc](https://sourceware.org/newlib/libc.html#malloc). You can use either of the following methods to implement malloc adaptation:
438
439- Implement the `_sbrk_r` function. In this method, the memory allocation function in `newlib` is used.
440
441- Implement `_malloc_r`, `_realloc_r`, `_reallocf_r`, `_free_r`, `_memalign_r`, and `_malloc_usable_size_r`. In this method, the memory allocation function in the kernel can be used.
442
443To facilitate memory allocation algorithm optimization and fault locating based on services, the latter method is used in this example.
444
445First, as the symbols of the functions in the second method already exist in `newlib`, you need to use the `wrap` link option of `gcc` to replace these function symbols with the kernel implementation code in `//kernel/liteos_m/kal/libc/newlib/porting/src/malloc.c`.
446
447Then, add the `wrap` link option of these functions to `//device/board/fnlink/v200zr/liteos_m/config.gni`.
448
449```
450board_ld_flags += [
451     "-Wl,--wrap=_malloc_r",
452     "-Wl,--wrap=_realloc_r",
453     "-Wl,--wrap=_reallocf_r",
454     "-Wl,--wrap=_free_r",
455     "-Wl,--wrap=_memalign_r",
456     "-Wl,--wrap=_malloc_usable_size_r",
457]
458```
459
460#### vsprintf and Related Adaptation
461
462Implement `vprintf`, `vfprintf`, `printf`, `snprintf`, and `sprintf`. For details, see [vfprintf](https://sourceware.org/newlib/libc.html#vfprintf).
463
464Similar to `malloc` adaptation, the implementation of these functions must be provided first, that is, `//device/soc/bestechnic/bes2600/liteos_m/components/utils/src/printf.c`. In this example, the friendly implementation of the open-source protocol is used. Different from `malloc` adaptation, this function is provided by the SoC vendor. This is because the implementation size varies in terms of printing based on the project requirements, and therefore the kernel cannot provide a unified implementation.
465
466Then, add the `wrap` link option of these functions to `//device/board/fnlink/v200zr/liteos_m/config.gni`.
467
468```
469board_ld_flags += [
470     "-Wl,--wrap=printf",
471     "-Wl,--wrap=sprintf",
472     "-Wl,--wrap=snprintf",
473     "-Wl,--wrap=vsnprintf",
474     "-Wl,--wrap=vprintf",
475]
476```
477
478#### open and Related Adaptation
479
480The adaptation is implemented by the kernel and does not need attention from the SoC. The kernel file `//kernel/liteos_m/kal/libc/newlib/porting/src/fs.c` has been adapted to the `_read`, `_write`, and other related functions of `newlib`, as shown below.
481
482```
483...
484ssize_t _read(int fd, void *buf, size_t nbyte)
485{
486    return LOS_Read(fd, buf, nbyte);
487}
488
489ssize_t _write(int fd, const void *buf, size_t nbyte)
490{
491    return LOS_Write(fd, buf, nbyte);
492}
493
494off_t _lseek(int fd, off_t offset, int whence)
495{
496    return LOS_Lseek(fd, offset, whence);
497}
498...
499```
500
501## Board-Level OS Porting
502
503### Driver Porting
504
505#### Porting the HDF Driver for the SoC Platform
506
507Driver adaptation files are stored in `drivers/adapter/platform`, including `gpio`, `i2c`, `pwm`, `spi`, `uart`, and `watchdog`, which are loaded using the `HDF` mechanism. This section uses `gpio` as an example.
508
509##### GPIO Driver Adaptation
510
511The `gpio` driver adaptation requires building adaptation and source code adaptation.
512
513The `//drivers/adapter/platform/gpio/BUILD.gn` file describes the building adaptation of the `gpio` driver, as shown below:
514
515```
516module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO)	 --- If the GPIO configuration switch of the HDF is enabled, the following is built:
517module_name = get_path_info(rebase_path("."), "name")
518
519hdf_driver(module_name) {
520  sources = []
521  if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) {				 --- If the Bestechnic SoC configuration switch is enabled, the Bestechnic GPIO driver is built.
522    sources += [ "gpio_bes.c" ]
523  }
524
525  include_dirs = [ "." ]
526}
527```
528
529The `//drivers/adapter/platform/gpio/gpio_bes.c` file describes the source code adaptation of the Bestechnic GPIO driver.
530First, load the basic driver adaptation framework based on OpenHarmony `HDF`, as shown below:
531
532```
533struct HdfDriverEntry g_GpioDriverEntry = {
534    .moduleVersion = 1,
535    .moduleName = "BES_GPIO_MODULE_HDF",
536    .Bind = GpioDriverBind,
537    .Init = GpioDriverInit,
538    .Release = GpioDriverRelease,
539};
540HDF_INIT(g_GpioDriverEntry); 	 --- Load the GPIO driver through HDF_INIT.
541```
542
543Then, obtain the `hcs` parameter for initialization as follows:
544
545```
546static int32_t GpioDriverInit(struct HdfDeviceObject *device)
547{
548    int32_t ret;
549    struct GpioCntlr *gpioCntlr = NULL;
550
551    if (device == NULL) {
552        HDF_LOGE("%s: device is NULL", __func__);
553        return HDF_ERR_INVALID_PARAM;
554    }
555
556    gpioCntlr = GpioCntlrFromDevice(device); 	 --- Obtain the GPIO configuration.
557    if (gpioCntlr == NULL) {
558      ...
559```
560
561
562
563#### Porting the HDF Drivers of Peripheral Components on the Board
564
565Peripheral components are connected to the board through the `SoC` bus. In this example, the peripheral component is a display, whose driver adaptation code is stored in the `//device/board/fnlink/drivers/liteos_m` directory.
566
567##### Display Driver Adaptation
568
569The display driver adaptation process is similar to the `SoC` driver adaptation process. In the `//device/board/fnlink/drivers/liteos_m/display/BUILD.gn` file, load the driver module based on the `hdf_driver` template, as shown below:
570
571```
572module_name = get_path_info(rebase_path("."), "name")
573hdf_driver(module_name) {
574  sources = [
575    "zzw395.c",
576  ]
577  include_dirs = [
578    "//drivers/peripheral/display/interfaces/include",
579  ...
580  ]
581}
582```
583
584In the `//device/board/fnlink/drivers/liteos_m/display/zzw395.c` file, load the display driver based on HDF, as shown below:
585
586```
587static struct HdfDriverEntry g_ZZW395DriverEntry = {
588    .moduleVersion = 1,
589    .moduleName = "HDF_PANEL_ZZW395",
590    .Bind = PanelDriverBind,
591    .Init = PanelDriverInit,
592    .Release = PanelDriverRelease,
593};
594
595HDF_INIT(g_ZZW395DriverEntry);
596```
597
598Configure the driver parameters based on `hcs`, which are loaded during `PanelDriverInit` initialization. The sample code is as follows:
599
600```
601static int32_t PanelDriverInit(struct HdfDeviceObject *object)
602{
603    if (object == NULL) {
604        return HDF_FAILURE;
605    }
606    HDF_LOGD("%s entry !!!", __func__);
607    if (object->property) {
608        if (PanelGetResource(&priv, object->property) != HDF_SUCCESS) {
609            HDF_LOGE("%s: PanelGetResource failed", __func__);
610            return HDF_FAILURE;
611        }
612    }
613...
614```
615
616### Adapting OpenHarmony Subsystems
617
618The adaptation of OpenHarmony subsystems consists of two parts:
619
620- Add the target subsystem and component to the `config.json` file so that the component can be included in the compilation by the compilation system.
621- Perform hardware adaptation or optional software adaptation for the `HAL` layer APIs of the component.
622
623#### Communication Subsystem Adaptation
624
625##### wifi_lite Component Adaptation
626
627Add the `wifi_lite` component of the `communication` subsystem to the `config.json` file.
628
629```
630    {
631      "subsystem": "communication",
632      "components": [
633        {
634          "component": "wifi_lite",
635          "optional": "true"
636        }
637      ]
638    },
639```
640
641The `wifi_lite` component is described in the `//build/lite/components/communication.json` file as follows:
642
643```
644    {
645      "component": "wifi_lite",
646...
647      "targets": [
648        "//foundation/communication/wifi_lite:wifi"		 --- wifi_lite in the compilation targets
649      ],
650...
651    },
652
653```
654
655In the `//foundation/communication/wifi_lite/BUILD.gn` file, describe the path of the API header file to be adapted as follows:
656
657```
658config("include") {
659  include_dirs = [ "interfaces/wifiservice" ]	 --- The wifi_lite component provides the header file but not the implementation. Therefore, it exposes the adaptation directory to the hardware vendor for adaptation. The vendor provides the Wi-Fi protocol stack source code for implementation.
660}
661
662group("wifi") {
663  public_configs = [ ":include" ]
664}
665```
666
667In this example, Wi-Fi is provided by `SoC`. Therefore, the Wi-Fi adaptation source code is stored in the `//device/soc/bestechnic/hals/communication/wifi_lite/wifiservice` directory of `SoC`, which contains `wifi_device.c` and `wifi_hotspot.c` to adapt to `wifi_device.h` and `wifi_hotspot.h`, respectively. The sample code is as follows:
668
669```
670...
671WifiErrorCode Scan(void)	 --- Wi-Fi hotspot scanning function in wifi_device.c, which is used to adapt to the Scan function in wifi_device.h.
672{
673    WifiErrorCode ret = ERROR_WIFI_BUSY;
674
675
676    if (IsWifiActive() != WIFI_STA_ACTIVE)
677        return ERROR_WIFI_IFACE_INVALID;
678
679    if (g_HalHmosWifiInfo.scan_state == SCAN_REQUEST ||
680        g_HalHmosWifiInfo.scan_state == SCAN_TRIGGER)
681        return ERROR_WIFI_BUSY;
682
683    HalHmosWifiLock();
684    ret = ((HalHmosSendEvent(HMOS_ON_WIFI_SCAN_STATE_CHANGED, NULL) == 0) ? WIFI_SUCCESS : ERROR_WIFI_BUSY);
685    HalHmosWifiUnLock();
686
687    return ret;
688}
689...
690int GetSignalLevel(int rssi, int band)	 --- Function in wifi_hotspot.c for obtaining Wi-Fi hotspot parameters, which is used to adapt to the GetSignalLevel function in wifi_hotspot.h.
691{
692    if (band == HOTSPOT_BAND_TYPE_2G) {
693        if (rssi >= RSSI_LEVEL_4_2_G)
694            return RSSI_LEVEL_4;
695        if (rssi >= RSSI_LEVEL_3_2_G)
696            return RSSI_LEVEL_3;
697        if (rssi >= RSSI_LEVEL_2_2_G)
698            return RSSI_LEVEL_2;
699        if (rssi >= RSSI_LEVEL_1_2_G)
700            return RSSI_LEVEL_1;
701    }
702
703    if (band == HOTSPOT_BAND_TYPE_5G) {
704        if (rssi >= RSSI_LEVEL_4_5_G)
705            return RSSI_LEVEL_4;
706        if (rssi >= RSSI_LEVEL_3_5_G)
707            return RSSI_LEVEL_3;
708        if (rssi >= RSSI_LEVEL_2_5_G)
709            return RSSI_LEVEL_2;
710        if (rssi >= RSSI_LEVEL_1_5_G)
711            return RSSI_LEVEL_1;
712    }
713    return ERROR_WIFI_INVALID_ARGS;
714}
715```
716
717##### lwIP Component Adaptation
718
719By default, `lwip` is configured in the `LiteOS-M kernel` directory. Therefore, you can include the `lwip` directory in the `kernel` component for compilation. The sample code is as follows:
720
721```
722    {
723      "subsystem": "kernel",
724      "components": [
725        {
726          "component": "liteos_m",
727          "features": [
728            "ohos_kernel_liteos_m_lwip_path = \"//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1\""		 --- Specify the SoC vendor directory for compilation.
729          ]
730        }
731      ]
732    },
733```
734
735The `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/BUILD.gn` file describes the compilation of `lwip` as follows:
736
737```
738import("//kernel/liteos_m/liteos.gni")
739import("$LITEOSTHIRDPARTY/lwip/lwip.gni")
740import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni")
741
742module_switch = defined(LOSCFG_NET_LWIP_SACK)
743module_name = "lwip"
744kernel_module(module_name) {
745  sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES -
746            [ "$LWIPDIR/api/sockets.c" ] + [ "porting/src/ethernetif.c" ]		 --- Add the ethernetif.c file to adapt to the initialization of the Ethernet adapter.
747  defines = [ "LITEOS_LWIP=1" ]
748  defines += [ "CHECKSUM_BY_HARDWARE=1" ]
749}
750
751config("public") {
752  defines = [ "_BSD_SOURCE=1" ]
753  include_dirs =
754      [ "porting/include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS
755}
756
757```
758
759In the `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/include/lwip/lwipopts.h` file, retain the original `lwip` configuration, on which the software bus depends, and add the following hardware adaptation options:
760
761```
762#ifndef _PORTING_LWIPOPTS_H_
763#define _PORTING_LWIPOPTS_H_
764
765#include_next "lwip/lwipopts.h"				 --- Retain the original configuration.
766
767#define LWIP_NETIF_STATUS_CALLBACK      1
768#define LWIP_CHECKSUM_ON_COPY           0
769#define CHECKSUM_GEN_UDP                0	 --- Add hardware adaptation options.
770
771#endif /* _PORTING_LWIPOPTS_H_ */
772
773```
774
775In the `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/src/ethernetif.c` file, add the adaptation to the initialization of the Ethernet adapter as follows:
776
777```
778err_t
779ethernetif_init(struct netif *netif)
780{
781...
782#ifdef CHECKSUM_BY_HARDWARE
783    eth_hw_checksum_init();
784#endif
785...
786    netif->linkoutput = low_level_output;
787
788    netif->drv_send = liteos_low_level_output;
789    netif->hwaddr_len = NETIF_MAX_HWADDR_LEN;
790    low_level_init(netif);
791    driverif_init(netif);
792    return ERR_OK;
793...
794}
795```
796
797##### dsoftbus Component Adaptation
798
799Add the `dsoftbus` component to the `config.json` file as follows:
800
801```
802{
803  "component": "dsoftbus",
804  "features": [
805    "softbus_adapter_config = \"//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config\""
806  ]
807},
808```
809
810The `dsoftbus` component provides the `softbus_adapter_config` configuration option in the `//foundation/communication/dsoftbus/dsoftbus.gni` file for configuration during porting. The configuration specifies the path for DSoftBus porting adaptation.
811
812In this example, `softbus_adapter_config` is set to `//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config`. The structure of this path is as follows:
813
814```
815.
816├── feature_config					--- DSoftBus configuration, for example, whether to enable self-discovery.
817│   └── mini
818│       └── config.gni
819└── spec_config						--- DSoftBus configuration, for example, the DSoftBus log level.
820    ├── softbus_config_adapter.c
821    ├── softbus_config_adapter.h
822    └── softbus_config_type.h
823```
824
825The following configuration items are defined in the `config.gni` file:
826
827| Item                                    | Description                    |
828| ------------------------------------------ | ------------------------ |
829| dsoftbus_feature_disc_ble         | Whether to enable BLE discovery.     |
830| dsoftbus_feature_disc_coap        | Whether to enable CoAP discovery.    |
831| dsoftbus_feature_conn_tcp         | Whether to enable TCP connection.     |
832| dsoftbus_feature_conn_br          | Whether to enable BR connection.      |
833| dsoftbus_feature_conn_ble         | Whether to enable BLE connection.     |
834| dsoftbus_feature_conn_p2p         | Whether to enable P2P connection.     |
835| dsoftbus_feature_trans_udp        | Whether to enable UDP transmission.     |
836| dsoftbus_feature_trans_udp_stream | Whether to enable the UDP transport stream.   |
837| dsoftbus_feature_trans_udp_file   | Whether to enable UDP file transfer. |
838| dsoftbus_feature_ip_auth          | Whether to enable transmission channel authentication.|
839| dsoftbus_feature_auth_account     | Whether to enable account-based authentication.|
840| dsoftbus_feature_qos              | Whether to enable QoS.         |
841
842The following configuration items are defined in the `softbus_config_adapter.c` file:
843
844| Item                              | Description                         |
845| ------------------------------------ | ----------------------------- |
846| SOFTBUS_INT_MAX_BYTES_LENGTH         | SendBytes: maximum number of bytes that can be sent.   |
847| SOFTBUS_INT_MAX_MESSAGE_LENGTH       | SendMessage: maximum length of a message that can be sent.|
848| SOFTBUS_INT_CONN_BR_MAX_DATA_LENGTH  | Maximum volume of data received over Bluetooth.           |
849| SOFTBUS_INT_CONN_RFCOM_SEND_MAX_LEN  | Maximum volume of data sent over Bluetooth.           |
850| SOFTBUS_INT_ADAPTER_LOG_LEVEL        | Log level.                 |
851| SOFTBUS_STR_STORAGE_DIRECTORY        | Storage directory.                 |
852
853After DSoftBus is configured, it is not started by default. Therefore, you need to invoke the `InitSoftBusServer` function through the startup framework as follows:
854
855```
856static void DSoftBus(void)
857{
858    osThreadAttr_t attr;
859    attr.name = "dsoftbus task";
860    attr.attr_bits = 0U;
861    attr.cb_mem = NULL;
862    attr.cb_size = 0U;
863    attr.stack_mem = NULL;
864    attr.stack_size = 65536;
865    attr.priority = 24;
866
867    extern void InitSoftBusServer(void);
868    if (osThreadNew((osThreadFunc_t) InitSoftBusServer, NULL, &attr) == NULL) {
869        printf("Failed to create WifiSTATask!\n");
870    }
871}
872
873APP_FEATURE_INIT(DSoftBus);
874```
875
876##### RPC Component Adaptation
877
878Add the following `rpc` configuration to the `config.json` file:
879
880```
881{
882  "component": "rpc"
883},
884```
885
886Similarly, for the `rpc` component, you need to invoke the `StartDBinderService` function through the startup framework. The running of this function depends on the `IP` address obtained by the host. Therefore, invoke this function in the callback of the IP address change event registered by the lwIP protocol stack as follows:
887
888```
889static void RpcServerWifiDHCPSucCB(struct netif *netif, netif_nsc_reason_t reason,
890                                   const netif_ext_callback_args_t *args)
891{
892    (void) args;
893    if (netif == NULL) {
894        printf("%s %d, error: input netif is NULL!\n", __FUNCTION__, __LINE__);
895        return;
896    }
897    if (reason == LWIP_NSC_IPSTATUS_CHANGE) {
898        if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr)) {
899            printf("%s %d, start rpc server!\n", __FUNCTION__, __LINE__);
900            StartDBinderService();
901        }
902    }
903}
904
905static void WifiDHCPRpcServerCB(void)
906{
907    NETIF_DECLARE_EXT_CALLBACK(WifiReadyRpcServerCallback);
908    netif_add_ext_callback(&WifiReadyRpcServerCallback, RpcServerWifiDHCPSucCB);
909}
910
911APP_FEATURE_INIT(WifiDHCPRpcServerCB);
912```
913
914#### Startup Subsystem Adaptation
915
916For the `startup` subsystem, adapt the `bootstrap_lite` and `syspara_lite` components. Add the corresponding configuration items to the `vendor/bestechnic_bak/display_demo/config.json` file, as shown below:
917
918```
919{
920  "subsystem": "startup",
921  "components": [
922	{
923	  "component": "bootstrap_lite"		 --- bootstrap_lite component
924	},
925	{
926	  "component": "syspara_lite",		 --- syspara_lite component
927	  "features": [
928		"enable_ohos_startup_syspara_lite_use_posix_file_api = true"
929	  ]
930	}
931  ]
932},
933```
934
935When adapting the `bootstrap_lite` component, you need to add the following code snippet to the `//device/soc/bestechnic/bes2600/liteos_m/sdk/bsp/out/best2600w_liteos/_best2001.lds` file:
936
937```
938       __zinitcall_bsp_start = .;
939      KEEP (*(.zinitcall.bsp0.init))
940      KEEP (*(.zinitcall.bsp1.init))
941      KEEP (*(.zinitcall.bsp2.init))
942      KEEP (*(.zinitcall.bsp3.init))
943      KEEP (*(.zinitcall.bsp4.init))
944      __zinitcall_bsp_end = .;
945      __zinitcall_device_start = .;
946      KEEP (*(.zinitcall.device0.init))
947      KEEP (*(.zinitcall.device1.init))
948      KEEP (*(.zinitcall.device2.init))
949      KEEP (*(.zinitcall.device3.init))
950      KEEP (*(.zinitcall.device4.init))
951      __zinitcall_device_end = .;
952      __zinitcall_core_start = .;
953      KEEP (*(.zinitcall.core0.init))
954      KEEP (*(.zinitcall.core1.init))
955      KEEP (*(.zinitcall.core2.init))
956      KEEP (*(.zinitcall.core3.init))
957      KEEP (*(.zinitcall.core4.init))
958      __zinitcall_core_end = .;
959      __zinitcall_sys_service_start = .;
960      KEEP (*(.zinitcall.sys.service0.init))
961      KEEP (*(.zinitcall.sys.service1.init))
962      KEEP (*(.zinitcall.sys.service2.init))
963      KEEP (*(.zinitcall.sys.service3.init))
964      KEEP (*(.zinitcall.sys.service4.init))
965      __zinitcall_sys_service_end = .;
966      __zinitcall_sys_feature_start = .;
967      KEEP (*(.zinitcall.sys.feature0.init))
968      KEEP (*(.zinitcall.sys.feature1.init))
969      KEEP (*(.zinitcall.sys.feature2.init))
970      KEEP (*(.zinitcall.sys.feature3.init))
971      KEEP (*(.zinitcall.sys.feature4.init))
972      __zinitcall_sys_feature_end = .;
973      __zinitcall_run_start = .;
974      KEEP (*(.zinitcall.run0.init))
975      KEEP (*(.zinitcall.run1.init))
976      KEEP (*(.zinitcall.run2.init))
977      KEEP (*(.zinitcall.run3.init))
978      KEEP (*(.zinitcall.run4.init))
979      __zinitcall_run_end = .;
980      __zinitcall_app_service_start = .;
981      KEEP (*(.zinitcall.app.service0.init))
982      KEEP (*(.zinitcall.app.service1.init))
983      KEEP (*(.zinitcall.app.service2.init))
984      KEEP (*(.zinitcall.app.service3.init))
985      KEEP (*(.zinitcall.app.service4.init))
986      __zinitcall_app_service_end = .;
987      __zinitcall_app_feature_start = .;
988      KEEP (*(.zinitcall.app.feature0.init))
989      KEEP (*(.zinitcall.app.feature1.init))
990      KEEP (*(.zinitcall.app.feature2.init))
991      KEEP (*(.zinitcall.app.feature3.init))
992      KEEP (*(.zinitcall.app.feature4.init))
993      __zinitcall_app_feature_end = .;
994      __zinitcall_test_start = .;
995      KEEP (*(.zinitcall.test0.init))
996      KEEP (*(.zinitcall.test1.init))
997      KEEP (*(.zinitcall.test2.init))
998      KEEP (*(.zinitcall.test3.init))
999      KEEP (*(.zinitcall.test4.init))
1000      __zinitcall_test_end = .;
1001      __zinitcall_exit_start = .;
1002      KEEP (*(.zinitcall.exit0.init))
1003      KEEP (*(.zinitcall.exit1.init))
1004      KEEP (*(.zinitcall.exit2.init))
1005      KEEP (*(.zinitcall.exit3.init))
1006      KEEP (*(.zinitcall.exit4.init))
1007      __zinitcall_exit_end = .;
1008```
1009
1010The added code snippet is for storing the external APIs provided by `bootstrap_init`, which are injected. For details about the APIs, see `//utils/native/lite/include/ohos_init.h`. The following table lists the main macros for automatic service initialization.
1011
1012| API                | Description                            |
1013| ---------------------- | -------------------------------- |
1014| SYS_SERVICE_INIT(func) | Entry for initializing and starting a core system service.|
1015| SYS_FEATURE_INIT(func) | Entry for initializing and starting a core system feature.|
1016| APP_SERVICE_INIT(func) | Entry for initializing and starting an application-layer service.  |
1017| APP_FEATURE_INIT(func) | Entry for initializing and starting an application-layer feature.  |
1018
1019![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
1020	You need to add a forcible link to the` lib` file generated by building the previous loaded components.
1021
1022​	If the `bootstrap_lite` component is configured in the `vendor/bestechnic/display_demo/config.json` file, as shown below:
1023
1024```
1025    {
1026      "subsystem": "startup",
1027      "components": [
1028        {
1029          "component": "bootstrap_lite"
1030        },
1031        ...
1032      ]
1033    },
1034```
1035
1036​	The `bootstrap_lite` component will compile the `//base/startup/bootstrap_lite/services/source/bootstrap_service.c` file. In this file, inject the `Init` function symbol to `__zinitcall_sys_service_start` and `__zinitcall_sys_service_end` through `SYS_SERVICE_INIT`. Because the `Init` function is not explicitly called, it needs to be forcibly linked to the final image. The sample code is as follows:
1037
1038```
1039static void Init(void)
1040{
1041    static Bootstrap bootstrap;
1042    bootstrap.GetName = GetName;
1043    bootstrap.Initialize = Initialize;
1044    bootstrap.MessageHandle = MessageHandle;
1045    bootstrap.GetTaskConfig = GetTaskConfig;
1046    bootstrap.flag = FALSE;
1047    SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
1048}
1049SYS_SERVICE_INIT(Init);   --- Once SYS (SYS_INIT) is started, the generated library needs to be forcibly linked.
1050```
1051
1052​	In the `//base/startup/bootstrap_lite/services/source/BUILD.gn` file, the save path of `libbootstrap.a` is set to `out/v200zr/display_demo/libs` as follows:
1053
1054```
1055static_library("bootstrap") {
1056  sources = [
1057    "bootstrap_service.c",
1058    "system_init.c",
1059  ]
1060  ....
1061```
1062
1063​	In this case, you need to add `bootstrap` under `force_link_libs` in `vendor/bestechnic/display_demo/config.json`, as shown below:
1064
1065```
1066  "bin_list": [
1067    {
1068      "elf_name": "wifiiot",
1069      "bsp_target_name": "best2600w_liteos",
1070      "signature": "false",
1071      "burn_name": "rtos_main",
1072      "enable": "true",
1073      "force_link_libs": [
1074        "bootstrap",	 --- Forcibly link to libbootstrap.a.
1075        ...
1076      ]
1077    },
1078```
1079
1080
1081
1082When the `syspara_lite` component is adapted, system parameters are written to a file for persistent storage. In the mini system, file operation APIs include `POSIX` and `HalFiles`.
1083
1084For access to the file system in the kernel, use the `POSIX` API, which means you need to add `enable_ohos_startup_syspara_lite_use_posix_file_api = true` to the `features` field.
1085
1086If you are using the `HalFiles` API, no modification is required.
1087
1088During adaptation of the `GetSerial` API, no `Serial Number` is written to the development board, which is different from the case in the production line. Therefore, you need to assign an attribute to uniquely identify the development board. In this example, the Wi-Fi MAC address is used.
1089
1090```
1091#define ETH_ALEN 6
1092#define MAC_BITS 4
1093#define MAC_HIGH_MASK 0xf0
1094#define MAC_LOW_MASK 0x0f
1095#define HEX_A 0xa
1096#define CHAR_NUM_OFFSET 0x30
1097#define CHAR_CAPITAL_OFFSET 0x37
1098#define STR_END_FLAG '\0'
1099
1100typedef unsigned char               u8;
1101
1102static char serialNumber[2*ETH_ALEN + 1];		 --- The last character is used as the end character '\0'.
1103
1104
1105static char Hex2Char(u8 hex)
1106{
1107    if (hex < HEX_A) {
1108        return hex + CHAR_NUM_OFFSET;			 --- Convert the value 0 to char '0'.
1109    } else {
1110        return hex + CHAR_CAPITAL_OFFSET;		 --- Convert the value 0xa to char 'A'.
1111    }
1112}
1113
1114const char* HalGetSerial(void)
1115{
1116    char macAddr[ETH_ALEN];
1117    // as devboard has no production serial number, we just
1118    // use wifi mac address as device serial number.
1119    if (serialNumber[0] == STR_END_FLAG) {		 --- The MAC address is obtained only when the API is invoked for the first time.
1120        extern int bwifi_get_own_mac(u8 *addr);
1121        bwifi_get_own_mac(macAddr);				 --- Obtain the MAC address.
1122        int j = 0;
1123        for (int i = 0; i < ETH_ALEN; i++) {
1124            u8 lowFour, highFour;
1125            highFour = (macAddr[i] & MAC_HIGH_MASK) >> MAC_BITS;
1126            serialNumber[j] = Hex2Char(highFour);
1127            j++;
1128            lowFour = macAddr[i] & MAC_LOW_MASK;
1129            serialNumber[j] = Hex2Char(lowFour);
1130            j++;
1131        }		 --- Convert the MAC address to the serial number.
1132    }
1133    return serialNumber;
1134}
1135```
1136
1137#### DFX Subsystem Adaptation
1138
1139To adapt the DFX subsystem, you need to add the `hilog_lite` component in the `config.json` file.
1140
1141```
1142{
1143  "subsystem": "hiviewdfx",
1144  "components": [
1145	{
1146	  "component": "hilog_lite",
1147	  "optional": "true"
1148	}
1149  ]
1150},
1151```
1152
1153Register the log output implementation function in `//device/soc/bestechnic/bes2600/liteos_m/components/utils/src/hm_sys.c`.
1154
1155```
1156boolean HilogProc_Impl(const HiLogContent *hilogContent, uint32 len)
1157{
1158    char tempOutStr[LOG_FMT_MAX_LEN] = {0};
1159    if (LogContentFmt(tempOutStr, sizeof(tempOutStr), hilogContent) > 0) {
1160        printf(tempOutStr);
1161    }
1162	return TRUE;
1163}
1164
1165HiviewRegisterHilogProc(HilogProc_Impl);
1166```
1167
1168#### systemabilitymgr Subsystem Adaptation
1169
1170To adapt the `systemabilitymgr` subsystem, you need to add the `samgr_lite` component in the `config.json` file, as shown below:
1171
1172```
1173{
1174  "subsystem": "systemabilitymgr",
1175  "components": [
1176	{
1177	  "component": "samgr_lite",
1178	  "features": [
1179		"config_ohos_systemabilitymgr_samgr_lite_shared_task_size = 4096"
1180	  ]
1181	}
1182  ]
1183},
1184```
1185
1186In the mini system, the default size of the shared task stack for `samgr_lite` is `0x800`. To avoid stack overflow, adjust the size to `0x1000`.
1187
1188#### Security Subsystem Adaptation
1189
1190To adapt the `security` subsystem, you need to add the `huks/deviceauth_lite` component in the `config.json` file, as shown below:
1191
1192```
1193    {
1194      "subsystem": "security",
1195      "components": [
1196        {
1197          "component": "huks",
1198          "features": [
1199            "huks_use_lite_storage = true",
1200            "huks_use_hardware_root_key = true",
1201            "huks_config_file = \"hks_config_lite.h\"",
1202            "huks_key_store_path = \"/data/\"",
1203            "ohos_security_huks_mbedtls_porting_path = \"//device/soc/bestechnic/hals/mbedtls\""
1204          ]
1205        },
1206        {
1207          "component": "deviceauth_lite",
1208          "features": [
1209            "deviceauth_storage_path = \"/data/\"",
1210            "deviceauth_hichain_thread_stack_size = 9472"
1211          ]
1212        }
1213      ]
1214    }
1215```
1216
1217During `huks` component adaptation, set `huks_key_store_path` to the path for storing the key and `ohos_security_huks_mbedtls_porting_path` to the directory for `mbedtls` adaptation, so that the chip can adapt `mbedtls` to hardware random numbers.
1218
1219During `deviceauth_lite` component adaptation, set `deviceauth_storage_path` to the path for storing device authentication information and `deviceauth_hichain_thread_stack_size` to the thread stack size.
1220
1221#### Multimedia Subsystem Adaptation
1222
1223To adapt the multimedia subsystem, you need to add the `histreamer` component in the `config.json` file, as shown below:
1224
1225```
1226{
1227  "subsystem": "multimedia",
1228  "components": [
1229    {
1230      "component": "histreamer",
1231      "features": [
1232        "multimedia_histreamer_enable_plugin_hdi_adapter = true",
1233        "multimedia_histreamer_enable_plugin_minimp3_adapter = true",
1234        "multimedia_histreamer_enable_plugin_ffmpeg_adapter = false",
1235        "config_ohos_multimedia_histreamer_stack_size = 65536"
1236      ]
1237    }
1238  ]
1239},
1240```
1241
1242The configuration items of the `histreamer` component are described as follows:
1243
1244| Item                                             | Description                           |
1245| --------------------------------------------------- | ------------------------------- |
1246| multimedia_histreamer_enable_plugin_hdi_adapter     | Whether to enable histreamer to connect to the HDMI interface.|
1247| multimedia_histreamer_enable_plugin_minimp3_adapter | Whether to enable the plug-in to adapt to miniMP3.        |
1248| multimedia_histreamer_enable_plugin_ffmpeg_adapter  | Whether to enable the plug-in to adapt to FFmpeg.         |
1249| config_ohos_multimedia_histreamer_stack_size        | Size of the histreamer stack.           |
1250
1251#### utils Subsystem Adaptation
1252
1253To adapt the `utils` subsystem, you need to add the `kv_store`, `js_builtin`, `timer_task`, and `kal_timer` components in the `config.json` file, as shown below:
1254
1255```
1256{
1257  "subsystem": "utils",
1258  "components": [
1259	{
1260	  "component": "kv_store",
1261	  "features": [
1262		"enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true"
1263	  ]
1264	},
1265	{
1266	  "component": "js_builtin"
1267	},
1268	{
1269	  "component": "timer_task"
1270	},
1271	{
1272	  "component": "kal_timer",
1273	}
1274  ]
1275},
1276```
1277
1278Similar to that in the `syspara_lite` component, the key-value pair is written to a file during adaptation of the `kv_store` component. In the mini system, file operation APIs include `POSIX` and `HalFiles`. For access to the file system in the kernel, use the `POSIX` API, which means that you need to add `enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true` to the `features` field. If you are using the `HalFiles` API, no modification is required.
1279
1280#### Graphics Subsystem Adaptation
1281
1282To adapt the `graphic` subsystem, you need to add the `graphic_utils` component in the `config.json` file, as shown below:
1283
1284```
1285      "components": [
1286        {
1287          "component": "graphic_utils",
1288          "features": [
1289            "enable_ohos_graphic_utils_product_config = true"
1290          ]
1291        },
1292        {
1293          "component": "ui"
1294        }
1295      ]
1296    }
1297```
1298
1299For details about `graphic` configuration, see `//vendor/bestechnic/display_demo/graphic_config/product_graphic_lite_config.h`.
1300
1301For details about `graphic` adaptation, see `//device/soc/bestechnic/bes2600/liteos_m/components/ui`, . The main functions are as follows:
1302
1303- `display_device`: instantiates `BaseGfxEngine`.
1304- `touch_input`: instantiates `PointerInputDevice`.
1305- `UiMainTask`: initializes the font engine and executes rendering tasks.
1306
1307Layers of the `graphic` subsystem:
1308
1309```
1310aafwk_lite + appexecfwk_lite    (AAFWK + APPEXECFWK)
1311      |
1312ace_engine_lite + jerryscript + i18n_lite + resmgr_lite + utils/native/lite/... (ACE and JS engines and their dependencies)
1313      |
1314graphic_ui + graphic_utils      (Graphic framework)
1315      |
1316giflib + libjpeg + libpng + qrcodegen + freetype... (Third-party graphics library)
1317```
1318
1319For details about the graphic application demo, see the `//vendor/bestechnic/display_demo/tests/app.cpp` file, as shown below:
1320
1321```
1322/* ui app entry */
1323void RunApp()
1324{
1325#ifdef UI_TEST
1326    AnimatorDemoStart(); 	 --- native ui demo
1327#elif defined(ABILITY_TEST)
1328    StartJSApp(); 			 --- js demo
1329#endif
1330}
1331
1332void AppEntry(void)
1333{
1334    UiMain();
1335}
1336
1337APP_FEATURE_INIT(AppEntry);
1338```
1339
1340#### ACE Subsystem Adaptation
1341
1342To adapt the ACE subsystem, you need to add the `ace_engine_lite` component in the `config.json` file, as shown below:
1343
1344    {
1345      "subsystem": "ace",
1346      "components": [
1347        {
1348          "component": "ace_engine_lite",
1349          "features": [
1350            "enable_ohos_ace_engine_lite_product_config = true"
1351          ]
1352        }
1353      ]
1354    },
1355
1356For details about the `ace_engine_lite` configuration, see `//vendor/bestechnic/display_demo/ace_lite_config/product_acelite_config.h`.
1357
1358The `ace_lite` application is developed in JavaScript. The detailed procedure is as follows:
1359
13601. Use DevEco Studio to compile a JavaScript application. For details, see [Lite Wearable Development Specifications](https://developer.harmonyos.com/en/docs/documentation/doc-references/lite-wearable-file-0000001176751380).
13612. Use the Previewer feature to preview the application and obtain the JS package `entry\.preview\intermediates\res\debug\lite\assets\js\default`.
13623. Place the JS package to the corresponding file system path `vendor/bestechnic/display_demo/fs/data/data/js`, as shown below:
1363
1364```
1365├── app.js
1366├── common
1367├── i18n
1368├── manifest.json
1369└── pages
1370```
1371
13724. Start building to generate the system image. Burn the system image the development board, and the system will load and start the `ace` application from `app.js`.
1373
1374#### aafwk Subsystem Adaptation
1375
1376To adapt the `aafwk` subsystem, you need to add the `aafwk_lite` component in the `config.json` file, as shown below:
1377
1378```
1379    {
1380      "subsystem": "aafwk",
1381      "components": [
1382        {
1383          "component": "aafwk_lite",
1384          "features": [
1385            "enable_ohos_appexecfwk_feature_ability = true",	 --- Enable the FA to support the graphics capability.
1386            "config_ohos_aafwk_ams_task_size = 4096"			 --- Configure the size of the aafwk stack.
1387          ]
1388        }
1389      ]
1390    },
1391```
1392
1393For details about the `aafwk_lite` use cases, see the `vendor/bestechnic/display_demo/tests/ability` directory, which includes the `launcher` and `js app` applications. The function invocation process of the applications is described as follows:
1394
13951. `launcher` application: Use `InstallLauncher` to install the `native ui` application, whose `BundleName` is `"com.example.launcher"`. After `AbilityMgrSliteFeature` is started, `AbilityMgrHandler::StartLauncher()` is invoked to start the `launcher` application.
1396
13972. `StartJSApp` application: Use `StartAbility` to start any `Want` and pass `want data` to `JS_APP_PATH`,
1398   `SetWantData(&want, JS_APP_PATH, strlen(JS_APP_PATH) + 1)`.
1399
1400#### appexecfwk Subsystem Adaptation
1401
1402To adapt the `appexecfwk` subsystem, you need to add the `appexecfwk_lite` component in the `config.json` file, as shown below:
1403
1404```
1405    {
1406      "subsystem": "appexecfwk",
1407      "components": [
1408        {
1409          "component": "appexecfwk_lite"
1410        }
1411      ]
1412    },
1413```
1414
1415## Compatibility Test
1416
1417### Product Compatibility Specifications
1418
1419For details about product compatibility specifications, see [Introduction to Product Compatibility SIG](https://gitee.com/openharmony-sig/compatibility/tree/master).
1420
1421### XTS Test Cases
1422
1423For details about the `XTS` test cases, see [XTS](../device-test/xts.md). To adapt the `XTS` subsystem, you need to add the `xts_acts`/`xts_tools` component in the `config.json` file, as shown below:
1424
1425    {
1426      "subsystem": "xts",
1427      "components": [
1428        { "component": "xts_acts", "features":
1429          [
1430            "config_ohos_xts_acts_utils_lite_kv_store_data_path = \"/data\"",
1431            "enable_ohos_test_xts_acts_use_thirdparty_lwip = true"
1432          ]
1433        },
1434        { "component": "xts_tools", "features":[] }
1435      ]
1436    }
1437
1438Where:
1439
1440- `config_ohos_xts_acts_utils_lite_kv_store_data_path` is the name of the root directory to which the file system is mounted.
1441- `enable_ohos_test_xts_acts_use_thirdparty_lwip` indicates whether to use the source code in the `thirdparty/lwip` directory. The value `true` means to use the source code in the `thirdparty/lwip` directory, and `false` means the opposite.
1442
1443After the execution is complete, `xx Tests xx Failures xx Ignored` is displayed, as shown below:
1444
1445```
1446...
1447[16:53:43:438]../../../test/xts/acts/utils_lite/kv_store_hal/src/kvstore_func_test.c:793:testKvStoreMaxSize004:PASS
1448[16:53:43:438]+-------------------------------------------+
1449[16:53:43:438]
1450[16:53:43:438]-----------------------
1451[16:53:43:438]32 Tests 0 Failures 0 Ignored
1452[16:53:43:438]OK
1453[16:53:43:439]All the test suites finished!
1454```
1455
1456### Report Submission
1457
1458Save the preceding `XTS` test result as a test report and upload it to the OpenHarmony compatibility test website. This is a prerequisite for synchronizing the code from the `sig` repository to the `master` repository. The procedure is as follows:
1459
1460Step 1: Compress the `XTS` test report into a `zip` file.
1461
1462Step 2: Generate the SHA checksum of the test report. In this example, the SHA checksum is generated by uploading the `zip` file to the [SHA checksum online generator](https://tool.lmeee.com/jiami/filehash).
1463
1464Step 3: Go to the `OpenHarmony` [compatibility test website](https://www.openharmony.cn/old/#/Compatibility_test) and upload the report.
1465
1466 - Set `API Level` to the `"sdkApiLevel"` value in the report.
1467 - Set `OS` to the `"OS Version"` value in the report.
1468
1469## Coming Soon
1470
1471The following aspects will be added in the future:
1472
1473- Bluetooth
1474- `bms` package installation
1475- Verifying `bytecode` for running `JS`
1476- Distributed capabilities: `dms` and `dm`
1477- Example of a distributed music player
1478