Chinaunix首页 | 论坛 | 博客
  • 博客访问: 722838
  • 博文数量: 105
  • 博客积分: 3532
  • 博客等级: 中校
  • 技术积分: 1328
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 18:57
文章分类

全部博文(105)

文章存档

2015年(1)

2014年(1)

2013年(7)

2012年(14)

2011年(21)

2010年(61)

分类: 嵌入式

2010-08-21 07:41:01

  1. 平台:
    操作系统:linux-2.6.34
    硬件平台:s3c2440
    编译器版本:arm-none-eabi-gcc 4.4.1
  2. 实现功能:2个LED不断闪烁,间隔2s
  3. 电路图

    图1 两个上拉的LED

    图2 接到S3C2440的GPB10和GPB7
  4. 一个公共的头文件ypublic.h

    //ypublic.h

    #ifndef __Y_PUBLIC__
    #define __Y_PUBLIC__

    #include <linux/ioport.h>
    #include <linux/timer.h>

    #include <asm/io.h>

    //#define MS(n) (HZ*(n)/1000)

    #define PI 3.1415927
    #define uint unsigned int
    #define uchar unsigned char
    #define ulong unsigned long
    #define byte uchar

    static void* yioremap(ulong start,ulong n,char name[])
    {
        if(request_mem_region(start,n,name)==NULL)return NULL;
        return ioremap(start,n);
    }

    static void yiounmap(ulong start,ulong n)
    {
        iounmap(start);
        release_mem_region(start,n);
    }

    static ulong fortimems(ulong ms)
    {
        return (jiffies+HZ*ms/1000);
    }

    #define MS(n) fortimems(n)
    #endif


  5. LED驱动程序:yled.c

    //yled.c

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/cdev.h>
    #include <linux/ioport.h>
    #include <linux/fs.h>
    #include <linux/slab.h>

    #include <asm/io.h>
    #include "ypublic.h"

    MODULE_LICENSE("Dual BSD/GPL");
    #define YMAJOR 100
    #define YMINOR 1
    #define YDEVICENAME "uartdriver"
    #define YBUFSIZE 10
    #define UBRDIVn(baud) ()
    #define SETB(n) (1<<(n))
    #define CLRB(n) (~ SETB(n))
    #define SETN(v,n) (v<<n)
    #define SETNB(v,d,n,w)\
        ({\
        ulong rs;\
        rs=0xffffffff;\
        rs=rs<<(32-n-w);\
        rs=rs>>(32-w);\
        rs=~(rs<<n);\
        rs=n&rs|(v<<n);\
        rs;\
        })
    #if 0
    #define uint unsigned int
    #define uchar unsigned char
    #define ulong unsigned long
    #endif


    //io

    #define UARTBASE(n) (0x50000000+(0x00004000<<(n)))
    #define UARTREGNUM 3
    #define YUART0 UARTBASE(0)
    #define YUART1 UARTBASE(1)
    #define YUART2 UARTBASE(2)
    #define YINFRARED_MODE SETB(6)
    #define YNOPARITY 0
    #define Y2STOPBIT SETB(2)
    #define Y8BITS SETN(3,0)


    typedef struct {
        struct cdev dev;
        uchar inbuf[YBUFSIZE];
        uchar outbuf[YBUFSIZE];
    }ycdev;

    ycdev *_pdev;
    static int _major=YMAJOR;
    static struct timer_list _tm;

    //io regs

    #define GPBBASE 0x56000010
    ulong rgpbcon,rgpbdat,rgpbup;


    static void* initio(void)
    {
        if(request_mem_region(UARTBASE(0),sizeof(YRUart),"UART")==NULL)
            return NULL;
        _uart=(YRUart *)ioremap(UARTBASE(0),sizeof(YRUart));
        return (void*)_uart;
    }

    void releaseio(void)
    {
        if(_uart!=NULL){
            iounmap((void*)UARTBASE(0));
            release_mem_region(UARTBASE(0),sizeof(YRUart));
        }
    }
    irqreturn_t onIrq(int irq,void *dev_id)
    {
        _tm.expires=MS(2000);
        add_timer(&_tm);
        
        return IRQ_HANDLED;
    }

    void initUart(void)
    {
        iowrite32(Y8BITS,&_uart->ULCON);
    }

    static void onTime(ulong arg)
    {

        uint dat;
        dat=ioread32(rgpbdat);
        if(dat&SETB(10)){
            iowrite32((~(SETB(7)|SETB(10)))&dat,rgpbdat);
            }
        else{
            iowrite32(SETB(7)|SETB(10)|dat,rgpbdat);
            }
      
        _tm.expires=MS(2000);
        printk(KERN_INFO "on time:%u\n",dat);
        add_timer(&_tm);
    }

    int yopen(struct inode *pinode,struct file *pfile)
    {
        return 0;
    }

    int yrelease(struct inode *pinode,struct file *pfile)
    {
        return 0;
    }

    static struct file_operations _fops={
        .open=yopen,
        .release=yrelease,
    };

    int __init yinit(void)
    {
        dev_t devno=MKDEV(YMAJOR,YMINOR);
        int rs;
        uint tmp;
        if(_major){
                rs=register_chrdev_region(devno,1,YDEVICENAME);
            }
        else{
            rs=alloc_chrdev_region(&devno,YMINOR,1,YDEVICENAME);
            _major=MAJOR(devno);
            }
        if(rs<0)return rs;
        _pdev=kmalloc(sizeof(ycdev),GFP_KERNEL);
        if(!_pdev){
            
            rs= -ENOMEM;
            goto fail1;
            }
        cdev_init(&_pdev->dev,&_fops);
        _pdev->dev.owner=THIS_MODULE;
        rs=cdev_add(&_pdev->dev,MKDEV(_major,YMINOR),0);
        if(rs){
            rs=-EBUSY;
            goto fail2;
            }
    #if 0
        if(initio()==NULL)
            printk(KERN_ERR"ioremap failed\n");
        else printk(KERN_ERR"ioremap success\n");
    #endif
        rgpbcon=yioremap(GPBBASE,12,"gpbreg");
        rgpgcon=yioremap(GPBGASE,12,"gpgreg");
        if(rgpbcon==NULL||rgpgcon==NULL)goto fail2;
        else{
            rgpbdat=rgpbcon+4;
            rgpbup=rgpbcon+8;
            iowrite32(SETN(1,14)|SETN(1,20)|ioread32(rgpbcon),rgpbcon);
            iowrite32(SETB(7)|SETB(10)|ioread32(rgpbup),rgpbup);
            iowrite32(SETB(7)|SETB(10)|ioread32(rgpbdat),rgpbdat);
            if(rs)printk(KERN_INFO"irq failed");
            }
        setup_timer(&_tm,onTime,1);
        
        printk(KERN_INFO "driver ok\n");
        return 0;
    fail2:
        kfree(_pdev);
    fail1:
        unregister_chrdev_region(devno,1);
        return -EBUSY;
    }

    void __exit yexit(void)
    {
        del_timer(&_tm);
        yiounmap(GPBBASE,12);
        cdev_del(&_pdev->dev);
        kfree(_pdev);
        unregister_chrdev_region(MKDEV(_major,YMINOR),1);
    }

    MODULE_AUTHOR("MrY");
    module_init(yinit);
    module_exit(yexit);

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