Phytec中国的wiki
support@phytec.cn
热线:0755-61802110-803
GPIO
Kernel有一部分已经写好的gpio功能,如下面这个文档所写:
https://git.phytec.de/linux-mainline/tree/Documentation/gpio/drivers-on-gpio.txt?h=v4.9.98-phy
本文也写了一些接口的用法如gpio的LED,以及按键。
因此如果所用的功能在kernel中有实现,则可以直接使用内核提供的接口,如LED/按键,而如果并未找到,则可以使用下面表格描述的应用层接口来访问GPIO。
首先要确定该IO口的pinmux是否是GPIO,大多数的io口上电后默认是GPIO,这个可以在处理器的datasheet中查找。
但有时IO口的配置会被后边的bootloader修改为其他配置,因此最保险的方法是将要使用的GPIO都在设备树中将MUX/复用功能定义出来:
参考来源 | 配置 |
---|---|
am335x-pcm-953.dtsi | &am33xx_pinmux { pinctrl-names = "default"; pinctrl-0 = <&cb_gpio_pins>; cb_gpio_pins: pinmux_cb_gpio { pinctrl-single,pins = < 0x168 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart0_ctsn.gpio1_8 */ 0x16C (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart0_rtsn.gpio1_9 */ >; }; }; |
imx6qdl-phytec-pfla02.dtsi | &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; pinctrl_hog: hoggrp { fsl,pins = < MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x1b0b0 /* PMIC interrupt */ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x1b0b0 /* Green LED */ >; }; }; |
其他设备树的配置请参考:
linux内核设备树修改指南 / linux kernel device tree modify guide
中的pinmux部分。
接下来是不同对应不同版本内核的GPIO使用方法。
gpio字符设备方法 | gpiosys方法 | |
---|---|---|
适用的内核版本 使用uname -r查询 | V4.8或之后的版本 | V4.8之前的版本 |
命令行操作方法 | 设置gpio4的22引脚为低: gpioset 3 22=0 读取gpio4的22引脚,同时会设置引脚为输入: gpioget 3 22 0 更多例子: |
echo 65 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio65/direction echo 1 > /sys/class/gpio/gpio65/value echo 0 > /sys/class/gpio/gpio65/value |
程序开发 | https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git 可以直接参考其中tools中各个工具如: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/tools/gpioset.c 的代码 |
KEY
设备树gpio_keys配置文档:
https://www.kernel.org/doc/Documentation/devicetree/bindings/input/gpio-keys.txt
&iomuxc { pinctrl_gpio_keys: gpiokeysgrp { fsl,pins = < MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x1b0b0 MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28 0x1b0b0 >; }; }; / { gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_keys>; status = "disabled"; home { label = "Home"; gpios = <&gpio6 18 GPIO_ACTIVE_LOW>; linux,code = <KEY_HOME>; }; power { label = "Power Button"; gpios = <&gpio5 28 GPIO_ACTIVE_LOW>; linux,code = <KEY_POWER>; gpio-key,wakeup; }; }; };
测试按键事件:
$ evtest No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0: stmpe-ts /dev/input/event1: gpio-keys Select the device event number [0-1]:1
LED
gpio-leds设备树配置文档说明:
https://www.kernel.org/doc/Documentation/devicetree/bindings/leds/leds-gpio.txt
&iomuxc { pinctrl_user_leds: userledsgrp { fsl,pins = < MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b0 MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x1b0b0 >; }; }; / { user_leds: user-leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_user_leds>; status = "disabled"; user-led1 { gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>; linux,default-trigger = "gpio"; default-state = "on"; }; user-led2 { gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>; linux,default-trigger = "gpio"; default-state = "on"; }; user-led3 { gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; linux,default-trigger = "gpio"; default-state = "on"; }; }; };
linux上操作led:
查找所有可用的led:
$ ls /sys/class/leds mira-blue mira-red mmc1:: user-led1 user-led3 mira-green mmc0:: phycore-green user-led2
打开led:
$ echo 255 > /sys/class/leds/user-led1/brightness
如果该led硬件上不支持亮度选择的话, 输出任何一个非零数值都能点亮该led.
关闭led:
$ echo 0 > /sys/class/leds/user-led1/brightness
闪烁led:
$ echo timer > /sys/class/leds/user-led1/trigger $ echo 200 > /sys/class/leds/user-led1/delay_on #设置打开led时间 $ echo 200 > /sys/class/leds/user-led1/delay_off #设置关闭led时间
串口
SOC | 串口设备名称 | 备注 |
---|---|---|
am335x | /dev/ttyO2 | 注意是字母O,数字为串口号 |
imx6/6ul/7 | /dev/ttymxc2 | 数字为串口号 |
首先需要设置串口参数
stty -F /dev/ttyO2 115200 raw
如果是特殊波特率,需要使用如的方法来配置
可以使用 echo 来发送数据到串口
echo "hello~tty device" > /dev/ttyO2
然后就可以在接口处看到输出结果。
使用 cat 来接收数据
cat /dev/ttyO2
注意此时会有echo返回,如果想关闭echo功能可以通过stty设置
stty -F /dev/ttyO2 115200 -onlcr -iexten -echo -echoe -echok -echoctl -echoke raw
CAN
我们的开发板上的CAN口一般为一个DB9接口,它的引脚定义如下:
请按照座子中的编号来连接,2&7引脚为信号,3&6脚为地。
而这个也是CAN最通用的引脚顺序 https://en.wikipedia.org/wiki/CAN_bus#Layers
高速CAN(ISO 11898-2 High Speed CAN)接口需要将接线的两端用120Ω的电阻端接
图来自 http://www.ni.com/white-paper/9759/en/
我们的开发板一般都配一个跳线帽来使能这个120Ω的电阻(如下图中的JP9)。
在连接两个设备时,共地不是必须的,只需要对应连接CAN_L,CAN_H即可。
长距离高噪声的环境下对线缆和屏蔽地等接法和选型有要求,请阅读相关材料。
CAN的软件配置位于
/lib/systemd/system/can0.service
默认是500k的速率。
可以使用
cansend can0 123#45.67
测试发送,使用
candump can0
测试接收,另外如果不能收发请注意是否处在bus-off状态,使用下面的指令来检查。
ip -d -s link show can0 2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 bitrate 500000 sample-point 0.800 tq 400 prop-seg 1 phase-seg1 2 phase-seg2 1 sjw 1 c_can: tseg1 2..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp-inc 1 clock 25000000 re-started bus-errors arbit-lost error-warn error-pass bus-off 0 0 0 0 0 0 numtxqueues 1 gso_max_size 65536 gso_max_segs 65535 RX: bytes packets errors dropped overrun mcast 0 0 0 0 0 0 TX: bytes packets errors dropped carrier collsns 0 0 0 0 0 0
EEPROM
开发板进入根目录/下查找eeprom的位置
root@phycore-am335x-1:~# cd / root@phycore-am335x-1:/# find . -name eeprom ./sys/devices/platform/ocp/44e0b000.i2c/i2c-0/0-0052/eeprom
读eeprom的前1024个字节并在屏幕上输出
root@phycore-am335x-1:/# dd if=/sys/devices/platform/ocp/44e0b000.i2c/i2c-0/0-0052/eeprom bs=1 count=1024 | od -x 0000000 55aa 6850 7479 6365 4d2d 7365 7473 6365 0000020 6e68 6b69 ffff ffff ffff ffff ffff ffff 0000040 ffff ffff ffff ffff ffff ffff ffff ffff * 0002000 1024+0 records in 1024+0 records out
对eeprom的全部字节写入0操作
root@phycore-am335x-1:/# dd if=/dev/zero of=/sys/devices/platform/ocp/44e0b000.i2c/i2c-0/0-0052/eeprom bs=4096 count=1 1+0 records in 1+0 records out root@phycore-am335x-1:/# dd if=/sys/devices/platform/ocp/44e0b000.i2c/i2c-0/0-0052/eeprom bs=1 count=1024 | od -x 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 0002000 1024+0 records in 1024+0 records out
测试磁盘(SD/NAND/SATA)的速度
测试读取速度
hdparm -Tt /dev/sda
测试写入速度
dd if=/dev/zero of=/tmp/output bs=8k count=10k
iozone -a -g 256M -s 256M -b file.xls
怎样设置RTC
date -s "2017-7-17 15:44"
设置时间为07月17日,15点44分,2017
hwclock -w -u
更新RTC时间。
另,如果RTC未设置过时间,则会打印内核信息
[ 1.943438] rtc-m41t80 0-0068: Oscillator failure, data is invalid. [ 1.950394] rtc-m41t80 0-0068: rtc core: registered rv4162 as rtc0
怎样使用RTC1/RTC2来作为系统时钟
部分核心板具有多个RTC,如phyCORE i.MX6核心板板载2个RTC,一个是i.MX6 CPU自己带的SNVS rtc,另一个是PMIC的RTC,由于这两个RTC性能不是很好,因此我们开发板又加了一个RTC,接在I2C总线上。
在系统中,你可以用
oot@phyboard-mira-imx6-3:/sys/class/rtc# cat rtc*/name rtc-m41t80 0-0068 da9063-rtc da9062-rtc snvs_rtc 20cc000.snvs:snvs-rtc-lp
这样的方法来检查/dev/rtc#和硬件RTC的对应关系,而这个是在设备树中由 aliases 节点配置,如:
aliases { rtc1 = &da9062_rtc; rtc2 = &snvs_rtc; };
接下来,你可以用之前的指令来设定某个RTC的时间,或者读取RTC的时间并写入系统:
读取入系统: hwclock -s -u -f /dev/rtc# 写入RTC: hwclock -w -u -f /dev/rtc#
如果要设定系统开机默认使用的RTC,需要配置内核的menuconfig(https://cateee.net/lkddb/web-lkddb/RTC_HCTOSYS_DEVICE.html),然后重新编译来实现:
I2C接口
在测试i2c接口时,主要通过i2ctools这个工具,文档:https://manpages.debian.org/unstable/i2c-tools/index.html 。
如:
imx7d-phyboard-zeta-001:~# i2cdetect 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1. I will probe address range 0x03-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
以上例子使用i2cdetect工具检测i2c1总线上,每个地址对i2c指令是否有反应。
通过i2ctools工具还可以实现读取某个i2c设备的寄存器,设置寄存器等功能。
需要注意的是,如果有驱动在使用这个地址(上面例子中的UU),则不能通过i2ctools访问,需要访问的话需要在设备树中注释掉驱动。
imx7d-phyboard-zeta-001:~# i2cdump 1 0x41 No size specified (using byte-data access) Error: Could not set address to 0x41: Device or resource busy
要开发操作i2c接口的应用程序,可以参考一下i2ctools的源码。
https://github.com/mozilla-b2g/i2c-tools
SPI
请参考内核提供的例子:
https://git.phytec.de/linux-mainline/tree/tools/spi?h=v4.9.98-phy
以及我们的文档:spidev测试方法 /how to test spidev
CPU的使用
CPU频率设置
在linux下有专门的驱动cpufreq来控制/设定cpu的工作频率,很多CPU都可以根据工作负载来动态的调整工作频率。
该驱动的文档为 https://www.kernel.org/doc/Documentation/cpu-freq/user-guide.txt
事项 | 代码 |
---|---|
查看当前工作频率 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq |
查看可设置的频率列表 | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies |
设置最大的调整频率 | echo 2700000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq |
查看可用的频率调节器(governors) https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt | cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors |
设置为固定的频率 | echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo 2700000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed |
关闭CPU/关闭核心
查看CPU核数量:
ls /sys/devices/system/cpu -1
然后可通过以下指令关闭
echo 0 > /sys/devices/system/cpu/cpu3/online
关闭后echo 1 可以打开。