博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AliOS Things 硬件抽象层(HAL)对接系列1 — GPIO driver porting
阅读量:6195 次
发布时间:2019-06-21

本文共 5019 字,大约阅读时间需要 16 分钟。

HAL层(Hardware abstraction layer 硬件抽象层) 的目的是为了屏蔽底层不同芯片平台的差异,从而使驱动层上面的软件不会随芯片平台而改变。AliOS Things定义了全面的HAL抽象层,这个系列主要介绍AliOS ThingsHAL层与不同芯片平台对接的poring要点,并举例说明。

Hal 对接系列1 —— Gpio driver porting

一. 接口定义说明

gpio 对外接口定义在 include/hal/soc下面,接口函数主要有以下几个:

int32_t hal_gpio_init(gpio_dev_t *gpio)int32_t hal_gpio_output_high(gpio_dev_t *gpio);int32_t hal_gpio_output_low(gpio_dev_t *gpio);int32_t hal_gpio_output_toggle(gpio_dev_t *gpio);int32_t hal_gpio_input_get(gpio_dev_t *gpio, uint32_t *value);int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger, gpio_irq_handler_t handler, void *arg);int32_t hal_gpio_disable_irq(gpio_dev_t *gpio);int32_t hal_gpio_clear_irq(gpio_dev_t *gpio);int32_t hal_gpio_finalize(gpio_dev_t *gpio)

其中,结构体gpio_dev_t 定义为:

typedef struct {    uint8_t       port;           /* gpio port */    gpio_config_t config;  /* gpio config */    void         *priv;           /* priv data */} gpio_dev_t;

接口函数的含义清晰明了,这里用户有两种方式可以调用驱动:

  1. 直接调用接口函数,常用于对gpio驱动的二次封装,如在lcd驱动中调用gpio进行相关操作;
  2. 通过vfs虚拟文件系统进行操作,即使用open, read, write, ioctl等标准接口进行。

二. 接口使用说明

二者调用方式在hal层没有显著区别。以第一种为例:

调用gpio驱动时,首先定义
gpio_dev_t gpio_1 = {KEY_1, OUTPUT, &value}
即使用gpio 的输出功能,可以使用

hal_gpio_output_high(&gpio_1);hal_gpio_output_low(& gpio_1);hal_gpio_output_toggle(& gpio_1);

等接口函数操作gpio输出高、低电平或者反转电平。

gpio_dev_t gpio_2 = {KEY_2, INPUT, NULL}

即使用gpio的输入功能,可以使用
hal_gpio_input_get(&gpio_2 , uint32_t *value)
等接口函数操作读取gpio电平值;

gpio_dev_t gpio_3 = {KEY_3, IRQ_MODE, &value}

即使用gpio的输入中断功能,value值为上升沿、下降沿和边沿触发三种模式,
可以使用

hal_gpio_enable_irq(&gpio_3, gpio_irq_trigger_t trigger,                                                     gpio_irq_handler_t handler, void *arg);

进行中断初始化,用户还需要自行提供中断处理函数handler,定义如下:

typedef void (gpio_irq_handler_t)(void arg);

具体的操作示例,可以参考aos/example/peri_deiver_test_developerkit/peri_test.c

三. HAL层对接要点

HAL层需要严格按照位于include/hal/soc/gpio.h的实现进行对接, 新建两个文件hal_gpio_xxx.c和hal_gpio_xxx.h,将封装层代码放到这两个文件中,实现上面列出的接口函数。

hal_gpio_init是gpio初始化,不同系列芯片的初始化方式差异较大,我们往往无法直接调用芯片厂商的初始化函数,此时需要对接口进行一些转换以对接芯片厂商的驱动。举例说明。

ST系列:

我们最终需要的gpio初始化接口即:int32_t hal_gpio_init(gpio_dev_t *gpio)
ST系列芯片驱动的gpio初始化接口为:void HAL_GPIO_Init(GPIO_TypeDef GPIOx, GPIO_InitTypeDef GPIO_Init)
其中的结构体GPIO_TypeDef 、GPIO_InitTypeDef 为ST芯片专用的驱动结构体定义,
对接ST系列的gpio驱动时,需要手动对上述结构体进行定义,以满足继续调用ST的驱动的要求:
定义
GPIO_TypeDef *GPIOx;
GPIO_InitTypeDef GPIO_InitStruct;

/伪代码举例/

get_gpio_group(gpio, &GPIOx) 来获取GPIOx
gpio_para_transform(gpio, &GPIO_InitStruct); 来获取 GPIO_InitStruct
(get_gpio_group 和 gpio_para_transform 等函数的实现要点:根据GPIO_TypeDef 和GPIO_InitTypeDef 结构体的定义将 gpio_dev_t 实现转换 ,具体可参考ST驱动源码)
有了GPIOx 和 GPIO_InitStruct,进一步调用ST提供gpio初始化函数 HAL_GPIO_Init

再以NRF系列芯片为例:

NRF系列芯片驱动的gpio初始化接口为:ret_code_t renrf_drv_gpiote_init(void)
对接该系列hal层时,可以直接调用底层驱动,需要注意的是,NRF的gpio初始化分
输入gpio的初始化和输出gpio的初始化,即:

ret_code_t  nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin,                nrf_drv_gpiote_out_config_t const * p_config);ret_code_t  nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t  pin,                 nrf_drv_gpiote_in_config_t const * p_config,                 nrf_drv_gpiote_evt_handler_t  evt_handler);

这里的 nrf_drv_gpiote_pin_t 、nrf_drv_gpiote_out_config_t 、nrf_drv_gpiote_in_config_t 等结构体定义也是NRF系列专用,对接该系列的gpio驱动时,需要手动对上述结构体进行定义,如:

static nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);static nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);int32_t hal_gpio_init(gpio_dev_t *gpio){    int32_t ret = -1;    if (!nrf_drv_gpiote_is_init()) {        ret = nrf_drv_gpiote_init();         if (ret != NRF_SUCCESS)            return NRF_ERROR_INTERNAL;    }    switch (gpio->config) {    case OUTPUT_PUSH_PULL:    case OUTPUT_OPEN_DRAIN_NO_PULL:    case OUTPUT_OPEN_DRAIN_PULL_UP:        ret = nrf_drv_gpiote_out_init(gpio->port, &out_config);        break;    case IRQ_MODE:         in_config.pull = NRF_GPIO_PIN_PULLUP;         ret = nrf_drv_gpiote_in_init(gpio->port, &in_config, gpio->priv);    default:        ret = -1;     break;   }    return ret;}

hal_gpio_output_high、

​hal_gpio_output_low、
​hal_gpio_output_toggle 、
​hal_gpio_input_get
等函数的HAL层对接比较简单,一般在gpio初始化后直接调用相应芯片的驱动即可,
如ST系列: HAL_GPIO_WritePin、HAL_GPIO_ReadPin 进行gpio输入输出操作;
NRF系列:nrf_drv_gpiote_out_set、nrf_drv_gpiote_out_clear、nrf_drv_gpiote_in_is_set进行gpio输入输出操作。

对于gpio的输入中断的对接,ST系列使用了

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)进行gpio输入中断的响应,并在

int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger, gpio_irq_handler_t handler, void *arg)

中定义中断响应的handler 和传入的参数arg,如:

ret = hal_gpio_enable_irq(&gpio1, IRQ_TRIGGER_RISING_EDGE,  key_handle,  NULL);    if (ret != 0) {        printf("hal_gpio_enable_irq key return failed.\n");    }​    void key_handle(void *arg)     {          /*key interupt相关操作*/    }​  ​

与ST不同,NRF系列在使用

ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,                        nrf_drv_gpiote_in_config_t const * p_config,                          nrf_drv_gpiote_evt_handler_t  evt_handler);

最后一个参数evt_handler来表示中断响应函数,nrf 底层驱动会对这个参数进行判断,如果传入NULL,则表示不使用gpio输入中断功能。

综上所述, hal层porting需要根据不同芯片厂商的驱动的接口来进行。

转载地址:http://smyca.baihongyu.com/

你可能感兴趣的文章
wpf listbox 选中项 上移下移
查看>>
设计模式(4)------结构型模式------装饰者设计模式
查看>>
Ubuntu18.04下希捷移动硬盘Seagate Backup Plus读写慢
查看>>
NPOI导出EXCEL 打印设置分页及打印标题
查看>>
yum install --downloadonly 下载依赖包到本地 但不安装
查看>>
arcgis api for js入门开发系列二十二地图模态层
查看>>
【linux】linux查看文件大小,磁盘大小
查看>>
Spring容器-ApplicationContext的单例设计
查看>>
查询mysql 哪些表正在被锁状态
查看>>
交换机,路由器,集线器,有什么区别
查看>>
浅析form传值
查看>>
.NET编程 -- 字节数组、数值和十六进制字符串的转换
查看>>
Live Search for Windows Embedded CE 6.0
查看>>
JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载
查看>>
通过配置的方式Autofac 《第三篇》
查看>>
介绍WS Federaion 二:把百度和谷歌和谐起来
查看>>
VBS学习笔记(2): Call造成的麻烦
查看>>
QTP的那些事—WMI+SQL分析查询工具
查看>>
数学之路(3)-机器学习(3)-机器学习算法-欧氏距离(2)
查看>>
U盘启动引导安装linux
查看>>