一、什么是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