driver - 避免写内核驱动¶
user-sapce driver vs kernel driver
[[toc]]
GPIO¶
sysfs¶
linux内核中有sysfs, 可以通过操作 /sys/class/gpio
目录下的文件来控制gpio口的高低电平、中断等等
export: 将gpio口写入该文件中,将gpio导出到user space中
gpiochip0 gpiochip32 gpiochip64: 芯片有这几组gpio口,每组gpio口有32个pin
unexport: 与export相反的操作
interrupts
gpio可以产生中断,/sys/class/gpio/gpio37
目录下的edge文件可以用来处理中断
可以写入的参数有 none
rising
falling
both
gpio-cdev¶
网关有如下的 ls /dev/gpiochi*
设备号,可以使用ioctl来访问
/*
* Demonstrate using gpio cdev to output a single bit
* On a BeagleBone Black, GPIO1_21 is user LED 1
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/gpio.h>
int main(void)
{
int f; int ret;
struct gpiohandle_request req;
struct gpiohandle_data data;
f = open("/dev/gpiochip1", O_RDONLY);
req.lineoffsets[0] = 21;
req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */
req.default_values[0] = 0;
strcpy(req.consumer_label, "gpio-output"); /* up to 31 characters */
req.lines = 1;
ret = ioctl(f, GPIO_GET_LINEHANDLE_IOCTL, &req);
/* Note that there is a new file descriptor in req.fd to handle the GPIO lines */
data.values[0] = 1;
ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); close(f);
return 0;
}
PWM¶
PWM通常用来控制灯光的亮度,或者电机的转速
sysfs¶
跟上面gpio的情况类似
# ls /sys/class/pwm/pwmchip0
device
export -> Write to this file to export a PWM to user space
npwm
power
subsystem
uevent
unexport -> Write to this file to unexport a PWM to user space
# echo 0 > /sys/class/pwm/pwmchip0/export
# ls /sys/class/pwm/pwmchip0
device export npwm power pwm0 subsystem uevent unexport
# 上面命令如果成功,会有如下目录
# ls /sys/class/pwm/pwmchip0/pwm0
capture duty_cycle export period power uevent device enable npwm polarity subsystem unexport
# 设置period为1ms(1000 000ns), duty为0.5ms(500 000ns)
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period
echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
I2C¶
I2C通常用于连接传感器,比如温度传感器
• Each I2C device has a 7-bit address, usually hard wired
• 16 bus addresses are reserved, giving a maximum of 112 nodes per bus
• The master controller manages read/write transfers with slave nodes
• i2c-dev exposes I2C master controllers
• Need to load/configure the i2c-dev driver (CONFIG_I2C_CHARDEV)
• There is one device node per i2c master controller
# ls -l /dev/i2c*
crw-rw---T 1 root i2c 89, 0 Jan 1 2000 /dev/i2c-0
crw-rw---T 1 root i2c 89, 1 Jan 1 2000 /dev/i2c-1
• You access I2C slave nodes using read(2), write(2) and ioctl(2)
• Structures defined in usr/include/linux/i2c-dev.h
• i2cdetect, from i2c-tools package, lists i2c adapters and probes devices
• Example: detect devices on bus 1 (/dev/i2c-1)
# i2cdetect -y -r 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
# UU = device already handled by kernel driver
# 0x39 = device discovered at address 0x39
• i2cget \<bus> \<chip> \<register>: read data from an I2C device
• Example: read register 0x8a from device at 0x39
• i2cset \<bus> \<chip> \<register>: writedata to an I2C device
• Example: Write 0x03 to register 0x80:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
int main(int argc, char **argv)
{
int f;
char buf[4];
f = open("/dev/i2c-1", O_RDWR); ioctl(f, I2C_SLAVE, 0x39) < 0) {
buf[0] = 0x8a; /* Chip ID register */
write(f, buf, 1);
read(f, buf, 1);
printf("ID 0x%x\n", buf[0]);
}
}