分类: 嵌入式
2010-06-02 17:09:22
在uClinux-dist/linux-2.4.x/drivers/char 目录下 编写驱动程序
gpio.h (头文件)
#ifndef __GPIO_H
#define __GPIO_H
#include
#define GPIO_PIN_LOW 0
#define GPIO_PIN_HIGH 1
#define GPIO_PIN_ERR (~0)
#define GPIO_IOC_MAGIC 0xd0 (幻数)
#define GPIO_SET_PIN _IO(GPIO_IOC_MAGIC,0)
#define GPIO_SET_ALL_PIN _IO(GPIO_IOC_MAGIC,1)
#define GPIO_CLR_PIN _IO(GPIO_IOC_MAGIC,2)
#define GPIO_CLR_ALL_PIN _IO(GPIO_IOC_MAGIC,3)
#define GPIO_SET_PIN_OUT _IO(GPIO_IOC_MAGIC,4)
#define GPIO_SET_PIN_IN _IO(GPIO_IOC_MAGIC,5)
#define GPIO_MAXNR 6
#endif
##############################################################################
Ioctl 命令必须唯一防止错误的设备引用正确的设备号 这个ioctl号通常用一个头文件中的宏调用
(_IO,_IOR,_IOW或_IOWR——取决于类型)创建,(内核/include/asm/ioctl.h)
幻数不能重复,可以在内核/Documentation/magic-number.txt
gpio.c (驱动程序)
#include
#include
#include
#include
#include
#include
#include
#include"gpio.h"
static int gpio_open(struct inode *inode,struct file *filp);
static int gpio_release(struct inode *inode,struct file *filp);
static int gpio_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,
unsigned long param);
#define GPIO_MAJOR_NR 126 //主设备号
#define DEVICE_NAME "gpio" //设备名称
#define MAX_PORT 1 /* 1 devices */
#define GPIO_CONC_ADDR 0x01d20010 //PortC的配置寄存器地址
#define GPIO_DATA_ADDR 0x01d20014 //PortC的数据寄存器地址
static struct file_operations gpio_fops=
{
ioctl: gpio_ioctl,
open: gpio_open,
release:gpio_release,
};
int __init gpio_init(void)
{
int result;
result = register_chrdev(GPIO_MAJOR_NR, DEVICE_NAME, &gpio_fops);
if (result < 0) {
printk(KERN_ERR DEVICE_NAME ":Unable to get major %d\n", GPIO_MAJOR_NR);
return result;
}
printk(KERN_INFO DEVICE_NAME ": init OK\n");
return 0;
}
void __exit gpio_cleanup(void)
{
unregister_chrdev(GPIO_MAJOR_NR, DEVICE_NAME);
}
static int gpio_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT; //2.6内核 没有这2个宏定义
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int gpio_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int num;
volatile u32 *Regconc,*Regdata;
num = MINOR(inode->i_rdev);
if (num >= MAX_PORT) {
return -ENODEV;
}
if (_IOC_TYPE(cmd) != GPIO_IOC_MAGIC) {
return -ENOTTY;
}
if (_IOC_NR(cmd) >= GPIO_MAXNR) {
return -ENOTTY;
}
Regconc = (volatile u32 *)(GPIO_CONC_ADDR);
Regdata = (volatile u32 *)(GPIO_DATA_ADDR);
//需要查看PortC的PCONC和PDATC寄存器的相关参数来对I/O引脚进行配置
switch(cmd){
case GPIO_SET_PIN://设置某个I/O引脚为为高电平
if (arg < 16) {
*Regdata |= 1u << arg;
}
break;
case GPIO_SET_ALL_PIN://设置多个I/O引脚为高电平
*Regdata |= arg;
break;
case GPIO_CLR_PIN:// 设置某个I/O引脚为为低电平
if (arg < 16) {
*Regdata &= ~(1u << arg);
}
break;
case GPIO_CLR_ALL_PIN: //设置多个I/O引脚为低电平
*Regdata &= ~arg;
break;
case GPIO_SET_PIN_OUT://设置某个I/O引脚为输出引脚
if (arg < 16) {
*Regconc &= ~(1u << (2*arg + 1));
*Regconc |= 1u << (2*arg);
}
break;
case GPIO_SET_PIN_IN: //设置某个I/O引脚为输入引脚
if (arg < 16) {
*Regconc &= ~(1u << (2*arg));
*Regconc &= ~(1u << (2*arg + 1));
}
break;
}
return 0;
}
在uClinux/vendors/samsung/44b0目录下的Makefile文件里添加
\
gpio,c,126,0 \
设备名称 字符型驱动 主设备号 次设备号
进入uClinux-dist/linux-2.4.x/drivers/char/config.in
添加
bool 'gpiotest' CONFIG_GPIO
进入 uClinux-dist/linux-2.4.x/drivers/char/Makefile
添加 obj-$(CONFIG_GPIO) +=gpio.o
进入 uClinux-dist/linux-2.4.x/drivers/char/mem.c
添加
#ifdef CONFIG_GPIO
extern gpio_init(void);
#endif
和
#ifdef CONFIG_GPIO
goio_init();
#endif
在uClinuc-dist/user/ioport
编写应用程序 ioport.c
编写Makefile
在uClinux-dist/config/config.in添加相关程序
在uClinux-dist/user/Makefile 添加相关程序
开始编译内核
makemenuconfig
make dep
make clean
make lib_only
make user_onlv
make romfs
make image
make
把镜像文件下载到板子上执行(如果要使系统启动自动执行该应用程序在uClinux-dist/vendors/Samsung/44B0/rc文件里添加/bin/..)