Introduction to "s3c6410 LED" driver

Introduction to  driver for "s3c6410  LED"

折腾着非得写个LED driver出来~不然心里都不舒服...

内核版本:3.0.1

环境: Ubuntu14.0 TSL

开发板上嵌有4个LED灯

4个LED对应的ARM芯片上的引脚

易知,这里4个LED对应的IO引脚就是GPM0~GPM3

三个寄存器控制这里的GPIO -- GPM0~GPM3

  • GPMCON
  • GPMDAT
  • GPMPUD

这里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 <[email protected]>
 *  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		: [email protected]

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		: [email protected]

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;
}

最后灯会闪亮

时间: 2024-10-30 09:57:18

Introduction to "s3c6410 LED" driver的相关文章

由一个LED闪烁问题发现的MTK的LED driver中存在的问题

今天根据最新的需求要对LED灯的提示闪烁频率进行修改,将之前默认的2000ms改为10000ms,但是修改之后没有产生预料中的效果,而是变成了常量,百思不得其解,最后还是read the fucking code,从上层到底层,一路追下来,最终发现了问题所在,下面直接上MTK的LED driver代码: #define PMIC_PERIOD_NUM 9 // 100 * period, ex: 0.01 Hz -> 0.01 * 100 = 1 int pmic_period_array[]

s3c6410 RTC driver——读取实时时间信息 &lt;LDD3 &amp; ELDD 学习笔记&gt;

s3c6410 RTC driver--读取实时时间信息 开发环境:Ubuntu 14.0 开发板内核版本:Linux 3.0 The Real Time Clock (RTC) unit can be operated by the backup battery when the system power is off. The data include the time by second, minute, hour, date, day, month, and year. The RTC

led driver 0--一个简单但完整的字符设备驱动程序

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/a

led driver 1--ioremap

#define GPIO_OFT(x) ((x) - 0x56000000)#define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050))) static int s3c24xx_leds_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev); switc

An Introduction to the C# Driver for Cassandra

链接: https://www.datastax.com/dev/blog/an-introduction-to-the-c-driver-for-cassandra

A LED AC driver Research: open-loop peak current control type

For some days, I have always wanted to design a LED driver which driving mid-power LEDs, to replace low-power LED tube design that we are using now. Start to do it, now! First of all, a specification: Input Voltage 220 VAC rms Expected LED String Vol

led驱动

驱动步骤: 1.驱动框架:一般读驱动代码需要module_init一层层找代码 2.硬件配置 代码中led_ioctl函数设置引脚的电平高低,该函数是驱动程序对设备的通道进行统一设置/控制的函数 一.  在用户空间,使用ioctl系统调用来控制设备,原型如下: int ioctl(int fd,unsigned long cmd,...); fd:文件描述符 cmd:控制命令 ...:可选参数:插入*argp,具体内容依赖于cmd用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这

(笔记)linux设备驱动--LED驱动

linux设备驱动--LED驱动 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋友一起学习技术,共同进步. 作者:liufei_learning(转载请注明出处) email:[email protected] IT学习交流群:160855096 转至:http://blog.csdn.net/liufei_learning/article/details/7025246 开发环

FL2440驱动添加(4)LED 驱动添加

硬件信息:FL2440板子,s3c2440CPU带四个LED,分别在链接GPB5,GPB6,GPB8,GPB10 内核版本:linux-3.8.0 led驱动代码如下: 值得注意地方地方: 1,定时器的使用:在include/linux/timer.h下定义struct timer_list struct timer_list { /* * All fields that change during normal runtime grouped to the * same cacheline *