GPIO的标准接口函数

一、什么是GPIO的标准接口函数

在chrdev章节中访问GPIO的方法:需自己编写地址映射的版本:
request_mem_region()申请GPIO寄存器的物理内存区---->ioremap()IO内存的动态映射,得到虚拟地址---->访问虚拟地址。
需要查找CPU的使用手册。

内核封装的标准接口函数,简单的GPIO访问方法:
GPIO是嵌入式平台最常见的一个硬件模块,所以linux内核将GPIO的访问过程封装成了标准的接口函数,这些接口函数在调用的时候和平台无关的。

二、GPIO标准接口函数

参考说明文档:Documentation\gpio.txt
#include <linux/gpio.h>

1. GPIO的申请和释放

GPIO使用之前先申请,使用之后需要释放

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

参数说明:
unsigned gpio ---->GPIO口号,GPIO的ID,每个GPIO口一个
const char *label ---->自定义的GPIO的名字
返回值:
returning 0 or negative errno

2. 配置GPIO为输出还是输入

int gpio_direction_input(unsigned gpio);
	
int gpio_direction_output(unsigned gpio, int value);

3. 获取GPIO的输入值或设置GPIO的输出值

/* GPIO INPUT:  return zero or nonzero */

int gpio_get_value(unsigned gpio);

/* GPIO OUTPUT */
	
void gpio_set_value(unsigned gpio, int value);

注意:这些函数是通用的标准函数,是与平台无关的。

三、GPIO口号

1. GPIO号是与硬件相关的

每个GPIO都有一个GPIO口号的,使用GPIO口号还识别/区分一个具体的GPIO。GPIO号是与硬件相关的。

2. GPIO号的定义

/kernel/arch/arm/plat-s5p6818/common/cfg_type.h

enum {
    PAD_GPIO_A      = (0 * 32),
    PAD_GPIO_B      = (1 * 32),
    PAD_GPIO_C      = (2 * 32),
    PAD_GPIO_D      = (3 * 32),
    PAD_GPIO_E      = (4 * 32),
    PAD_GPIO_ALV    = (5 * 32),
};

例子:
D8 —> GPIOC17 —>PAD_GPIO_C+17
D9 —> GPIOC8 —>PAD_GPIO_C+8
D10 —> GPIOC7 —>PAD_GPIO_C+7
D11 —> GPIOC12 —>PAD_GPIO_C+12

==============================================================================================

四、出错的解决方法:

1. 出的错误:

[root@GEC6818 /test]#insmod s5p6818_led_drv.ko 
[   25.508000] led_dev_id = 254803968, major = 243, minor = 0
[   25.510000] GPIOC17_D8 request error!!!
[   25.513000] S5P6818 led driver init errcode = -16
insmod: can't insert 's5p6818_led_drv.ko': Device or resource busy

2. 解决问题1:

说明在安装这个驱动的时候,可能有其他的驱动申请了这个GPIO

1)查看系统安装的module
[root@GEC6818 /test]#lsmod
x6818_humidity 2475 0 - Live 0xbf01d000 (O)
stepmotor 4256 0 - Live 0xbf018000 (O)
relay 1244 0 - Live 0xbf014000 (O)
led 1593 0 - Live 0xbf010000 (O)
gec6818_beep 1551 0 - Live 0xbf00c000 (O)
gas_drv 2257 0 - Live 0xbf008000 (O)
dc_motor 1802 0 - Live 0xbf004000 (O)
buttons_drv 2792 0 - Live 0xbf000000 (O)
2)去掉这些驱动的安装过程

修改profile文件,系统起来不让安装其他驱动:

#vi /etc/profile
#source /IOT/driver_ko/insmod_driver.sh

#cd /IOT
#./iot &
#cd /

复位再安装即可。

3. 解决问题2:(投机取巧)

因为在其他驱动程序已经申请,因此当前程序不再申请GPIO(gpio_request()),直接使用。

