上面兩節只是驅動程序的框架,下面就是點亮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;
}
下面就是測試了。