1、获取OH master系统底座

repo init -u git@gitcode.com:openharmony/manifest.git -b master --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
bash build/prebuilts_download.sh  (如执行不成功,可加上sudo权限)

 

2、iot connect 组件集成

1、使用git命令克隆communication_iot_connect复制到foundation/communication目录下,将文件夹名称修改为iot_connect。

2、在foundation/communication/iot_connect/iotc.gni修改如下配置

declare_args() {
  iot_connect_ble_support = true
  iot_connect_wifi_support = true
  iot_connect_kv_support = true
  iotc_connect_ble_net_cfg_support = true
  iotc_connect_wifi_cloud_support = true
  其他设置为false
  如
  iot_connect_ailife_support = false
  iot_connect_mbedtls_v2_support = false
  iot_connect_mbedtls_psk_support = false
  iot_connect_mbedtls_ccm_support = false
}
​
if (defined(ohos_lite)) {
    iot_connect_ble_support = true
    iot_connect_sle_support = false
}

3、在foundation/communication/iot_connect/adapter/adapter.gni中修改mbedtls库路径,

将gni文件内的所有的device/soc/hisilicon/hi3863v100/sdk_liteos/open_source/mbedtls/mbedtls_v3.1.0/include路径修改为 device/soc/hisilicon/ws63v100/sdk/open_source/mbedtls/mbedtls_v3.1.0/include

4、修改foundation/communication/iot_connect/adapter/os/cmsis2/iotc_os.c文件中,MS_PER_SECOND 常量修改为100(此tick频率是100Hz而非常见的1000Hz)

#ifndef MS_PER_SECOND
#define MS_PER_SECOND   100

5、进入foundation/communication/iot_connect/adapter/kv/oh_lite/iotc_kv.c进行如下修改,避免创建文件报错(hi3863不支持多级目录直接创建,需要手动创建目录)

uint32_t tagLen = strlen(tag);
if (tagLen > MAX_TAG_LEN) {
    IOTC_LOGE("tagLen[%u] out of range", tagLen);
    return IOTC_ERR_PARAM_INVALID;
}
​
int ret = fs_adapt_mkdir("/data");  //添加此处
ret = fs_adapt_mkdir("/data/app");  //添加此处
ret = fs_adapt_mkdir("/data/app/iotc");  //添加此处
ret = fs_adapt_mkdir(tag);  //添加此处

6、进入foundation/communication/iot_connect/core/infrastructure/utils/utils_mutex_ex.c,注释互斥锁创建,直接return(ws63v100锁的资源有限,若创建锁的话会导致编译失败,此处return)

bool UtilsExMutexLockInner(UtilsExMutex *mutex, uint32_t timeout, const char *func)
{
    return true; //添加此处
    if (mutex == NULL || func == NULL || mutex->mutexId == NULL) {
        IOTC_LOGW("param invalid");
        return false;
    } 
    …………
}
​
void UtilsExMutexUnlockInner(UtilsExMutex *mutex, const char *func)
{
    return;//添加此处
    if (mutex == NULL || func == NULL || mutex->mutexId == NULL) {
        IOTC_LOGW("param invalid");
        return;
    } 
    …………
}

7、进入foundation/communication/iot_connect/core/wifi/infrastructure/transport/coap/endpoint/coap_endpoint.c注释掉如下代码。(ws63v100锁的资源有限,若创建锁的话会导致编译失败,此处return)

/*
        endpoint->mutex = UtilsCreateExMutex();
        if (endpoint->mutex == NULL) {
            IOTC_LOGW("mutex create error");
            break;
        }
*/

8、进入foundation/communication/iot_connect/core/wifi/application/cloud/biz/m2m_cloud_ctl.c可以参考如下改法(云端下发的控制报文解析失败问题修改):