4. 解决问题3:(投机取巧)

申请GPIO之前,先调用gpio_free(),释放已被其他驱动程序申请的gpio;
再调研gpio_request(),申请该gpio。

4. 解决问题4:(正规的方法(内核裁剪LED驱动))

去内核源码中,找到使用这个GPIO的驱动,(内核裁剪)卸载这个驱动,不将该驱动编译到内核。

内核源码工程中搜索:PAD_GPIO_C + 17

// /arch/arm/plat-s5p6818/gec6818/devices.c
#if defined(CONFIG_LEDS_GPIO)
static struct gpio_led GEC6818_leds[] = {
	{
		.name = "led1",	//D7
		.default_trigger = "none",
		.active_low = 1,
		.gpio = PAD_GPIO_E + 13,
	}, {
		.name = "led2",	//D8
		.default_trigger = "none",
		.active_low = 1,
		.gpio = PAD_GPIO_C + 17,
	}, {
		.name = "led3",	//D9
		.default_trigger = "none",
		.active_low = 1,
		.gpio = PAD_GPIO_C + 8,
	}, {
		.name = "led4",	//D10
		.default_trigger = "none",
		.active_low = 1,
		.gpio = PAD_GPIO_C + 7,
	},{
		.name = "led5",	//D11
		.default_trigger = "heartbeat",
		.active_low = 1,
		.gpio = PAD_GPIO_C + 12,
	},
};
#endif

CONFIG_LEDS_GPIO —>条件编译选项,内核通过条件编译来配置源码。

需要将:“CONFIG_LEDS_GPIO” 从内核中去掉

关键:重新配置并编译内核

1)拷贝配置文件
wsl@wsl-VirtualBox:~/kernel/S5P6818/kernel$ cp arch/arm/configs/GEC6818_defconfig  ./config
2)调出配置菜单
wsl@wsl-VirtualBox:~/kernel/S5P6818/kernel$ make menuconfig  --->出现内核的配置菜单。
3)进入内核配置菜单

输入**"/"**,进入搜索窗口,搜索条件编译选项:CONFIG_LEDS_GPIO

Symbol: LEDS_GPIO [=y] │
│ Type : tristate │
│ Prompt: LED Support for GPIO connected LEDs │
│ Defined at drivers/leds/Kconfig:149 │
│ Depends on: NEW_LEDS [=y] && LEDS_CLASS [=y] && GENERIC_GPIO [=y] │
│ Location: │
│ -> Device Drivers │
│ -> LED Support (NEW_LEDS [=y]) │
│ │
│ │
│ Symbol: LEDS_GPIO_REGISTER [=n] │
│ Type : boolean

条件编译选项的默认值是y,我们将它改成n。

4)修改配置

Device Drivers —>
-*- LED Support —>
< > LED Support for GPIO connected LEDs
如果找不到条件编译选项,查看help

5)保存退出
6)拷贝回去

因为修改是在kernel下的 .config,但编译时是使用GEC6818_defconfig。

wsl@wsl-VirtualBox:~/kernel/S5P6818/kernel$ cp .config  arch/arm/configs/GEC6818_defconfig 	
7)重新编译内核
wsl@wsl-VirtualBox:~/kernel/S5P6818/kernel$ ./mk -k
8)将内核的映像文件烧写到emmc中

/home/wsl/kernel/S5P6818/out/release/boot.img

更新下系统的方法:
fastboot
TF卡

五、编译内核出错

/home/wsl/kernel/S5P6818/out/host/linux-x86/bin/mkuserimg.sh: line 84: /home/wsl/kernel/S5P6818/out/host/linux-x86/bin/make_ext4fs: No such file or directory

不会生成新的boot.img

解决方法:
安装32bits支持包

#sudo apt-get install lib32c-dev 
#sudo apt-get install lib32stdc++6 

六、源码

例程源码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值