LED驱动程序相关头文件简单介绍

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                《常识》
¥应用程序----->系统内核----->设备驱动----->硬件设备
¥设备驱动既是系统内核的下属,又是硬件设备的老大。  
¥在inux系统中用一个文件来代表一个设备。这个文件就叫设备文件。设备驱动的责任是将应用程序对设备文件
的打开、读、写、定位等操作转化为对硬件设备的打开、读、写、定位等操作。而对于任何硬件设备,应用程序
只需利用这些基本操作就可以完全控制它!
¥编写linux设备驱动需要的知识结构:
1、40%的设计模式相关知识。设计模式是系统内核限定的,做别人的下属就得按照别人的规矩办事。
2、30%的内核工作原理相关知识。内核是你领导,领会领导意图才能把事情办好。
3、30%的硬件相关知识。控制好硬件是你的的本质工作,你得把你的小弟管理好.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

在解读OK6410官方提供的LED驱动程序源码的过程中,发现很多没见过的宏和函数。例如S3C64XX_GPM(0)、S3C64XX_GPM_OUTPUT(0)、__raw_writel(tmp,S3C64XX_GPMPUD)、__raw_writel(tmp,S3C64XX_GPMCON)等。而这些都包含在一些头文件里面。另一方面,我们自己动手编写LED的驱动程序也必须知道相关的头文件有哪些,对我们有哪些用。因此,我觉得在自己动手编写LED驱动程序之前对相关头文件进行简单的分析是非常有必要的。以下是我自己结合源码分析得出的一些结论,如有不正确的地方,希望能够得到指正。

OK6410官方提供的LED驱动程序源码:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <mach/gpio.h>
#include <plat/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/hardware.h>
#include <linux/io.h>

#define DEVICE_NAME	"leds"
#define LED_MAJOR 231


static unsigned long led_table [] = {
       S3C64XX_GPM(0),
       S3C64XX_GPM(1),
       S3C64XX_GPM(2),
       S3C64XX_GPM(3),
};

static unsigned int led_cfg_table [] = {
	S3C64XX_GPM_OUTPUT(0),
	S3C64XX_GPM_OUTPUT(1),
	S3C64XX_GPM_OUTPUT(2),
	S3C64XX_GPM_OUTPUT(3),
};

static int s3c6410_leds_ioctl(
	struct inode *inode, 
	struct file *file, 
	unsigned int cmd, 
	unsigned long arg)
{
	unsigned long tmp;
	switch(cmd) {
	case 0:
	case 1:
		if (arg > 4) {
			return -EINVAL;
		}
		tmp = __raw_readl(S3C64XX_GPMDAT);
		if(cmd)
			tmp &= (~(1<<arg));
		else
			tmp |= (1<<arg);
		__raw_writel(tmp,S3C64XX_GPMDAT);
//		gpio_set_value(led_table[arg], !cmd);
		return 0;
	default:
		return -EINVAL;
	}
}


static struct file_operations s3c6410_leds_fops = {
	.owner	=	THIS_MODULE,
	.ioctl	=	s3c6410_leds_ioctl,
};

static struct cdev cdev_leds;
struct class * my_class;

static int __init s3c6410_leds_init(void)
{
	int ret;
	unsigned long tmp;
	int i;
	dev_t devno;
	printk(KERN_NOTICE "enter s3c6410_leds_init\n");


	devno = MKDEV(LED_MAJOR,0);

	ret = register_chrdev_region(devno,1,DEVICE_NAME);
	ret = 0;
	if(ret<0)
	{
		printk(KERN_NOTICE "can not register led device");
		return ret;
	}
	
	cdev_init(&cdev_leds,&s3c6410_leds_fops);
	cdev_leds.owner = THIS_MODULE;

	ret =cdev_add(&cdev_leds,devno,1);
	if(ret)
	{
		printk(KERN_NOTICE "can not add leds device");
		return ret;
	}

	my_class = class_create(THIS_MODULE,"my_class");
	if(IS_ERR(my_class))
	{
		printk("Err: Failed in creating class\n");
		return -1;	
	}

	device_create(my_class,NULL,MKDEV(LED_MAJOR,0),NULL,DEVICE_NAME);

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

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

	//printk("S3C64XX_GPMCON is %x\n",__raw_readl(S3C64XX_GPMCON));
	//printk("S3C64XX_GPMDAT is %x\n",__raw_readl(S3C64XX_GPMDAT));
	//printk("S3C64XX_GPMPUD is %x\n",__raw_readl(S3C64XX_GPMPUD));

	printk(DEVICE_NAME " initialized\n");

	return 0;
}

