1. 程式人生 > >linux 核心模組程式設計之LED驅動程式(六)

linux 核心模組程式設計之LED驅動程式(六)

我使用的是tiny6410的核心板,板子如下,淘寶可以買到


為了不與板子上的任何驅動發生IO衝突,我使用CON1那一排沒用到的IO口,引腳如下

 

LED1

LED2

LED3

LED4

對應GPIO

GPM0

GPM1

GPM2

GPM3

在板子的手冊中,電路如下


這個是板子上的4個LED的電路圖,當然我不可能用這4個led來做實驗,但是除了IO口不一樣外,電路其實是可以作為參考的,於是我手動焊了個,如下:


由電路圖也是可以看出,他是低電平有效的

關於s3c6410的的IO說明如下


myled.c檔案如下

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>    /*copy_to_user,copy_from_user*/
#include <linux/io.h>         /*inl(),outl()*/
#include <linux/miscdevice.h>
#include <linux/pci.h>

#include <asm/io.h>

#define GPBCON 0x7F008820 //實體地址
#define GPBDAT 0x7F008824 //實體地址

static long S3C64XX_GPMCON; 
static long S3C64XX_GPMDAT;

#define LED_MAJOR 240                    /*主裝置號*/

int led_open(struct inode *inode,struct file *file)
{
    unsigned tmp;

    S3C64XX_GPMCON = ioremap(GPBCON, 4);//實體地址轉為虛擬地址
    S3C64XX_GPMDAT = ioremap(GPBDAT, 4);

    tmp=inl(S3C64XX_GPMCON);
    printk("the pre GPMCON is %x",tmp);
    tmp=inl(S3C64XX_GPMDAT);
    printk("the pre GPMDAT is %x",tmp);
    //這裡為什麼是0x00111111 ??
    outl(0x00111111,S3C64XX_GPMCON);         /*向GPMCON命令埠寫命令字,設定GPM0-5為output口*/
    printk("#############open#############");
    return 0;
}

static ssize_t led_read(struct file *file,char __user *buf,size_t count,loff_t * f_pos)
{
    unsigned tmp=inl(S3C64XX_GPMDAT);
        int num=copy_to_user(buf,&tmp,count);
    if(num==0)
       printk("copy successfully");
    else printk("sorry  copy failly");

    printk("the GPMDAT is %x.",tmp);
    return count;
}
static ssize_t led_write(struct file * file,const char __user * buf,size_t count,loff_t * f_pos) //我是通過write()來控制LED燈的,也可以通過ioctl()來控制
{
    char kbuf[10];
    printk("###########write###########");
    int num=copy_from_user(kbuf,buf,count);
    if(num==0)
         printk("copy successfully");
        else printk("sorry  copy failly");
    printk("##the kbuf is %c",kbuf[0]);
    switch(kbuf[0])
    {
        case 0://off
            //這裡為什麼是 0xFF ?
            outl(0xff,S3C64XX_GPMDAT);  /*拉高GPMDAT[0:5]的引腳,使LED燈滅,因為LED是低電平有電流通過*/
            break;
        case 1://on
            //這裡為什麼是 0x00 ?
            outl(0x00,S3C64XX_GPMDAT);  /*拉低GPMDAT[0:5]的引腳,使LED燈亮*/
            break;
        default:
            break;
    }
    return count;
}

int led_release(struct inode *inode,struct file *file)
{
    printk("#######release##########");
    return 0;
}

struct file_operations led_fops={
    .owner = THIS_MODULE,
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .release = led_release,
};
int __init led_init(void)
{
    int rc;
    printk("Test led dev\n");

    rc=register_chrdev(LED_MAJOR,"led",&led_fops); //註冊字元裝置
    if(rc<0)
    {
        printk("register %s char dev error\n","led");
        return -1;
    }
    printk("OK!\n");
    return 0;
}

void __exit led_exit(void)
{
    unregister_chrdev(LED_MAJOR,"led");
    printk("module exit\n");
}

module_init(led_init);
module_exit(led_exit);

makefile檔案如下

ifneq ($(KERNELRELEASE),)

obj-m := myled.o

else

KERNELDIR ?= /home/grb/grb/arm/linux-2.6.38/

PWD := $(shell pwd)

all:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers *~ *.order

endif

測試用的應用程式程式碼如下

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
	printf("hello led device .\n");
	int buf[10]={0,1,0,1};
	printf("1\n");
	int fd=open("/dev/led",2,0777);
	printf("2\n");
	if(fd<0){
		printf("can't open led device\n");
		return -1;
	}
	printf("open the led device successfully.\n");

	while(1)
	{
		int num=write(fd,&buf[0],1);
		if(num<0)
		    printf("we set the led failly.\n");
		else 
			printf("we set the led off\n");
		sleep(1);
		write(fd,&buf[1],1);
		printf("we set the led on\n");
		sleep(1);
	}
	close(fd);
	printf("bye led device .\n");
	return 0;
}	

將上面的檔案分別編譯成驅動檔案:myled.ko和應用程式out檔案,然後拷貝到板子上。本人開發板上跑的是linux 2.6.38的核心,這個關係不大,只要你編譯時所用的核心和板子的核心版本一致就好。

然後按照下面步驟執行


此時我們的驅動就已經安裝好了,接下來執行我們的應用程式out就可以了,執行如下


然後就可以看到我們的led在一閃一閃的了。

程式碼還有很多我也不是很明白,希望大夥多指點指點

參考網址:

http://bbs.csdn.net/topics/391038318
http://blog.csdn.net/wq897387/article/details/7387615