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) modulesclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules cleanobj-m := led_drv.o
編譯沒有問題,就可以下到板子測試了。