static void __exit s3c6410_leds_exit(void)
{
	cdev_del(&cdev_leds);

	unregister_chrdev_region(MKDEV(LED_MAJOR,0),1);

	printk(KERN_NOTICE "s3c2440_leds_exit\n");
}


module_init(s3c6410_leds_init);
module_exit(s3c6410_leds_exit);

MODULE_LICENSE("GPL");



 一、模块相关头文件:

1、#include <linux/module.h>:在编写任何模块都需要包含此头文件。该头文件自动包含了 <linux/version.h>头文件,该头文件包含了宏MODULE_LICENSE("GPL")的定义。
2、#include <linux/init.h>:此头文件也是必须的,module_init()与module_exit()宏就是定义在它里面的。而且正是这个头文件定义了初始化函数加__init和推出函数加__exit的作用(static int __init s3c6410_leds_init(void)和static void __exit s3c6410_leds_exit(void))
3、#include <linux/kernel.h>:此头文件也是常用头文件,如果需要使用printk函数,则必须包含此头文件。另外该头文件还包含了<types.h>头文件,而这个头文件定义许多常用的数据类型,其中就包括设备号类型dev_t。如下:

#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H

#ifdef	__KERNEL__

#define DECLARE_BITMAP(name,bits) \
	unsigned long name[BITS_TO_LONGS(bits)]

#endif

#include <linux/posix_types.h>
#include <asm/types.h>

#ifndef __KERNEL_STRICT_NAMES

typedef __u32 __kernel_dev_t;

typedef __kernel_fd_set		fd_set;
typedef __kernel_dev_t		dev_t;
typedef __kernel_ino_t		ino_t;
typedef __kernel_mode_t		mode_t;
typedef __kernel_nlink_t	nlink_t;
typedef __kernel_off_t		off_t;
typedef __kernel_pid_t		pid_t;
typedef __kernel_daddr_t	daddr_t;
typedef __kernel_key_t		key_t;
typedef __kernel_suseconds_t	suseconds_t;
typedef __kernel_timer_t	timer_t;
typedef __kernel_clockid_t	clockid_t;
typedef __kernel_mqd_t		mqd_t;

#ifdef __KERNEL__
typedef _Bool			bool;

typedef __kernel_uid32_t	uid_t;
typedef __kernel_gid32_t	gid_t;
typedef __kernel_uid16_t        uid16_t;
typedef __kernel_gid16_t        gid16_t;

typedef unsigned long		uintptr_t;

#ifdef CONFIG_UID16
/* This is defined by include/asm-{arch}/posix_types.h */
typedef __kernel_old_uid_t	old_uid_t;
typedef __kernel_old_gid_t	old_gid_t;
#endif /* CONFIG_UID16 */

/* libc5 includes this file to define uid_t, thus uid_t can never change
 * when it is included by non-kernel code
 */
#else
typedef __kernel_uid_t		uid_t;
typedef __kernel_gid_t		gid_t;
#endif /* __KERNEL__ */

#if defined(__GNUC__)
typedef __kernel_loff_t		loff_t;
#endif

/*
 * The following typedefs are also protected by individual ifdefs for
 * historical reasons:
 */
#ifndef _SIZE_T
#define _SIZE_T
typedef __kernel_size_t		size_t;
#endif

#ifndef _SSIZE_T
#define _SSIZE_T
typedef __kernel_ssize_t	ssize_t;
#endif

#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef __kernel_ptrdiff_t	ptrdiff_t;
#endif

#ifndef _TIME_T
#define _TIME_T
typedef __kernel_time_t		time_t;
#endif

#ifndef _CLOCK_T
#define _CLOCK_T
typedef __kernel_clock_t	clock_t;
#endif

#ifndef _CADDR_T
#define _CADDR_T
typedef __kernel_caddr_t	caddr_t;
#endif

/* bsd */
typedef unsigned char		u_char;
typedef unsigned short		u_short;
typedef unsigned int		u_int;
typedef unsigned long		u_long;

/* sysv */
typedef unsigned char		unchar;
typedef unsigned short		ushort;
typedef unsigned int		uint;
typedef unsigned long		ulong;

#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__

typedef		__u8		u_int8_t;
typedef		__s8		int8_t;
typedef		__u16		u_int16_t;
typedef		__s16		int16_t;
typedef		__u32		u_int32_t;
typedef		__s32		int32_t;

#endif /* !(__BIT_TYPES_DEFINED__) */

typedef		__u8		uint8_t;
typedef		__u16		uint16_t;
typedef		__u32		uint32_t;

