操作系统:虚拟机下centos
交叉编译环境:arm-linux-gcc 4.2.2 ,安装位置 /usr/local/arm/4.3.2/
6410板子内核源码路径:/linux3.0.1/linux3.0.1/ 3.0.1
目标板环境:OK6410-A 3.0.1
1.实验步骤
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>
#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_LICENSE("GPL");
module_init(led_init);
module_exit(led_exit);
2.编写Makefile
obj-m := led.o
KERNELDIR := /lib/modules/3.0.1/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
3.编写led的测试程序ledapp.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;
}
4.将这几个文件放到同样一个目录下
然后使用make命令编译一下驱动程序
接着使用arm-linux-gcc ledapp.c -o ledapp 编译应用程序
5.将生成的led.ko 和ledapp发送到ok6410板子下
测试:
加载驱动 #insmod led.ko
创建设备文件 #mknod /dev/my_led c 240 0
测试 ./test
[root@FORLINX6410]# ./ledapp
此时可以看到OK6410板子上的LED0在闪烁。
卸载驱动 #rmmod led
从上面的结果我们可以看到,当用户调用相应的文件操作函数时,驱动程序中的相应的函数也会被调用。
大家可以修改相应程序,测试一下其他的情况。