上面两节只是驱动程序的框架,下面就是点亮led了。
目的:点亮led
步骤:
1.写框架。
2.完善硬件相关操作。
a.看原理图
b.看2440手册
c.写代码
下面是所用到的函数及结构:
/*由于用户空间中的指针,数据不能直接使用要用下面两个函数进行操作*/
/* 从用户空间得到数据,to:内核空间;from:用户空间;n:复制的数据长度*/
copy_from_user(void *to, const void __user *from, unsigned long n)
/* 传数据到用户空间,to:内核空间;from:用户空间;n:复制的数据长度*/
copy_to_user(void __user *to, const void *from, unsigned long n)
/*地址映射,把物理地址转化为虚拟地址。
*cookie:物理地址的首地址,size:映射的大小,字节的大小
*/
ioremap(cookie,size)
/*注销虚拟地址的映射 cookie:物理地址的首地址*/
iounmap(cookie)
驱动程序:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/poll.h>
static int major;
/*定义class结构体*/
static struct class *first_led_class;
/*定义一个class_device结构体*/
/*此定义也是可以的:static struct class_device *first_led_device;*/
static struct class_device *first_led_device;
volatile unsigned long *GPBCON = NULL;
volatile unsigned long *GPBDAT = NULL;
static int first_led_open (struct inode *inode, struct file *file)
{
*GPBCON &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16));
*GPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
return 0;
}
static ssize_t first_led_write(struct file *file,
const char __user *user_buffer, size_t count, loff_t * loff)
{
int ret;
/*从用户空间得到数据*/
copy_from_user(&ret,user_buffer,count);
if(0 == ret)
/*点亮led*/
*GPBDAT &= ~((1<<5)|(1<<6)|(1<<7)|(1<<8));
else
/*熄灭led*/
*GPBDAT |= ((1<<5)|(1<<6)|(1<<7)|(1<<8));
return count;
}
/*定义一个file_operations结构体*/
static struct file_operations first_led_fops = {
.owner = THIS_MODULE,
.open = first_led_open,
.write = first_led_write,
};
/*入口函数*/
static int first_led_init(void){
/*注册,主设备的位置为0,代表自动分配主设备号*/
major = register_chrdev(0,"first_dev_led",&first_led_fops);
/*创建一个类,可在/sys/class目录下查看到*/
first_led_class = class_create(THIS_MODULE,"fisrst_led_class");
/*类下创建一个设备,可在/sys/class/fisrst_led_class目录下查看到*/
first_led_device = device_create(first_led_class,NULL,
MKDEV(major,0),NULL,"first_led");
/*地址映射*/
GPBCON = (volatile int *)ioremap(0x56000010,16);
GPBDAT = GPBCON + 1;
return 0;
}
static void first_led_exit(void){
/*注销*/
unregister_chrdev(major,"first_dev_led");
/*注销设备*/
device_unregister(first_led_device);
/*销毁类*/
class_destroy(first_led_class);
/*注销虚拟地址的映射*/
iounmap(GPBCON);
}
MODULE_LICENSE("GPL");
module_init(first_led_init);
module_exit(first_led_exit);
测试程序:
//usage< file on | off >
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
int main(int argc,char **argv){
int fd;
int val=1;
fd=open("/dev/first_led",O_RDWR);
if(fd<0)
printf("can't open!\n");
if(argc != 2)
{
printf("usage:\n");
printf("first_devdritest <on|off>\n");
return 0;
}
if(strcmp(argv[1],"on")==0)
val=0;
else
val=1;
write(fd,&val,4);
return 0;
}
下面就是测试了。