#if defined(__GNUC__)
typedef		__u64		uint64_t;
typedef		__u64		u_int64_t;
typedef		__s64		int64_t;
#endif

/* this is a special 64bit data type that is 8-byte aligned */
#define aligned_u64 __u64 __attribute__((aligned(8)))
#define aligned_be64 __be64 __attribute__((aligned(8)))
#define aligned_le64 __le64 __attribute__((aligned(8)))

/**
 * The type used for indexing onto a disc or disc partition.
 *
 * Linux always considers sectors to be 512 bytes long independently
 * of the devices real block size.
 */
#ifdef CONFIG_LBD
typedef u64 sector_t;
#else
typedef unsigned long sector_t;
#endif

/*
 * The type of the inode's block count.
 */
#ifdef CONFIG_LSF
typedef u64 blkcnt_t;
#else
typedef unsigned long blkcnt_t;
#endif

/*
 * The type of an index into the pagecache.  Use a #define so asm/types.h
 * can override it.
 */
#ifndef pgoff_t
#define pgoff_t unsigned long
#endif

#endif /* __KERNEL_STRICT_NAMES */

/*
 * Below are truly Linux-specific types that should never collide with
 * any application/library that wants linux/types.h.
 */

#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif
#ifdef __CHECK_ENDIAN__
#define __bitwise __bitwise__
#else
#define __bitwise
#endif

typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
#if defined(__GNUC__)
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
#endif
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;

#ifdef __KERNEL__
typedef unsigned __bitwise__ gfp_t;
typedef unsigned __bitwise__ fmode_t;

#ifdef CONFIG_PHYS_ADDR_T_64BIT
typedef u64 phys_addr_t;
#else
typedef u32 phys_addr_t;
#endif

typedef phys_addr_t resource_size_t;

struct ustat {
	__kernel_daddr_t	f_tfree;
	__kernel_ino_t		f_tinode;
	char			f_fname[6];
	char			f_fpack[6];
};

#endif	/* __KERNEL__ */

#endif /* _LINUX_TYPES_H */




二、字符设备驱动相关头文件:
1、#include <linux/fs.h>:该头文件包含了常用的数据结构,当然也包括三种最重要的:struct file、struct file_operation、struct inode。另外该头文件还包含了<linux/ioctl.h>头文件。
2、#include <linux/cdev.h>:该头文件定义了struct cdev数据结构,也包含了字符设备操作的相关函数:

#ifndef _LINUX_CDEV_H
#define _LINUX_CDEV_H

#include <linux/kobject.h>
#include <linux/kdev_t.h>
#include <linux/list.h>

struct file_operations;
struct inode;
struct module;

struct cdev {
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
};

void cdev_init(struct cdev *, const struct file_operations *);

struct cdev *cdev_alloc(void);

void cdev_put(struct cdev *p);

int cdev_add(struct cdev *, dev_t, unsigned);

void cdev_del(struct cdev *);

void cd_forget(struct inode *);

extern struct backing_dev_info directly_mappable_cdev_bdi;

#endif


3、<linux/device.h>:包含自动创建设备文件的相关函数的申明:原函数中-class_create(THIS_MODULE,"my_class")、device_create(my_class,NULL,MKDEV(LED_MAJOR,0),NULL,DEVICE_NAME)。


三、s3c64xx  GPIO操作相关头文件:
1、#include <mach/gpio.h>:此头文件包含了对S3C64xx 各个GPIO的宏定义,并包含了各个端口的读写函数,如下:

/* linux/arch/arm/mach-s3c6400/include/mach/gpio.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C6400 - GPIO lib support
 *
 * 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 gpio_get_value	__gpio_get_value
#define gpio_set_value	__gpio_set_value
#define gpio_cansleep	__gpio_cansleep
#define gpio_to_irq	__gpio_to_irq

/* GPIO bank sizes */
#define S3C64XX_GPIO_A_NR	(8)
#define S3C64XX_GPIO_B_NR	(7)
#define S3C64XX_GPIO_C_NR	(8)
#define S3C64XX_GPIO_D_NR	(5)
#define S3C64XX_GPIO_E_NR	(5)
#define S3C64XX_GPIO_F_NR	(16)
#define S3C64XX_GPIO_G_NR	(7)
#define S3C64XX_GPIO_H_NR	(10)
#define S3C64XX_GPIO_I_NR	(16)
#define S3C64XX_GPIO_J_NR	(12)
#define S3C64XX_GPIO_K_NR	(16)
#define S3C64XX_GPIO_L_NR	(15)
#define S3C64XX_GPIO_M_NR	(6)
#define S3C64XX_GPIO_N_NR	(16)
#define S3C64XX_GPIO_O_NR	(16)
#define S3C64XX_GPIO_P_NR	(15)
#define S3C64XX_GPIO_Q_NR	(9)