static int32_t BuildCloudCtlRespMsg(CoapEndpoint *endpoint, const CoapPacket *req, const SocketAddr *addr,
                                    const M2mCloudContext *ctx, IotcJson *respJson)
{
    int32_t ret = IOTC_OK;
    do {
        uint32_t seg = 0;
        const CoapOption *reqIdOpt = CoapUtilsFindOption(req,COAP_OPTION_TYPE_REQ_ID, &seg);
        if(reqIdOpt == NULL || seg != 1 || reqIdOpt -> value.data == NULL || reqIdOpt -> value.len == 0){
            ret = IOTC_CORE_WIFI_M2M_ERR_CLOUD_GET_OPT_REQ_ID;
            break;
        }
        const CoapOption *devIdOpt = CoapUtilsFindOption(req,COAP_OPTION_TYPE_DEV_ID, &seg);
        if(devIdOpt == NULL || seg != 1 || devIdOpt -> value.data == NULL || devIdOpt -> value.len == 0){
            ret = IOTC_CORE_WIFI_M2M_ERR_CLOUD_GET_OPT_DEV_ID;
            break;
        }
        const CoapOption *userIdOpt = CoapUtilsFindOption(req,COAP_OPTION_TYPE_USER_ID, &seg);
        if(userIdOpt == NULL || seg != 1 || userIdOpt -> value.data == NULL || userIdOpt -> value.len == 0){
            ret = IOTC_CORE_WIFI_M2M_ERR_CLOUD_GET_OPT_USER_ID;
            break;
        }
        const CoapOption *seqIdOpt = CoapUtilsFindOption(req,COAP_OPTION_TYPE_SEQ_NUM_ID, &seg);
        if(seqIdOpt == NULL || seg != 1 || seqIdOpt -> value.data == NULL || seqIdOpt -> value.len == 0){
            ret = IOTC_CORE_WIFI_M2M_ERR_CLOUD_GET_OPT_SEQ_NUM_ID;
            break;
        }
​
        const CoapOption options[] = {
            {COAP_OPTION_TYPE_ACCESS_TOKEN_ID, {(const uint8_t *)ctx->tokenInfo.access, strlen(ctx->tokenInfo.access)}},
            {COAP_OPTION_TYPE_REQ_ID, {(const uint8_t *)reqIdOpt->value.data, reqIdOpt->value.len}},
            {COAP_OPTION_TYPE_DEV_ID, {(const uint8_t *)devIdOpt->value.data, devIdOpt->value.len}},
            {COAP_OPTION_TYPE_USER_ID, {(const uint8_t *)userIdOpt->value.data, userIdOpt->value.len}},
            {COAP_OPTION_TYPE_SEQ_NUM_ID, {(const uint8_t *)seqIdOpt->value.data, seqIdOpt->value.len}},
        };
​
        CoapServerRespParam respParam = {
            .req = req,
            .type = COAP_MSG_TYPE_NCON,
            .code = COAP_RESPONSE_CODE_CONTENT,
            .opNum = ARRAY_SIZE(options),
            .options = options,
            .payload = NULL,
            .payloadBuilder = CoapUtilsBuildJsonPayloadFunc,
            .payloadUserData = respJson,
            .preSize = 0,
        };
        CoapPacket packet;
        ret = CoapServerSendResp(endpoint, &respParam, addr, &packet);
        if (ret != IOTC_OK) {
            IOTC_LOGW("send e2e ctrl resp msg error %d", ret);
        }
    } while (false);
    return ret;
}
​
/*    
    CoapResponeNode *respInfo = M2mCloudCreateCoapNode(endpoint, req, addr, ctx);
    if (respInfo == NULL) {
        IOTC_LOGW("create cloud resp node error");
        return IOTC_ERROR;
    }
*/

9、进入foundation/communication/iot_connect/core/wifi/infrastructure/transport/socket/trans_socket_udp.c(加入套接字会失败,且配网走的是tcp),注释掉以下内容:

/*
    ret = JoinMulticastGroup(fd, param);
    if (ret != IOTC_OK) {
        return ret;
    }
*/

