PS:花了一个晚上,将led驱动搞定了,很欣慰啊,下面记录下这个经过。
1.[看TE6410底板原理图] 在飞凌TE6410的开发板上面任意找一个空闲的GPIO口,然后再GPIO口上面挂载一个led。比如在GPP1上面挂载一个led;
2.[S3C6410用户手册] 找到有关GPP的一章节,看到如下语句:
3.[回到虚拟机] 现在可以写驱动程序了,当然预先要知道内核模块的知识,因为我打算采用内核模块的方式来加载驱动。内核模块的知识就不介绍了;
1)先写驱动函数led.c:参考http://blog.csdn.net/eastmoon502136/article/details/7705733
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <linux/device.h> #include <linux/cdev.h> #include <asm/irq.h> #include <mach/gpio.h> #include <mach/map.h> #include <mach/gpio-bank-p.h> #include <mach/regs-gpio.h> #include <plat/gpio-cfg.h> #include <mach/hardware.h> #include <linux/io.h> MODULE_LICENSE("GPL"); #define LED_MAJOR 240 int led_open(struct inode *inode, struct file *filp) { unsigned int tmp; tmp = readl(S3C64XX_GPPCON);//read the value of GPPCON tmp = (tmp & ~(0xffff)|(0x4)); //set the GPIO output mode writel(tmp, S3C64XX_GPPCON);//set the value of GPPCON printk(KERN_EMERG"led_open!\n");//print return 0; } ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { printk(KERN_EMERG"led_read!\n"); return count; } ssize_t led_write(struct file *filp,const char __user *buf, size_t count, loff_t *f_pos) { char mbuf[10]; unsigned int tmp; copy_from_user(mbuf,buf,count); switch(mbuf[0]) { case 0: tmp = readl(S3C64XX_GPPDAT); tmp |= (0x2); writel(tmp, S3C64XX_GPPDAT); break; default: break; } printk(KERN_EMERG"led_write!\n"); return count; } int led_release(struct inode *inode, struct file *filp) { printk(KERN_EMERG"led_release!\n"); return 0; } struct file_operations my_fops = { .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release, }; static int led_init(void) { int rc; printk(KERN_EMERG"Test led dev\n"); rc = register_chrdev(LED_MAJOR, "led_GPP1", &my_fops); if(rc < 0) { printk(KERN_EMERG"register %s dev error\n", "led_GPP1"); return -1; } printk(KERN_EMERG"register led dev OK!\n"); return 0; } static void led_exit(void) { unregister_chrdev(LED_MAJOR, "led_GPP1"); printk(KERN_EMERG"Good Bye!\n"); } module_init(led_init); module_exit(led_exit);
ifneq ($(KERNELRELEASE),) obj-m := led.o //obj-m是将led.o加入内核模块 else KDIR := /joe/linux-3.0.1 //linux3.0.1的系统目录 joe是我自己建立的工作目录 all: make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux- //一定要制定交叉编译工具 clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif
3).在终端输入make命令:生成led.ko内核模块文件
4.编写一个测试程序led_test.c:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define DEVICE "/dev/led_GPP1" int main(void) { int fd, i; char buf[1] = {0}; fd = open(DEVICE, O_RDWR); if(fd < 0) { printf("Open /dev/led_gpp1 file error\n"); return -1; } while(1) { write(fd, &buf[0], 1); } close(fd); return 0; }
5.交叉编译一下led_test.c 生成二进制文件led_test
6.将led.ko,led_test两个文件拷贝到sdcard,然后放到开发板上面去测试一下:
7.启动开发板,
[root@FORLINX6410]# [root@FORLINX6410]# [root@FORLINX6410]# [root@FORLINX6410]# [root@FORLINX6410]# mknod /dev/led_GPP1 c 240 0 //建立设备节点 [root@FORLINX6410]# ls /dev/led [root@FORLINX6410]# ls /dev/led_GPP1 /dev/led_GPP1 //建立成功 [root@FORLINX6410]# insmod //查看系统载入的模块 [root@FORLINX6410]# insmod /sdcard/led.ko //挂载led.ko驱动模块 Test led dev register led dev OK! [root@FORLINX6410]# lsmod led 1866 0 - Live 0xbf000000 //查看 [root@FORLINX6410]# [root@FORLINX6410]# [root@FORLINX6410]# [root@FORLINX6410]# ./sdcard/ led_ [root@FORLINX6410]# ./sdcard/led_test //测试程序 led_open! led_write! //成功 led_write! led_write! led_write!