目标环境:搭载A20芯片的核心板Cubieboard2,使用522扩展板,用TF卡搭载cb2-dvk-sdcard-ubuntu-desktop-lcd-ctp-lvds-1024x600-v1.1.img系统
管脚图:http://docs.cubieboard.org/cubieboard1_and_cubieboard2_gpio_pin
GPIO是General Purpose Input/Output的简写,通用输入输出接口。GPIO是一种泛指,几乎所有MCU芯片都有GPIO。包括UART/SPI等接口管脚,也是一种GPIO。在中文上,我觉得用“输入输出管脚”的说法比较合适。。既然GPIO与硬件相关,那么必然厂家需要提供支持。
全志芯片的GPIO,由运行其上的Linux版本:linux-sunxi提供直接支持。可以用过两种方式操作GPIO。
一、设置linux-sunxi启动脚本配置文件,开启系统对gpio的支持,然后通过echo指令进行操作。优点:不用编程;缺点:改系统配置文件,重启系统后生效;
二、使用sunxi的相关驱动(C、python等)。优点:不论系统配置文件是否声明,均可操作;缺点:C语言需要编译对应系统的二进制文件。(Python可以绕开)
方法一、通过脚本配置文件和Linux指令操作GPIO
linux-sunxi有个配置文件script.bin,在系统启动时,通过该配置文件来设置全志芯片的各个管脚和操作参数。修改script.bin需要使用全志提供工具sunxi-tools。通过sunxi-tools将script.bin文件转换为script.fex文本文件,修改script.fex文件之后,再用sunxi-tools将其转换为script.bin文件,重启系统。系统将会开放对应设置的GPIO。我们常在各种文章看到“修改script.fex文件“,就是指这个。实际上,script.fex中,不仅仅只有对GPIO配置的声明。可参看全志资料:
Fex Guide:http://linux-sunxi.org/Fex_Guide#.5Bgpio_para.5D
GPIO:http://linux-sunxi.org/GPIO
1、script.bin在什么位置?
根据系统启动的方式不同,其位置不同:
1)TF启动:
/dev/目录下的mmcblk0p1包含uEnv.txt 、 script.bin和uImage;mmcblk0p2 是文件系统。挂载相应目录,可执行以下命令:
$mkdir /mnt/mmp1
$mkdir /mnt/mmp2
$mount /dev/mmcblk0p1 /mnt/mmp1
$mount /dev/mmcblk0p2 /mnt/mmp2
2)Nand启动:
/dev/目录下的nanda 包含boot.ini、sprite.axf、uEnv.txt、script.bin 和uImage 等;nandb 是文件系统。挂载相应目录,执行命令:
$mkdir /mnt/nanda
$mkdir /mnt/nandb
$mount /dev/nanda /mnt/nanda
$mount /dev/nandb /mnt/nandb
2、对script.bin操作
script.bin 为二进制文件,不可以直接更改,需要通过 bin2fex命令转换为 script.fex。 script.fex为文本格式,可以直接更改。更改后, 再通过fex2bin命令把script.fex转换成script.bin。 如果没有 bin2fex 和 fex2bin 命令,需要安装,在终端输入相应命令:
apt-get install git
git clone git://github.com/linux-sunxi/sunxi-tools.git
通过该命令,会在当前目录下得到安装文件 sunxi-tools。
cd sunxi-tools/
apt-get install make
apt-get install gcc
apt-get install libusb-1.0
make
sunxi-tools 目录下会产生 fex2bin 与 bin2fex两个工具。 把它们拷贝到/usr/bin目录下。
cp fex2bin bin2fex /usr/bin/
相应的转换操作如下:
fex2bin script.fex script.bin bin2fex script.bin script.fex
修改script.fex 需要使用 vim,执行以下命令安装:
apt-get install vim
3、修改script.fex中
[gpio_para] gpio_used = 1 gpio_num = 5 gpio_pin_1 = port:PH20<1><1> gpio_pin_2 = port:PH21<1><1> gpio_pin_3 = port:PH07<6> gpio_pin_4 = port:PE10<1><0> gpio_pin_5 = port:PE11<1><0>
说明:
1)script.fex中要按规定声明节段名,gpio是:[gpio_para]
2)script.fex中采用key=value的形式进行配置;
3)gpio_used:用于声明是否使用gpio,1标识使用,0标识不使用;
4)gpio_num:使用gpio的数量
5)gpio_pin_N=port:
:端口编号
:0标识输入;1标识输出;2-7根据不同芯片定义不同;
:0标识无效disabled;1标识“上升沿”有效;2标识“下降沿”有效;(仅当作为输入管脚时有用);default标识该选项采用默认值,可忽略;
:标识输出管脚的驱动能力(mA),0-3分别代表10mA、20mA、30mA和40mA;default标识该选项采用默认值,可忽略;
:标识输出管脚的初始电平,1标识高电平,0标识低电平(仅当作为输出管脚时有用);default标识该选项采用默认值,可忽略;
其中,PH20是核心板上的绿灯,PH21是核心板上的红灯,PE10和PE11是522扩展板上已经外接好的LED测试排灯。总共有8个,接核心板的PE4~PE11管脚。
4、将script.fex转换为script.bin并重启系统
fex2bin script.fex script.bin
reboot
5、启动好之后,用linux的echo指令打开系统对gpio的映射,对应我们新配置的script.fex,就是第4号和5号两个管脚:
root@cubieboard2:/# echo 4 > /sys/class/gpio/export
root@cubieboard2:/# echo 5 > /sys/class/gpio/export
然后我们就可以看到系统赋予的gpio名称:
root@cubieboard2:/# ls sys/class/gpio export gpio4_pe10 gpio5_pe11 gpiochip1 unexport
操作gpio的势能方向:
root@cubieboard2:/# echo out > /sys/class/gpio/gpio4_pe10/direction
root@cubieboard2:/# echo out > /sys/class/gpio/gpio4_pe11/direction
操作gpio控制led灯的亮灭:
root@cubieboard2:/# echo 1 > /sys/class/gpio/gpio4_pe10/value
root@cubieboard2:/# echo 0 > /sys/class/gpio/gpio4_pe10/value
方法二、使用sunxi的相关驱动(C、python等)
附件分别是C和py的库文件。
1、C语言示例代码(只使用gpio_lib.c和gpio_lib.h):
#include
#include
#include "gpio_lib.h"
#define PE5 SUNXI_GPE(5)
#define PE8 SUNXI_GPE(8)
#define PE9 SUNXI_GPE(9)
#define PE10 SUNXI_GPE(10)
#define PE11 SUNXI_GPE(11)
int main()
{
if(SETUP_OK!=sunxi_gpio_init()){
printf("Failed to initialize GPIO\n");
return -1;
}
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE5,OUTPUT)){
printf("Failed to config GPIO PE5 pin\n");
return -1;
}
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE8,OUTPUT)){
printf("Failed to config GPIO PE8 pin\n");
return -1;
}
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE9,OUTPUT)){
printf("Failed to config GPIO PE9 pin\n");
return -1;
}
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE10,OUTPUT)){
printf("Failed to config GPIO PE10 pin\n");
return -1;
}
if(SETUP_OK!=sunxi_gpio_set_cfgpin(PE11,OUTPUT)){
printf("Failed to config GPIO PE11 pin\n");
return -1;
}
while(1){
if(sunxi_gpio_output(PE5,HIGH)){
printf("Failed to set GPIO PE5 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE5,LOW)){
printf("Failed to set GPIO PE5 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE8,HIGH)){
printf("Failed to set GPIO PE8 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE8,LOW)){
printf("Failed to set GPIO PE8 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE9,HIGH)){
printf("Failed to set GPIO PE9 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE9,LOW)){
printf("Failed to set GPIO PE9 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE10,HIGH)){
printf("Failed to set GPIO PE10 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE10,LOW)){
printf("Failed to set GPIO PE10 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE11,HIGH)){
printf("Failed to set GPIO PE11 pin value\n");
return -1;
}
usleep(500000);
if(sunxi_gpio_output(PE11,LOW)){
printf("Failed to set GPIO PE11 pin value\n");
return -1;
}
usleep(500000);
}
sunxi_gpio_cleanup();
return 0;
}
可以在目标操作系统上直接编译:
$sudo apt-get install gcc build-essential
$tar -xf gpio.tar $cd gpio/ $gcc gpio_lib.c -c
$gcc gpio.c -c $gcc gpio.o gpio_lib.o -o gpio
$./gpio
也可以搭建交叉编译环境来编译:
$arm-linux-gnueabi-gcc gpio_lib.c gpio.c -static -o gpio
$./gpio
2、python代码示例
配置python
sudo apt-get install python-dev wget http://dl.linux-sunxi.org/users/tom/pySUNXI-0.1.12.tar.gz tar zxf pySUNXI-0.1.12.tar.gz sudo python setup.py install
新建一个blink.py文件
#!/usr/bin/env python
import SUNXI_GPIO as GPIO
import time
RED_LED = GPIO.PE11
GPIO.init()
GPIO.setcfg(RED_LED, GPIO.OUT)
while True:
GPIO.output(RED_LED, GPIO.HIGH)
time.sleep(1)
GPIO.output(RED_LED, GPIO.LOW)
time.sleep(1)
运行代码:
chmod +x blink.py sudo ./blink.py
顺便补充一下,经过测试,本例中A20搭载的是ubuntu的一个精简版linaro 12.09。示例中交叉编译好的C语言执行文件,同样可以在cb2-dvk-nand-android-4.2.2-lcd-ctp-lvds-1024x600-v1.1.img中执行。