mini2440 LED驱动 (用ioremap实现访问CPU寄存器)

转载 2012年03月25日 23:24:32

I/O 内存访问流程:

1. request_mem_region()  申请IO内存

2.ioremap() 将物理地址映射到虚拟地址

3.ioread8() 、ioread16()、ioread32()、iowrite8()、iowrite16()、iowrite32() 读写

4.iounmap() 释放虚拟内存

5.release_mem_region() 释放IO内存

注意:

1、2 在模块初始化或打开设备时调用

4、5 在模块卸载或关闭设备时调用

request_mem_region()不是必须使用,但建议使用。任务是检查申请的资源是否可用,如果可用则申请成功,并标志为已经使用,其他驱动想再次申请该资源就会失败。

 

 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/ioport.h>

#define DEVICE_NAME "led_decly"

#define LED1_ON   ~(1<<5) //低电平点亮LED
#define LED2_ON   ~(1<<6)
#define LED3_ON   ~(1<<7)
#define LED4_ON   ~(1<<8)

#define LED1_OFF   (1<<5)
#define LED2_OFF   (1<<6)
#define LED3_OFF   (1<<7)
#define LED4_OFF   (1<<8)

#define GPBCON 0x56000010 //寄存器地址(物理地址)
#define GPBDAT 0x56000014
static volatile unsigned long *gpbcon_addr; //经过ioremap映射后的虚拟地址
static volatile unsigned long *gpbdat_addr;

static void Led_port_init(void)
{
   //设置GPB5-GPB8为输出端口
   *gpbcon_addr &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16)); 
   *gpbcon_addr |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
   
   //全亮
   *gpbdat_addr &= LED1_ON & LED2_ON & LED3_ON & LED4_ON;
}


static void led_turn_on(unsigned int led_nu)
{
 switch (led_nu)
 {
  case 1:
   *gpbdat_addr &= LED1_ON;
   break;
  case 2:
   *gpbdat_addr &= LED2_ON;
   break;
  case 3:
   *gpbdat_addr &= LED3_ON;
   break;
  case 4:
   *gpbdat_addr &= LED4_ON;
   break;
  default:
   break;
 }
}

static void led_turn_off(unsigned int led_nu)
{
 switch (led_nu)
 {
  case 1:
   *gpbdat_addr |= LED1_OFF;
   break;
  case 2:
   *gpbdat_addr |= LED2_OFF;
   break;
  case 3:
   *gpbdat_addr |= LED3_OFF;
   break;
  case 4:
   *gpbdat_addr |= LED4_OFF;
   break;
  default:
   break;
 }
}

static int led_open(struct inode * inode , struct file * filp)
{
 return 0;
}

static int led_release(struct inode * inode, struct file *filp)
{
 return 0;
}

static int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
 int ret = 0;
 switch (cmd)
 {
  case 0:
   led_turn_off(arg);
   break;
  case 1:
   led_turn_on(arg);
   break;
  default:
   ret = -EINVAL;
   break;
 }
 return ret;
}

static const struct file_operations led_fops =
{
 .owner = THIS_MODULE,
 .open = led_open,
 .release = led_release,
 .ioctl = led_ioctl,
};

static struct miscdevice led_dev =
{
 .minor = MISC_DYNAMIC_MINOR,
 .name = DEVICE_NAME,
 .fops = &led_fops,
};

static int __init led_init(void)

 int ret;
 
 //申请IO内存,不是必须的。
 if (!request_mem_region(GPBCON, 8, "leds"))
 {
  ret = -EBUSY;
  goto request_mem_failed;
 }
 
 gpbcon_addr = ioremap(GPBCON, 4);//将物理地址映射为虚拟地址
 if (NULL == gpbcon_addr)
 {
  ret = -EIO;
  printk("gpbcon remap failed\n");
  goto con_map_failed;
 }
 gpbdat_addr = ioremap(GPBDAT, 4);
 if (NULL == gpbdat_addr)
 {
  ret = -EIO;
  printk("gpbdat remap failed\n");
  goto dat_map_failed;
 }
 printk("gpbcon_addr remap on %p\n", gpbcon_addr);
 printk("gpbdat_addr remap on %p\n", gpbdat_addr);
 
 Led_port_init();

 ret = misc_register(&led_dev);
 if (ret)
 {
  printk("misc_register failed\n");
  goto failed;
 }
 
 printk("leds init\n");
 return 0;
 
 failed:
  iounmap(gpbdat_addr);
 dat_map_failed:
  iounmap(gpbcon_addr);
 con_map_failed:
  release_mem_region(GPBCON, 8);
 request_mem_failed:
  return ret;
}

static void __exit led_exit(void)
{
 iounmap(gpbdat_addr); //取消映射
 iounmap(gpbcon_addr);
 release_mem_region(GPBCON, 8); //释放I/O内存
 misc_deregister(&led_dev);
 
 printk("leds exit\n");
}

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Decly");
module_init(led_init);
module_exit(led_exit);

相关文章推荐

驱动案例一:mini2440 LED驱动 (用ioremap实现访问CPU寄存器)

I/O 内存访问流程: 1. request_mem_region()  申请IO内存 2.ioremap() 将物理地址映射到虚拟地址 3.ioread8() 、ioread16()、iore...

《OK6410-LED驱动程序设计》之使用ioremap实现访问CPU寄存器

Ok6410开发板LED连接电路图:            从电路图上我们可以看到,发光二极管LED 的一端连接到了ARM 的GPIO,另一端经过一个限流电阻接电源VCC3。当GPIO 口为低电...

[2014.3.20]mini2440用ioremap写LED驱动程序

这两天移植在实验室和师兄测试接收机,没有什么时间学嵌入式。现在这个程序还只是一个半成品,暂且贴在这,有很多地方还不完美,回来再写个更好的。果然把裸机代码加个init open read write c...

Linux2.6.32驱动笔记(4)ioctl方法解析及mini2440-led驱动实现

摘要: 介绍了字符设备驱动的控制方式——ioctl,同时利用该方式在mini2440上实现led驱动。 驱动中,除了read,write,open,close之外,还有很多的访问方式,其中对...

mini2440LED驱动程序开发

mini2440LED驱动程序开发

对mini2440LED灯驱动开发

一直在学习友善之臂的MINI2440开发板,今天完成了,led的实验在此总结一下 1.编写驱动程序(led1.c) #include #include #include #include...

mini2440 led驱动

mini2440 led驱动  2009-09-27 18:36:12|  分类: C++学习 |  标签: |字号大中小 订阅 整理一下思路,刚刚看的mi...

mini2440 led驱动程序经典分析

*************************转载请注明出处***************************************************** Linux内核为2.6.3...

linux-2.6.32在mini2440开发板上移植(16)之LED 驱动程序移植

转载:http://blog.csdn.net/weiqifa0/article/details/8904453 LED 驱动程序移植 编者;对于led的驱动程序,很多文章都有...

mini2440Led驱动——linux-3.10.59

mini2440的led驱动,linux3.10.59
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)