OK6410 点亮LED灯

OK6410gpio控制led


led原理图如下:











































由原理突分析可得:GPM*(01 2 3) -> NLED* (1 2 3 4)为低时,则VDD33VNLED*之间有电压差,产生电流,LED亮。即GPM配置成低,LED亮,反之灭

















s3c6410手册中对GPM的配置:
































前面我们要把GPM*配置为低,达到点亮led的目的,那么我们要配置GPIO,通过GPM我们在芯片手册里找到了GPMCON配置寄存器,关于为什么这个寄存器是这个地址可以去看下统一编址和bank这些内容(我也不是很懂,哈哈)


既然在芯片手册里找到了这些有用的信息,那么下一步我们就要分析手册和电亮led了。


首先我们获取了GPMCON的地址,通过芯片手册可知,它一共0—23位有效,并每四位控制一个引脚

,即一共控制6gpio,这些gpio可以配置成8种模式,我们需要的是配置成output模式,并使其输出低电平


看下GPM的定义,当GPMCON配置成输出模式时,引脚的状态和GPMDAT中相应的位状态是一样的,即GPMDAT[i]对应GPM[i]


获取了这些硬件原理和芯片手册的信息,那么下一步我们就可以写linux驱动了

还有几点需要注意的是,在linux下我们用的时虚拟地址,我们要通过我们所直到的GPMCONGPMDAT的物理地址获取其虚拟地址ioremp


#defineioremap(cookie,size) __arch_ioremap((cookie), (size),MT_DEVICE)

linux的定义下它是一个和平台相关的宏实现


有了这些我们就可以写驱动了,由于能力有限, 不会写很麻烦的,都是以实现位目的的。。字符型吧。。


关于字符型设备驱动,需要的有 设备号,设备名, 和file_operations的实现


#include <linux/module.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
#include <linux/fs.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("tyfanxzh");


#define LED_MAJOR 250
struct cdev cdev;

//定义gpio_va的目的是为了可以使定义的宏可以直接通过虚拟地址操作物理地址
static unsigned long gpio_va;

//定义我们需要的GPM控制器的地址 GPMCON: 0x7F008820 GPMDAT: 0x7F008824
#define GPMCON (*(volatile unsigned long*) (gpio_va))
#define GPMDAT (*(volatile unsigned long*) (gpio_va + 4))

//要配置的GPM的值
#define GPM_OUTPUT_MASK (~0xf)
#define GPM_OUTPUT	 0x1
#define GPM_DAT 	 0x1

//实现cdev的fops
int led_open(struct inode *node, struct file *filp)
{
//初始化四个gpio
//初始化GPM0
printk("fanxzh led_open\n");
	GPMCON = (GPMCON & ~0xf) | 0x1;
	GPMDAT &= ~(0x1);

	GPMCON = (GPMCON & ~(0xf << 4)) | (0x1 << 4);
	GPMDAT &= ~(0x1 << 1);

	GPMCON = (GPMCON & ~(0xf << 8)) | (0x1 << 8);
	GPMDAT &= ~(0x1 << 2);

	GPMCON = (GPMCON & ~(0xf << 12)) | (0x1 << 12);
	GPMDAT &= ~(0x1 << 3);

	return 0;
}
int led_close(struct inode *node, struct file *filp)
{
	printk("fanxzh Close the file\n");
	
	return 0;
}
long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
printk("fanxzh led_ioctl\n");
	switch(cmd) {
		case 0:
			GPMCON = (GPMCON & ~0xf) | 0x1;
    		GPMDAT |= 0x1;
			break;
		case 1:
			GPMCON = (GPMCON & ~(0xf << 4)) | (0x1 << 4);
    		GPMDAT |= ~(0x1 << 1);	
		break;
	}
	return 0;
}

static const struct file_operations fanxzh_fops = {
	.owner = THIS_MODULE,
	.open  = led_open,
	.unlocked_ioctl = led_ioctl,
	.release = led_close,
};


int fanxzh_led_init(void)
{
	int ret;
	dev_t devno = MKDEV(LED_MAJOR, 0);
//test 首先映射物理地址获取其物理地址, 然后对其进行控制,配置GPMCON后然后对pin脚进行控制
	gpio_va = (unsigned long)ioremap(0x7F008820, 8);

//	GPMCON = (GPMCON & GPM_OUTPUT_MASK) | 0x1; //首先后四位置为0, 然后配置成output模式
//	GPMDAT = GPMDAT & ~(0x1); //把最后一位置为0 ,则pin脚输出低电平
	
	printk("Install fanxzh leds module\n");

//开始字符型设备的书写
	ret = register_chrdev_region(devno, 1, "fanxzh_led");
	
	if(ret < 0) {
		return -1;
	}

	cdev_init(&cdev, &fanxzh_fops);
	cdev.owner = THIS_MODULE;
	ret = cdev_add(&cdev, devno, 1);

	if(ret) {
		printk(KERN_NOTICE "Error: %d adding LED\n", ret);
	}
	
	return 0;
}

void fanxzh_led_exit(void)
{
	iounmap((void*)gpio_va);
	printk("Remove fanxzh leds module\n");
}

module_init(fanxzh_led_init);
module_exit(fanxzh_led_exit);

终于凑了出来。。对于设备模型和gpio还是不熟, 需要继续学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值