gpiolib库详解

发布者:Serene123最新更新时间:2025-01-07 来源: cnblogs关键字:S5PV210 手机看文章 扫描二维码
随时随地手机看文章

1. gpiolib库简介

linux中从2.6.35以后就开始有gpiolib库了,gpiolib的作用是对所有的gpio实行统一管理,因为驱动在工作的时候,会出现好几个驱动共同使用同一个gpio的情况;这会造成混乱。所以内核提供了一些方法来管理gpio资源。


2. gpiolib库的建立

gpiolib库建立的目标函数:


//所在文件:/kernel/arch/arm/mach-s5pv210/mach-smdkc110.c

static void __init smdkc110_map_io(void)

{

    ......

    s5pv210_gpiolib_init();

    ......

}



//所在文件:/kernel/arch/arm/mach-s5pv210/gpiolib.c

__init int s5pv210_gpiolib_init(void)

{

    struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;

    int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);

    int i = 0;

        

    for (i = 0; i < nr_chips; i++, chip++) 

    {

        if (chip->config == NULL)

            chip->config = &gpio_cfg;

        if (chip->base == NULL)

            chip->base = S5PV210_BANK_BASE(i);

    }


    samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);


    return 0;

}


 s5pv210_gpiolib_init()函数分析:


(1)gpiolib库的初始化实质就是对s3c_gpio_chip结构体数组进行赋值;struct s3c_gpio_chip用以描述一个GPIO端口。


struct s3c_gpio_chip 

{

    struct gpio_chip    chip;  

    struct s3c_gpio_cfg *config;

    struct s3c_gpio_pm  *pm;

    void __iomem        *base;  //存放GPIO的虚拟地址

    int            eint_offset;

    spinlock_t         lock;

#ifdef CONFIG_PM

    u32            pm_save[7];

#endif

};


struct gpio_chip 

{

  ......

  const char  *label; //GPIO端口名称

  int  base;         //GPIO端口号

  ......

}


(2)内核中建立了static struct s3c_gpio_chip s5pv210_gpio_4bit[] 这个数组,将所有的gpio的.chip结构体中的一些元素初始化,这个数组的所有元素是与数据手册中的所有gpio是一一对应的。


static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {

    {

        .chip    = {

            .base    = S5PV210_GPA0(0),

            .ngpio    = S5PV210_GPIO_A0_NR,

            .label    = 'GPA0',

            .to_irq = s5p_gpiolib_gpioint_to_irq,

        },

    }, {

        .chip    = {

            .base    = S5PV210_GPA1(0),

            .ngpio    = S5PV210_GPIO_A1_NR,

            .label    = 'GPA1',

            .to_irq = s5p_gpiolib_gpioint_to_irq,

        },

    }, {

        .chip    = {

            .base    = S5PV210_GPB(0),

            .ngpio    = S5PV210_GPIO_B_NR,

            .label    = 'GPB',

            .to_irq = s5p_gpiolib_gpioint_to_irq,

        },

    }, 

       ......

}


.chip.base是GPIO的编号,用宏定义表示。S5PV210_GPA0(0)宏解析如下,即S5PV210_GPA0(0) = 0,S5PV210_GPA0(1) = 1。


#define S5PV210_GPA0(_nr) (S5PV210_GPIO_A0_START + (_nr))

#define S5PV210_GPA1(_nr) (S5PV210_GPIO_A1_START + (_nr)) 


S5PV210_GPIO_A0_START = 0,

S5PV210_GPIO_A1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_A0),


#define S5PV210_GPIO_NEXT(__gpio)

((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) 


#define S5PV210_GPIO_A0_NR (8)

#define S5PV210_GPIO_A1_NR (4)

#define S5PV210_GPIO_B_NR  (8)

#define S5PV210_GPIO_C0_NR (5)


(3)chip->base = S5PV210_BANK_BASE(i),将GPIO的虚拟地址写入。


 //每个gpio的地址差0x20

#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20)

(4)samsung_gpiolib_add_4bit_chips()函数的作用是将所有GPIO向内核注册。注册的实质是:在linux内核中有一个gpio_desc结构体数组,注册就是把我们封装的gpio的所有信息的结构体放到数组的格子中。


void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip, int nr_chips)

{

    for (; nr_chips > 0; nr_chips--, chip++) 

    {

        samsung_gpiolib_add_4bit(chip);

        s3c_gpiolib_add(chip);

    }

}