10、进入foundation/communication/iot_connect/adapter/log/hilog_m/iotc_log.c(添加日志换行,日志才会规则显示)

void IotcLogOutputImpl(uint8_t level, const char *fileName,
    const char *funcName, uint32_t line, const char *fmt, ...)
{
    const char *tag[6] = {"IC_FATAL", "IC_ERROR", "IC_WARN", "IC_NOTICE", "IC_INFO", "IC_DEBUG"};
    (void)fmt;
    if (funcName != NULL) {
        printf("%s:%s:%u, ", tag[level - 1], funcName, line);
    } else {
        printf("%s:%s:%u, ", tag[level - 1], fileName != NULL ? fileName : "NULL", line);
    }
    printf("\r\n");     //添加换行,方便后面查看日志
}

3、ble 接口适配

1、clone communication_nearlink,将communication_nearlink中的openharmony/device/soc/hisilicon/hi3863v100/hi3863_adapter/hals/communication/bluetooth文件夹复制到OpenHarmony源码的device/soc/hisilicon/ws63v100/adapter/hals/communication目录下。

2、在\device\soc\hisilicon\ws63v100\sdk\BUILD.gn中更改为如下配置

lite_component("sdk") {
  features = []
​
  deps = [
    "//build/lite/config/component/cJSON:cjson_static",
    "//device/soc/hisilicon/ws63v100/adapter/hals/communication/bluetooth/services:btservice",
    "//device/soc/hisilicon/ws63v100/adapter/hals/communication/sle_lite",
    "//device/soc/hisilicon/ws63v100/adapter/hals/communication/wifi_lite/wifiservice",
​
    #   "//device/soc/hisilicon/ws63v100/adapter/kal",
  ]
}

 

3、在\device\soc\hisilicon\ws63v100\adapter\hals\communication\bluetooth\services\BUILD.gn中,将文件内所有的//device/soc/hisilicon/hi3863v100路径改为//device/soc/hisilicon/ws63v100,例如将//device/soc/hisilicon/hi3863v100/sdk_liteos/include/middleware/services/bts/ble改为//device/soc/hisilicon/ws63v100/sdk/include/middleware/services/bts/ble",文件路径都要对应起来。

 

4、lwip协议栈适配

1、foundation/communication/iot_connect/adapter/socket/iotc_socket.c路径下将原头文件替换成以下头文件

#include "lwip/inet.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "iotc_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include "securec.h"
#include "iotc_errcode.h"
#include "iotc_network.h"
#include "iotc_mem.h"
#include "iotc_log.h"
#include <sys/time.h>
// #include <arpa/inet.h>
// #include <unistd.h>
// #include <fcntl.h>

如果遇到fcntl或close接口未定义,把fcntl改为lwip_fcntl,close改为lwip_close

2、foundation/communication/iot_connect/adapter/socket/iotc_socket.c文件中的IotcSelect方法中,修改selectlwip_select (改为使用ws63v100 sdk实现的lwip_select去监听套接字,而不是直接使用系统的Select)

int32_t ret = select(maxFd + 1, (readSet == NULL) ? NULL : &read,
        (writeSet == NULL) ? NULL : &write,
        (exceptSet == NULL) ? NULL : &except, &timeout);
        
        修改为
        
int32_t ret = lwip_select(maxFd + 1, (readSet == NULL) ? NULL : &read,
        (writeSet == NULL) ? NULL : &write,
        (exceptSet == NULL) ? NULL : &except, &timeout);

 

5、ws63 sdk适配

1、进入device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/menuconfig/acore/ws63_liteos_app.config(hi3863不支持多级目录直接创建,需要手动创建目录,需要修改CONFIG_LFS_PARTITION_ID为0x21,手动创建才能生效)

CONFIG_LFS_PARTITION_ID=0x21

