6410之点灯驱动

写一个点LED的驱动分为下面几个步骤:
1.框架
2.完善硬件的操作
a.看原理图
b.看6410手册
c.写代码:
单片机:操作物理地址

驱动:操作虚拟地址:ioremap来进行映射。


查看6410原理图LED SCH如下:

6410之点灯驱动_第1张图片

从上图可以看到,要使得LED点亮,需要使得nLEDx输出的电平为低电平,继续查看SCH,可以看到nLEDx连接到主核心板的GPM 引脚,如下所示:

6410之点灯驱动_第2张图片

所以要操作的工作有:

1.设置GPM0 - GPM3为输出引脚 

2.点灯或者灭灯,对GPMDAT 进行操作即可。

3.使用ioremap和iounmap对物理地址进行映射和取消映射。


具体代码如下:

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

struct class *first_dev_class;
struct device *first_dev;

volatile unsigned long *gpmcon = NULL;
volatile unsigned long *gpmdat = NULL;

static int first_drv_open(struct inode *inode, struct file *file) //设备节点的相关操作函数
{
	printk("first_drv_open!!\n");

	//设置gpio为输出引脚
	*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);  
    *gpmcon |= (0x1 | 0x1 << 4 | 0x1 << 8 | 0x1 << 12);  
	
	return 0;
}

static int first_drv_read(struct file *filp, char __user *buff, 
                                         size_t count, loff_t *offp)
{
	printk("first_drv_read!!\n");
	return 0;
}


ssize_t first_drv_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
	printk("first_drv_write!!\n");

	int val;

	copy_from_user(&val,buf,len);

	if(val == 1){
		//点灯  
        *gpmdat &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
	}else if(val == 0){
		//灭灯
		*gpmdat |= (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);  
	}
	
	return sizeof(buf);
}

static struct file_operations first_drv_fops = {  //填充file_operations结构体
    .owner   =   THIS_MODULE,    
    .open    =   first_drv_open,
    .read    =   first_drv_read,
    .write   =   first_drv_write,
};

int major;
static int __init first_drv_init(void)//入口函数
{
	printk("first_drv_init\n");
	major = register_chrdev(0,"first_drv",&first_drv_fops);//告诉内核设备的操作,将first_drv_fops挂接到主设备为123的索引节点上从而让app可以找到
	first_dev_class = class_create(THIS_MODULE,"first_class");
	first_dev = device_create(first_dev_class,NULL,MKDEV(major,0),NULL,"shanl");

	gpmcon = (volatile unsigned long *)ioremap(0x7F008820, 16);//地理地址转换为虚拟地址
	gpmdat = gpmcon + 1;		

	return 0;
}

static void __exit first_drv_exit(void)
{
	printk("first_drv_exit\n");
	device_destroy(first_dev_class,MKDEV(major,0));
	class_destroy(first_dev_class);
	unregister_chrdev(major,"first_drv");
	iounmap(0x7F008820);
}

module_init(first_drv_init);//入口修饰函数
module_exit(first_drv_exit);

MODULE_LICENSE("GPL"); //证书

测试代码:

#include <stdio.h>
#include <fcntl.h>



int main(int argc , char **argv)
{
	int fd ;
	int val;

	if(argc < 2){
	        printf("Usage : %s <on/off> \n",argv[0]);
		return -1;
	}
	
	if(!strcmp(argv[1],"on")){
		val = 1;
	}else if(!strcmp(argv[1],"off")){
		val = 0;
	}
	fd = open("/dev/shanl",O_RDWR); //打开设备节点/dev/shanl
	if(fd < 0){
		printf("Can not open devices\n");
		return -1;
	}

	write(fd,&val,4);//向设备节点做写操作
	return 0;
}







   

你可能感兴趣的:(点灯)