您的位置:首页 > 其它

点亮GT2440开发板上的led(基于IO内存实现)

2012-05-15 17:16 288 查看
首先的感谢这微博主:http://blog.csdn.net/jianchi88/article/details/6848035

我在这先粘下我的开发版的数据手册的led截图,毕竟涉及到硬件知识,也是为了让大家读更加容易明白:








驱动程序源码:

#include <linux/module.h> //内核模块头文件  
#include <linux/moduleparam.h>  //内核模块参数头文件  
#include <linux/kernel.h>  //printk头文件  
 
#include<asm/io.h>//ioremap需要  
//包含有可装载模块需要的大量符合和函数的定义;  
#include <linux/init.h>  
//指定初始化和清除函数;  
 
//struct file_operactions 相关头文件  
#include <linux/fs.h>  
#include <asm/uaccess.h>  
 
//struct cdev 相关头文件  
#include <linux/types.h>  
#include <linux/cdev.h>  
 
//定义设备名称  
#define DEVICE_NAME "led"  
 
//定义主次设备号  
static unsigned int LedMajor=0;  
static unsigned int LedMinor=0;  
 
/* 注册字符设备 */  
static struct cdev *led_cdev;  
static dev_t dev;  //设备号  
 
volatile unsigned int long *gpb_con = NULL;    
volatile unsigned int long *gpb_data = NULL;    
 
 
static int led_ioctl(struct inode *inode, struct file *file,    
                    unsigned int cmd, unsigned long arg)    
{    
    
         if((cmd>1) | (cmd<0) | (arg>3) | (arg<0))    
                   return -EINVAL;    
                      
         switch(cmd)    
         {    
                   case 0:    
                            *gpb_data|= (1<<(arg+5));  //0
                            break;    
                   case 1:    
                            *gpb_data&= ~(1<<(arg+5));  //1   
                            break;    
                               
                   default:    
                            return -EINVAL;    
                               
         }    
            
         return 0;    
}    
 
 
/*static int led_open(struct inode *inode, struct file *file)  
{  
    printk("led_open\n");  
      
    //映射I/O内存    
    gpb_con = (volatile unsigned long *)ioremap(0x56000010,16); //0x56000010为GPIOB控制寄存器的物理地址    
    gpb_data = gpb_con+1;  //这里+1是加了4个字节,因为指针+1是以指针的长度为单位的(unsigned long *)  
 
    // 配置GPB5,6,7,8为输出  
    *gpb_con &= ~((1<<(5)) & (1<<(6)) & (1<<(7)) & (1<<(8)));  
    // 初始化为灭
    *gpb_data |=(1<<5) | (1<<6) | (1<<7) | (1<<8);   
 
    printk("leaving led_open\n");  
    return 0;  
 
}  
  */
/*static int led_release(struct inode *inode,struct file *file)  
{  
 
        printk("close major=%d, minor=%d\n", imajor(inode), iminor(inode));  
    return 0;  
}  
  */
static struct file_operations chardev_fops={  
    .owner = THIS_MODULE,  
    //.open = led_open,  
    //.release = led_release,  
    .ioctl = led_ioctl,  
};  
 
 
static int __init dev_init(void)  
{  
    int result;  
/*分配设备编号*/  
    if(LedMajor)  
    {  
        dev=MKDEV(LedMajor,LedMinor);//创建设备编号  
        result=register_chrdev_region(dev,1,DEVICE_NAME);  
    }   
    else   
    {  
        result=alloc_chrdev_region(&dev,LedMinor,1,DEVICE_NAME);  
        LedMajor=MAJOR(dev);  
    }  
    if(result<0)  
    {  
        printk(KERN_WARNING"LED: cannot get major %d \n",LedMajor);  
        return result;  
    }  
/* 注册字符设备 */  
    led_cdev=cdev_alloc();//为struct cdev 分配空间  
 
    cdev_init(led_cdev,&chardev_fops);//初始化struct cdev  
      
    led_cdev->owner=THIS_MODULE;  
      
    result=cdev_add(led_cdev,dev,1);  
      
    if(result)  
        printk("<1>Error %d while register led device!\n",result);  
          
    printk("initialzed.\n");  
        //映射I/O内存    
    gpb_con = (volatile unsigned long *)ioremap(0x56000010,16); //0x56000010为GPIOB控制寄存器的物理地址    
    gpb_data = gpb_con+1;  //这里+1是加了4个字节,因为指针+1是以指针的长度为单位的(unsigned long *)  
 
    // 配置GPB5,6,7,8为输出  
    *gpb_con &= ~((1<<(5)) & (1<<(6)) & (1<<(7)) & (1<<(8)));  
    // 初始化为灭
    *gpb_data |=(1<<5) | (1<<6) | (1<<7) | (1<<8);   
    return 0;  
}  
 
static void __exit dev_exit(void)  
{  
    unregister_chrdev_region(MKDEV(LedMajor,LedMinor),1);  
    cdev_del(led_cdev);  
}  
 
module_init(dev_init);  
module_exit(dev_exit);  
MODULE_LICENSE("GPL");  
MODULE_AUTHOR("Bai"); 

测试程序就补贴出来了,我想大家都不会感到有难度。

运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  io struct module file cmd null