一款开发板除了板子的外设以外,资料也是非常重要地,尤其是基于linux的系统,如果没有资料这块板子很难发挥功效。米尔STM32MP135开发板的资料还是比较全面地,本次测试的是板子的GPIO输入/输出系统,板子的驱动提供了GPIO子系统的驱动,这样可以省去修改内核和设备树的麻烦。
- root@myd-yf13x:~
- export gpiochip112 gpiochip16 gpiochip48 gpiochip80 unexport
- gpiochip0 gpiochip128 gpiochip32 gpiochip64 gpiochip96
- root@myd-yf13x:~
同时板子上也带了很多设备的驱动,常见到的设备基本都内置了驱动。usb、IIC、SPI、uart...
- root@myd-yf13x:~
- 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,
导出成功后会在/sys/class/gpio/目录下生成 PF14 目录,
- root@myd-yf13x:~
- PF14 gpiochip0 gpiochip128 gpiochip32 gpiochip64 gpiochip96
- export gpiochip112 gpiochip16 gpiochip48 gpiochip80 unexport
- root@myd-yf13x:~
2、设置引脚“方向”
向/sys/class/gpio/PF14/direction文件写“in”或“out”,就可以设置引脚的方向。
3、设置引脚输出
向/sys/class/gpio/PF14/value文件写0或1,就可以设置引脚的输出电平。反之读取该文件的内容,就可以知道引脚当前的电平。但是这个方法不是很好,比较低效尤其是多个输入的情况。
知道了怎样操作GPIO,就编写一个程序测试一下,这个程序是用的LED驱动,但是方法是一样的。
-
-
-
-
-
- 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:~
- 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设备无法加载的情况。不知道这是何故。
有对该板子有兴趣的朋友,欢迎大家一起来讨论。
|