首先用户进程是不可以直接操作硬件,只能通过调用设备驱动,让设备驱动来操作硬件.
设备驱动又可以实现一个字符设备驱动接口让用户进程来调用.
如让用户进程通过ioctl来控制板上的led灯(PA(15).
驱动源码test.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <mach/gpio.h>
#include <linux/gpio.h>
#define MYMA 1234
#define MYMI 3344
#define COUNT 1
#define LED_IO GPIOA(15)
dev_t devid; //用于存放设备号
struct cdev mycdev;
long myioctl(struct file *fl, unsigned int cmd, unsigned long arg)
{
//根据用户进程ioctl的第二个参数值来设置led灯亮或灭
if (cmd) // led on
gpio_set_value(LED_IO, 1);
else // led off
gpio_set_value(LED_IO, 0);
return 0;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = myioctl,
};
static int __init test_init(void)
{
int ret;
devid = MKDEV(MYMA, MYMI); //生成一个设备号
ret = register_chrdev_region(devid, COUNT, "mydev");
if (ret < 0)
goto err0;
cdev_init(&mycdev, &fops);
mycdev.owner = THIS_MODULE;
ret = cdev_add(&mycdev, devid, COUNT);
if (ret < 0)
goto err1;
gpio_request(LED_IO, "mydev"); //请求gpio口
gpio_direction_output(LED_IO, 0); //配置gpio口为输出,先输出低电平
return 0;
err1:
unregister_chrdev_region(devid, COUNT);
err0:
return ret;
}
static void __exit test_exit(void)
{
unregister_chrdev_region(devid, COUNT);
cdev_del(&mycdev);
gpio_free(LED_IO); //释放gpio
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
编译加载驱动模块后,需创建设备文件
mknod /dev/mydev c 1234 3344
应用程序app.c:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(void)
{
int fd;
fd = open("/dev/mydev", O_RDWR);
if (fd < 0)
return 1;
while (1)
{
ioctl(fd, 0xff); //led灯亮
sleep(1);
ioctl(fd, 0); // led灯灭
sleep(1);
}
return 0;
}