一款开发板除了板子的外设以外,资料也是非常重要地,尤其是基于linux的系统,如果没有资料这块板子很难发挥功效。米尔STM32MP135开发板的资料还是比较全面地,本次测试的是板子的GPIO输入/输出系统,板子的驱动提供了GPIO子系统的驱动,这样可以省去修改内核和设备树的麻烦。
root@myd-yf13x:~# ls /sys/class/gpio/
export gpiochip112 gpiochip16 gpiochip48 gpiochip80 unexport
gpiochip0 gpiochip128 gpiochip32 gpiochip64 gpiochip96
root@myd-yf13x:~#
同时板子上也带了很多设备的驱动,常见到的设备基本都内置了驱动。usb、IIC、SPI、uart...
root@myd-yf13x:~# cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
21 sg
29 fb
81 video4linux
89 i2c
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
153 spi
166 ttyACM
180 usb
188 ttyUSB
189 usb_device
226 drm
242 media
243 rpmb
244 ttyUSI
245 ttySTM
246 bsg
247 watchdog
248 tee
249 iio
250 ptp
251 pps
252 cec
253 rtc
254 gpiochip
Block devices:
1 ramdisk
7 loop
8 sd
11 sr
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
253 device-mapper
254 virtblk
259 blkext
root@myd-yf13x:~#
本次测试主要是使用用户程序对GPIO进行测试,不涉及到驱动的编写。
首先是控制LED灯的亮灭,这个LED是系统内置的一个专用驱动,用户可以根据该代码进行修改。虽然是专用的,但是只是多了一些命令和普通的GPIO操作非常相似。下面就简述一下GPIO的输出测试过程:
一、操作GPIO输出
1、导出引脚
使用export导出需要操作的引脚,这里面有个引脚编号计算的问题:
公式:PinPortIndex*16 + PinNum,端口号*16 + 引脚编号
例如:PF14引脚,PA=0,PB=1....,F就是5,引脚号14 ,16*5+14=94,
root@myd-yf13x:~# echo 94 > /sys/class/gpio/export
导出成功后会在/sys/class/gpio/目录下生成 PF14 目录,
root@myd-yf13x:~# ls /sys/class/gpio/
PF14 gpiochip0 gpiochip128 gpiochip32 gpiochip64 gpiochip96
export gpiochip112 gpiochip16 gpiochip48 gpiochip80 unexport
root@myd-yf13x:~#
2、设置引脚“方向”
向/sys/class/gpio/PF14/direction文件写“in”或“out”,就可以设置引脚的方向。
root@myd-yf13x:~# echo "out" > /sys/class/gpio/PF14/direction
3、设置引脚输出
向/sys/class/gpio/PF14/value文件写0或1,就可以设置引脚的输出电平。反之读取该文件的内容,就可以知道引脚当前的电平。但是这个方法不是很好,比较低效尤其是多个输入的情况。
知道了怎样操作GPIO,就编写一个程序测试一下,这个程序是用的LED驱动,但是方法是一样的。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc,char **argv){
int status = 0;
FILE *pf = NULL;
printf("Hello World!\n\r");
if (argc > 1 )
{
status = 1;
printf("argc=%d , argv =%s \n\r",argc,(char *)argv[1]);
pf = fopen("/sys/class/leds/blue:heartbeat/brightness","w");
fprintf(pf,"%s",(char *)argv[1]);
fclose(pf);
}
return status;
}
使用 hello 1 打开led,hello 0 关闭led
二、GPIO的输入
输入要比输出复杂一些,尤其是在linux系统下更甚,通常输入有两种方法,一是:使用程序轮询的方法,这种方法效率不高很是占用资源,但是简单,另一种是:通过中断程序的方法。这种方法效率较高,但是需要专门的驱动,幸好板子的BSP中内置了驱动程序。
开发板中设计有一个用户按键S2,这个按键的驱动在/dev/input/event0下。
root@myd-yf13x:~# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio-keys"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/gpio-keys/input/input1
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=10000000
root@myd-yf13x:~#
只要读取/dev/input/event0的内容就可以获得按键事件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/input-event-codes.h>
const char * path = "/dev/input/event0";
int main(int argc,char *argv[])
{
int ret;
int fd;
struct input_event event;
fd = open(path,O_RDONLY);
if(fd < 0)
{
perror(path);
exit(-1);
}
while(1)
{
ret = read(fd,&event,sizeof(struct input_event));
if(ret == sizeof(struct input_event))
{
if(event.type != EV_SYN)
{
printf("Event: time %ld.%ld,",event.time.tv_sec,event.time.tv_usec);
printf("type:%d,code:%d,value:%d\n", event.type,event.code,event.value);
}
}
}
close(fd);
return 0;
}
程序的输出:
可以发现每次按键松开时都会“同时”生成两个事件,这可能是驱动设置错误造成地,按照程序的逻辑应该是:按下S2时产生一次事件,放开S2时产生一次事件,而不应该是只有放开时同时产生两个事件。等有时间了查看一下这个驱动的源码。
总结:虽然驱动有一些瑕疵,但是总体的过程还是比较顺利地,但是在测试驱动和编译内核时也出现了一个例外情况,将ST开发板的镜像系统写入开发板时,在UFD的第二阶段时出现了USB设备无法加载的情况。不知道这是何故。
有对该板子有兴趣的朋友,欢迎大家一起来讨论。
一款开发板除了板子的外设以外,资料也是非常重要地,尤其是基于linux的系统,如果没有资料这块板子很难发挥功效。米尔STM32MP135开发板的资料还是比较全面地,本次测试的是板子的GPIO输入/输出系统,板子的驱动提供了GPIO子系统的驱动,这样可以省去修改内核和设备树的麻烦。
米尔的东西还是不错的。