• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Standard System Porting Guide
2
3
4This document describes the general process for porting a development board, rather than the porting process specific to a System on Chip (SoC). In the future, the community will provide more development board porting examples for your reference.
5
6
7## Defining a Development Board
8
9This document uses the process of porting a development board named **MyProduct** as an example. This development board is provided by **MyProductVendor** and uses the SoC **MySOC** produced by **MySoCVendor**.
10
11
12### Defining a Product
13
14Create a file named **config.json** in the **//vendor/MyProductVendor/*{product_name}*** directory. This file is used to describe the SoC used by the product and the required subsystems. For example, if **product_name** is **MyProduct**, configure the **//vendor/MyProductVendor/MyProduct/config.json** file as follows:
15
16//vendor/MyProductVendor/MyProduct/config.json
17
18
19```
20{
21    "product_name": "MyProduct",
22    "version": "3.0",
23    "type": "standard",
24    "target_cpu": "arm",
25    "ohos_version": "OpenHarmony 1.0",
26    "device_company": "MyProductVendor",
27    "board": "MySOC",
28    "enable_ramdisk": true,
29    "subsystems": [
30      {
31        "subsystem": "ace",
32        "components": [
33          { "component": "ace_engine_lite", "features":[""] }
34        ]
35      },
3637    ]
38}
39
40
41```
42The main configurations are as follows:
43
44**product_name**: product name. This parameter is required.
45
46**version**: version. This parameter is required.
47
48**type**: system level, such as **small** or **standard**. This parameter is required.
49
50**target_cpu**: CPU type of the device, such as **arm64**, **riscv**, or **x86**. This parameter is required.
51
52**ohos_version**: operating system version. This parameter is optional.
53
54**device_company**: device manufacturer name. This parameter is required.
55
56**board**: board name. This parameter is required.
57
58**enable_ramdisk**: whether to enable the RAM disk. This parameter is required.
59
60**kernel_type**: kernel type. This parameter is optional.
61
62**kernel_version**: kernel version. This parameter is optional. Both **kernel_type** and **kernel_version** are fixed.
63
64**subsystems**: subsystem to enable. A subsystem can be treated as an independently built functional block. This parameter is required.
65
66**product_company**: device manufacturer name. It is not set in the configuration, but in the directory name, next to the vendor name. It can be accessed from **build.gn script**.
67
68
69You can find predefined subsystems in **//build/subsystem_config.json**. You can also customize subsystems.
70
71You are advised to copy the configuration file of Hi3516D V300 and delete the **hisilicon_products** subsystem, which is used to compile the kernel for Hi3516D V300.
72
73
74### Verifying the Porting
75
76  Run the following command to start the build of your product:
77
78```
79./build.sh --product-name MyProduct
80```
81
82After the build is complete, you can view the built image file in **//out/{*device_name*}/packages/phone/images**.
83
84
85## Porting the Kernel
86
87Now, you need to port the Linux kernel to enable it to run successfully.
88
89
90### Adding a Kernel-built Subsystem to the SoC
91
92Add the following subsystem configuration to the **//build/subsystem_config.json** file:
93
94
95```
96  "MySOCVendor_products": {
97    "project": "hmf/MySOCVendor_products",
98    "path": "device/MySOCVendor/MySOC/build",
99    "name": "MySOCVendor_products",
100    "dir": "device/MySOCVendor"
101  },
102```
103
104Then, open the configuration file **//vendor/MyProductVendor/MyProduct/config.json** and add the new subsystem to the product.
105
106
107### Building the Kernel
108
109The OpenHarmony source code provides the Linux kernel 4.19, which is archived in **//kernel/linux-4.19**. This section uses this kernel version as an example to describe how to build the kernel.
110
111The path for building the subsystem is defined when you define the subsystem in the previous step. In this example, the path is `//device/MySOCVendor/MySOC/build`. Now, you need to create a build script in this path to instruct the build system to build the kernel.
112
113The recommended directory structure is as follows:
114
115
116```
117├── build
118│ ├── kernel
119│ │     ├── linux
120│ │           ├──standard_patch_for_4_19.patch // Patch for the Linux kernel 4.19
121│ ├── BUILD.gn
122│ ├── ohos.build
123```
124
125The **BUILD.gn** file is the only entry for building the subsystem.
126
127The expected build result described in the table below.
128
129| File| Description|
130| -------- | -------- |
131| $root_build_dir/packages/phone/images/uImage | Kernel image.|
132| $root_build_dir/packages/phone/images/uboot | Bootloader image.|
133
134
135### Verifying the Porting
136
137Now start build, and check whether the kernel image is generated as expected.
138
139## User-mode Boot
140
1411. Overview of user-mode boot process
142
143![user-mode boot](figures/user-mode boot.png)
144
145   When the system is powered on, the kernel loads and starts services and applications as follows:
146
1471. The kernel loads the init process, which is specified by **cmdline** of the kernel when the bootloader starts the kernel, for example, **init=/init root/dev/xxx**.
1482. After the init process is started, **tmpfs** and **procfs** are mounted and basic **dev** nodes are created to establish a basic root file system.
1493. The init process starts the ueventd process to listen for device hot-swap events in the kernel and creates **dev** nodes for related devices as well as partitions for the block device.
1504. After mounting partitions (**system** and **vendor**) of the block device, the init process scans for the init startup script of each system service and launches the respective service ability (SA).
1515. Each SA registers with the samgr process, which serves as the service registration center. The samgr process assigns each SA with an ID, which will be used by an application to access the desired SA.
1526. The foundation process implements application lifecycle management. It is a special SA service process that provides the user program management framework and basic services.
1537. The appspawn process directly spawns the application process, eliminating the need for the application to load the JS runtime environment. This reduces the application startup time.
154
1552. init module
156
157   The configuration file of the init module contains service names, executable file paths, permissions, and other information of all key system services that need to be started by the init process. The boot script of each system service is installed in the **/system/etc/init** directory.
158
159   When porting a new chip platform, you need to add the **/vendor/etc/init/init.{hardware}.cfg** file that contains the platform-level initialization configuration. This file is used to implement platform-level initialization, for example, installing the ko driver and configuring information on the related **/proc** nodes.
160
161   The code of the init process is stored in the **//base/startup/init** directory. This process is the first process in the system and does not depend on other processes.
162
163   For details about how to develop the initialization configuration file, see [Startup](../subsystems/subsys-boot-overview.md).
164
165
166## Porting the HDF Driver
167
168
169### LCD
170
171This section describes how to port a Liquid Crystal Display (LCD) driver. The hardware driver framework (HDF) designs a driver model for the LCD. To support an LCD, you must compile a driver, generate a model instance in the driver, and register the instance.
172
173The LCD drivers are stored in the **//drivers/framework/model/display/driver/panel** directory.
174
175- Create a panel driver.
176
177  In the **Init** method of the driver, call **RegisterPanel** to register the model instance.
178
179
180```
181int32_t XXXInit(struct HdfDeviceObject *object)
182{
183    struct PanelData *panel = CreateYourPanel();
184
185    // Registration
186    if (RegisterPanel(panel) != HDF_SUCCESS) {
187        HDF_LOGE("%s: RegisterPanel failed", __func__);
188        return HDF_FAILURE;
189    }
190    return HDF_SUCCESS;
191}
192
193struct HdfDriverEntry g_xxxxDevEntry = {
194    .moduleVersion = 1,
195    .moduleName = "LCD_XXXX",
196    .Init = XXXInit,
197};
198
199HDF_INIT(g_xxxxDevEntry);
200```
201
202- Configure and load the panel driver. All device information about the product is defined in the **//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs** file. Modify the file by adding configurations for the device named **device_lcd** to the host named **display**. Note: The value of **moduleName** must be the same as that in the panel driver.
203
204
205```
206root {
207    ...
208    display :: host {
209        device_lcd :: device {
210            deviceN :: deviceNode {
211                policy = 0;
212                priority = 100;
213                preload = 2;
214                moduleName = "LCD_XXXX";
215            }
216        }
217    }
218}
219```
220
221For details about driver development, see [LCD](../driver/driver-peripherals-lcd-des.md).
222
223
224### Touchscreen
225
226This section describes how to port a touchscreen driver. The touchscreen driver is stored in the **//drivers/framework/model/input/driver/touchscreen** directory. To port a touchscreen driver, register a **ChipDevice** model instance.
227
228- Create a touchscreen driver.
229
230  Create the **touch_ic_name.c** file in the directory. Replace **ic_name** with the name of your chip. The file template is as follows:
231
232
233```
234#include "hdf_touch.h"
235
236static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device)
237{
238    ChipDevice *tpImpl = CreateXXXXTpImpl();
239    if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) {
240        ReleaseXXXXTpImpl(tpImpl);
241        return HDF_FAILURE;
242    }
243    return HDF_SUCCESS;
244}
245
246struct HdfDriverEntry g_touchXXXXChipEntry = {
247    .moduleVersion = 1,
248    .moduleName = "HDF_TOUCH_XXXX",
249    .Init = HdfXXXXChipInit,
250};
251
252HDF_INIT(g_touchXXXXChipEntry);
253```
254
255Implement the following APIs in **ChipDevice**:
256
257| API| Description|
258| -------- | -------- |
259| int32_t (\*Init)(ChipDevice \*device) | Initializes a touchscreen.|
260| int32_t (\*Detect)(ChipDevice \*device) | Detects a touchscreen.|
261| int32_t (\*Suspend)(ChipDevice \*device) | Suspends a touchscreen.|
262| int32_t (\*Resume)(ChipDevice \*device) | Resumes a touchscreen.|
263| int32_t (\*DataHandle)(ChipDevice \*device) | Reads data from a touchscreen and writes the touch point data to **device** > **driver** > **frameData**.|
264| int32_t (\*UpdateFirmware)(ChipDevice \*device) | Upgrades the firmware.|
265
266- Configure the product and load the driver.
267
268  All device information about the product is defined in the **//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs** file. Modify the file by adding configurations for the device named **device_touch_chip** to the host named **input**. Note: The value of **moduleName** must be the same as that in the touchscreen driver.
269
270```
271                deviceN :: deviceNode {
272                    policy = 0;
273                    priority = 130;
274                    preload = 0;
275                    permission = 0660;
276                    moduleName = "HDF_TOUCH_XXXX";
277                    deviceMatchAttr = "touch_XXXX_configs";
278                }
279```
280
281For details about driver development, see [Touchscreen](../driver/driver-peripherals-touch-des.md).
282
283
284### WLAN
285
286The WLAN driver is divided into two parts. One of the parts manages WLAN devices, and the other part manages WLAN traffic. HDF WLAN provides abstraction for the two parts. Currently, only the WLAN with the SDIO interface is supported.
287
288**Figure 1** WLAN chip
289
290![hdf_wifi](figures/hdf_wifi.png)
291
292To support a chip, implement a **ChipDriver** for it. The major task is to implement the following interfaces provided by **HDF_WLAN_CORE** and **NetDevice**.
293
294| API| Header File| Description|
295| -------- | -------- | -------- |
296| HdfChipDriverFactory | //drivers/framework/include/wifi/hdf_wlan_chipdriver_manager.h | Supports multiple WLAN interfaces of a chip.|
297| HdfChipDriver | //drivers/framework/include/wifi/wifi_module.h | Manages a specific WLAN interface. Each WLAN interface corresponds to an **HdfChipDriver**.|
298| NetDeviceInterFace | //drivers/framework/include/net/net_device.h | Communicates with the protocol stack, such as sending data and setting the status of network interfaces.|
299
300To port a WLAN driver, perform the following steps:
301
3021. Create an HDF driver. You are advised to place the code file in the **//device/MySoCVendor/peripheral/wifi/chip_name/** directory. The file template is as follows:
303
304
305```
306static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) {
307    static struct HdfChipDriverFactory factory = CreateChipDriverFactory();
308    struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr();
309    if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) {
310        HDF_LOGE("%s fail: driverMgr is NULL!", __func__);
311        return HDF_FAILURE;
312    }
313    return HDF_SUCCESS;
314}
315
316struct HdfDriverEntry g_hdfXXXChipEntry = {
317    .moduleVersion = 1,
318    .Init = HdfWlanXXXChipDriverInit,
319    .Release = HdfWlanXXXChipRelease,
320    .moduleName = "HDF_WIFI_CHIP_XXX"
321};
322
323HDF_INIT(g_hdfXXXChipEntry);
324```
325
326Create an **HdfChipDriverFactory** in the **CreateChipDriverFactory**. The APIs are as follows:
327
328| API| Description|
329| -------- | -------- |
330| const char \*driverName | Indicates the driver name.|
331| int32_t (\*InitChip)(struct HdfWlanDevice \*device) | Initializes a chip.|
332| int32_t (\*DeinitChip)(struct HdfWlanDevice \*device) | Deinitializes a chip.|
333| void (*ReleaseFactory)(struct HdfChipDriverFactory *factory) | Releases the **HdfChipDriverFactory** object.|
334| struct HdfChipDriver *(_Build)(struct HdfWlanDevice \*device, uint8*t ifIndex) | Creates an **HdfChipDriver**. In the input parameters, **device** indicates the device information, and **ifIndex** indicates the sequence number of this interface in the chip.|
335| void (*Release)(struct HdfChipDriver *chipDriver) | Releases the **HdfChipDriver**.|
336| uint8_t (\*GetMaxIFCount)(struct HdfChipDriverFactory \*factory) | Obtains the maximum number of APIs supported by the current chip.|
337
338Implement the following APIs in the **HdfChipDriver**.
339
340| API| Description|
341| -------- | -------- |
342| int32_t (\*init)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | Initializes the current network interface. The **NetDeviceInterFace** needs to be provided for the **netDev**.|
343| int32_t (\*deinit)(struct HdfChipDriver \*chipDriver, NetDevice \*netDev) | Deinitializes the current network interface.|
344| struct HdfMac80211BaseOps \*ops | Provides the WLAN basic capability interface set.|
345| struct HdfMac80211STAOps \*staOps | Provides the interface set required for supporting the standalone (STA) mode.|
346| struct HdfMac80211APOps \*apOps | Provides the interface set required for supporting the access point (AP) mode.|
347
3482. Compile the configuration file to describe the devices supported by the driver.
349
350   Create the chip configuration file **//vendor/MyProductVendor/MyProduct/config/wifi/wlan_chip_chip_name.hcs** in the product configuration directory.
351
352   Replace **MyProductVendor**, **MyProduct**, and **chip_name** in the path with the actual names.
353
354   The sample code is as follows:
355
356
357```
358root {
359    wlan_config {
360        chip_name :& chipList {
361            chip_name :: chipInst {
362                match_attr = "hdf_wlan_chips_chip_name"; /* Configure the matching attribute, which is used to provide the configuration root of the driver.*/
363                driverName = "driverName"; /* The value must be the same as that of driverName in HdfChipDriverFactory.*/
364                sdio {
365                    vendorId = 0x0296;
366                    deviceId = [0x5347];
367                }
368            }
369        }
370    }
371}
372```
373
3743. Edit the configuration file and load the driver.
375
376   All device information about the product is defined in the **//vendor/MyProductVendor/MyProduct/config/device_info/device_info.hcs** file. Modify the file by adding configurations for the device named **device_wlan_chips** to the host named **network**. Note: The value of **moduleName** must be the same as that in the touchscreen driver.
377
378
379```
380                deviceN :: deviceNode {
381                    policy = 0;
382                    preload = 2;
383                    moduleName = "HDF_WLAN_CHIPS";
384                    deviceMatchAttr = "hdf_wlan_chips_chip_name";
385                    serviceName = "driverName";
386                }
387```
388
3894. Build the driver.
390
391- Create a kernel configuration menu. Create a **Kconfig** file in the **//device/MySoCVendor/peripheral** directory. The file template is as follows:
392
393```
394config DRIVERS_WLAN_XXX
395    bool "Enable XXX WLAN Host driver"
396    default n
397    depends on DRIVERS_HDF_WIFI
398    help
399      Answer Y to enable XXX Host driver. Support chip xxx
400```
401
402Add the following sample code to the end of the **//drivers/adapter/khdf/linux/model/network/wifi/Kconfig** file to add the configuration menu to the kernel:
403
404
405```
406source "../../../../../device/MySoCVendor/peripheral/Kconfig"
407```
408
409- Create a build script.
410
411Add the following configuration to the end of the **//drivers/adapter/khdf/linux/model/network/wifi/Makefile** file:
412```
413HDF_DEVICE_ROOT := $(HDF_DIR_PREFIX)/../device
414obj-$(CONFIG_DRIVERS_WLAN_XXX) += $(HDF_DEVICE_ROOT)/MySoCVendor/peripheral/build/standard/
415```
416
417When **DRIVERS_WLAN_XXX** is enabled in the kernel, **makefile** in **//device/MySoCVendor/peripheral/build/standard/** is called. For details about the development, see [LED Peripheral Control](../guide/device-wlan-led-control.md).
418