Chinaunix首页 | 论坛 | 博客
  • 博客访问: 254348
  • 博文数量: 89
  • 博客积分: 1380
  • 博客等级: 中尉
  • 技术积分: 705
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-10 11:04
文章分类

全部博文(89)

文章存档

2014年(4)

2011年(1)

2010年(42)

2009年(42)

我的朋友

分类: 嵌入式

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

阅读(819) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~