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.gn和domains/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 88 在BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a。 89 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 104 此BUILD.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.a。 208 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 265 在helloworld.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.a。 282 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