Tiny6410_LED驱动程序_手动分配主设备号+手动创建设备节点


1. 查看原理图

 

 

 

 

2.查询tiny6410芯片手册

 

 

 

LED1---à GPK4

LED2---à GPK5

LED3---à GPK6

LED4---à GPK7

 

下面还需要3个步骤:

1、设置GPIOOUTPUT

    GPK4GPK5GPK6GPK7设置为输出output=0001

     GPKCON0 [19:16]配置为0001  GPKCON0 [23:20]配置为0001

GPKCON0 [27:24]配置为0001   GPKCON0 [28:31]配置为0001

 

2、设置GPIO的数据。

   GPKDATA4:7位赋值为0

GPKDATA[4] = 01   GPKDATA[5] = 01

GPKDATA[6] = 01   GPKDATA[7] = 01

 

3、设置GPKUP为上拉。

   GPKUP4:7位设置为10

GPKUP [4] = 1   GPKUP [5] = 1

GPKUP [6] = 1  GPKUP [7] = 1

(也可以不用设置)

 

led_drv.c

 

#include <linux/init.h>			/* For __init/__exit/... */
#include <linux/kernel.h>		/* For printk/panic/... */
#include <linux/module.h>		/* For module specific items */
#include <linux/fs.h>			/* For file operations */
#include <linux/types.h>		/* For standard types (like size_t) */
#include <linux/errno.h>		/* For the -ENODEV/... values */
#include <linux/ioport.h>		/* For io-port access */
#include <linux/uaccess.h>		/* For copy_to_user/put_user/... */
#include <linux/io.h>			/* For inb/outb/.../ioremap/... */


#define GPKCON_PA  (0x7F008800)
#define GPKDAT_PA  (0x7F008808)

static int major = 243; /* 首先在开发板上,使用命令cat /proc/devices 查看空余的主设备号*/
static volatile unsigned long *gpkcon = NULL;
static volatile unsigned long *gpkdat = NULL;

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

/* buf[0] - which led
 *          0 -   GPK4
 *          1 -   GPK5
 *          2 -   GPK6
 *          3 -   GPK7
 * buf[1] - 0:on / 1:off */
static ssize_t led_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	char which;
	char status;
	
	char ker_buf[2];

	copy_from_user(ker_buf, buf, 2);
	which = ker_buf[0];
	status   = ker_buf[1];


	if (which < 0 || which > 3)
	{
		printk("No led%d.\n", (which+1));
		return -EINVAL;
	}
	else
	{	
		printk("led%d, status = %s\n", (which+1), status?("off"):("on"));

		if (status)
			*gpkdat |=  (1<<(which+4));
		else
			*gpkdat &= ~(1<<(which+4));
			
	}
	
	return 2;
}

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

static struct file_operations led_fops = {
	.owner 		= THIS_MODULE,
	.open  		= led_open,
	.write 		= led_write,
	.release 	= led_release,
};

static int led_init(void)
{
	int ret;
	ret = register_chrdev(major, "led", &led_fops);
	if(ret < 0)
	{
		printk("register failed!\n"); 
		return ret;
	}
	
	printk("register char dev successful!\n"); /* 如果没有打印,使用$ dmesg | grep register */
	
	/* 获取对应的虚拟地址 */
	gpkcon = ioremap(GPKCON_PA, 4);
	gpkdat = ioremap(GPKDAT_PA, 4);
	
	/* 配置为输出 */
	*gpkcon &= ~(0xffff<<16);
	*gpkcon |= 0x1111<<16;
	
	/* 熄灭4个led */
	*gpkdat |= (0x1<<4|0x1<<5|0x1<<6|0x1<<7);
	
	return ret;
}

static void led_exit(void)
{
	/* 点亮4个led */
	*gpkdat &= ~(0x1<<4|0x1<<5|0x1<<6|0x1<<7);
	
	iounmap(gpkcon);
	iounmap(gpkdat);
	
	unregister_chrdev(major, "led");
	printk("unregister char dev successful!\n");
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");



led_app.c

 

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

/* led_test <which> <on|off> */

void print_usage(char *file)
{
	printf("Usage: \n");
	printf("%s <0 | 1 | 2 | 3> <on | off>\n", file);
}

int main(int argc, char* argv[])
{
	char buf[2];
	int  fd;
	int  len;

	if (argc != 3)
	{
		print_usage(argv[0]);
		return -1;
	}

	fd = open("/dev/my_led", O_RDWR);
	if (fd < 0)
	{	
		printf("Open error!\n");
		exit(-1);
	}
	
	buf[0] = strtoul(argv[1], NULL, 0);
	if (strcmp(argv[2], "on") == 0)
	{	
		buf[1] = 0;
	}
	else if(strcmp(argv[2], "off") == 0)
	{	
		buf[1] = 1;
	}
	else
	{
		print_usage(argv[0]);
		return -1;
	}

	write(fd, buf, 2);
	
	close(fd);
	
	return 0;
}


Makefile

 

KERNELDIR = /sdb/kernel/linux-2.6.38-tiny6410/linux-2.6.38/
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules  clean

obj-m := led_drv.o


编译没有问题,就可以下到板子测试了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值