2、进入device/soc/hisilicon/ws63v100/sdk/open_source/lwip/lwip_adapter/liteos_207/src/arch/sys_arch.c注释掉加锁的地方(ws63v100锁的资源不够,创建锁会失败),如下所示

  mbox->first = 0;
  mbox->last = 0;
  mbox->is_full = 0;
  mbox->is_empty = 1;
  mbox->is_autoexpand = is_auto_expand;
​
//  ret = osal_mutex_init(&(mbox->mutex)); //注释掉这行
  ret = 0;      //添加ret = 0

3、进入device/soc/hisilicon/ws63v100/sdk/open_source/lwip/lwip_v2.1.3/src/api/tcpip.c为保证有足够时间清理tcpip资源,需要添加休眠时间,进行如下修改:

static void
tcpip_timeouts_mbox_fetch(sys_mbox_t *tbox, void **msg)
{
  u32_t sleeptime, res;
​
again:
  LWIP_ASSERT_CORE_LOCKED();
​
  sleeptime = sys_timeouts_sleeptime();
  if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {
    UNLOCK_TCPIP_CORE();
    sys_arch_mbox_fetch(tbox, msg, 0);
    LOCK_TCPIP_CORE();
    return;
  } else if (sleeptime == 0) {
    sys_check_timeouts();
    /* We try again to fetch a message from the mbox. */
    UNLOCK_TCPIP_CORE();   //新增
    sys_msleep(100);   //新增
    LOCK_TCPIP_CORE();  //新增
    goto again;
  }
​
  UNLOCK_TCPIP_CORE();
  res = sys_arch_mbox_fetch(tbox, msg, sleeptime);
  LOCK_TCPIP_CORE();
  if (res == SYS_ARCH_TIMEOUT) {
    /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred
       before a message could be fetched. */
    sys_check_timeouts();
    /* We try again to fetch a message from the mbox. */
    goto again;
  }
}
#endif /* !LWIP_TIMERS */
static void
tcpip_thread(void *arg)
{
  struct tcpip_msg *msg;
  LWIP_UNUSED_ARG(arg);
​
  LWIP_MARK_TCPIP_THREAD();
​
  LOCK_TCPIP_CORE();
  if (tcpip_init_done != NULL) {
    tcpip_init_done(tcpip_init_done_arg);
  }
​
  tcpip_init_finish = 1;   //@@@add  新增
​
  while (1) {                          /* MAIN Loop */
#if defined(LWIP_HI3861_THREAD_SLEEP) && LWIP_HI3861_THREAD_SLEEP
    UNLOCK_TCPIP_CORE();
    hi_cpup_load_check_proc(hi_task_get_current_id(), LOAD_SLEEP_TIME_DEFAULT);
    LOCK_TCPIP_CORE();
#endif
    LWIP_TCPIP_THREAD_ALIVE();
    /* wait for a message, timeouts are processed while waiting */
    TCPIP_MBOX_FETCH(MBOXPTR, (void **)&msg);
    if (msg == NULL) {
      LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
      LWIP_ASSERT("tcpip_thread: invalid message", 0);
      UNLOCK_TCPIP_CORE(); //新增
      sys_msleep(100);    //新增
      LOCK_TCPIP_CORE(); //新增
      continue;
    }
    tcpip_thread_handle_msg(msg);
  }
}

4、进入device/soc/hisilicon/ws63v100/adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件。(修改扫描信道和按wifi名扫描,才能扫描到wifi)

AdvanceScan修改如下:

    params->freqs = 2 ;     //新增
    sp.ssid_len = params->ssidLen;
    sp.scan_type = params->scanType;
    sp.channel_num = params->freqs;
    sp.scan_type = 2;       //新增
    
    hiRet = wifi_sta_scan_advance(&sp);
​
//添加这个修改才能扫描到wifi

ConnectTo函数修改如下(增加启动dhcp,获取ip地址):

    if (StaConnect(0, &assocReq, g_wifiConfigs[networkId].wapiPskType) != WIFI_SUCCESS) {
        if (UnlockWifiEventLock() != WIFI_SUCCESS) {
            return ERROR_WIFI_UNKNOWN;
        }
        return ERROR_WIFI_UNKNOWN;
    }
    if (UnlockWifiEventLock() != WIFI_SUCCESS) {
        return ERROR_WIFI_UNKNOWN;
    }
