天天看點

linux裝置驅動之我是led燈-基于OK6410開發闆

原創作品轉載請注明出處

http://blog.csdn.net/cediy2088long?viewmode=contents

學習嵌入式linux程式設計,我們接觸到的大多是linux裝置驅動程式的程式設計。今天我就給大家簡單的分析一下飛淩的led驅動程式,有了我們前面led的裸機的程式的基礎,這個led的驅動也就簡單多了。

大家最好是看一下linux裝置驅動程式一書的前六章,這樣不會對linux中的led中的一些函數太陌生。首先要對linux的字元裝置驅動架構有一個大概的了解。

打開linux的源碼目錄,找到drivers/char/s3c6410-led.c

打開看一下源碼。裡邊的函數都不難。

主要的函數實作就是下面這個函數,我們在使用者空間調用的時候也是最終調用到這個函數

#define DEVICE_NAME "leds"

static long s3c6410_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	switch(cmd) {
		unsigned tmp;
	case 0:
	case 1:
                 if (arg > 4) 
                 {
		 	return -EINVAL;
		 }
		tmp = readl(S3C64XX_GPMDAT);
            
		if(cmd==0) //close light
                  { 
			tmp &= (~(1<<arg));
                  }
		else  //open light
                  { 
			tmp |= (1<<arg);
                  }

                writel(tmp,S3C64XX_GPMDAT);

		printk (DEVICE_NAME": %d %d\n", arg, cmd);
		return 0;
	default:
		return -EINVAL;
	}
}
           

那麼是如何映射到使用者空間的呢?

static struct file_operations dev_fops = {
	.owner			= THIS_MODULE,
	.unlocked_ioctl	= s3c6410_leds_ioctl,
};
           

原來在這裡。

static struct miscdevice misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &dev_fops,
};

static int __init dev_init(void)
{
	int ret;
        
       unsigned tmp;

       //gpm0-3 pull up
	tmp = readl(S3C64XX_GPMPUD);
	tmp &= (~0xFF);
	tmp |= 0xaa;
	writel(tmp,S3C64XX_GPMPUD);

	//gpm0-3 output mode
	tmp =readl(S3C64XX_GPMCON);
	tmp &= (~0xFFFF);
	tmp |= 0x1111;
	writel(tmp,S3C64XX_GPMCON);
	
	//gpm0-3 output 0
	tmp = __raw_readl(S3C64XX_GPMDAT);
	tmp |= 0x10;
	writel(tmp,S3C64XX_GPMDAT);  

	ret = misc_register(&misc);

	printk (DEVICE_NAME"\tinitialized\n");

	return ret;
}

static void __exit dev_exit(void)
{
	misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FORLINX Inc.");
           

上面是初始化部分和注冊裝置。代碼很簡單,就不多說了。

如何把這個編譯進入核心呢?

還有再給大家說一下怎麼來把led驅動加到核心中呢,linux的編譯用的是makefile管理的,初學者對于makefile的基本結構要知道一些,不用把整個makefile的文檔都看一遍,但也要把知道大概,  makefile的格式規則是這樣的

target : prerequisites  

            command 

我們打開char目錄下的makefie看一下,

linux裝置驅動之我是led燈-基于OK6410開發闆

這一行是把led的驅動加入核心的關鍵,而我們在編譯的時候要配置是加入核心還是編譯成子產品呢,我們運作make menuconfig的時候是怎麼出現的配置的呢?這個要看我們的Kconfig檔案

linux裝置驅動之我是led燈-基于OK6410開發闆

這個就是我們在make menuconfig 的時候的配置選項。

進入到Device DriversàCharacter devices找到LedS driver forlinx6410

linux裝置驅動之我是led燈-基于OK6410開發闆

我們選上這一項就是編譯進核心,如果是M,就是要編譯成子產品,可以動态加載,如果是空就是不編譯。Makemenuconfig的時候就是如何剪裁作業系統了,我們可以把不需要的或者沒有必要的驅動不選上,重新編譯,就可以得到自己剪裁過的核心了

這樣就會在dev目錄下生成一個led裝置了。這樣驅動部分就好了。我們如何測試我們的led能用呢?

寫個流水燈吧

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>

sleeps(int j){
	int i=0,m=0;
	for(i=0;i<j;i++){
		for(m=0;m<100000;m++){
		
		}	
	}
}
int main(void){
	int i,fd;
	fd=open("/dev/leds",O_RDWR);
	if(fd == -1)
	    exit(1);
	for(i=0;i<4;i++){
		ioctl(fd,0,i);
		sleeps(100);
		ioctl(fd,1,i);
		if(i == 3)
			i=0;
	}

}
           

編譯一下這個程式,

arm-linux-gcc -o ledtest ledtest.c -static

就可以生成ledtest,注意如果把arm-linux-gcc的路徑加到PATH環境變量中去,否則會出現找到不指令的錯誤。

把ledtest通過序列槽發到開發闆中,因為沒有執行權限,先運作chmod 777 ledtest

然後再./ledtest

linux裝置驅動之我是led燈-基于OK6410開發闆

就可以看到流水燈閃動了。

繼續閱讀