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);
上一篇:make: Warning: File `led.c' has modification time 15 s in the future
下一篇:喜羊羊系列【设备 - 驱动器 编译进内核】
推荐阅读最新更新时间:2026-03-25 11:32
- 用于 7VIN 至 16VIN、1.5V 和 1.2V 输出的 LTM4628EV DC/DC 模块稳压器的典型应用电路
- 使用 Analog Devices 的 LTC3728LIGN 的参考设计
- DER-406 - 适用于 A19 灯的 5.76 W 高 PF 非隔离降压-升压型 TRIAC 调光 LED 驱动器
- ADR5045B 5V 输出精密微功率并联模式电压基准的典型应用
- LT3970EDDB-3.42 2.5V 降压转换器的典型应用
- MC78M08BDTG 8V 电流调节器的典型应用
- LT1021DCN8-5 精密电压基准的典型应用
- DER-282 - 100W, 扁平(11 mm), LLC DC-DC转换器
- REF193 低压差开尔文连接电压基准的典型应用电路
- LT3088EM 线性稳压器用于添加软启动的典型应用

allegro标准库
Altium Designer26库(schLib/pcbLib)安装与封装关联排查指南
Arduino IDE 2.3.7
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号