​
    StaSetWifiNetConfig(WIFI_CONNECTED);    //添加这行,才能启动dhcp,成功获取ip地址
​
    return WIFI_SUCCESS;

5、进入device/soc/hisilicon/ws63v100/adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件

这里的sdk的DispatchScanStateChangeEvent没有定义,注释掉DispatchScanStateChangeEvent函数调用

    for (int i = 0; i < WIFI_MAX_EVENT_SIZE; i++) {
        if (g_wifiEvents[i] == NULL) {
            continue;
        }
        // DispatchScanStateChangeEvent(NULL, g_wifiEvents[i], WIFI_STATE_NOT_AVAILABLE);
    }

6、进入device/soc/hisilicon/ws63v100/sdk/open_source/lwip/lwip_v2.1.3/src/include/lwip/sockets.h文件,ws63v100中将lwip_select重定向到了系统select。这样调用的就是系统select而不是自身实现的lwip_select了,需要将重定向注释掉。

// #define lwip_select       select
将这行注释掉,否则lwip_select调用的是系统select而不是ws63 SDk 自身实现的lwip_select

 

6、mbedtls修改

在third_party/mbedtls/port/config/config_liteos_m.h这个头文件中,打开MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES宏

#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES

 

7、集成WifiBleCombo的demo

获取hi3863平台 WiFi/BLE Combo demo,将wifi_ble_combo/hi3863文件夹复制到applications/sample/wifi-iot/app 目录下并改名为wifi_ble_demo

 

8、编译配置

1、\vendor/hihope/nearlink_dk_3863目录下的config.json中添加iot_connect模块

    {
      "subsystem": "communication",
      "components": [
        { "component": "iot_connect", "features":[] }
      ]
    }

2、\device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/config.py

添加如下配置,并删除’ble_lite‘ 、 'sle_lite'

{
    'ws63-liteos-app': {
        ...
        'ram_component': {
            ...
            'iotc','wifi_ble_combo','btservice',
        }
    }
}

3、\device/soc/hisilicon/ws63v100/sdk/libs_url/ws63/cmake/ohos.cmake

添加如下配置,并删除’ble_lite‘ 、'sle_lite'

(${TARGET_COMMAND} MATCHES "ws63-liteos-app")
set(COMPONENT_LIST
    ... "btservice"  "iotc" "wifi_ble_combo" )
endif()

4、\applications/sample/wifi-iot/app/BUILD.gn添加如下配置

lite_component("app") {
  features = [ "startup" ]
  features += [ "./wifi_ble_demo:wifi_ble_combo" ]   //添加这行
}

5、\build\lite\components\communication.json添加如下配置

    {
      "component": "iot_connect",
      "description": "iot_connect based on liteos-m and liteos-a.",
      "optional": "true",
      "dirs": [
        "foundation/communication/iot_connect"
      ],
      "targets": [
        "//foundation/communication/iot_connect:iotc_static"
      ],
      "rom": "",
      "ram": "",
      "output": [ ],
      "adapted_kernel": [ "liteos_m", "liteos_a" ],
      "features": [],
      "deps": {
        "third_party": [
        ],
        "kernel_special": {},
        "board_special": {},
        "components": [
        ]
      }
    }
​

6、工具链添加到环境变量

vim ~/.bashrc               # 编辑环境变量
export PATH=~/device/soc/hisilicon/ws63v100/sdk/tools/bin/compiler/riscv/cc_riscv32_musl_100/cc_riscv32_musl/bin     # 在环境变量的最后添加一行编译工具链路径信息
source ~/.bashrc            # 应用环境变量

 

9、编译和烧录

编译步骤

hb set
选择mini/hihope/nearlink_dk_3863
hb build -f

烧录参考ws63 官方文档

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