/* GPIO bank numbes */

/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
 * space for debugging purposes so that any accidental
 * change from one gpio bank to another can be caught.
*/

#define S3C64XX_GPIO_NEXT(__gpio) \
	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)

enum s3c_gpio_number {
	S3C64XX_GPIO_A_START = 0,
	S3C64XX_GPIO_B_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_A),
	S3C64XX_GPIO_C_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_B),
	S3C64XX_GPIO_D_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_C),
	S3C64XX_GPIO_E_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_D),
	S3C64XX_GPIO_F_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_E),
	S3C64XX_GPIO_G_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_F),
	S3C64XX_GPIO_H_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_G),
	S3C64XX_GPIO_I_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_H),
	S3C64XX_GPIO_J_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_I),
	S3C64XX_GPIO_K_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_J),
	S3C64XX_GPIO_L_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_K),
	S3C64XX_GPIO_M_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_L),
	S3C64XX_GPIO_N_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_M),
	S3C64XX_GPIO_O_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_N),
	S3C64XX_GPIO_P_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_O),
	S3C64XX_GPIO_Q_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_P),
};

/* S3C64XX GPIO number definitions. */

#define S3C64XX_GPA(_nr)	(S3C64XX_GPIO_A_START + (_nr))
#define S3C64XX_GPB(_nr)	(S3C64XX_GPIO_B_START + (_nr))
#define S3C64XX_GPC(_nr)	(S3C64XX_GPIO_C_START + (_nr))
#define S3C64XX_GPD(_nr)	(S3C64XX_GPIO_D_START + (_nr))
#define S3C64XX_GPE(_nr)	(S3C64XX_GPIO_E_START + (_nr))
#define S3C64XX_GPF(_nr)	(S3C64XX_GPIO_F_START + (_nr))
#define S3C64XX_GPG(_nr)	(S3C64XX_GPIO_G_START + (_nr))
#define S3C64XX_GPH(_nr)	(S3C64XX_GPIO_H_START + (_nr))
#define S3C64XX_GPI(_nr)	(S3C64XX_GPIO_I_START + (_nr))
#define S3C64XX_GPJ(_nr)	(S3C64XX_GPIO_J_START + (_nr))
#define S3C64XX_GPK(_nr)	(S3C64XX_GPIO_K_START + (_nr))
#define S3C64XX_GPL(_nr)	(S3C64XX_GPIO_L_START + (_nr))
#define S3C64XX_GPM(_nr)	(S3C64XX_GPIO_M_START + (_nr))
#define S3C64XX_GPN(_nr)	(S3C64XX_GPIO_N_START + (_nr))
#define S3C64XX_GPO(_nr)	(S3C64XX_GPIO_O_START + (_nr))
#define S3C64XX_GPP(_nr)	(S3C64XX_GPIO_P_START + (_nr))
#define S3C64XX_GPQ(_nr)	(S3C64XX_GPIO_Q_START + (_nr))

/* the end of the S3C64XX specific gpios */
#define S3C64XX_GPIO_END	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
#define S3C_GPIO_END		S3C64XX_GPIO_END

/* define the number of gpios we need to the one after the GPQ() range */
#define ARCH_NR_GPIOS	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)

#include <asm-generic/gpio.h>

上面的头文件包含了<asm-generic/gpio.h>头文件,该头文件包含了GPIO的数据读写函数,如下:

#ifndef _ASM_GENERIC_GPIO_H
#define _ASM_GENERIC_GPIO_H

#include <linux/types.h>
#include <linux/errno.h>

#ifdef CONFIG_GPIOLIB

#include <linux/compiler.h>

/* Platforms may implement their GPIO interface with library code,
 * at a small performance cost for non-inlined operations and some
 * extra memory (for code and for per-GPIO table entries).
 *
 * While the GPIO programming interface defines valid GPIO numbers
 * to be in the range 0..MAX_INT, this library restricts them to the
 * smaller range 0..ARCH_NR_GPIOS-1.
 */

#ifndef ARCH_NR_GPIOS
#define ARCH_NR_GPIOS		256
#endif

static inline int gpio_is_valid(int number)
{
	/* only some non-negative numbers are valid */
	return ((unsigned)number) < ARCH_NR_GPIOS;
}

struct seq_file;
struct module;

