arm驅動程序——點亮led(韋東山的視頻總結及針對linux-2.6.30)

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


下面就是測試了。




發佈了36 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章