• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 集成三方SDK<a name="ZH-CN_TOPIC_0000001051612018"></a>
2
3-   [规划目录结构](#section1736472718351)
4-   [构建业务libs](#section442815485351)
5-   [编写适配代码](#section3984721113613)
6-   [代码编写](#section830417531286)
7-   [脚本编写](#section13500201173710)
8-   [编写业务代码](#section8754114803918)
9-   [运行](#section7737749184012)
10-   [结束](#section153301392411)
11
12OpenHarmony致力于打造一套更加开放完善的IoT生态系统,为此OpenHarmony规划了一组目录,用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板,向平台开发者介绍将SDK集成到OpenHarmony的方法。
13
14## 规划目录结构<a name="section1736472718351"></a>
15
16三方SDK通常由静态库和适配代码构成。SDK的业务逻辑通过硬件模组工具链编译得到静态库libs,每款模组都有其对应的libs。SDK的南向API与OpenHarmony 的API存在使用差异,该差异可通过adapter适配代码屏蔽,不同模组可共用一套adapter。
17
18基于以上特征,在OpenHarmony目录结构中,可以对三方SDK目录做如下划分。
19
20-   适配代码adapter,放置到domains/iot/link/ 目录下,与模组解耦。
21-   业务库libs,放置到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/ 目录下,与模组绑定。
22
23平台开发者在适配前,务必先依次完成以下步骤,下面以demolink SDK举例,进行介绍。
24
251.  创建厂商目录,domains/iot/link/demolink/、device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/ ,用于厂商隔离。
262.  创建domains/iot/link/demolink/BUILD.gn ,用于构建适配代码。
273.  创建device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录,用于存放业务库libs。
28
29```
30.
31├── domains
32│   └── iot
33│       └── link
34│           ├── demolink
35│           │   └── BUILD.gn
36│           ├── libbuild
37│           │   └── BUILD.gn
38│           └── BUILD.gn
39└── device
40     └── hisilicon
41         └── hispark_pegasus
42             └── sdk_liteos
43                 └── 3rd_sdk
44                     └── demolink
45                         └── libs
46```
47
48## 构建业务libs<a name="section442815485351"></a>
49
50平台SDK业务一般以静态库的形式提供,平台厂商在获取到OpenHarmony代码后,需要根据对应的硬件模组vendor,编译业务libs,并将编译结果放置在device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下。下面介绍业务libs的构建方法。
51
52OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ ,该目录中包含domains/iot/link/libbuild/BUILD.gndomains/iot/link/BUILD.gn文件,目录结构如下。
53
54```
55.
56└── domains
57    └── iot
58        └── link
59            ├── demolink
60            │   └── BUILD.gn
61            ├── libbuild
62            │   └── BUILD.gn
63            └── BUILD.gn
64```
65
66平台开发者在构建libs前,务必先完成如下步骤。
67
681.  在domains/iot/link/libbuild/ 目录下放置业务源码文件,包括.c和.h文件。
69
70    ```
71    .
72    └── domains
73        └── iot
74            └── link
75                ├── demolink
76                │   ├── demosdk_adapter.c
77                │   ├── demosdk_adapter.h
78                │   └── BUILD.gn
79                ├── libbuild
80                │   ├── demosdk.c
81                │   ├── demosdk.h
82                │   └── BUILD.gn
83                └── BUILD.gn
84    ```
85
862.  适配domains/iot/link/libbuild/BUILD.gn,在编译完成后还原该文件。
87
88BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a89
90    ```
91    static_library("demosdk") {
92        sources = [
93            "demosdk.c"
94        ]
95        include_dirs = [
96            "//domains/iot/link/libbuild",
97            "//domains/iot/link/demolink"
98        ]
99    }
100    ```
101
1023.  适配domains/iot/link/BUILD.gn,在编译完成后还原该文件。
103
104BUILD.gn文件用于指定构建条目,需要在features中填入所有需参与编译的静态库条目,使domains/iot/link/libbuild/BUILD.gn参与到构建中来。
105
106    ```
107    import("//build/lite/config/subsystem/lite_subsystem.gni")
108    import("//build/lite/config/component/lite_component.gni")
109    lite_subsystem("iot") {
110        subsystem_components = [
111            ":link"
112        ]
113    }
114    lite_component("link") {
115        features = [
116            "libbuild:demosdk"
117        ]
118    }
119    ```
120
121
122完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。
123
124![](figures/device-wlan-sdk-files.png)
125
126将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。
127
128## 编写适配代码<a name="section3984721113613"></a>
129
130## 代码编写<a name="section830417531286"></a>
131
132平台SDK中使用的API通常与OpenHarmony API存在差异,无法直接使用,需要一层适配代码adapter进行中间转换。本节以domains/iot/link/demolink/demosdk\_adapter.c中的任务创建接口DemoSdkCreateTask举例,向开发者演示如何在OpenHarmony上编写适配代码。
133
1341.  查看待适配接口DemoSdkCreateTask的描述、参数、返回值。
135
136    ```
137    struct TaskPara {
138        char *name;
139        void *(*func)(char* arg);
140        void *arg;
141        unsigned char prio;
142        unsigned int size;
143    };
144
145    /*
146     * IoT OS 创建线程接口
147     * 返回值: 返回0 成功, 其他 失败
148     */
149    int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para);
150    ```
151
1522.  查看OpenHarmony API接口文档,选取一个功能类似的接口,并比对参数及用法上的差异。例如本文选取osThreadNew ,通过和DemoSdkCreateTask接口比对,可以发现两接口依赖的参数基本一致,只是参数所归属的结构体不同。
153
154    ```
155    typedef struct {
156        const char                   *name;   ///< name of the thread
157        uint32_t                 attr_bits;   ///< attribute bits
158        void                      *cb_mem;    ///< memory for control block
159        uint32_t                   cb_size;   ///< size of provided memory for control block
160        void                   *stack_mem;    ///< memory for stack
161        uint32_t                stack_size;   ///< size of stack
162        osPriority_t              priority;   ///< initial thread priority (default: osPriorityNormal)
163        TZ_ModuleId_t            tz_module;   ///< TrustZone module identifier
164        uint32_t                  reserved;   ///< reserved (must be 0)
165    } osThreadAttr_t;
166
167    /// Create a thread and add it to Active Threads.
168    /// \param[in]     func          thread function.
169    /// \param[in]     argument      pointer that is passed to the thread function as start argument.
170    /// \param[in]     attr          thread attributes; NULL: default values.
171    /// \return thread ID for reference by other functions or NULL in case of error.
172    osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);
173    ```
174
1753.  完成代码差异转换。
176
177    ```
178    int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para)
179    {
180        osThreadAttr_t attr = {0};
181        osThreadId_t threadId;
182        if (handle == 0 || para == 0) {
183            return DEMOSDK_ERR;
184        }
185        if (para->func == 0) {
186            return DEMOSDK_ERR;
187        }
188        if (para->name == 0) {
189            return DEMOSDK_ERR;
190        }
191        attr.name = para->name;
192        attr.priority = para->prio;
193        attr.stack_size = para->size;
194        threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr);
195        if (threadId == 0) {
196            printf("osThreadNew fail\n");
197            return DEMOSDK_ERR;
198        }
199        *(unsigned int *)handle = (unsigned int)threadId;
200        return DEMOSDK_OK;
201    }
202    ```
203
204
205## 脚本编写<a name="section13500201173710"></a>
206
207开发者在完成代码适配后,还需要在adapter同级目录下新建BUILD.gn文件。该文件可在整包构建时,将适配代码编译成静态库,并链接到bin包中去。在domains/iot/link/demolink/BUILD.gn中,sources中为需要参与构建的源文件,include\_dirs中为依赖的头文件路径,构建目标结果是生产静态库libdemolinkadapter.a208
209```
210import("//build/lite/config/component/lite_component.gni")
211static_library("demolinkadapter") {
212    sources = [
213        "demosdk_adapter.c"
214    ]
215    include_dirs = [
216        "//kernel/liteos-m/kal/cmsis",
217        "//domains/iot/link/demolink"
218    ]
219}
220```
221
222修改domains/iot/link/BUILD.gn文件,使domain/iot/hilink/BUILD.gn参与到构建系统中。
223
224```
225import("//build/lite/config/subsystem/lite_subsystem.gni")
226import("//build/lite/config/component/lite_component.gni")
227lite_subsystem("iot") {
228    subsystem_components = [
229        ":link"
230    ]
231}
232lite_component("link") {
233    features = [
234        "demolink:demolinkadapter"
235    ]
236}
237```
238
239## 编写业务代码<a name="section8754114803918"></a>
240
241业务libs库和适配代码准备就绪后,还需要编写业务入口函数,调起三方SDK的业务入口。
242
243下面以demolink举例,介绍如何在applications/sample/wifi-iot/app/路径下编写代码,调起demosdk的入口函数。
244
2451.  目录创建
246
247    开发者编写业务时,务必先在applications/sample/wifi-iot/app/ 路径下新建一个目录(或一套目录结构),用于存放业务源码文件。
248
249    例如:在app下新增业务目录demolink,并在其中创建业务入口代码helloworld.c和编译构建文件BUILD.gn,如下。
250
251    ```
252    .
253    └── applications
254        └── sample
255            └── wifi-iot
256                └── app
257                    │── demolink
258                    │    │── helloworld.c
259                    │    └── BUILD.gn
260                    └── BUILD.gn
261    ```
262
2632.  编写业务代码。
264
265helloworld.c文件中编写业务入口函数DemoSdkMain,并调起demolink的业务DemoSdkEntry,最后通过SYS\_RUN\(\)调用入口函数完成业务启动。
266
267    ```
268    #include "hos_init.h"
269    #include "demosdk.h"
270
271    void DemoSdkMain(void)
272    {
273        DemoSdkEntry();
274    }
275
276    SYS_RUN(DemoSdkMain);
277    ```
278
2793.  编写构建脚本
280
281    新增applications/sample/wifi-iot/app/demolink/BUILD.gn文件,指定源码和头文件路径,编译输出静态库文件libexample\_demolink.a282
283    ```
284    static_library("example_demolink") {
285        sources = [
286            "helloworld.c"
287        ]
288        include_dirs = [
289            "//utils/native/lite/include",
290            "//domains/iot/link/libbuild"
291        ]
292    }
293    ```
294
295    修改applications/sample/wifi-iot/app/BUILD.gn,使demolink参与编译。
296
297    ```
298    import("//build/lite/config/component/lite_component.gni")
299    lite_component("app") {
300        features = [
301            "demolink:example_demolink"
302        ]
303    }
304    ```
305
306
307## 运行<a name="section7737749184012"></a>
308
309在代码根目录下,执行命令“hb build”编译输出版本包。最后启动运行,运行结果如图所示,与demolink预期相符。
310
311```
312ready to OS start
313sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00
314formatting spiffs...
315FileSystem mount ok.
316wifi init success!
317it is demosdk entry.
318it is demo biz: hello world.
319it is demo biz: hello world.
320```
321
322## 结束<a name="section153301392411"></a>
323
324至此,三方SDK集成已介绍完毕。
325
326