OpenHarmony 2.0 Canary 的 IoT硬件子系统 原创 精华

liangkz_梁开祝
发布于 2021-7-22 10:36
浏览
5收藏

OpenHarmony 2.0 Canary 的 IoT硬件子系统

liangkz 2021.07.22

 

前文《Hi3861_WiFi IoT工程:理解IoT外设控制模块》是基于DevEco IDE的HPM工具下载和安装的“@ohos/wifi_iot”工程(下文的D_Hi3861项目)所做出的一些分析,但这个工程,看上去是在非常久远以前的鸿蒙系统裁剪出来的,鸿蒙系统在不停地优化和调整,但这个工程并没有同步更新,所以最新的鸿蒙系统master分支(Canary)或者LTS分支(下文的A_Master/B_LTS项目),很多子系统/组件的结构和API等,都与“@ohos/wifi_iot”工程的代码有很大差异,最明显的例子之一,是这个IoT硬件子系统部分的差异。

 

先看一下IoT硬件子系统在D_Hi3861项目和A_Master/B_LTS项目的相关目录结构的差异,如下表:

OpenHarmony 2.0 Canary 的 IoT硬件子系统-鸿蒙开发者社区

OpenHarmony 2.0 Canary 的 IoT硬件子系统-鸿蒙开发者社区

通过两个表格的对比(以及更细致的具体的代码对比),可以明显看出,A_Master/B_LTS项目的API实现和调用层次比D_Hi3861项目的少了一层,相对简洁了不少。

A_Master/B_LTS项目中,在framework层只提供接口的声明,而对接口的实现则直接由芯片/平台的适配层调用硬件驱动的相关接口来操作硬件来完成,当需要适配别的芯片时,只需要在芯片的适配层完成实现即可,不需要改动framework的任何东西。

而在framework声明的API,相关文件/API的命名,也从D_Hi3861项目的wifiiot_xxx改为A_Master/B_LTS项目的iot_xxx,基本上是重新写了一遍,需要注意的是,有部分在D_Hi3861项目中存在的API,不清楚什么原因,在A_Master/B_LTS项目上没有实现,下面的例子会提到,需要我们开发者根据需要来自己实现

 

我们看一下B_LTS项目的官方的示例程序://applications/sample/wifi-iot/app/iothardware/led_example.c

增加一点简单的代码,通过开发板上的USER按键来实现切换LED1灯的亮灯模式。

通过查看原理图,可以知道Hi3861开发板上的USER按键是连接在主芯片的GPIO5上,这个GPIO5是一个可复用的IO口。系统在上电时会根据CONFIG_UART1_SUPPORT的配置,默认将其配置为uart1 串口的一个信号引脚,见B_LTS/device/hisilicon/hispark_pegasus/sdk_liteos/app/wifiiot_app/init/app_io_init.c 的:

hi_void app_io_init(hi_void)

{

......

#ifdef CONFIG_UART1_SUPPORT

    /* uart1 AT命令串口 */

    hi_io_set_func(HI_IO_NAME_GPIO_5, HI_IO_FUNC_GPIO_5_UART1_RXD); /* uart1 rx */

    hi_io_set_func(HI_IO_NAME_GPIO_6, HI_IO_FUNC_GPIO_6_UART1_TXD); /* uart1 tx */

#endif

......

}

“CONFIG_UART1_SUPPORT”定义在B_LTS/device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk 文件内。

备份该文件后打开它,找到“CONFIG_UART1_SUPPORT=y”,行首加“#”将其注释掉,不编译uart1功能即可。

如果是D_Hi3861项目,则上述文件分别位于:

D_Hi3861/vendor/hisi/hi3861/hi3861/app/wifiiot_app/init/app_io_init.c

D_Hi3861/vendor/hisi/hi3861/hi3861/build/config/usr_config.mk

 

打开//applications/sample/wifi-iot/app/ 目录下的BUILD.gn,在features列表中增加"iothardware:led_example"让led_example参与编译,这里需要注意格式,只能用空格键,不能用Tab键:

lite_component("app") {

    features = [

        "startup",

        "iothardware:led_example",

    ]

}

打开led_example.c文件,在LedExampleEntry()函数前增加GPIO5的宏定义以及响应USER按键中断的回调函数的定义:

#define IOT_IO_NAME_GPIO_5  (5)   //USR buttom
static void UsrBtnDetect(char *arg)
{
    (void)arg;
    g_ledState = (g_ledState+1)%LED_MAX;  //LED_MAX define to 3
    return;
}

在LedExampleEntry()函数内,GPIO9初始化的下面,增加:

/////////////////////////////////////
    IoTGpioInit(IOT_IO_NAME_GPIO_5);
    IoTGpioSetFunc(IOT_IO_NAME_GPIO_5, 0);    //0-HI_IO_FUNC_GPIO_5_GPIO
    IoTGpioSetDir(IOT_IO_NAME_GPIO_5, IOT_GPIO_DIR_IN);
    IoTGpioSetPull(IOT_IO_NAME_GPIO_5, HI_IO_PULL_UP);    //1
    IoTGpioRegisterIsrFunc( IOT_IO_NAME_GPIO_5,     
                                           IOT_INT_TYPE_EDGE,             //边沿触发
                                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,  //下降沿触发
                                           UsrBtnDetect,                   //下降沿触发中断调用回调函数处理
                                           NULL); 
/////////////////////////////////////

因为IoTGpioSetFunc()和IoTGpioSetPull()两个函数在A_Master/B_LTS项目中并没有定义和实现,需要我们自己参考D_Hi3861的代码,添加定义和实现,如下:

打开B_LTS/base/iot_hardware/peripheral/interfaces/kits/iot_gpio.h 头文件,在文件末尾添加这两个函数的声明(其它的函数可以按此套路自行添加和实现):

typedef enum {
    IOT_IO_PULL_NONE,    /**< Disabled.CNcomment:无拉CNend */
    IOT_IO_PULL_UP,      /**< Pull-up enabled.CNcomment:上拉CNend */
    IOT_IO_PULL_DOWN,    /**< Pull-down enabled.CNcomment:下拉CNend */
    IOT_IO_PULL_MAX,     /**< Invalid.CNcomment:无效值CNend */
} iot_io_pull;

unsigned int IoTGpioSetPull(unsigned int id, iot_io_pull val);
//unsigned int IoTGpioGetPull(unsigned int id, iot_io_pull *val);
unsigned int IoTGpioSetFunc(unsigned int id, unsigned char val);
//unsigned int IoTGpioGetFunc(unsigned int id, unsigned char *val);

#if 0
typedef enum {
    IOT_IO_DRIVER_STRENGTH_0 = 0,      /**< Drive strength level 0 (highest).CNcomment:驱动能力0级,驱动能力最高CNend */
    IOT_IO_DRIVER_STRENGTH_1,          /**< Drive strength level 1.CNcomment:驱动能力1级CNend */
    IOT_IO_DRIVER_STRENGTH_2,          /**< Drive strength level 2.CNcomment:驱动能力2级CNend */
    IOT_IO_DRIVER_STRENGTH_3,          /**< Drive strength level 3.CNcomment:驱动能力3级CNend */
    IOT_IO_DRIVER_STRENGTH_4,          /**< Drive strength level 4.CNcomment:驱动能力4级CNend */
    IOT_IO_DRIVER_STRENGTH_5,          /**< Drive strength level 5.CNcomment:驱动能力5级CNend */
    IOT_IO_DRIVER_STRENGTH_6,          /**< Drive strength level 6.CNcomment:驱动能力6级CNend */
    IOT_IO_DRIVER_STRENGTH_7,          /**< Drive strength level 7 (lowest).CNcomment:驱动能力7级,驱动能力最低CNend */
    IOT_IO_DRIVER_STRENGTH_MAX,
} iot_io_driver_strength;

unsigned int IoTGpioGetDriverStrength(unsigned int id, iot_io_driver_strength *val);
unsigned int IoTGpioSetDriverStrength(unsigned int id, iot_io_driver_strength val);
#endif

打开B_LTS/device/hisilicon/hispark_pegasus/hi3861_adapter/hals/iot_hardware/wifiiot_lite/hal_iot_gpio.c文件,在文件头部增加 #include "hi_io.h",在文件尾部增加两个函数的定义(其它函数可以按此套路增加定义):

/////////////////////////////////////
unsigned int IoTGpioSetPull(unsigned int id, iot_io_pull val)
{
    if (id >= HI_GPIO_IDX_MAX) {
        return IOT_FAILURE;
    }

    return hi_io_set_pull((hi_gpio_idx)id, (hi_io_pull)val);
}

unsigned int IoTGpioSetFunc(unsigned int id, unsigned char val)
{
    if (id >= HI_GPIO_IDX_MAX) {
        return IOT_FAILURE;
    }

    return hi_io_set_func((hi_gpio_idx)id, val);
}
/////////////////////////////////////

编译工程后烧录bin到开发板上,重启,查看LED1灯的状态,按下USER按键就可以切换LED1的亮灯状态了。

 

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2021-7-22 11:42:56修改
7
收藏 5
回复
举报
4条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

每次通过楼主的表格都能看的挺明了。

回复
2021-7-22 10:39:42
liangkz_梁开祝
liangkz_梁开祝

还是一句话,文不如表,表不如图。

1
回复
2021-7-22 10:47:09
金水.
金水.

“IoTGpioSetFunc()和IoTGpioSetPull()两个函数在A_Master/B_LTS项目中并没有定义和实现“,我也发现这个问题,正常是鸿蒙系统写好吧?

如果需要用户自己添加,这些函数接口无法保持一致的。

回复
2021-7-22 11:18:02
txwtech
txwtech

我测试一下呢。感谢分享

回复
2021-8-19 10:04:16
回复
    相关推荐