【Hi3559V200 BSP 开发】GPIO 设备驱动

一、前言

       搭建好环境后,先做一项 BSP 开发最基础的调试,通过 GPIO 驱动配置以及编写字符设备驱动来实现 Hi3559V200 引脚电平变化,

下面使用按键作输入,LED作输出,通过按键控制 LED 的亮灭这种方式能直观地展示电平变化的结果。使用的硬件平台是 Hi3559V200DMEB VER.A,

使用的 SDK 版本是 Hi3559V200_MobileCam_SDK_V1.0.1.5。

 

 

二、硬件原理图

2.1 Hi3559V200 平台 GPIO 介绍

      Hi3559V200 平台一共有 12 组 GPIO,每组有 8 个 IO 口,即一共有 96 个 IO 口,通过管脚复用可以把具有 IO 功能的管脚复用为 GPIO 功能,

然后通过设置寄存器的值设置 GPIO 的输入输出模式,并写入输出的值或读取输入的值。

2.2 确认用作输出的 GPIO

      查看原理图可以发现板上的 WIFI_LED,即 D9 是连接到 SoC 的 GPIO5_1,因此可以选用 GPIO5_1 来验证 GPIO 的输出。

图 2.1 GPIO5_1 作输出

 

2.3 确认用作输入的 GPIO

      查看原理图可以发现板上的 GPIO0_0 和 GPIO10_3 分别连接着两个按键,因此可以用来做 GPIO 输入管脚。

图 2.2 GPIO0_0 作输入



图 2.3 GPIO10_3 作输入

 

三、 硬件资源申请及分配

3.1 修改 hi3559v200-demb.dts

选用连接到 LED 的 GPIO5_1 作为输出,选用连接到 key 的 GPIO0_0 和 GPIO10_3 作为输入控制 LED 的亮灭。海思平台可以通过 DTS 文件对

硬件设备资源进行申请及分配,DTS 文件所在目录为 osdrv\opensource\kernel\linux-4.9.y\arch\arm\boot\dts,文件名是 hi3559v200-demb.dts。

只需在该文件内把第 0、5、10 组 GPIO 的状态设置为 “ok”即可:



图3.1 申请硬件资源分配

 

注:完成此步骤后需要重新编译 kernel 并更新到板端。

 


四、 管脚复用

4.1 查询管脚复用寄存器

在 《Hi3559V200_PINOUT_CN.xlsx》 中查询以上三个管脚的控制寄存器地址:




图 4.1 查询管脚复用寄存器



4.2 配置管脚复用

接下来需要把以上的三个引脚复用成 GPIO,海思提供了一个表格工具对引脚复用进行初始化配置,表格工具位于 osdrv\tools\pc\uboot_tools,

对于 Hi3559V200DMEB 板,适用 Hi3559V200-DMEB_6L_T-DDR3_1800M_512MB_16bitx2-A7_900M-SYSBUS_300M.xlsm 表格,

只需按照上面的例子把刚才查到的寄存器名称、地址、要写入的数据填进去即可:

图 4.2 配置管脚复用

 

注:添加复用后要重新编译 u-boot 并更新到板端。

 


五、 编写 GPIO 设备驱动

5.1 编写驱动代码 gpio_driver.c

① 以下为驱动代码框架:

static int __init gpio_control_init(void)

{

printk(KERN_ALERT "Driver init\r\n");

/*注册一个新的字符设备,返回主设备号*/

majorNumber = register_chrdev(0,DEVICE_NAME,&file_oprts);

if(majorNumber < 0 )

{

printk(KERN_ALERT "Register failed!!\r\n");

return majorNumber;

}

printk(KERN_ALERT "Registe success,major number is %d\r\n",majorNumber);



/*以CLASS_NAME创建一个class结构,这个动作将会在/sys/class目录创建一个名为CLASS_NAME的目录*/

gpio_control_class = class_create(THIS_MODULE,CLASS_NAME);

if(IS_ERR(gpio_control_class))

{

unregister_chrdev(majorNumber,DEVICE_NAME);

return PTR_ERR(gpio_control_class);

}



/*以DEVICE_NAME为名,参考/sys/class/CLASS_NAME在/dev目录下创建一个设备:/dev/DEVICE_NAME*/

gpio_control_device = device_create(gpio_control_class,NULL,MKDEV(majorNumber,0),NULL,DEVICE_NAME);

if(IS_ERR(gpio_control_device))

{

class_destroy(gpio_control_class);

unregister_chrdev(majorNumber,DEVICE_NAME);

return PTR_ERR(gpio_control_device);

}

printk(KERN_ALERT "gpio_control device init success!!\r\n");



return 0;

}

 

② 使用中断检测按键是否按下,检测到按下后设置 LED 的电平:

static  irqreturn_t key0_irq_handle(int irq, void *dev_id)

{

printk(KERN_INFO "Enter irq!!\n");

if(0 == led_status)

{

gpio_set_value(LED_PIN, 1);

led_status = 1;

}

else

{

gpio_set_value(LED_PIN, 0);

led_status = 0;

}

return (irqreturn_t)IRQ_HANDLED;

}





static void gpio_config(void)

{

int ret = 0;

if(!gpio_is_valid(LED_PIN) || !gpio_is_valid(KEY0_PIN) || !gpio_is_valid(KEY1_PIN))

{

printk(KERN_ALERT "Error wrong gpio number\n");

return ;

}

gpio_request(LED_PIN, "LED");

gpio_direction_output(LED_PIN, 1);

gpio_set_value(LED_PIN, 1);



gpio_request(KEY0_PIN, "KEY0");

gpio_direction_input(KEY0_PIN);



gpio_request(KEY1_PIN, "KEY1");

gpio_direction_input(KEY1_PIN);



key0_irq_num = gpio_to_irq(KEY0_PIN);

printk(KERN_INFO "NUM = %d",key0_irq_num);

ret = request_irq(key0_irq_num,

(irq_handler_t)key0_irq_handle,

IRQF_TRIGGER_RISING,

"KEY0",

NULL);

printk(KERN_INFO "GPIO_TEST: The interrupt request result is: %d\n", ret);



led_status = 1;

}

 
5.2 编写应用程序c,应用程序只需要打开字符设备就可以了。

int main(int argc,char *argv[])

{

int fd = open("/dev/gpio_control_demo", O_RDWR);



if(fd < 0)

{

perror("Open file failed!!!\r\n");

return -1;

}



while(1)

{

}



close(fd);

return 0;

}

 

 

六、 验证过程

6.1 把驱动文件编译成 ko 模块后拷贝到板端,安装模块,运行应用程序:

图 6.1 启动应用程序

 

6.2 按下 S2 和 S3 按键即可控制 D9 的亮灭

图 6.2 LED 灯亮

 

图 6.3 LED 灯灭

 

至此,已经可以利用 GPIO 设备驱动成功控制 GPIO 的输入和输出。 


参考资料:

【1】《外围设备驱动操作指南.doc》

【2】《Hi3559V200_PINOUT_CN.xlsx》

【3】《HI3559V200DMEB_VER_A_SCH.pdf》

 

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论