/**
 * struct gpio_chip - abstract a GPIO controller
 * @label: for diagnostics
 * @dev: optional device providing the GPIOs
 * @owner: helps prevent removal of modules exporting active GPIOs
 * @request: optional hook for chip-specific activation, such as
 *	enabling module power and clock; may sleep
 * @free: optional hook for chip-specific deactivation, such as
 *	disabling module power and clock; may sleep
 * @direction_input: configures signal "offset" as input, or returns error
 * @get: returns value for signal "offset"; for output signals this
 *	returns either the value actually sensed, or zero
 * @direction_output: configures signal "offset" as output, or returns error
 * @set: assigns output value for signal "offset"
 * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
 *	implementation may not sleep
 * @dbg_show: optional routine to show contents in debugfs; default code
 *	will be used when this is omitted, but custom code can show extra
 *	state (such as pullup/pulldown configuration).
 * @base: identifies the first GPIO number handled by this chip; or, if
 *	negative during registration, requests dynamic ID allocation.
 * @ngpio: the number of GPIOs handled by this controller; the last GPIO
 *	handled is (base + ngpio - 1).
 * @can_sleep: flag must be set iff get()/set() methods sleep, as they
 *	must while accessing GPIO expander chips over I2C or SPI
 *
 * A gpio_chip can help platforms abstract various sources of GPIOs so
 * they can all be accessed through a common programing interface.
 * Example sources would be SOC controllers, FPGAs, multifunction
 * chips, dedicated GPIO expanders, and so on.
 *
 * Each chip controls a number of signals, identified in method calls
 * by "offset" values in the range 0..(@ngpio - 1).  When those signals
 * are referenced through calls like gpio_get_value(gpio), the offset
 * is calculated by subtracting @base from the gpio number.
 */
struct gpio_chip {
	const char		*label;
	struct device		*dev;
	struct module		*owner;

	int			(*request)(struct gpio_chip *chip,
						unsigned offset);
	void			(*free)(struct gpio_chip *chip,
						unsigned offset);

	int			(*direction_input)(struct gpio_chip *chip,
						unsigned offset);
	int			(*get)(struct gpio_chip *chip,
						unsigned offset);
	int			(*direction_output)(struct gpio_chip *chip,
						unsigned offset, int value);
	void			(*set)(struct gpio_chip *chip,
						unsigned offset, int value);

	int			(*to_irq)(struct gpio_chip *chip,
						unsigned offset);

	void			(*dbg_show)(struct seq_file *s,
						struct gpio_chip *chip);
	int			base;
	u16			ngpio;
	unsigned		can_sleep:1;
	unsigned		exported:1;
};

extern const char *gpiochip_is_requested(struct gpio_chip *chip,
			unsigned offset);
extern int __must_check gpiochip_reserve(int start, int ngpio);

/* add/remove chips */
extern int gpiochip_add(struct gpio_chip *chip);
extern int __must_check gpiochip_remove(struct gpio_chip *chip);


/* Always use the library code for GPIO management calls,
 * or when sleeping may be involved.
 */
extern int gpio_request(unsigned gpio, const char *label);
extern void gpio_free(unsigned gpio);

extern int gpio_direction_input(unsigned gpio);
extern int gpio_direction_output(unsigned gpio, int value);

extern int gpio_get_value_cansleep(unsigned gpio);
extern void gpio_set_value_cansleep(unsigned gpio, int value);


/* A platform's <asm/gpio.h> code may want to inline the I/O calls when
 * the GPIO is constant and refers to some always-present controller,
 * giving direct access to chip registers and tight bitbanging loops.
 */
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);

extern int __gpio_cansleep(unsigned gpio);

extern int __gpio_to_irq(unsigned gpio);

#ifdef CONFIG_GPIO_SYSFS

/*
 * A sysfs interface can be exported by individual drivers if they want,
 * but more typically is configured entirely from userspace.
 */
extern int gpio_export(unsigned gpio, bool direction_may_change);
extern void gpio_unexport(unsigned gpio);

#endif	/* CONFIG_GPIO_SYSFS */

#else	/* !CONFIG_HAVE_GPIO_LIB */

static inline int gpio_is_valid(int number)
{
	/* only non-negative numbers are valid */
	return number >= 0;
}

/* platforms that don't directly support access to GPIOs through I2C, SPI,
 * or other blocking infrastructure can use these wrappers.
 */

static inline int gpio_cansleep(unsigned gpio)
{
	return 0;
}

static inline int gpio_get_value_cansleep(unsigned gpio)
{
	might_sleep();
	return gpio_get_value(gpio);
}

static inline void gpio_set_value_cansleep(unsigned gpio, int value)
{
	might_sleep();
	gpio_set_value(gpio, value);
}

#endif /* !CONFIG_HAVE_GPIO_LIB */

#ifndef CONFIG_GPIO_SYSFS

/* sysfs support is only available with gpiolib, where it's optional */

static inline int gpio_export(unsigned gpio, bool direction_may_change)
{
	return -ENOSYS;
}

static inline void gpio_unexport(unsigned gpio)
{
}
#endif	/* CONFIG_GPIO_SYSFS */

#endif /* _ASM_GENERIC_GPIO_H */



2、#include <plat/regs-gpio.h>:定义了GPIO相关的数据宏:

/* linux/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *      Ben Dooks <ben@simtec.co.uk>
 *      http://armlinux.simtec.co.uk/
 *
 * S3C64XX - GPIO register definitions
 */

#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_H
#define __ASM_PLAT_S3C64XX_REGS_GPIO_H __FILE__

#include <plat/gpio-bank-a.h>
#include <plat/gpio-bank-b.h>
#include <plat/gpio-bank-c.h>
#include <plat/gpio-bank-d.h>
#include <plat/gpio-bank-e.h>
#include <plat/gpio-bank-f.h>
#include <plat/gpio-bank-g.h>
#include <plat/gpio-bank-h.h>
#include <plat/gpio-bank-i.h>
#include <plat/gpio-bank-j.h>
#include <plat/gpio-bank-k.h>
#include <plat/gpio-bank-l.h>
#include <plat/gpio-bank-n.h>
#include #include <plat/gpio-bank-q.h>
#include <plat/gpio-bank-o.h>
#include <plat/gpio-bank-p.h>
#include <plat/gpio-bank-q.h>
#include <mach/map.h>

/* Base addresses for each of the banks */

#define S3C64XX_GPA_BASE	(S3C64XX_VA_GPIO + 0x0000)
#define S3C64XX_GPB_BASE	(S3C64XX_VA_GPIO + 0x0020)
#define S3C64XX_GPC_BASE	(S3C64XX_VA_GPIO + 0x0040)
#define S3C64XX_GPD_BASE	(S3C64XX_VA_GPIO + 0x0060)
#define S3C64XX_GPE_BASE	(S3C64XX_VA_GPIO + 0x0080)
#define S3C64XX_GPF_BASE	(S3C64XX_VA_GPIO + 0x00A0)
#define S3C64XX_GPG_BASE	(S3C64XX_VA_GPIO + 0x00C0)
#define S3C64XX_GPH_BASE	(S3C64XX_VA_GPIO + 0x00E0)
#define S3C64XX_GPI_BASE	(S3C64XX_VA_GPIO + 0x0100)
#define S3C64XX_GPJ_BASE	(S3C64XX_VA_GPIO + 0x0120)
#define S3C64XX_GPK_BASE	(S3C64XX_VA_GPIO + 0x0800)
#define S3C64XX_GPL_BASE	(S3C64XX_VA_GPIO + 0x0810)
#define S3C64XX_GPM_BASE	(S3C64XX_VA_GPIO + 0x0820)
#define S3C64XX_GPN_BASE	(S3C64XX_VA_GPIO + 0x0830)
#define S3C64XX_GPO_BASE	(S3C64XX_VA_GPIO + 0x0140)
#define S3C64XX_GPP_BASE	(S3C64XX_VA_GPIO + 0x0160)
#define S3C64XX_GPQ_BASE	(S3C64XX_VA_GPIO + 0x0180)
#define S3C64XX_SPC_BASE	(S3C64XX_VA_GPIO + 0x01A0)
#define S3C64XX_MEM0CONSTOP	(S3C64XX_VA_GPIO + 0x01B0)
#define S3C64XX_MEM1CONSTOP	(S3C64XX_VA_GPIO + 0x01B4)
#define S3C64XX_MEM0CONSLP0	(S3C64XX_VA_GPIO + 0x01C0)
#define S3C64XX_MEM0CONSLP1	(S3C64XX_VA_GPIO + 0x01C4)
#define S3C64XX_MEM1CONSLP	(S3C64XX_VA_GPIO + 0x01C8)
#define S3C64XX_MEM0DRVCON	(S3C64XX_VA_GPIO + 0x01D0)
#define S3C64XX_MEM1DRVCON	(S3C64XX_VA_GPIO + 0x01D4)
#define S3C64XX_EINT0CON0	(S3C64XX_VA_GPIO + 0x0900)
#define S3C64XX_EINT0CON1	(S3C64XX_VA_GPIO + 0x0904)
#define S3C64XX_EINT0FLTCON0	(S3C64XX_VA_GPIO + 0x0910)
#define S3C64XX_EINT0FLTCON1	(S3C64XX_VA_GPIO + 0x0914)
#define S3C64XX_EINT0FLTCON2	(S3C64XX_VA_GPIO + 0x0918)
#define S3C64XX_EINT0FLTCON3	(S3C64XX_VA_GPIO + 0x091C)
#define S3C64XX_EINT0MASK	(S3C64XX_VA_GPIO + 0x0920)
#define S3C64XX_EINT0PEND	(S3C64XX_VA_GPIO + 0x0924)
#define S3C64XX_SPCONSLP	(S3C64XX_VA_GPIO + 0x0880)
#define S3C64XX_SLPEN		(S3C64XX_VA_GPIO + 0x0930)
#define S3C64XX_EINT12CON	(S3C64XX_VA_GPIO + 0x0200)
#define S3C64XX_EINT34CON	(S3C64XX_VA_GPIO + 0x0204)
#define S3C64XX_EINT56CON	(S3C64XX_VA_GPIO + 0x0208)
#define S3C64XX_EINT78CON	(S3C64XX_VA_GPIO + 0x020C)
#define S3C64XX_EINT9CON	(S3C64XX_VA_GPIO + 0x0210)
#define S3C64XX_EINT12FLTCON	(S3C64XX_VA_GPIO + 0x0220)
#define S3C64XX_EINT34FLTCON	(S3C64XX_VA_GPIO + 0x0224)
#define S3C64XX_EINT56FLTCON	(S3C64XX_VA_GPIO + 0x0228)
#define S3C64XX_EINT78FLTCON	(S3C64XX_VA_GPIO + 0x022C)
#define S3C64XX_EINT9FLTCON	(S3C64XX_VA_GPIO + 0x0230)
#define S3C64XX_EINT12MASK	(S3C64XX_VA_GPIO + 0x0240)
#define S3C64XX_EINT34MASK	(S3C64XX_VA_GPIO + 0x0244)
#define S3C64XX_EINT56MASK	(S3C64XX_VA_GPIO + 0x0248)
#define S3C64XX_EINT78MASK	(S3C64XX_VA_GPIO + 0x024C)
#define S3C64XX_EINT9MASK	(S3C64XX_VA_GPIO + 0x0250)
#define S3C64XX_EINT12PEND	(S3C64XX_VA_GPIO + 0x0260)
#define S3C64XX_EINT34PEND	(S3C64XX_VA_GPIO + 0x0264)
#define S3C64XX_EINT56PEND	(S3C64XX_VA_GPIO + 0x0268)
#define S3C64XX_EINT78PEND	(S3C64XX_VA_GPIO + 0x026C)
#define S3C64XX_EINT9PEND	(S3C64XX_VA_GPIO + 0x0270)
#define S3C64XX_PRIORITY	(S3C64XX_VA_GPIO + 0x0280)
#define S3C64XX_SERVICE		(S3C64XX_VA_GPIO + 0x0284)
#define S3C64XX_SERVICEPEND	(S3C64XX_VA_GPIO + 0x0288)

/* values for S3C_EXTINT0 */
#define S3C64XX_EXTINT_LOWLEV	 (0x00)
#define S3C64XX_EXTINT_HILEV	 (0x01)
#define S3C64XX_EXTINT_FALLEDGE	 (0x02)
#define S3C64XX_EXTINT_RISEEDGE	 (0x04)
#define S3C64XX_EXTINT_BOTHEDGE	 (0x06)

#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */


由上可知此头文件包含了<plat/gpio-bank-a.h>-------><plat/gpio-bank-q.h>系列头文件,而这些头文件里面定义了对应GPIO的一系列数据宏,例如 <plat/gpio-bank-m.h>里面定义的是led程序中用到的GPM端口相关的数据宏,如下:

/* 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)


 3、#include <plat/gpio-cfg.h>:此头文件包含了GPIO的各种配置函数,例如设置输入输出方式,上拉电阻使能等等:

/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h
 *
 * Copyright 2008 Openmoko, Inc.
 * Copyright 2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C Platform - GPIO pin configuration
 *
 * 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.
*/

/* This file contains the necessary definitions to get the basic gpio
 * pin configuration done such as setting a pin to input or output or
 * changing the pull-{up,down} configurations.
 */

/* Note, this interface is being added to the s3c64xx arch first and will
 * be added to the s3c24xx systems later.
 */

#ifndef __PLAT_GPIO_CFG_H
#define __PLAT_GPIO_CFG_H __FILE__

typedef unsigned int __bitwise__ s3c_gpio_pull_t;

/* forward declaration if gpio-core.h hasn't been included */
struct s3c_gpio_chip;

