1 2# Combo Solution – W800 Chip Porting Case 3 4The combo solution is developed based on the OpenHarmony LiteOS-M kernel. This document exemplifies how to port code of the [Neptune100 development board](https://gitee.com/openharmony-sig/device_board_hihope) powered by the W800 chip from Winner Micro. The porting architecture uses the solution where Board and SoC are separated. Compilation options can be graphically configured through KConfig. The porting of the `ck804ef` architecture is added to adapt subsystems and components such as `HDF` and `XTS`. 5 6## Adaptation Preparation 7 8Prepare the ubuntu20.04 system environment and install the cross compilation toolchain [csky-abiv2-elf-gcc](https://occ.t-head.cn/community/download?id=3885366095506644992). 9 10## Compilation and Building 11 12### Directory Planning 13 14This solution designs the directory structure using the [board and SoC decoupling idea](https://gitee.com/openharmony-sig/sig-content/blob/master/devboard/docs/board-soc-arch-design.md). 15 16The SoC adaptation directory is planned as follows: 17 ``` 18 device 19 ├── board --- Board vendor directory 20 │ └── hihope --- Board vendor: HiHope 21 │ └── neptune100 --- Board name: Neptune100 22 └── soc --- SoC vendor directory 23 └── winnermicro --- SoC vendor: Winner Micro 24 └── wm800 --- SoC series: W800 25 ``` 26 27The planned product demo directory is as follows: 28 29 ``` 30 vendor 31 └── hihope --- Vendor of the product demo. 32 ├── neptune_iotlink_demo --- Product demo name: sample code of Neptune100 33 └── ... 34 ``` 35 36### Product Definition 37 38The `vendor/hihope/neptune_iotlink_demo/config.json` file describes the kernel, board, and subsystem information used by the product. The kernel, board model, and board vendor are required by the precompilation command `hb set` and must be planned. Example: 39 40 ``` 41 { 42 "product_name": "neptune_iotlink_demo", --- Product name 43 "ohos_version": "OpenHarmony 3.1", --- OS version in use 44 "type":"mini", --- OS type: mini 45 "version": "3.0", --- OS version: 3.0 46 "device_company": "hihope", --- Board vendor: hihope 47 "board": "neptune100", --- Board name: neptune100 48 "kernel_type": "liteos_m", --- Kernel type: liteos_m 49 "kernel_version": "3.0.0", --- Kernel version: 3.0.0 50 "subsystems": [] --- Subsystem 51 } 52 ``` 53The filled information corresponds to the planned directory. In the information, `device_company` and `board` are used to associate the `device/board/<device_company>/` directory. 54 55### Board Configuration 56 57In the associated **\<board>** directory, place the `config.gni` file to the `device/board/hihope/neptune100/liteos_m` directory. This file is used to describe the board information, including the CPU model, cross compilation toolchain, global compilation, and link parameters. 58 59``` 60# Kernel type, e.g. "linux", "liteos_a", "liteos_m". 61kernel_type = "liteos_m" 62 63# Kernel version. 64kernel_version = "3.0.0" 65 66# Board CPU type, e.g. "cortex-a7", "riscv32". 67board_cpu = "ck804ef" 68 69# Board arch, e.g. "armv7-a", "rv32imac". 70board_arch = "ck803" 71 72# Toolchain name used for system compiling. 73# E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. 74# Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toolchain. 75board_toolchain = "csky-elfabiv2-gcc" 76 77#use_board_toolchain = true 78 79# The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc. 80board_toolchain_path = "" 81 82# Compiler prefix. 83board_toolchain_prefix = "csky-elfabiv2-" 84 85# Compiler type, "gcc" or "clang". 86board_toolchain_type = "gcc" 87 88# config.json parse 89if (product_path != "") { 90 product_conf = read_file("${product_path}/config.json", "json") 91 product_name = product_conf.product_name 92 bin_list = product_conf.bin_list 93} 94 95# Board related common compile flags. 96board_cflags = [ 97 "-mcpu=ck804ef", 98 "-mhard-float", 99 "-DGCC_COMPILE=1", 100 "-DTLS_CONFIG_CPU_XT804=1", 101 "-DNIMBLE_FTR=1", 102 "-D__CSKY_V2__=1", 103 "-DCPU_CK804", 104 "-O2", 105 "-g3", 106 "-Wall", 107 "-ffunction-sections", 108 "-MMD", 109 "-MP", 110] 111 112board_cxx_flags = board_cflags 113 114board_asmflags = [ 115 "-mcpu=ck804ef", 116 "-DCPU_CK804", 117] 118 119board_ld_flags = [] 120 121# Board related headfiles search path. 122board_include_dirs = [] 123 124# Board adapter dir for OHOS components. 125board_adapter_dir = "" 126 127# Sysroot path. 128board_configed_sysroot = "" 129 130# Board storage type, it used for file system generation. 131storage_type = "" 132``` 133 134### Precompilation 135 136Run the precompilation command `hb set` in the project root directory to show relevant product information, as shown below: 137 138``` 139hb set 140OHOS Which product do you need? (Use arrow keys) 141 142hihope 143 > neptune_iotlink_demo 144 145OHOS Which product do you need? neptune_iotlink_demo 146``` 147 148After `hb set` is executed, an `ohos_config.json` file will be automatically generated in the root directory. The file lists the product information to be compiled. 149 150Run the `hb env` command to view the selected precompilation environment variables. 151 152``` 153[OHOS INFO] root path: /home/xxxx/openharmony_w800 154[OHOS INFO] board: neptune100 155[OHOS INFO] kernel: liteos_m 156[OHOS INFO] product: neptune_iotlink_demo 157[OHOS INFO] product path: /home/xxxx/openharmony_w800/vendor/hihope/neptune_iotlink_demo 158[OHOS INFO] device path: /home/xxxx/openharmony_w800/device/board/hihope/neptune100/liteos_m 159[OHOS INFO] device company: hihope 160``` 161 162So far, the precompilation adaptation is complete. However, the project cannot be compiled by running **hb build**. You also need to prepare for the subsequent LiteOS-M kernel porting. 163 164## Kernel Porting 165 166### Kconfig Adaptation 167 168During the compilation of `kernel/liteos_m`, you need to use the `Kconfig` file for indexing in the corresponding board and SoC directory. 169 1701. Create a **kernel_configs** directory in the `vendor/hihope/neptune_iotlink_demo` directory, and create an empty `debug.config` file. 171 1722. Open the `kernel/liteos_m/Kconfig` file. Multiple `Kconfig` files in `device/board` and `device/soc` have been imported using the **orsource** command in this file. You need to create and modify these files later. 173 174 ``` 175 orsource "../../device/board/*/Kconfig.liteos_m.shields" 176 orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.defconfig.boards" 177 orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.boards" 178 orsource "../../device/soc/*/Kconfig.liteos_m.defconfig" 179 orsource "../../device/soc/*/Kconfig.liteos_m.series" 180 orsource "../../device/soc/*/Kconfig.liteos_m.soc" 181 ``` 182 1833. Create corresponding `Kconfig` files in `device/board/hihope`. 184 185 ``` 186 ├── neptune100 --- neptune100 board configuration directory. 187 │ ├── Kconfig.liteos_m.board --- Board configuration options. 188 │ ├── Kconfig.liteos_m.defconfig.board --- Default board configuration options. 189 │ └── liteos_m 190 │ └── config.gni --- Board configuration file. 191 ├── Kconfig.liteos_m.boards --- Board configuration information of the board vendor. 192 └── Kconfig.liteos_m.defconfig.boards --- Default board configuration information of the board vendor. 193 ``` 194 1954. Modify the `Kconfig` file in the `Board` directory. 196 197 Add the following content to `neptune100/Kconfig.liteos_m.board`: 198 199 ``` 200 config BOARD_NEPTUNE100 201 bool "select board neptune100" 202 depends on SOC_WM800 203 ``` 204 205 Configure that **BOARD_NEPTUNE100** can be selected only when **SOC_WM800** is selected. 206 207 Add the following content to `neptune100/Kconfig.liteos_m.defconfig.board`: 208 209 ``` 210 if BOARD_NEPTUNE100 211 212 endif #BOARD_NEPTUNE100 213 ``` 214 215 This content is used to add the default configuration of **BOARD_NEPTUNE100**. 216 2175. Create corresponding `Kconfig` files in `device/soc/winnermicro`. 218 219 ``` 220 ├── wm800 --- W800 series. 221 │ ├── Kconfig.liteos_m.defconfig.wm800 --- Default W800 SoC configuration. 222 │ ├── Kconfig.liteos_m.defconfig.series --- Default configuration of the W800 series. 223 │ ├── Kconfig.liteos_m.series --- Configuration of the W800 series. 224 │ └── Kconfig.liteos_m.soc --- W800 SoC configuration. 225 ├── Kconfig.liteos_m.defconfig --- Default SoC configuration. 226 ├── Kconfig.liteos_m.series --- Series configuration. 227 └── Kconfig.liteos_m.soc --- SoC configuration. 228 ``` 229 2306. Modify the `Kconfig` file in the `Soc` directory. 231 232 Add the following content to `wm800/Kconfig.liteos_m.defconfig.wm800`: 233 234 ``` 235 config SOC 236 string 237 default "wm800" 238 depends on SOC_WM800 239 ``` 240 241 Add the following content to `wm800/Kconfig.liteos_m.defconfig.series`: 242 243 ``` 244 if SOC_SERIES_WM800 245 246 rsource "Kconfig.liteos_m.defconfig.wm800" 247 248 config SOC_SERIES 249 string 250 default "wm800" 251 252 endif 253 ``` 254 255 Add the following content to `wm800/Kconfig.liteos_m.series`: 256 257 ``` 258 config SOC_SERIES_WM800 259 bool "winnermicro 800 Series" 260 select ARM 261 select SOC_COMPANY_WINNERMICRO --- Select SOC_COMPANY_WINNERMICRO. 262 select CPU_XT804 263 help 264 Enable support for winnermicro 800 series 265 ``` 266 267 **SOC_WM800** in the `wm800/Kconfig.liteos_m.soc` file can be selected only after **SOC_SERIES_WM800** is selected. 268 269 ``` 270 choice 271 prompt "Winnermicro 800 series SoC" 272 depends on SOC_SERIES_WM800 273 274 config SOC_WM800 --- Select SOC_WM800. 275 bool "SoC WM800" 276 277 endchoice 278 ``` 279 280 In conclusion, to compile **BOARD_NEPTUNE100**, you need to select **SOC_COMPANY_WINNERMICRO**, **SOC_SERIES_WM800**, and **SOC_WM800**. 2817. Run `make menuconfig` in `kernel/liteos_m` for configuration selection. The SoC series can be selected. 282 283 ![w800_select.json](figures/w800_select.png) 284 285 The configured file is saved to `vendor/hihope/neptune_iotlink_demo/kernel_configs/debug.config` by default. You can also directly configure `debug.config`. 286 287 ``` 288 LOSCFG_PLATFORM_QEMU_CSKY_SMARTL=y 289 LOSCFG_SOC_SERIES_WM800=y 290 ``` 291 292### Modular Compilation 293 294The compilation of `Board` and `SoC` adopts the modular compilation method, starting from `kernel/liteos_m/BUILD.gn` and increasing by level. The adaptation process of this solution is as follows: 295 2961. Create the `BUILD.gn` file in `device/board/hihope` and add the following content to the file: 297 298 ``` 299 if (ohos_kernel_type == "liteos_m") { 300 import("//kernel/liteos_m/liteos.gni") 301 module_name = get_path_info(rebase_path("."), "name") 302 module_group(module_name) { 303 modules = [ 304 "neptune100", --- Board module. 305 "shields", 306 ] 307 } 308 } 309 ``` 310 311 In the preceding `BUILD.gn` file, **neptune100** and **shields** are the module names organized by directory level. 312 3132. Create the `BUILD.gn` file in `device/soc/winnermicro` and add the following content to the file: 314 315 ``` 316 if (ohos_kernel_type == "liteos_m") { 317 import("//kernel/liteos_m/liteos.gni") 318 module_name = get_path_info(rebase_path("."), "name") 319 module_group(module_name) { 320 modules = [ 321 "hals", 322 "wm800", 323 ] 324 } 325 } 326 ``` 327 3283. In the `device/soc/winnermicro` module at each level, add the `BUILD.gn` file and compile the module. The following uses `device/soc/winnermicro/wm800/board/platform/sys/BUILD.gn` as an example: 329 330 ``` 331 import("//kernel/liteos_m/liteos.gni") 332 module_name = get_path_info(rebase_path("."), "name") 333 kernel_module(module_name) { --- Compiled module. 334 sources = [ --- Compiled source file. 335 "wm_main.c", 336 ] 337 include_dirs = [ --- Header file used in the module. 338 ".", 339 ] 340 } 341 342 ``` 343 3444. To organize links and some compilation options, set the following parameters in `config("board_config")` in `device/soc/winnermicro/wm800/board/BUILD.gn`: 345 346 ``` 347 config("board_config") { 348 ldflags = [] --- Link parameters, including the Id file. 349 libs = [] --- Link library. 350 include_dirs = [] --- Common header file. 351 ``` 352 353 3545. To organize some product applications, this solution adds a corresponding list to the `config.json` file of the vendor. The following uses `vendor/hihope/neptune_iotlink_demo/config.json` as an example to describe how to add a corresponding list to the `config.json` file: 355 356 ``` 357 "bin_list": [ --- demo list 358 { 359 "elf_name": "hihope", 360 "enable": "false", --- List switch. 361 "force_link_libs": [ 362 "bootstrap", 363 "broadcast", 364 ... 365 ] 366 } 367 ``` 368 369 The demo is managed as a module. To enable or disable a demo, add or delete corresponding library files in **bin_list**. **bin_list** can be directly read in GN. You need to add the following content to `device/board/hihope/neptune100/liteos_m/config.gni`: 370 371 ``` 372 # config.json parse 373 if (product_path != "") { 374 product_conf = read_file("${product_path}/config.json", "json") 375 product_name = product_conf.product_name 376 bin_list = product_conf.bin_list 377 } 378 ``` 379 380 After reading the list, you can add related component libraries to the corresponding link options. Add the following content to `//device/soc/winnermicro/wm800/BUILD.gn`: 381 382 ``` 383 foreach(bin_file, bin_list) { 384 build_enable = bin_file.enable 385 ... 386 if(build_enable == "true") 387 { 388 ... 389 foreach(force_link_lib, bin_file.force_link_libs) { 390 ldflags += [ "-l${force_link_lib}" ] 391 } 392 ... 393 } 394 } 395 ``` 396 397### Kernel Subsystem Adaptation 398 399Add the kernel subsystem and relevant configuration to `vendor/hihope/neptune_iotlink_demo/config.json`, as shown below: 400 401 ``` 402 "subsystems": [ 403 { 404 "subsystem": "kernel", 405 "components": [ 406 { 407 "component": "liteos_m", "features":[] 408 } 409 ] 410 }, 411 ``` 412 413### Kernel Startup Adaptation 414 415The Neptune100 development board uses the SoC architecture **ck804ef**, which is not supported by OpenHarmony. You need to port the architecture **ck804ef**. Adapt general files and function lists defined in `kernel\liteos_m\arch\include`, and place them to the `kernel\liteos_m\arch\csky\v2\ck804\gcc` directory. 416 417The following is an example of kernel initialization: 418 419 ``` 420 osStatus_t ret = osKernelInitialize(); --- Kernel initialization. 421 if(ret == osOK) 422 { 423 threadId = osThreadNew((osThreadFunc_t)sys_init,NULL,&g_main_task); --- Create the init thread. 424 if(threadId!=NULL) 425 { 426 osKernelStart(); --- Thread scheduling. 427 } 428 } 429 ``` 430 431Initialize necessary actions before **board_main** starts **OHOS_SystemInit**, as shown below: 432 433 ``` 434 ... 435 UserMain(); --- Initialize the driver before starting OHOS_SystemInit of OpenHarmony. 436 ... 437 OHOS_SystemInit(); --- Start OpenHarmony services and initialize components. 438 ... 439 ``` 440 441The **UserMain** function is in the `device/soc/winnermicro/wm800/board/app/main.c` file, as shown below: 442 443 ``` 444 ... 445 if (DeviceManagerStart()) { --- HDF initialization. 446 printf("[%s] No drivers need load by hdf manager!",__func__); 447 } 448 ... 449 ``` 450 451### HDF Framework Adaptation 452 453HDF provides a set of unified APIs for applications to access hardware, simplifying application development. To add the HDF component, you need to add it to `//vendor/hihope/neptune_iotlink_demo/kernel_configs`: 454 455 ``` 456 LOSCFG_DRIVERS_HDF=y 457 LOSCFG_DRIVERS_HDF_PLATFORM=y 458 ``` 459 460Driver adaptation files are stored in `drivers/adapter/platform`, including the gpio, i2c, pwm, spi, uart, and watchdog drivers. These files are loaded using the HDF mechanism. This section uses GPIO and UART as an example. 461 462#### GPIO Adaptation 463 4641. The chip driver adaptation file is stored in the `drivers/adapter/platform` directory. Add the `gpio_wm.c` file to the **gpio** directory, and define the compilation adaptation of the W800 driver in `BUILD.gn`, as shown below: 465 466 ``` 467 ... 468 if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) { 469 sources += [ "gpio_wm.c" ] 470 } 471 ... 472 ``` 473 4742. Define the driver description file in `gpio_wm.c` as follows: 475 476 ``` 477 /* HdfDriverEntry definitions */ 478 struct HdfDriverEntry g_GpioDriverEntry = { 479 .moduleVersion = 1, 480 .moduleName = "WM_GPIO_MODULE_HDF", 481 .Bind = GpioDriverBind, 482 .Init = GpioDriverInit, 483 .Release = GpioDriverRelease, 484 }; 485 HDF_INIT(g_GpioDriverEntry); 486 ``` 487 4883. Add the GPIO hardware description information to `device/board/hihope/shields/neptune100/neptune100.hcs`. 489 490 ``` 491 root { 492 platform { 493 gpio_config { 494 match_attr = "gpio_config"; 495 groupNum = 1; 496 pinNum = 48; 497 } 498 } 499 } 500 ``` 501 5024. Obtain the **hcs** parameter from **GpioDriverInit** for initialization, as shown below: 503 504 ``` 505 ... 506 gpioCntlr = GpioCntlrFromHdfDev(device); --- Obtain specific GPIO configurations through the **gpioCntlr** node variable. 507 if (gpioCntlr == NULL) { 508 HDF_LOGE("GpioCntlrFromHdfDev fail\r\n"); 509 return HDF_DEV_ERR_NO_DEVICE_SERVICE; 510 } 511 ... 512 ``` 513 514#### UART Adaptation 515 5161. The chip driver adaptation file is stored in the `drivers/adapter/platform` directory. Add the `uart_wm.c` file to the **uart** directory, and define the compilation adaptation of the W800 driver in `BUILD.gn`, as shown below: 517 518 ``` 519 ... 520 if (defined(LOSCFG_SOC_COMPANY_WINNERMICRO)) { 521 sources += [ "uart_wm.c" ] 522 } 523 ... 524 ``` 525 5262. Define the driver description file in `uart_wm.c` as follows: 527 528 ``` 529 /* HdfDriverEntry definitions */ 530 struct HdfDriverEntry g_UartDriverEntry = { 531 .moduleVersion = 1, 532 .moduleName = "W800_UART_MODULE_HDF", 533 .Bind = UartDriverBind, 534 .Init = UartDriverInit, 535 .Release = UartDriverRelease, 536 }; 537 538 /* Initialize HdfDriverEntry */ 539 HDF_INIT(g_UartDriverEntry); 540 ``` 541 5423. Add the UART hardware description information to `device/board/hihope/shields/neptune100/neptune100.hcs`. 543 544 ``` 545 root { 546 platform { 547 uart_config { 548 /* 549 uart0 { 550 match_attr = "uart0_config"; 551 num = 0; 552 baudrate = 115200; 553 parity = 0; 554 stopBit = 1; 555 data = 8; 556 }*/ 557 uart1 { 558 match_attr = "uart1_config"; 559 num = 1; 560 baudrate = 115200; 561 parity = 0; 562 stopBit = 1; 563 data = 8; 564 } 565 } 566 } 567 } 568 ``` 569 5704. Obtain the **hcs** parameter from **UartDriverInit** for initialization, as shown below: 571 572 ``` 573 ... 574 host = UartHostFromDevice(device); 575 if (host == NULL) { 576 HDF_LOGE("%s: host is NULL", __func__); 577 return HDF_ERR_INVALID_OBJECT; 578 } 579 ... 580 ``` 581 582## OpenHarmony Subsystem Adaptation 583 584Subsystem compilation options are configured in the `config.json` file of the corresponding product, for example, `vendor/hihope/neptune_iotlink_demo/config.json`. 585 586### wifi_lite Component 587 588Add the `wifi_lite` component of the `communication` subsystem to the `config.json` file, as shown below: 589 590 ``` 591 { 592 "subsystem": "communication", 593 "components": [ 594 { 595 "component": "wifi_lite", 596 "optional": "true" 597 } 598 ] 599 }, 600 ``` 601 602The `wifi_lite` component is in the `build/lite/components/communication.json` file, which is described as follows: 603 604 ``` 605 { 606 "component": "wifi_lite", 607 "targets": [ 608 "//foundation/communication/wifi_lite:wifi" --- Compilation target of the wifi_lite component. 609 ] 610 }, 611 ``` 612 613In this case, the `wifi` adaptation source code can be checked in `device/soc/winnermicro/wm800/board/src/wifi/wm_wifi.c`, which is shown below: 614 615 ``` 616 int tls_wifi_netif_add_status_event(tls_wifi_netif_status_event_fn event_fn) --- Used to add the wifi event function. 617 { 618 u32 cpu_sr; 619 struct tls_wifi_netif_status_event *evt; 620 //if exist, remove from event list first. 621 tls_wifi_netif_remove_status_event(event_fn); 622 evt = tls_mem_alloc(sizeof(struct tls_wifi_netif_status_event)); 623 if(evt==NULL) 624 return -1; 625 memset(evt, 0, sizeof(struct tls_wifi_netif_status_event)); 626 evt->status_callback = event_fn; 627 cpu_sr = tls_os_set_critical(); 628 dl_list_add_tail(&wifi_netif_status_event.list, &evt->list); 629 tls_os_release_critical(cpu_sr); 630 631 return 0; 632 } 633 ``` 634 635### systemabilitymgr Subsystem Adaptation 636To adapt the **systemabilitymgr** subsystem, you need to add the `samgr_lite` component to the `config.json` file, as shown below: 637 638 ``` 639 { 640 "subsystem": "systemabilitymgr", 641 "components": [ 642 { 643 "component": "samgr_lite" 644 } 645 ] 646 }, 647 ``` 648 649### utils Subsystem Adaptation 650 651To adapt the utils subsystem, you need to add the `kv_store` and `file` components to the `config.json` file, as shown below: 652 653 ``` 654 { 655 "subsystem": "utils", 656 "components": [ 657 { 658 "component": "kv_store", 659 "features": [ 660 "enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true" 661 ] 662 }, 663 { "component": "file", "features":[] } 664 ] 665 }, 666 ``` 667 668When the `kv_store` component is adapted, key-value pairs will be written to the file. In the lite system, file operation APIs include `POSIX` and `HalFiles`. 669The `POSIX` API is used for accessing the file system in the kernel. Therefore, you need to add `enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true` to `features`. 670 671### Startup Subsystem Adaptation 672 673To adapt the startup subsystem, you need to add the `bootstrap_lite` and `syspara_lite` components to the `config.json` file, as shown below: 674 675 ``` 676 { 677 "subsystem": "startup", 678 "components": [ 679 { 680 "component": "bootstrap_lite" 681 }, 682 { 683 "component": "syspara_lite", 684 "features": [ 685 "enable_ohos_startup_syspara_lite_use_posix_file_api = true", 686 "config_ohos_startup_syspara_lite_data_path = \"/data/\"" 687 ] 688 } 689 ] 690 }, 691 ``` 692 693When adapting the **bootstrap_lite** component, you need to manually add the following content to the link script file `device/soc/winnermicro/wm800/board/ld/w800/gcc_csky.ld`: 694 695 ``` 696 .zinitcall_array : 697 { 698 . = ALIGN(0x4) ; 699 PROVIDE_HIDDEN (__zinitcall_core_start = .); 700 KEEP (*(SORT(.zinitcall.core*))) 701 KEEP (*(.zinitcall.core*)) 702 PROVIDE_HIDDEN (__zinitcall_core_end = .); 703 . = ALIGN(0x4) ; 704 PROVIDE_HIDDEN (__zinitcall_device_start = .); 705 KEEP (*(SORT(.zinitcall.device*))) 706 KEEP (*(.zinitcall.device*)) 707 PROVIDE_HIDDEN (__zinitcall_device_end = .); 708 . = ALIGN(0x4) ; 709 PROVIDE_HIDDEN (__zinitcall_bsp_start = .); 710 KEEP (*(SORT(.zinitcall.bsp*))) 711 KEEP (*(.zinitcall.bsp*)) 712 PROVIDE_HIDDEN (__zinitcall_bsp_end = .); 713 . = ALIGN(0x4) ; 714 PROVIDE_HIDDEN (__zinitcall_sys_service_start = .); 715 KEEP (*(SORT(.zinitcall.sys.service*))) 716 KEEP (*(.zinitcall.sys.service*)) 717 PROVIDE_HIDDEN (__zinitcall_sys_service_end = .); 718 . = ALIGN(0x4) ; 719 PROVIDE_HIDDEN (__zinitcall_app_service_start = .); 720 KEEP (*(SORT(.zinitcall.app.service*))) 721 KEEP (*(.zinitcall.app.service*)) 722 PROVIDE_HIDDEN (__zinitcall_app_service_end = .); 723 . = ALIGN(0x4) ; 724 PROVIDE_HIDDEN (__zinitcall_sys_feature_start = .); 725 KEEP (*(SORT(.zinitcall.sys.feature*))) 726 KEEP (*(.zinitcall.sys.feature*)) 727 PROVIDE_HIDDEN (__zinitcall_sys_feature_end = .); 728 . = ALIGN(0x4) ; 729 PROVIDE_HIDDEN (__zinitcall_app_feature_start = .); 730 KEEP (*(SORT(.zinitcall.app.feature*))) 731 KEEP (*(.zinitcall.app.feature*)) 732 PROVIDE_HIDDEN (__zinitcall_app_feature_end = .); 733 . = ALIGN(0x4) ; 734 PROVIDE_HIDDEN (__zinitcall_run_start = .); 735 KEEP (*(SORT(.zinitcall.run*))) 736 KEEP (*(.zinitcall.run*)) 737 PROVIDE_HIDDEN (__zinitcall_run_end = .); 738 . = ALIGN(0x4) ; 739 PROVIDE_HIDDEN (__zinitcall_test_start = .); 740 KEEP (*(SORT(.zinitcall.test*))) 741 KEEP (*(.zinitcall.test*)) 742 PROVIDE_HIDDEN (__zinitcall_test_end = .); 743 . = ALIGN(0x4) ; 744 PROVIDE_HIDDEN (__zinitcall_exit_start = .); 745 KEEP (*(SORT(.zinitcall.exit*))) 746 KEEP (*(.zinitcall.exit*)) 747 PROVIDE_HIDDEN (__zinitcall_exit_end = .); 748 } > REGION_RODATA 749 ``` 750 751Adding the preceding content is because external APIs provided by `bootstrap_init` uses the segment injection mode and will be saved to the link segment. For details, see `utils/native/lite/include/ohos_init.h`. The following table lists the automatic initialization macros of main services. 752 753| API | Description | 754| ---------------------- | -------------------------------- | 755| SYS_SERVICE_INIT(func) | Entry for initializing and starting a core system service.| 756| SYS_FEATURE_INIT(func) | Entry for initializing and starting a core system feature.| 757| APP_SERVICE_INIT(func) | Entry for initializing and starting an application-layer service. | 758| APP_FEATURE_INIT(func) | Entry for initializing and starting an application-layer feature. | 759 760 761 762The **lib** file compiled using the loaded components needs to be manually add to the forcible link. 763 764If the `bootstrap_lite` component is configured in `vendor/hihope/neptune_iotlink_demo/config.json`: 765 766 ``` 767 { 768 "subsystem": "startup", 769 "components": [ 770 { 771 "component": "bootstrap_lite" 772 }, 773 ... 774 ] 775 }, 776 ``` 777 778The `bootstrap_lite` component will compile the `base/startup/bootstrap_lite/services/source/bootstrap_service.c` file. In this file, `SYS_SERVICE_INIT` is used to inject the `Init` function symbol to `__zinitcall_sys_service_start` and `__zinitcall_sys_service_end`. Since the `Init` function does not support explicit call, you need to forcibly link it to the final image, as shown below: 779 780 ``` 781 static void Init(void) 782 { 783 static Bootstrap bootstrap; 784 bootstrap.GetName = GetName; 785 bootstrap.Initialize = Initialize; 786 bootstrap.MessageHandle = MessageHandle; 787 bootstrap.GetTaskConfig = GetTaskConfig; 788 bootstrap.flag = FALSE; 789 SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); 790 } 791 SYS_SERVICE_INIT(Init); --- Forcible link to the generated lib file is required if SYS_INIT is used for startup. 792 ``` 793 794The `base/startup/bootstrap_lite/services/source/BUILD.gn` file describes `libbootstrap.a` generated in `out/neptune100/neptune_iotlink_demo/libs`, as shown below: 795 796 ``` 797 static_library("bootstrap") { 798 sources = [ 799 "bootstrap_service.c", 800 "system_init.c", 801 ] 802 ... 803 ``` 804 805 806When the `syspara_lite` component is adapted, system parameters will be written into the file for persistent storage. In the lite system, file operation APIs include **POSIX** and **HalFiles**. 807 808The **POSIX** API is used for accessing the file system in the kernel. Therefore, you need to add `enable_ohos_startup_syspara_lite_use_posix_file_api = true` to the **features** field. 809 810### XTS Subsystem Adaptation 811 812To adapt the XTS subsystem, add the following component options to `config.json`: 813 814 ``` 815 { 816 "subsystem": "xts", 817 "components": [ 818 { 819 "component": "xts_acts", 820 "features": 821 [ 822 "config_ohos_xts_acts_utils_lite_kv_store_data_path = \"/data\"", 823 "enable_ohos_test_xts_acts_use_thirdparty_lwip = true" 824 ] 825 }, 826 { "component": "xts_tools", "features":[] } 827 ] 828 } 829 ``` 830 831The XTS function is also organized using **list**. You can add or delete relevant modules in the `config.json` file. 832 833 ``` 834 "bin_list": [ 835 { 836 "enable": "true", 837 "force_link_libs": [ 838 "module_ActsParameterTest", 839 "module_ActsBootstrapTest", 840 "module_ActsDfxFuncTest", 841 "module_ActsHieventLiteTest", 842 "module_ActsSamgrTest", 843 "module_ActsUtilsFileTest", 844 "module_ActsKvStoreTest", 845 "module_ActsWifiServiceTest" 846 ] 847 } 848 ], 849 ``` 850 851The adaptation process of other components is similar to that of other vendors. 852