回到顶部

3. gpiolib库的使用

(1)申请GPIO


/*

*参数:

*        unsigned gpio:GPIO编号

*        const char *label:GPIO名称

*返回值:

*        返回值为0,GPIO申请成功;否则,GPIO申请失败

*/

int gpio_request(unsigned gpio, const char *label); 


(2)设置GPIO方向


1)设置为输入


/*

*参数:

*        unsigned gpio:GPIO编号

*返回值:

*        返回值为<0,设置失败

*/

int gpio_direction_input(unsigned gpio);


2)设置为输出


/*

*参数:

*        unsigned gpio:GPIO编号

*        int value:GPIO输出值

*返回值:

*        返回值为<0,设置失败

*/

int gpio_direction_output(unsigned gpio, int value);


(3)获取/设置GPIO的值


a. 可睡眠


对于有些挂载在I2C,SPI总线上的扩展GPIO,读写操作可能会导致睡眠,因此不能在中断函数中使用可睡眠操作。使用下面的函数以区别于正常的GPIO:


1)获取GPIO的值


/*

*参数:

*        unsigned gpio:GPIO编号

*返回值:

*        返回GPIO的值,0或1

*/

int gpio_get_value_cansleep(unsigned gpio);


2)设置GPIO的值


/*

*参数:

*        unsigned gpio:GPIO编号

*        int value:GPIO设置值

*返回值:

*        无

*/

void gpio_set_value_cansleep(unsigned gpio, int value);


b. 不可睡眠


1)获取GPIO的值


/*

*参数:

*        unsigned gpio:GPIO编号

*返回值:

*        返回GPIO的值,0或1

*/

int gpio_get_value(unsigned gpio);


2)设置GPIO的值


/*

*参数:

*        unsigned gpio:GPIO编号

*        int value:GPIO设置值

*返回值:

*        无

*/

void gpio_set_value(unsigned gpio, int value);


(4)释放GPIO


/*

*参数:

*        unsigned gpio:GPIO编号

*返回值:

*        无

*/

void gpio_free(unsigned gpio);


(5)批量初始化/释放GPIO


1)批量初始化GPIO


/*

*参数:

*        unsigned gpio  *array:GPIO数组(多个GPIO编号)

*        size_t num:GPIO数组大小,GPIO即的个数

*返回值:

*        返回0,初始化成功;否则,初始化失败

*/

int gpio_request_array(struct gpio *array, size_t num);


2)批量释放GPIO


/*

*参数:

*        unsigned gpio  *array:GPIO数组(多个GPIO编号)

*        size_t num:GPIO数组大小,GPIO即的个数

*返回值:

*        无

*/

void gpio_free_array(struct gpio *array, size_t num);


回到顶部

 4. S3C平台的GPIO操作接口

kernel/arch/arm/plat-s3c/include/plat/gpio-cfg.h文件中提供了S3C平台的GPIO操作接口,以下列举一些常用的GPIO操作接口。


(1)GPIO的工作模式设置


Linux内核中GPIO的工作模式的定义。


/*

*GPIO的工作模式定义

*/

#define S3C_GPIO_INPUT    (S3C_GPIO_SPECIAL(0))   //输出模式

#define S3C_GPIO_OUTPUT   (S3C_GPIO_SPECIAL(1))   //输入模式

#define S3C_GPIO_SFN(x)   (S3C_GPIO_SPECIAL(x))   //其他模式,根据参数x决定


S3C_GPIO_SFN(x)中x的值对应的功能可通过数据手册来查阅。譬如,根据D5PV210的数据手册可知:


/*

*x = 0,GPH0_0为输入模式

*x = 1,GPH0_0为输出模式

*x = 0x0f,GPH0_0为外部中断模式

*/


S3C_GPIO_SFN(0)   //输入模式 

S3C_GPIO_SFN(1)   //输出模式 

S3C_GPIO_SFN(0x0f)//外部中断模式 


1)s3c_gpio_cfgpin()设置指定引脚的工作模式


/*

*功能:设置指定引脚的工作模式

*参数:

*        unsigned int pin:需要设置的引脚号

*        unsigned int to:需要设置的工作模式

*/

int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);


s3c_gpio_cfgpin(S5PV210_GPA0(0), S3C_GPIO_SFN(0));   //设置GPH0_0为输入模式 

