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

硬件环境

开发板: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口的值
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

底层芯片具体实现

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

驱动程序源码

#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");

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

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

内核配置参考文档

内核模块编译

make CROSS_COMPILE=arm-linux- modules
 
 
  • 1
  • 1

内核模块不能加载问题

insmod 加载出现如下问题

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

 
 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

查看错误信息,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 '
 
 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

修改内核版本信息,-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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值