2022-01-29

GPIO设备驱动测试使用说明-liteos

[TOC]

一、概述

HI3559A芯片的CPU子系统分为两部分,一个是以为A73+A53为主的SOC部分,另一个是为M7为主的Sensor Hub部分,其中SOC子系统与Sensor Hub子系统的外设均采用统一的外设接口,即寄存器组完全一样,并且可以通过地址转换实现跨子系统访问,但是SOC子系统与Sensor Hub子系统的中断系统完全肚子,并不能完全共享中断向量。

主 SOC 子系统支持 19 组 GPIO(General Purpose Input/Output),即 GPIO0~GPIO18。每组 GPIO 提供 8 个可编程的输入输出管脚(GPIO18 只有 4 个)。

Sensor Hub 子系统支持 5 组 GPIO,即 GPIO0~GPIO4。每组 GPIO 提供 8 个可编程的输入输出管脚(GPIO4 只有 2 个)。 每个管脚可以配置为输入或者输出。这些管脚用于生成特定应用的输出信号或采集特定应用的输入信号。作为输入管脚时,GPIO 可作为中断源;作为输出管脚时,每个GPIO 都可以独立地清 0 或置 1。

该文档就GPIO的操作使用以及GPIO的复用功能做详细讲解。

二、 参考文件

GPIO复用功能描述文件《Hi3559A V100_PINOUT_EN.xlsx》

驱动操作使用指南《外围设备驱动 操作指南.pdf》

寄存器相关操作《Hi3559A╱C V100 ultra-HD Mobile Camera SoC 用户指南.pdf》

三、驱动编译

1. 官方GPIO驱动编译

海思官方提供的程序兼容posix接口,实现了部分函数功能,gpio相关的驱动程序源码路径为 drivers/gpio,在编译脚本里指定源码路径与头文件路径,编译成功后,out目录下会生成名为 libgpio.a 的库文件,链接时通过-lgpio 指定对应库文件。

海思官方提供的API函数如下:

gpio_chip_init:GPIO 初始化接口。

gpio_chip_deinit:GPIO 去初始化接口。

gpio_get_direction:获取 GPIO 方向。

gpio_direction_input:设置 GPIO 方向为输入。

gpio_direction_output:设置 GPIO 方向为输出。

gpio_get_value:获取 GPIO 值。

gpio_set_value:设置 GPIO 值。

gpio_irq_register:注册 GPIO 中断。

gpio_set_irq_type:设置 GPIO 中断类型。

gpio_irq_enable:使能 GPIO 中断。

gpio_get_irq_status:获取中断状态。

gpio_clear_irq:清除 GPIO 寄存器中断状态。

但是在posix接口部分只提供了open(),close(),ioctl()函数,因此下面就该部分代码做一定的解读。

#include"fcntl.h"#include"linux/kernel.h"#include"fs/fs.h"#include"sys/ioctl.h"#include"gpio.h"#include"gpio_dev.h"structgpio_descriptor*gpio=NULL;staticintgpio_open(structfile*filep){return0;}staticintgpio_close(structfile*filep){return0;}staticintgpio_ioctl(structfile*filep,intcmd,unsignedlongarg){intret=0;structinode*inode=filep->f_inode;structgpio_descriptor*gd=(structgpio_descriptor*)(inode->i_private);if(!gd)    {        gpio_err("gpio_descriptor is null!\n");return-1;    }switch(cmd)    {caseGPIO_SET_DIR:if(gd->ops->setdir)                ret=gd->ops->setdir(gd,(gpio_groupbit_info*)arg);elseret=-1;break;caseGPIO_GET_DIR:if(gd->ops->getdir)                ret=gd->ops->getdir(gd,(gpio_groupbit_info*)arg);elseret=-1;break;caseGPIO_READ_BIT:if(gd->ops->readbit)                ret=gd->ops->readbit(gd,(gpio_groupbit_info*)arg);elseret=-1;break;caseGPIO_WRITE_BIT:if(gd->ops->writebit)                ret=gd->ops->writebit(gd,(gpio_groupbit_info*)arg);elseret=-1;break;default:ret=-1;    }returnret;}conststructfile_operations_vfs gpio_dev_ops={    gpio_open,/* open */gpio_close,/* close */0,/* read */0,/* write */0,/* seek */gpio_ioctl/* ioctl */#ifndef CONFIG_DISABLE_POLL,0/* poll */#endif};

如上述代码所示:posix驱动部分只实现了open(),close(),ioctl()函数,其中open(),close()函数未做任何操作,ioctl()支持GPIO_SET_DIR,GPIO_GET_DIR,GPIO_READ_BIT,GPIO_WRITE_BIT等操作。

在liteos代码目录下直接执行make便可以实现该部分代码的编译。

2.GPIO复用功能拓展

GPIO除了设计为GPIO功能之外,有时候还会设计为其他功能,例如uart,spi,PWM等,因此根据实际情况,可以选择使用作为第二功能。该部分寄存器位于《Hi3559A V100_PINOUT_EN.xlsx》中。

新建hal_gpioaf.c,hal_gpioaf.h。

hal_gpioaf.h