s3c_gpio_cfgpin(S5PV210_GPA0(0), S3C_GPIO_SFN(1));   //设置GPH0_0为输出模式 

s3c_gpio_cfgpin(S5PV210_GPA0(0), S3C_GPIO_SFN(0x0f));//设置GPH0_0为外部中断模式


2)s3c_gpio_getcfg()读取指定引脚的设置值


/*

*功能:读取指定引脚的设置值

*参数:

*        unsigned int pin:需要获取的引脚号

*返回值:获取G引脚工作模式的值

*/

unsigned s3c_gpio_getcfg(unsigned int pin);


 3)s3c_gpio_cfgin_range()批量设置多个引脚的工作模式


/*

*功能:批量设置多个引脚的工作模式

*参数:

*        unsigned int start:起始引脚号

*        unsigned int nr:   需要设置的引脚个数

*        unsigned int cfg:  需要设置的工作模式

*/

int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, unsigned int cfg);


 (2)GPIO的上下拉设置


 Linux内核中,上下拉的状态值的定义。


#define S3C_GPIO_PULL_NONE  ((__force s3c_gpio_pull_t)0x00)  //关闭,上拉下拉都关闭

#define S3C_GPIO_PULL_DOWN  ((__force s3c_gpio_pull_t)0x01)  //下拉

#define S3C_GPIO_PULL_UP    ((__force s3c_gpio_pull_t)0x02)  //上拉

 1)s3c_gpio_setpull()设置GPIO引脚的上下拉使能


/*

*功能:设置单个引脚的上下拉模式

*参数:

*        unsigned int pin:需要设置的引脚

*        s3c_gpio_pull_t pull:上下拉的状态值

*/

int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);


 2)s3c_gpio_getpull()读取指定引脚的上下拉状态


/*

*功能:读取指定引脚的上下拉状态

*参数:

*        unsigned int pin:需要读取的引脚

*返回值:        

*        s3c_gpio_pull_t :上下拉的状态值

*/

s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);


3) s3c_gpio_cfgall()批量设置多个引脚的工作模式和上下拉状态


/*

*功能:批量设置多个引脚的工作模式和上下拉状态

*参数:

*       unsigned int start:  起始引脚号

*       unsigned int nr:     需要设置的引脚个数

*       unsigned int cfg:    需要设置的引脚工作模式

*       s3c_gpio_pull_t pull:需要设置的引脚的上下拉状态

*/

int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, unsigned int cfg, s3c_gpio_pull_t pull);


关键字:S5PV210 引用地址:gpiolib库详解