/**
 * struct s3c_gpio_cfg GPIO configuration
 * @cfg_eint: Configuration setting when used for external interrupt source
 * @get_pull: Read the current pull configuration for the GPIO
 * @set_pull: Set the current pull configuraiton for the GPIO
 * @set_config: Set the current configuration for the GPIO
 * @get_config: Read the current configuration for the GPIO
 *
 * Each chip can have more than one type of GPIO bank available and some
 * have different capabilites even when they have the same control register
 * layouts. Provide an point to vector control routine and provide any
 * per-bank configuration information that other systems such as the
 * external interrupt code will need.
 */
struct s3c_gpio_cfg {
	unsigned int	cfg_eint;

	s3c_gpio_pull_t	(*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);
	int		(*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
				    s3c_gpio_pull_t pull);

	unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
	int	 (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
			       unsigned config);
};

#define S3C_GPIO_SPECIAL_MARK	(0xfffffff0)
#define S3C_GPIO_SPECIAL(x)	(S3C_GPIO_SPECIAL_MARK | (x))

/* Defines for generic pin configurations */
#define S3C_GPIO_INPUT	(S3C_GPIO_SPECIAL(0))
#define S3C_GPIO_OUTPUT	(S3C_GPIO_SPECIAL(1))
#define S3C_GPIO_SFN(x)	(S3C_GPIO_SPECIAL(x))

#define s3c_gpio_is_cfg_special(_cfg) \
	(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)

/**
 * s3c_gpio_cfgpin() - Change the GPIO function of a pin.
 * @pin pin The pin number to configure.
 * @pin to The configuration for the pin's function.
 *
 * Configure which function is actually connected to the external
 * pin, such as an gpio input, output or some form of special function
 * connected to an internal peripheral block.
 */
extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);

/* Define values for the pull-{up,down} available for each gpio pin.
 *
 * These values control the state of the weak pull-{up,down} resistors
 * available on most pins on the S3C series. Not all chips support both
 * up or down settings, and it may be dependant on the chip that is being
 * used to whether the particular mode is available.
 */
#define S3C_GPIO_PULL_NONE	((__force s3c_gpio_pull_t)0x00)
#define S3C_GPIO_PULL_DOWN	((__force s3c_gpio_pull_t)0x01)
#define S3C_GPIO_PULL_UP	((__force s3c_gpio_pull_t)0x02)

/**
 * s3c_gpio_setpull() - set the state of a gpio pin pull resistor
 * @pin: The pin number to configure the pull resistor.
 * @pull: The configuration for the pull resistor.
 *
 * This function sets the state of the pull-{up,down} resistor for the
 * specified pin. It will return 0 if successfull, or a negative error
 * code if the pin cannot support the requested pull setting.
*/
extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);

/**
 * s3c_gpio_getpull() - get the pull resistor state of a gpio pin
 * @pin: The pin number to get the settings for
 *
 * Read the pull resistor value for the specified pin.
*/
extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);

#endif /* __PLAT_GPIO_CFG_H */


 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
/** ************************************************************ ************************************************************ ************************************************************ * 文件名: main.c * * 作者: 张继瑞 * * 日期: 2017-01-09 * * 版本: V1.0 * * 说明: GPIO初始化,点亮LED * * 修改记录: ************************************************************ ************************************************************ ************************************************************ **/ //单片机头文件 #include "stm32f10x.h" //硬件驱动 #include "delay.h" #include "led.h" /* ************************************************************ * 函数名称: Hardware_Init * * 函数功能: 硬件初始化 * * 入口参数: 无 * * 返回参数: 无 * * 说明: 初始化单片机功能以及外接设备 ************************************************************ */ void Hardware_Init(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置 Delay_Init(); //Systick初始化,用于普通的延时 Led_Init(); //LED接口初始化 } /* ************************************************************ * 函数名称: main * * 函数功能: LED流水灯 * * 入口参数: 无 * * 返回参数: 0 * * 说明: ************************************************************ */ int main(void) { Hardware_Init(); //硬件初始化 while(1) { Led2_Set(LED_ON);DelayXms(100);Led2_Set(LED_OFF); //点亮LED4,并延时500ms,然后熄灭LED4 Led3_Set(LED_ON);DelayXms(100);Led3_Set(LED_OFF); //点亮LED5,并延时500ms,然后熄灭LED5 Led4_Set(LED_ON);DelayXms(100);Led4_Set(LED_OFF); //点亮LED6,并延时500ms,然后熄灭LED6 Led5_Set(LED_ON);DelayXms(100);Led5_Set(LED_OFF); //点亮LED7,并延时500ms,然后熄灭LED7 } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值