#ifndef __HAL_GPIOAF_H__#define __HAL_GPIOAF_H__#include"hal.h"#define IOREGL(N)              (0x1F000000 + N * 4)#define IOREGM(N)              (0x1F001000 + (N - 76) * 4)#define IOREGH(N)              (0x1F002000 + (N - 138) * 4)#define IOREG(N)                (N <= 75 ?  IOREGL(N): IOREGM(N))#define AF_UART0_VAL            0x01#define AF_UART0_TX            IOREG(53)#define AF_UART0_RX            IOREG(54)#define AF_UART1_VAL            0x01#define AF_UART1_TX            IOREG(55)#define AF_UART1_RX            IOREG(56)#define AF_UART2_VAL            0x01#define AF_UART2_TX            IOREG(57)#define AF_UART2_RX            IOREG(58)#define AF_UART3_VAL            0x01#define AF_UART3_TX            IOREG(59)#define AF_UART3_RX            IOREG(60)#define AF_UART4_VAL            0x01#define AF_UART4_TX            IOREG(61)#define AF_UART4_RX            IOREG(62)#define AF_UARTO_Config()      {          \    writeor(AF_UART0_TX, AF_UART0_VAL);    \    writeor(AF_UART0_RX, AF_UART0_VAL);    \}#define AF_UART1_Config()      {          \    writeor(AF_UART1_TX, AF_UART1_VAL);    \    writeor(AF_UART1_RX, AF_UART1_VAL);    \}#define AF_UART2_Config()      {          \    writeor(AF_UART2_TX, AF_UART2_VAL);    \    writeor(AF_UART2_RX, AF_UART2_VAL);    \}#define AF_UART3_Config()      {          \    writeor(AF_UART3_TX, AF_UART3_VAL);    \    writeor(AF_UART3_RX, AF_UART3_VAL);    \}#define AF_UART4_Config()      {          \    writeor(AF_UART4_TX, AF_UART4_VAL);    \    writeor(AF_UART4_RX, AF_UART4_VAL);    \}#endif

上述代码中实现了UART部分的gpio复用功能,如需要实现其他功能的IO复用,可以类似于上述代码编写IO复用函数。

四、 API描述

1. 官方GPIO驱动API

官方提供的posix接口只提供了ioctl函数,其中open,close函数的函数内容均为空,因此仅需要分析ioctl函数即可,ioctl()支持GPIO_SET_DIR,GPIO_GET_DIR,GPIO_READ_BIT,GPIO_WRITE_BIT等操作。

ioctl可配置参数如下:

命令号命令码参数说明

GPIO_SET_DIR4GPIO结构体设置一个GPIO的方向

GPIO_GET_DIR5GPIO结构体获取一个GPIO的设置方向

GPIO_READ_BIT6GPIO结构体读取一个GPIO的电平值

GPIO_WRITE_BIT7GPIO结构体设置一个GPIO的电平值

2.GPIO复用功能拓展

上述的GPIO复用功能拓展提供了五个GPIO函数,如果使用有需要,可以进一步编写相关的代码以实现更多设备的GPIO复用功能支持,上述代码支持的函数如下:

AF_UARTO_Config()//设置相应的GPIO复用功能为UART0

AF_UART1_Config()//设置相应的GPIO复用功能为UART1

AF_UART2_Config()//设置相应的GPIO复用功能为UART2

AF_UART3_Config()//设置相应的GPIO复用功能为UART3

AF_UART4_Config()//设置相应的GPIO复用功能为UART4

五、 应用实例

1.官方GPIO驱动实例

如上图所示:电脑通过网线连接HI3559A板卡,实现程序的烧写与调试,示波器通过探头连接到HI3559A的GPIO上,通过程序设置GPIO的输出电平,在示波器上观察IO点评的变化。

gpio_dev_initopenGPIO_SET_DIRGPIO_WRITE_BITclose

其中gpio_dev_init在liteos初始化时候便已经被调用了,因此使用上述代码只需要执行oepn,ioctl,close等函数,如上分析,新建user_gpio.c、user_gpio.h。

user_gpio.h

#ifndef __USER_GPIO_H__#define __USER_GPIO_H__#include"user.h"#include"gpio.h"voiduser_gpio_initial(void);#endif

user_gpio.c

#include"user_gpio.h"#include"gpio.h"intfd;voiduser_gpio_initial(void){    fd=open("/dev/gpio", O_RDWR);    gpio_groupbit_info group_bit_info;    group_bit_info.groupnumber=3;    group_bit_info.bitnumber=6;    group_bit_info.direction=GPIO_DIR_OUT;    ioctl(fd, GPIO_SET_DIR,&group_bit_info);while(1){        LOS_Msleep(10);        group_bit_info.value=GPIO_VALUE_HIGH;        ioctl(fd, GPIO_WRITE_BIT,&group_bit_info);        LOS_Msleep(10);        group_bit_info.value=GPIO_VALUE_LOW;        ioctl(fd, GPIO_WRITE_BIT,&group_bit_info);    }    close(fd);}

2.GPIO复用驱动实例

在使用串口功能时候直接调用API函数即可。

voiduartxxx_initial(){    ...    AF_UARTxxx_Config()    ...    ...}

六、注意事项

官方提供的API不能跨子系统调用,如有必要,需要自行操作寄存器。

注意项目的路径依赖问题。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容