环境及工具:
linux-3.0.1内核 硬件平台OK6410
测试基本流程:
PC与OK6410通过NFS文件系统成功连接后,编译驱动和APP程序即可测试
1://建立NFS文件系统,让板子能和PC机建立通信。
2:#make //编译驱动程序
3:#arm-linux-gcc test.c -o test //编译APP程序
4:将测试程序拷贝到的是nfs下的文件系统中的/lib/modules/3.0.1
5:板子连接好NFS文件系统,并打开PC机下的串口终端, 启动后加载驱动模块
#insmod /lib/modules/3.0.1/driver_led.ko
6:创建设备文件 #mknod /dev/my_led c 240 0
7:测试 ./LED_APP
遇到的问题:
提示ioctl错误,原因是2.6.3以后的内核file_opretione 将ioctl改为了Ulockl_ioctl,
提示KELLOC 错误,原因添加LINUX_TBLS.H
提示arm-linux-gcc 找不到,原因交叉编译环境及超级用户权限问题
以上导致make编译不过,
提示MODULE LICENSE错误,原因是要定义MODULE_LICENSE("GPL" ); ,看了OK6410内核驱动模块是GPL
这里就改为GPL,如果不是,加载时会提示错误。
先粘贴代码
1驱动程序LED.C
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/fs.h> #include <asm/uaccess.h> /* copy_to_user,copy_from_user */ #include <linux/miscdevice.h> #include <linux/pci.h> #include <mach/map.h> #include <mach/regs-gpio.h> #include <mach/gpio-bank-m.h> #include <plat/gpio-cfg.h>
MODULE_LICENSE("GPL" );
#define LED_MAJOR 240
int led_open (struct inode *inode,struct file *filp)
{ unsigned tmp; tmp = readl(S3C64XX_GPMCON); tmp = (tmp & ~(0x7U<<1))|(0x1U); writel(tmp, S3C64XX_GPMCON); printk("#########open######\n"); return 0; }
ssize_t led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) { printk("#########read######\n"); return count; }
ssize_t led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) { char wbuf[10]; unsigned tmp; printk("#########write######\n"); copy_from_user(wbuf,buf,count); switch(wbuf[0]) { case 0: //off tmp = readl(S3C64XX_GPMDAT); tmp |= (0x1U); writel(tmp, S3C64XX_GPMDAT); break; case 1: //on tmp = readl(S3C64XX_GPMDAT); tmp &= ~(0x1U); writel(tmp, S3C64XX_GPMDAT); break; default : break; } return count; }
int led_release (struct inode *inode, struct file *filp) { printk("#########release######\n"); return 0; }
struct file_operations led_fops ={ .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release, };
int __init led_init (void) { int rc; printk ("Test led dev\n"); rc = register_chrdev(LED_MAJOR,"led",&led_fops); if (rc <0) { printk ("register %s char dev error\n","led"); return -1; } printk ("ok!\n"); return 0; }
void __exit led_exit (void) { unregister_chrdev(LED_MAJOR,"led"); printk ("module exit\n"); return ; }
module_init(led_init); module_exit(led_exit);
LED_APP.C测试程序
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main (void) { int fd; char buf[10]={0,1}; fd = open("/dev/my_led",O_RDWR); if (fd < 0) { printf ("Open /dev/my_led file error\n"); return -1; } while(1) { write(fd,&buf[0],1); sleep(1); write(fd,&buf[1],1); sleep(1); } close (fd); return 0;
}
makefile 文件
ifneq ($(KERNELRELEASE),)
obj-m := LED.o
else KDIR := /home/share/source/linux-3.0.1/ all: make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux- clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers modul*
endif