Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

Table of Contents

GPIO

Kernel有一部分已经写好的gpio功能,如下面这个文档所写:

https://git.phytec.de/linux-mainline/tree/Documentation/gpio/drivers-on-gpio.txt?h=v4.9.98-phy

本文也写了一些接口的用法如gpio的LED,以及按键。

Code Block
collapsetrue
- leds-gpio: drivers/leds/leds-gpio.c will handle LEDs connected to GPIO
lines, giving you the LED sysfs interface

- ledtrig-gpio: drivers/leds/trigger/ledtrig-gpio.c will provide a LED trigger,
i.e. a LED will turn on/off in response to a GPIO line going high or low
(and that LED may in turn use the leds-gpio as per above).

- gpio-keys: drivers/input/keyboard/gpio_keys.c is used when your GPIO line
can generate interrupts in response to a key press. Also supports debounce.

- gpio-keys-polled: drivers/input/keyboard/gpio_keys_polled.c is used when your
GPIO line cannot generate interrupts, so it needs to be periodically polled
by a timer.

- gpio_mouse: drivers/input/mouse/gpio_mouse.c is used to provide a mouse with
up to three buttons by simply using GPIOs and no mouse port. You can cut the
mouse cable and connect the wires to GPIO lines or solder a mouse connector
to the lines for a more permanent solution of this type.

- gpio-beeper: drivers/input/misc/gpio-beeper.c is used to provide a beep from
an external speaker connected to a GPIO line.

- gpio-tilt-polled: drivers/input/misc/gpio_tilt_polled.c provides tilt
detection switches using GPIO, which is useful for your homebrewn pinball
machine if for nothing else. It can detect different tilt angles of the
monitored object.

- extcon-gpio: drivers/extcon/extcon-gpio.c is used when you need to read an
external connector status, such as a headset line for an audio driver or an
HDMI connector. It will provide a better userspace sysfs interface than GPIO.

- restart-gpio: drivers/power/reset/gpio-restart.c is used to restart/reboot
the system by pulling a GPIO line and will register a restart handler so
userspace can issue the right system call to restart the system.

- poweroff-gpio: drivers/power/reset/gpio-poweroff.c is used to power the
system down by pulling a GPIO line and will register a pm_power_off()
callback so that userspace can issue the right system call to power down the
system.

- gpio-gate-clock: drivers/clk/clk-gpio.c is used to control a gated clock
(off/on) that uses a GPIO, and integrated with the clock subsystem.

- i2c-gpio: drivers/i2c/busses/i2c-gpio.c is used to drive an I2C bus
(two wires, SDA and SCL lines) by hammering (bitbang) two GPIO lines. It will
appear as any other I2C bus to the system and makes it possible to connect
drivers for the I2C devices on the bus like any other I2C bus driver.

- spi_gpio: drivers/spi/spi-gpio.c is used to drive an SPI bus (variable number
of wires, at least SCK and optionally MISO, MOSI and chip select lines) using
GPIO hammering (bitbang). It will appear as any other SPI bus on the system
and makes it possible to connect drivers for SPI devices on the bus like
any other SPI bus driver. For example any MMC/SD card can then be connected
to this SPI by using the mmc_spi host from the MMC/SD card subsystem.

- w1-gpio: drivers/w1/masters/w1-gpio.c is used to drive a one-wire bus using
a GPIO line, integrating with the W1 subsystem and handling devices on
the bus like any other W1 device.

- gpio-fan: drivers/hwmon/gpio-fan.c is used to control a fan for cooling the
system, connected to a GPIO line (and optionally a GPIO alarm line),
presenting all the right in-kernel and sysfs interfaces to make your system
not overheat.

- gpio-regulator: drivers/regulator/gpio-regulator.c is used to control a
regulator providing a certain voltage by pulling a GPIO line, integrating
with the regulator subsystem and giving you all the right interfaces.

- gpio-wdt: drivers/watchdog/gpio_wdt.c is used to provide a watchdog timer
that will periodically "ping" a hardware connected to a GPIO line by toggling
it from 1-to-0-to-1. If that hardware does not receive its "ping"
periodically, it will reset the system.

- gpio-nand: drivers/mtd/nand/gpio.c is used to connect a NAND flash chip to
a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
NAND flash MTD subsystem and provides chip access and partition parsing like
any other NAND driving hardware.

因此如果所用的功能在kernel中有实现,则可以直接使用内核提供的接口,如LED/按键,而如果并未找到,则可以使用下面表格描述的应用层接口来访问GPIO。

首先要确定该IO口的pinmux是否是GPIO,大多数的io口上电后默认是GPIO,这个可以在处理器的datasheet中查找。

但有时IO口的配置会被后边的bootloader修改为其他配置,因此最保险的方法是将要使用的GPIO都在设备树中将MUX/复用功能定义出来:

参考来源配置
am335x-pcm-953.dtsi


Code Block
languagebash
themeMidnight
&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


Code Block
languagebash
themeMidnight
&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引脚为低:

Code Block
languagebash
themeMidnight
gpioset 3 22=0

读取gpio4的22引脚,同时会设置引脚为输入:

Code Block
languagebash
themeMidnight
gpioget 3 22
0

更多例子:

https://github.com/brgl/libgpiod/blob/master/README

  • i.MX6q/i.MX6ul:     Linux GPIO number: <N> = (<X> - 1) * 32 + <Y> 

  • AM57x:     Linux GPIO number: <N> = (<X> - 1) * 32 + <Y> 
  • AM335x: Linux GPIO number: <N> = <X> * 32 + <Y>

  • The GPIOs are identified as GPIO<X>_<Y> (e.g. GPIO5_07). <X> identifies the GPIO bank and counts from 1 to 7, while <Y> stands for the GPIO within the bank. <Y> is being counted from 0 to 31 (32 GPIOs on each bank).

Code Block
languagebash
themeMidnight
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

Code Block
languagebash
themeMidnight
titleimx6qdl-phytec-mira-peb-eval-01.dtsi
&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;
		};
	};
};

测试按键事件:

Code Block
languagebash
themeMidnight
$ 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

Code Block
languagebash
themeMidnight
titleimx6qdl-phytec-mira-peb-eval-01.dtsi
&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:

Code Block
languagebash
themeMidnight
$ ls /sys/class/leds
mira-blue      mira-red       mmc1::         user-led1      user-led3
mira-green     mmc0::         phycore-green  user-led2

打开led:

Code Block
languagebash
themeMidnight
$ echo 255 > /sys/class/leds/user-led1/brightness


Note

如果该led硬件上不支持亮度选择的话, 输出任何一个非零数值都能点亮该led.

关闭led:

Code Block
languagebash
themeMidnight
$ echo 0 > /sys/class/leds/user-led1/brightness

闪烁led:

Code Block
languagebash
themeMidnight
$ 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数字为串口号




首先需要设置串口参数

Code Block
languagebash
themeMidnight
title注意这个例子是在am335x平台
stty -F /dev/ttyO2 115200 raw

如果是特殊波特率,需要使用如的方法来配置

可以使用 echo 来发送数据到串口

Code Block
languagebash
themeMidnight
title注意这个例子是在am335x平台
echo "hello~tty device" > /dev/ttyO2

然后就可以在接口处看到输出结果。

使用 cat 来接收数据

Code Block
languagebash
themeMidnight
title注意这个例子是在am335x平台
cat /dev/ttyO2

注意此时会有echo返回,如果想关闭echo功能可以通过stty设置

Code Block
languagebash
themeMidnight
title注意这个例子是在am335x平台
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的速率。

可以使用

Code Block
languagebash
themeMidnight
cansend can0 123#45.67

测试发送,使用

Code Block
languagebash
themeMidnight
candump can0

测试接收,另外如果不能收发请注意是否处在bus-off状态,使用下面的指令来检查。

Code Block
languagebash
themeMidnight
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的位置

Code Block
languagebash
themeMidnight
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个字节并在屏幕上输出

Code Block
languagebash
themeMidnight
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操作

Code Block
languagebash
themeMidnight
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)的速度

测试读取速度

Code Block
languagebash
themeMidnight
hdparm -Tt /dev/sda

测试写入速度

Code Block
languagebash
themeMidnight
dd if=/dev/zero of=/tmp/output bs=8k count=10k


Code Block
languagebash
themeMidnight
iozone -a -g 256M -s 256M -b file.xls

怎样设置RTC

Code Block
languagebash
themeMidnight
date -s "2017-7-17 15:44"

设置时间为07月17日,15点44分,2017

Code Block
languagebash
themeMidnight
hwclock -w -u

更新RTC时间。

另,如果RTC未设置过时间,则会打印内核信息

Code Block
languagebash
themeMidnight
[    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总线上。

在系统中,你可以用

Code Block
languagebash
themeMidnight
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 节点配置,如:

Code Block
languagebash
themeMidnight
 aliases {
 	rtc1 = &da9062_rtc;
	rtc2 = &snvs_rtc;
};

接下来,你可以用之前的指令来设定某个RTC的时间,或者读取RTC的时间并写入系统:

Code Block
languagebash
themeMidnight
读取入系统:
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 。

如:

Code Block
languagebash
themeMidnight
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访问,需要访问的话需要在设备树中注释掉驱动。

Code Block
languagebash
themeMidnight
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


事项代码
查看当前工作频率


Code Block
languagebash
themeMidnight
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq


查看可设置的频率列表


Code Block
languagebash
themeMidnight
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 


设置最大的调整频率


Code Block
languagebash
themeMidnight
echo 2700000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq  


查看可用的频率调节器(governors)

https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt


Code Block
languagebash
themeMidnight
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors


设置为固定的频率


Code Block
languagebash
themeMidnight
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
echo 2700000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed


关闭CPU/关闭核心

查看CPU核数量:

Code Block
languagebash
themeMidnight
ls /sys/devices/system/cpu  -1

然后可通过以下指令关闭

Code Block
languagebash
themeMidnight
echo 0 > /sys/devices/system/cpu/cpu3/online

关闭后echo 1 可以打开。