上一篇:make: Warning: File `led.c' has modification time 15 s in the future
下一篇:喜羊羊系列【设备 - 驱动器 编译进内核】

推荐阅读最新更新时间:2026-03-25 11:32

5.4.10.linux内核的gpiolib学习2
总结:先分析杂碎:struct s3c_gpio_chip,s5pv210_gpio_4bit 5.4.10.1、struct s3c_gpio_chip gpiolib库的初始化实质就是对这个结构体数组进行赋值 (1)这个结构体是一个GPIO端口的抽象,这个结构体的一个变量就可以完全的描述一个IO端口。 (2)端口和IO口是两个概念。S5PV210有很多个IO口(160个左右),这些IO口首先被分成N个端口(port group),然后每个端口中又包含了M个IO口。譬如GPA0是一个端口,里面包含了8个IO口,我们一般记作:GPA0_0(或GPA0.0)、GPA0_1、 (3)内核中为每个GPIO分配了一个编号,编号是
[单片机]
5.4.10.linux内核的<font color='red'>gpiolib</font>学习2
S5PV210中的定时器
什么是定时器? 定时器是SoC中常见外设 定时器与计数器。计数器是用来计数的(每隔一个固定时间会计一个数),因为计数器的技术时间周期是固定的,因此到了一定时间,只要用计数值乘以技术的时间周期就能得到一个时间段。这个时间段就是我们定的时间(这就是定时器了)。 定时器/计数器作为SoC的外设,主要用来实现定时执行代码功能,定时器相对于SoC来说,就好像闹钟相对于人来说意义一样 定时器有什么用? 定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU回去处理中断并执行定时器中断的isr从而去执行预先设定好的事件。 定时器就好像是CPU的秘书一样,这
[单片机]
S5PV210 固件烧写 u-boot烧写
首先阅读CW210_CD自带光盘中CW210 开发板使用手册.pdf 使用usb 拨码开关置成usb启动。xx可以是ON或OFF。开发板上面也有丝印提示 usb线接好,串口线接好 使用DNW下载 自带光盘的usb驱动(x210 usb Driver)只适用于XP系统,如果在Windows 7下使用usb下载,只能使用linux dnw代替 配置DNW串口和下载地址,0xd0020010是x210_usb.bin的下载地址 连接串口,显示连接成功 此时,长按开发板复位按键 直到USB连接显示OK 现在可以通过usb发送文件,首先发送x210_usb.bin 修改下载地址,0x23e00000是u-boot.bin的下
[单片机]
<font color='red'>S5PV210</font> 固件烧写 u-boot烧写
S5PV210版本NDT嵌入式Linux主机目录分布及开发流程简要说明
开发才用win10宿主机+VMWare12.5+Ubuntu14.04 LTS虚拟机环境。 1、文件目录介绍 开发机器所建用户名为administrator,机器密码为******。 嵌入式QT目录:/home/administrator/linuxtools/armqt/ tftp共享目录:/home/administrator/tftp 根文件系统: /home/administrator/rootfs 内核目录: /home/administrator/kernel/linux-2.6.35.7 工程目录: /home/administrator/NDT-2015/NDT-F 2、
[单片机]
S5PV210 点亮Led
GPC1CON, R/W, Address = 0xE020_0080 GPC1DAT, R/W, Address = 0xE020_0084 举例 #define GPC1CON *((volatile unsigned int*)0xE0200080) #define GPC1DAT *((volatile unsigned int*)0xE0200084) *(unsigned int*)GPC1CON &= ~(0xf 12); *(unsigned int*)GPC1CON |= (0x1 12); *(unsigned int*)GPC1DAT &= ~(0x1 3); *(un
[单片机]
<font color='red'>S5PV210</font> 点亮Led
S5PV210根文件系统的制作(一)
一、基本概念 文件管理:数据管理算法 文件系统:管理文件算法的载体 文件系统的功能:管理分区上的数据(增删查改) 文件系统的分类:fat32/ntfs/ext3/ext4/yaffs/jffs/cramfs/..... 文件系统的表现形态:   window--------- 森林   linux------------ 树 ------- 文件目录标准 文件系统与根文件系统:   根文件系统:  系统启动时加载的助文件系统   其他文件系统:  根系统启动后挂载的其他文件系统 二、需要用到的工具 busybox-1.20.2.tar,yaffs2-source,bash-4.0.t
[单片机]
s5pv210 的启动
1、开发板已启动从0x0获取数据(内部64k的硬盘,里面含有三星固化的BL0段代码),将其读到a8软核中,进行运算,主要用于初始化时钟,96k的内部IRAM.并负责 指定启动设备(通常为外部硬盘),从指定的启动设备中拷贝BL1段代码(不超过16k)到I RAM中(96k),并从BL1代码的启示位置开始运行. 2、BL1段代码再从启动设备中取BL1段后面的代码BL2段代码,也将其拷贝到96k的IRAM中(BL1,BL2属于u-boot部分)。并从BL2的起始地址开始运行。 3、然后BL2段代码初始化外部内存以及其他的配置,并将硬盘启动设备中的内核,根文件系统加载到SDRAM中(512m)再到OS开始的起始位置开始运行,并挂载根文件
[单片机]
<font color='red'>s5pv210</font> 的启动
三星s5pv210之芯灵思Sin210与Ti Beaglebone Black之对比
1.外观对比 Ø 芯灵思Sin210 Ø TI Beaglebone Black 2.尺寸对比 Ø 芯灵思Sin210 采用核心板+底板结构,核心板尺寸5CM*6CM;底板尺寸10.6CM*15CM Ø TI Beaglebone Black 8.636cm * 5.334cm 3.配件对比 Ø 芯灵思Sin210 Ø TI Beaglebone Black 只提供一块板子 + miniUSB线 4.液晶LCD对比 Ø 芯灵思Sin210 标配4.3 电阻触摸屏 Ø TI Beaglebone Black 无 5.主打操作系统 Ø 芯灵思Sin210 WinCE Ø TI Beaglebone Bla
[单片机]
三星<font color='red'>s5pv210</font>之芯灵思Sin210与Ti Beaglebone Black之对比
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved