本篇文章的驅動程序實現的要點:一是實現了設備文件的自動創建,不用每次運行驅動都要使用mknod指令自動創建設備文件,本文通過udev(mdev)來實現設備文件的自動創建。二是對LED燈的控制不是通過直接設置相關GPIO的二進制位來實現,本文使用linux系統中提供的對S3C2410 GPIO的操作函數,直接實現對相關GPIO的控制。三是實現了LED燈的閃爍效果,本文雖然沒有在驅動程序代碼中直接實現LED燈的閃爍效果,但是通過上層應用程序調用驅動程序中的ioctl間接實現了LED燈的閃爍效果。
Ubuntu下搭建TQ2440的程序下載環境 http://www.linuxidc.com/Linux/2011-03/32869.htm
Ubuntu 12.04(32位)下TQ2440開發板環境搭建 http://www.linuxidc.com/Linux/2014-04/100085.htm
【Linux驅動】TQ2440 LED驅動程序 http://www.linuxidc.com/Linux/2014-06/103328.htm
一,驅動程序源代碼My_Led.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h> //定義s3c2410的GPIO,S3C2410_GPB5至S3C2410_GPB8
#include <mach/hardware.h> //定義操作s3c2410的GPIO的函數
#include <linux/device.h> //自動創建設備文件應該包含的頭文件
#define DEVICE_NAME "My_led" //加載模塊後執行cat/proc/devices中看到的設備名稱
#define Led_MAJOR 103 //主設備號
#define LED_ON 1
#define LED_OFF 0
//Led的控制引腳
//注意S3C2410_GPB5就是GPIO的編號,類型定義為unsigned long
//編號的規則是把所有的io口從0開始進行統一編號,如S3c2410_GPA0=0 S3c2410_GPA1=1 S3C2410_GPB0=32
static unsigned long led_table[] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static int My_led_open(struct inode *inode,struct file *file)
{
printk("My_led open\n");
return 0;
}
static int My_led_ioctl(struct inode * inode, struct file * file,unsigned int cmd,unsigned long arg)
{
if(arg > 4)
{
return -1;
}
switch(cmd)
{
case LED_ON:
s3c2410_gpio_setpin(led_table[arg], 0);//設置指定引腳為輸出電平為0
return 0;
case LED_OFF:
s3c2410_gpio_setpin(led_table[arg], 1);//設置指定引腳為輸出電平為1
return 0;
default:
return -1;
}
}
//定義文件操作 file_operations
static struct file_operations My_led_fops =
{
.owner = THIS_MODULE,
.open = My_led_open,
.ioctl = My_led_ioctl,
};
static struct class *led_class;
static int __init My_led_init(void)
{
int ret;
printk("My_led start\n");
//冊字符設備驅動程序
//參數為主設備號、設備名字、file_operations結構
//這樣主設備號就與file_operations聯系起來
ret = register_chrdev(Led_MAJOR, DEVICE_NAME, &My_led_fops);
if(ret < 0)
{
printk("can't register major number\n");
return ret;
}
//注冊一個類,使mdev可以在"/dev/目錄下建立設備節點"
led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("failed in My_led class.\n");
return -1;
}
device_create(led_class, NULL, MKDEV(Led_MAJOR,0), NULL, DEVICE_NAME);
printk(DEVICE_NAME "initialized\n");
return 0;
}
static void __exit My_led_exit(void)
{
unregister_chrdev(Led_MAJOR, DEVICE_NAME);
device_destroy(led_class, MKDEV(Led_MAJOR,0));//注銷設備節點
class_destroy(led_class);//注銷類
}
module_init(My_led_init);
module_exit(My_led_exit);
MODULE_LICENSE("GPL");
源碼分析:
1.本驅動程序中設備文件的自動創建是通過在驅動初始化代碼裡調用class_create為該設備創建一個class,然後再為設備調用device_create創建對應的設備。class_create和device_create定義在內核源碼include/linux下,可去此目錄查看他們的定義。
2.本驅動程序通過內核中提供的對S3C2410 GPIO的操作函數S3C2410_gpio_setpin來控制指定引腳高低電平的輸出。此函數定義在hardware.h的頭文件中,需在驅動程序中添加#include<mach/hardware.h> 。
3.至於LED燈閃爍效果的實現等下將上層應用程序代碼列出來後再進行分析。
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-08/106010p2.htm