今天利用自己之前移植的内核与最小文件系统写了个点灯的驱动程序,先附代码和操作,后面将会不断更新。
以下是驱动程序:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm/system.h>
#include <linux/fs.h>
//#include <linux/cdev.h>
#include <asm/io.h>
#define LED_MAJOR 0
static int major;
volatile unsigned long virt, phys;//存放虚拟地址和物理地址
volatile unsigned long *GPC0CON, *GPC0DAT;
//#define GPC0CON *((volatile unsigned int *)0xE0200060)
//#define GPC0DAT *((volatile unsigned int *)0xE0200064)
//static dev_t devt;
static void led_off(void);
static void led_config(void)
{
phys = 0xE0200060; // 0x56000010=GPBCON
//在虚拟地址空间中申请一块长度为0x10的连续空间
//这样,物理地址phys到phys+0x10对应虚拟地址virt到virt+0x10
virt =(unsigned long)ioremap(phys, 0x10);
GPC0CON = (unsigned long *)(virt + 0x00);//指定需要操作的三个寄存器的地址
GPC0DAT = (unsigned long *)(virt + 0x04);
*GPC0CON &= ~(0xFF << 12);
*GPC0CON |= 0x11 << 12; // 配置GPC0_3和GPC0_4为输出
led_off();
}
static void led_on(void)
{
*GPC0DAT |= 1 << 3; // 点亮LED1
*GPC0DAT |= 1 << 4; // 点亮LED2
}
static void led_off(void)
{
*GPC0DAT &= ~(0x3 << 3); // 熄灭LED1和LED2
}
static int led_drv_open(struct inode *inode,struct file *file)
{
printk("led drv open\n");
return 0;
}
static int led_drv_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)
{
printk("led drv write\n");
return 0;
}
static int led_drv_read(struct file *file,char __user *buf,size_t count,loff_t *ppos)
{
printk("first drv read\n");
return 0;
}
struct file_operations led_fops = {
.owner = THIS_MODULE,
.write = led_drv_write,
.open = led_drv_open,
.read = led_drv_read,
};
static int led_init(void)
{
major = register_chrdev(0, "led_device",&led_fops);
if (major) {
printk("success register chrdev region %d\n",major);
}
led_config();
led_on();
printk("led device add success\n");
return 0;
}
static void led_exit(void)
{
led_off();
iounmap((void *)virt); //撤销映射关系
printk(KERN_ALERT "led_dev_exit\n");
unregister_chrdev(major,"led_device");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Ethyn");
以下是Makefile文件
KERNELDIR=/home/yike/mywork/linux-3.2.8
PWD:=$(shell pwd)
INSTALLDIR=$(PWD)
CC=arm-linux-gcc
obj-m := leddriver.o
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c *.markers *.order *.symvers
.PHONY:modules clean
在开发板系统上直接用insmod leddriver.ko 发现灯可以亮
lsmod可以查看你的模块,如下显示
[@Ethyn ledtest]#lsmod
leddriver 1682 0 - Live 0x7f008000 (O)
[@Ethyn ledtest]#
卸载模块使用rmmod leddriver,灯灭将驱动程序编译完成后移植到开发板上,这个可以不用测试程序就能直接将灯点亮,后面将会在此程序基础加上流水灯驱动的操作程序