1. 查看原理图
2.查询tiny6410芯片手册
LED1---à GPK4
LED2---à GPK5
LED3---à GPK6
LED4---à GPK7
下面还需要3个步骤:
1、设置GPIO为OUTPUT。
将GPK4、GPK5、GPK6、GPK7设置为输出output=0001
即GPKCON0 [19:16]配置为0001 GPKCON0 [23:20]配置为0001
GPKCON0 [27:24]配置为0001 GPKCON0 [28:31]配置为0001
2、设置GPIO的数据。
将GPKDATA的4:7位赋值为0
GPKDATA[4] = 0或1 GPKDATA[5] = 0或1
GPKDATA[6] = 0或1 GPKDATA[7] = 0或1
3、设置GPKUP为上拉。
将GPKUP的4: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
编译没有问题,就可以下到板子测试了。