05_使用linux内核的gpio库函数

1. 回顾ARM裸板GPIO输出开关灯操作代码:

//四选一:选择为GPIO功能
GPIOCALTFN0 &= ~(3 << 24);
GPIOCALTFN0 |= (1 << 24);

//二选一:选择为输出功能
GPIOCOUTENB |= (1 << 12);

//输出1或者0
GPIOCOUT |= (1 << 12);
GPIOCOUT &= ~(1 << 12);

缺点:此代码可读性非常差劲,还必须研究手册,然后做位运算
办法:在linux内核中,内核提供了相关的GPIO操作函数,可以直接使用,从而简化GPIO操作的流程

2. 内核提供的GPIO操作函数

2.1.int gpio_request(unsigned gpio, const char *label)
功能:在linux内核中,处理器的任何GPIO硬件对于linux内核来说
都是一种宝贵的资源,内核程序要想访问操作某个GPIO
硬件,必须利用此函数先向内核申请这个GPIO资源
类似:malloc
参数:
gpio:在linux内核中,内核给每个GPIO硬件都指定分配唯一的一个
软件编号,简称GPIO编号,类似GPIO硬件的身份证号
GPIO硬件对应的软件编号定义:
例如:
GPIO硬件 GPIO编号
GPIOC12 PAD_GPIO_C + 12
GPIOB26 PAD_GPIO_B + 26
... ...
label:随意指定一个标签名称即可,表示申请的GPIO硬件的标识
返回值:不用记,只需参考内核代码如何使用判断此函数的返回值即可

2.2.void gpio_free(unsigned gpio)
功能:如果内核程序不再使用某个GPIO硬件,记得要释放资源

2.3.gpio_direction_output(unsigned gpio, int value);
功能:配置GPIO为输出功能同时输出value(1高/0低)

2.4.gpio_direction_input(unsigned gpio);
功能:配置GPIO为输入功能

2.5.gpio_set_value(unsigned gpio, int value);
设置GPIO的输出值为value(1/0)
此函数使用的前提是提前配置为输出功能

2.6.int gpio_get_value(unsigned gpio);
获取GPIO的电平状态,返回值保存状态
此函数对输入还是输出无要求

3. 编写代码和测试

// led.c
#include <linux/init.h>
#include <linux/module.h>
#include <mach/platform.h> // 定义PAD_GPIO_C 等宏
#include <linux/gpio.h>

struct led_resource {
    char *name;
    int gpio;
};

static struct led_resource led_info[] = {
    {
        .name = "led1",
        .gpio = PAD_GPIO_C + 12
    },
    {
        .name = "led4",
        .gpio = PAD_GPIO_B + 26
    }
};

static int led_init(void) {
    int i;
    for (i = 0; i < ARRAY_SIZE(led_info); i++) {
        gpio_request(led_info[i].gpio, led_info[i].name);
        gpio_direction_output(led_info[i].gpio, 0);
        printk("%s: 打开第%d个灯\n", __func__,  i+1);
    }

    return 0;
}

static void led_exit(void) {
    int i;
    for (i = 0; i < ARRAY_SIZE(led_info); i++) {
        gpio_set_value(led_info[i].gpio, 1);
        gpio_free(led_info[i].gpio);
        printk("%s: 关闭第%d个灯\n", __FUNCTION__, i);
    }
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
obj-m += led.o
all:
    make -C /opt/kernel SUBDIRS=$(PWD) modules
clean:
    make -C /opt/kernel SUBDIRS=$(PWD) clean

// 开发板的测试结果

/home/driver # insmod led.ko 
[ 7411.801000] led_init: 打开第1个灯
[ 7411.801000] led_init: 打开第2个灯
/home/driver # 
/home/driver # rmmod led
[ 7415.065000] led_exit: 关闭第0个灯
[ 7415.065000] led_exit: 关闭第1个灯
/home/driver # 

 

posted @ 2025-05-30 15:57  靖意风  Views(59)  Comments(0)    收藏  举报