基于NanoPi2的Linux3.4内核GPIO驱动

    xiaoxiao2022-06-24  57

    硬件环境

    开发板:nanopi2 (cpu:A9 s5p4418 )

    软件环境

    内核版本: linux3.4.39 交叉编译器:arm-linux-gcc version 4.9.3 (ctng-1.21.0-229g-FA) 64位系统版本

    Linux3.4内核GPIO驱动说明

    Kernel 2.6.32版本以上提供了gpio口管理的库文件/kernel/drivers/gpio/gpiolib.c。

    相关的接口: 1.int gpio_request(unsigned gpio, const char *label) 申请一个pin脚作为gpio口,命名为 * label,如果经过判断空闲的 申请成功了做一些初始的bit位设置。 2.void gpio_free(unsigned gpio) 释放这个gpio口 3.int gpio_direction_input(unsigned gpio) 设置gpio口为输入模式 4.int gpio_direction_output(unsigned gpio, int value) 设置gpio口为输出模式 value为初始值 0为高电平/1为低电平 5.void __gpio_set_value(unsigned gpio, int value) 设置gpio口的值 6.int __gpio_get_value(unsigned gpio) 获取gpio口的值

    底层芯片具体实现

    在drivers/gpio下实现了通用的基于gpiolib的GPIO驱动,其中定义了一个通用的用于描述底层GPIO控制器的gpio_chip结构体,并要求具体的SoC实现gpio_chip结构体的成员函数,最后透过gpiochip_add()注册gpio_chip。

    驱动程序源码

    #include <linux/module.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/hrtimer.h> #include <linux/ktime.h> #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/miscdevice.h> #include <mach/platform.h> #include <mach/devices.h> #define DEVICE_NAME "4418_relay" //nanopi2 4418 unsigned int J1_GPIO = PAD_GPIO_C + 11;//模块GPIO脚 unsigned int J2_GPIO = PAD_GPIO_C + 12;//模块GPIO脚 #define J1_OFF 0x00 #define J1_ON 0x01 #define J2_OFF 0x10 #define J2_ON 0x11 char drv_buf[2]; static int update_relay(void) { switch(drv_buf[0]) { case J1_ON: gpio_set_value(J1_GPIO, 0); //输出低电平 return 0; case J1_OFF: gpio_set_value(J1_GPIO, 1); //输出高电平 return 0; case J2_ON: gpio_set_value(J2_GPIO, 0); //输出低电平 return 0; case J2_OFF: gpio_set_value(J2_GPIO, 1); //输出高电平 return 0; default: return -EINVAL; } } static int relay_write(struct file *file, const char * buffer, size_t count, loff_t * ppos) { unsigned long err; err = copy_from_user(drv_buf, buffer, 1); update_relay(); return 1; } static struct file_operations dev_fops={ write:relay_write, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init my_relay_init(void) { int ret; gpio_direction_output(J1_GPIO, 1);//设置输出 gpio_direction_output(J2_GPIO, 1);//设置输出 ret = misc_register(&misc); printk (DEVICE_NAME"\t#NanoPi2 J1 J2 initialized\n"); return ret; } static void __exit my_relay_exit(void) { misc_deregister(&misc); } module_init(my_relay_init); module_exit(my_relay_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("TONY"); MODULE_DESCRIPTION("91arm.com Relay Driver");

    修改内核配置菜单,增加当前驱动配置。

    内核配置参考文档

    内核模块编译

    make CROSS_COMPILE=arm-linux- modules

    内核模块不能加载问题

    insmod 加载出现如下问题

    root@nanopi2:/home/fa# insmod 4418_relay.ko insmod: ERROR: could not insert module 4418_relay.ko: Invalid module format

    查看错误信息,version magic驱动程序同开发板内核不匹配。

    root@nanopi2:/home/fa# dmesg |tail [ 2589.164000] 4418_relay: version magic '3.4.39-s5p4418 SMP preempt mod_unload ARMv7 p2v8 ' should be '3.4.39-FriendlyARM SMP preempt mod_unload ARMv7 p2v8 '

    修改内核版本信息,-s5p4418改成内核的FriendlyARM。

    测试程序源码

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #define DEV_FILE "/dev/4418_relay" #define J1_OFF 0x00 #define J1_ON 0x01 #define J2_OFF 0x10 #define J2_ON 0x11 int main() { int fd_dev=-1; char dat[2]; int cmd; printf("nanoPi driver Test\n"); fd_dev = open(DEV_FILE,O_RDWR); if(fd_dev<0){ printf("open device err\n"); return 0; } while(1){ printf("1:J1 OFF 2:J1 ON 3:J2 OFF 4:J2 ON\n"); printf("Please input:"); scanf("%d",&cmd); switch(cmd){ case 1: dat[0] = J1_OFF; break; case 2: dat[0] = J1_ON; break; case 3: dat[0] = J2_OFF; break; case 4: dat[0] = J2_ON; break; default: break; } write(fd_dev,dat,1); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1123945.html

    最新回复(0)