标签:kernel modules linux driver
折腾着非得写个LED driver出来~不然心里都不舒服...
内核版本:3.0.1
环境: Ubuntu14.0 TSL
开发板上嵌有4个LED灯
 
4个LED对应的ARM芯片上的引脚
易知,这里4个LED对应的IO引脚就是GPM0~GPM3
三个寄存器控制这里的GPIO -- GPM0~GPM3
这里gpio-bank-m.h定义了GPM相关的寄存器地址~这是一层爽歪歪的封装~(发现这是飞凌添加的header file...)
/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-m.h * * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * http://armlinux.simtec.co.uk/ * * GPIO Bank M register and configuration definitions * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #define S3C64XX_GPMCON (S3C64XX_GPM_BASE + 0x00) #define S3C64XX_GPMDAT (S3C64XX_GPM_BASE + 0x04) #define S3C64XX_GPMPUD (S3C64XX_GPM_BASE + 0x08) #define S3C64XX_GPM_CONMASK(__gpio) (0x3 << ((__gpio) * 2)) #define S3C64XX_GPM_INPUT(__gpio) (0x0 << ((__gpio) * 2)) #define S3C64XX_GPM_OUTPUT(__gpio) (0x1 << ((__gpio) * 2)) #define S3C64XX_GPM0_HOSTIF_CS (0x02 << 0) #define S3C64XX_GPM0_EINT23 (0x03 << 0) #define S3C64XX_GPM0_RESERVED1 (0x04 << 0) #define S3C64XX_GPM0_DATA_CF10 (0x05 << 0) #define S3C64XX_GPM0_CE_CF0 (0x06 << 0) #define S3C64XX_GPM0_RESERVED2 (0x07 << 0) #define S3C64XX_GPM1_HOSTIF_CS_M (0x02 << 0) #define S3C64XX_GPM1_EINT24 (0x03 << 0) #define S3C64XX_GPM1_RESERVED1 (0x04 << 0) #define S3C64XX_GPM1_DATA_CF11 (0x05 << 0) #define S3C64XX_GPM1_CE_CF1 (0x06 << 0) #define S3C64XX_GPM1_RESERVED2 (0x07 << 0) #define S3C64XX_GPM2_HOSTIF_IF_CS_S (0x02 << 0) #define S3C64XX_GPM2_EINT25 (0x03 << 0) #define S3C64XX_GPM2_HOSTIF_MDP_VSYNC (0x04 << 0) #define S3C64XX_GPM2_DATA_CF12 (0x05 << 0) #define S3C64XX_GPM2_IORD_CF (0x06 << 0) #define S3C64XX_GPM2_RESERVED2 (0x07 << 0) #define S3C64XX_GPM3_HOSTIF_WE (0x02 << 0) #define S3C64XX_GPM3_EINT26 (0x03 << 0) #define S3C64XX_GPM3_RESERVED1 (0x04 << 0) #define S3C64XX_GPM3_DATA_CF13 (0x05 << 0) #define S3C64XX_GPM3_IOWR_CF (0x06 << 0) #define S3C64XX_GPM3_RESERVED2 (0x07 << 0) #define S3C64XX_GPM4_HOSTIF_OE (0x02 << 0) #define S3C64XX_GPM4_EINT27 (0x03 << 0) #define S3C64XX_GPM4_RESERVED1 (0x04 << 0) #define S3C64XX_GPM4_DATA_CF14 (0x05 << 0) #define S3C64XX_GPM4_IORDY_CF (0x06 << 0) #define S3C64XX_GPM4_RESERVED2 (0x07 << 0) #define S3C64XX_GPM5_HOSTIF_INTR (0x02 << 0) #define S3C64XX_GPM5_CF_DATA_DIR (0x03 << 0) #define S3C64XX_GPM5_RESERVED1 (0x04 << 0) #define S3C64XX_GPM5_DATA_CF15 (0x05 << 0) #define S3C64XX_GPM5_RESERVED2 (0x06 << 0) #define S3C64XX_GPM5_RESERVED3 (0x07 << 0)
S3C64XX_GPM_BASE这个在regs-gpio.h 里面
节选了部分,不全部贴出了
...
#define S3C64XX_GPL_BASE S3C64XX_GPIOREG(0x0810) #define S3C64XX_GPM_BASE S3C64XX_GPIOREG(0x0820) #define S3C64XX_GPN_BASE S3C64XX_GPIOREG(0x0830)...
Here my source code for my led-device driver.
/*
code writer	: EOF
code date	: 2014.08.19.com
code file	: led_by_EOF.c
e-mail		: jasonleaster@gmail.com
code purpos:
	This code is a demo for beginner how to write a
character device to drive IO port.
	If you find there is something wrong with my code
and change it into a better version , please touch me 
by e-mail. Thank you.
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <asm/uaccess.h> /* for 'copy_from_user' */
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <mach/gpio-bank-m.h>
#include <mach/regs-gpio.h>
#include <mach/map.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/delay.h> /* for 'msleep' */
MODULE_AUTHOR("EOF");
MODULE_LICENSE("Dual BSD/GPL");
#define DEVICE_NAME	"led_by_EOF"
#define DEVICE_MAJOR_NUMBER 0 
#define USE_IMMEDIATE
static dev_t dev_number = DEVICE_MAJOR_NUMBER;
static struct class* led_class;
static struct cdev my_led_cdev;
static int led_open(struct inode* node,struct file* file)
{
	printk(KERN_ALERT "Device Opened successful!\n");
	return 0;
}
static ssize_t led_write(struct file* file,const char __user* buf,size_t count,loff_t* ppos)
{
	int kbuf;
	int ret = 0;
	kbuf = readl(S3C64XX_GPMCON);
	kbuf &= (~0xFFFF);
	kbuf |= 0x1111;
	writel(kbuf,S3C64XX_GPMCON);
	printk(KERN_ALERT "before writing...  &kbuf:%p buf:%p\n",&kbuf,buf);
	ret = __copy_from_user(&kbuf,buf,count);
	if(ret != 0)
	{
		printk(KERN_ALERT "'__copy_from_user' failed! ret:%d\n",ret);
		
		return -1;
	}
	printk(KERN_ALERT "writing...   kbuf:%x \n",kbuf);
	writel(kbuf,S3C64XX_GPMDAT);
	return 0;
}
static int led_release(struct inode* inode,struct file*file)
{
	printk(KERN_ALERT "Device released\n");
	return 0;
}
static struct file_operations led_fops =
{
	.owner	=	THIS_MODULE,
	.open	=	led_open,
	.write	=	led_write,
	.release=	led_release,
};
int led_init(void)
{
	int kbuf;
	if(alloc_chrdev_region(&dev_number,0,1,DEVICE_NAME) < 0)
	{
		printk(KERN_ALERT "Error in function '%s' : can't register device\n",__FUNCTION__);
		return -1;
	}
	led_class = class_create(THIS_MODULE,DEVICE_NAME);
	if(IS_ERR(led_class))
	{
		printk(KERN_ALERT "Bad class create\n");
		return -1;
	}
	cdev_init(&my_led_cdev,&led_fops);
	/*
	** GPM0~GPM3 pull up
	*/
	kbuf = readl(S3C64XX_GPMPUD);
	kbuf &= (~0xFF);
	kbuf |= 0xaa;//1010 1010
	writel(kbuf,S3C64XX_GPMPUD);	
	/*
	** GPM0~3 output mode
	*/
	kbuf = readl(S3C64XX_GPMCON);
	kbuf &= (~0xFFFF);
	kbuf |= 0x1111;
	writel(kbuf,S3C64XX_GPMCON);
	/*
	**	GPM0~GPM3 output 0 and light up all LED
	*/
	kbuf  = __raw_readl(S3C64XX_GPMDAT);
	kbuf |= 0x10;
	writel(kbuf,S3C64XX_GPMDAT);
	if(cdev_add(&my_led_cdev,dev_number,1))
	{
		printk(KERN_ALERT "Bad cdev add\n");
		return 1;
	}
	device_create(led_class,NULL,dev_number,NULL,DEVICE_NAME);
	return 0;
}
void led_cleanup(void)
{
	device_destroy(led_class,MKDEV(MAJOR(dev_number),0));
	class_destroy(led_class);
	unregister_chrdev_region(MAJOR(dev_number),1);
	printk(KERN_ALERT "See you! My LED\n");
}
module_init(led_init);
module_exit(led_cleanup);Test code:
/*
code writer	: EOF
code date	: 2014.08.19.com
code file	: led_by_EOF.c
e-mail		: jasonleaster@gmail.com
code purpos:
	This code is a demo for test my led-device.
	If you find there is something wrong with my code
and change it into a better version , please touch me 
by e-mail. Thank you.
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
	int fd = 0;
	int ret = 0;
	if((fd = open("/dev/led_by_EOF",O_RDWR)) < 0)
	{
		printf("line %d open failed\n",__LINE__);
		return 0;
	}
	int buf = 0;
	int time = 0;
	buf = 0x0;
	for(time = 0,buf = 0;time < 5;time++)
	{
		if((ret = write(fd,&buf,sizeof(buf))) < 0)
		{
			printf("write error!\n ret : %d\n",ret);
			
			//goto failed;
		}
		else
		{
			printf("write successful! ret %d,buf:%d &buf:%p\n",ret,buf,&buf);
		}
		buf = ~buf;
		sleep(2);
	}
	
failed:
	close(fd);
	
	return 0;
}最后灯会闪亮
Introduction to "s3c6410 LED" driver
标签:kernel modules linux driver
原文地址:http://blog.csdn.net/cinmyheart/article/details/38688661