编写led灯驱动:
驱动代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include<linux/io.h>
#include<linux/delay.h>
#include<linux/string.h>
#define CHRNAME "ledchrdev"
unsigned int *led1_odr;
unsigned int *led2_odr;
unsigned int *led3_odr;
unsigned int *vir_moder;
unsigned int *vir_rcc;
char buf[100] = {0};
int major = 0;
ssize_t ledchrdev_write (struct file *fd, const char __user *user, size_t count, loff_t *off)
{
int ret = 0;
if(count>sizeof(buf))
count=sizeof(buf);
ret = copy_from_user(buf,user,count);
if(ret)
{
printk("数据从内核拷贝失败\r\n");
return -EIO;
}
switch(buf[0])
{
case '1':
{
*led1_odr |= (1<<10);
}
break;
case '2':
{
*led2_odr |= (1<<10);
}
break;
case '3':
{
*led3_odr |= (1<<8);
}
break;
case '0':
{
*led1_odr &= (~(1<<10));
*led2_odr &= (~(1<<10));
*led3_odr &= (~(1<<8));
}
break;
}
return count;
}
int ledchrdev_open (struct inode *node, struct file *fd)
{
return 0;
}
int ledchrdev_release (struct inode *node, struct file *fd)
{
return 0;
}
struct file_operations ledchrdev_fops =
{
.open = ledchrdev_open,
.release = ledchrdev_release,
.write = ledchrdev_write,
};
static void led_init(void)
{
//led1初始化
vir_moder = ioremap(0x50006000,4);
led1_odr = ioremap(0x50006014,4);
vir_rcc = ioremap(0x50000A28,4);
*vir_moder &= (~(3<<20));
*vir_moder |= (1<<20);
*led1_odr &= (~(1<<10));
*vir_rcc |= (1<<4);
printk("led1_init success!\r\n");
//led2初始化
vir_moder = ioremap(0x50007000,4);
led2_odr = ioremap(0x50007014,4);
vir_rcc = ioremap(0x50000A28,4);
*vir_moder &= (~(3<<20));
*vir_moder |= (1<<20);
*led2_odr &= (~(1<<10));
*vir_rcc |= (1<<5);
printk("led2_init success!\r\n");
//led3初始化
vir_moder = ioremap(0x50006000,4);
led3_odr = ioremap(0x50006014,4);
vir_rcc = ioremap(0x50000A28,4);
*vir_moder &= (~(3<<16));
*vir_moder |= (1<<16);
*led3_odr &= (~(1<<8));
*vir_rcc |= (1<<4);
printk("led3_init success!\r\n");
}
//gpioe_moder[21:20]->01 0X50006000
//GPIOE_ODR[10]->1 0X50006014
//RCC_MP_AHB4ENSETR->1 0X50000A28
static int __init ledchrdev_init(void)
{
major = register_chrdev(0,CHRNAME,&ledchrdev_fops);
if(major < 0)
{
printk("register_chrdev failed!\r\n");
return major;
}
led_init();
printk("major = %d\r\n",major);
printk("ledchrdev init\r\n");
return 0;
}
static void __exit ledchrdev_exit(void)
{
iounmap(vir_moder);
iounmap(led1_odr);
iounmap(led2_odr);
iounmap(led3_odr);
iounmap(vir_rcc);
unregister_chrdev(major,CHRNAME);
printk("ledchrdev exit\r\n");
}
module_init(ledchrdev_init);
module_exit(ledchrdev_exit);
MODULE_LICENSE("GPL");
应用测试代码:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
void delay()
{
int i,j;
for(i=0;i<4000;i++)
for(j=0;j<2000;j++);
}
int main()
{
char buf[128] = {};
int fd = open("/dev/ledchrdev",O_RDWR);
if(fd<0)
{
printf("打开设备文件失败\n");
return -1;
}
while(1)
{
printf("请输入命令 0:关灯 1:LED1 2:LED2 3:LED3 4:流水灯\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
if(buf[0] == '4')
{
while(1)
{
if((buf[0]++) == '4')
{
buf[0] = '1';
}
delay();
write(fd,buf,sizeof(buf));
delay();
write(fd,"0",sizeof("0"));
}
}
write(fd,buf,sizeof(buf));
}
close(fd);
return 0;
}
实现结果: