[国嵌攻略][117][LED驱动程序设计]
LED程序设计
1.编写内核模块
2.搭建字符驱动框架
3.实现设备方法
头文件
<linux/io.h>
writel()
1.编译/安装驱动
make
cp leddev.ko .../rootfs
insmod leddev.ko
2.创建设备文件
mknod /dev/myled0 c 253 0
3.编译/运行应用程序
arm-linux-gcc -static ledapp.c -o ledapp
cp ledapp .../rootfs
./ledadd 0
./ledadd 1
leddev.h
/******************************************************************** *设备命令 *********************************************************************/ #define LED_MAGIC 'L' //LED幻数 #define LED_ON _IO(LED_MAGIC, 0) //LED打开 #define LED_OFF _IO(LED_MAGIC, 1) //LED关闭
leddev.c
/******************************************************************** *头文件 *********************************************************************/ #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/io.h> #include "leddev.h" /******************************************************************** *宏定义 *********************************************************************/ #define GPBCON 0x56000010 //控制寄存器物理地址 #define GPBDAT 0x56000014 //数据寄存器物理地址 /******************************************************************** *全局变量 *********************************************************************/ struct cdev chrdev; //字符设备 dev_t devnum; //主设备号 unsigned int *ledCon; //控制寄存器指针 unsigned int *ledDat; //数据寄存器指针 /******************************************************************** *设备方法 *********************************************************************/ //控制设备 long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ //处理命令 switch(cmd){ case LED_ON: //打开LED writel(0x00000000, ledDat); //GPBDAT[8:5]:0000 break; case LED_OFF: //关闭LED writel(0x000001E0, ledDat); //GPBDAT[8:5]:1111 break; default: return -EINVAL; } return 0; } //打开设备 int led_open(struct inode *node, struct file *filp){ //配置LED引脚 ledCon = ioremap(GPBCON, 4); //虚拟地址转换 writel(0x00015400, ledCon); //GPBCON[17:10]:01010101 //设置LED状态 ledDat = ioremap(GPBDAT, 4); //虚拟地址转换 writel(0x00000140, ledDat); //GPBDAT[8:5]:1010 return 0; } //关闭设备 int led_close(struct inode *node, struct file *filp){ return 0; } //设备方法 struct file_operations led_fops = { .unlocked_ioctl = led_ioctl, .open = led_open, .release = led_close }; /******************************************************************** *模块安装 *********************************************************************/ //安装模块 static int led_init(){ //注册设备标识 cdev_init(&chrdev, &led_fops); //注册主设备号 alloc_chrdev_region(&devnum, 0, 1, "myled"); //添加设备标识 cdev_add(&chrdev, devnum, 1); return 0; } //卸载模块 static void led_exit(){ //注销设备标识 cdev_del(&chrdev); //注销主设备号 unregister_chrdev_region(devnum, 1); } /******************************************************************** *模块声明 *********************************************************************/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("D"); MODULE_DESCRIPTION(""); MODULE_VERSION("v1.0"); module_init(led_init); module_exit(led_exit);
ledapp.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> #include "leddev.h" int main(int argc, char **argv){ //参数检测 if(argc != 2){ printf("Usage:\n\t%s <state>\n", argv[0]); return -1; } //打开设备 int fd; fd = open("/dev/myled0", O_RDWR); //控制设备 int state; state = atoi(argv[1]); if(state){ //打开LED ioctl(fd, LED_ON); }else{ //关闭LED ioctl(fd, LED_OFF); } //关闭设备 close(fd); return 0; }