LED驱动程序点击打开链接
led.c
#include <linux/module.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/io.h>
#include "led.h"
#define LEDCON 0xE0200060
#define LEDDAT 0xE0200064
#define DEVICE_NAME "tqled"
volatile unsigned int *led_config;
volatile unsigned int *led_data;
struct cdev cdev; //描述字符设备
dev_t devno; //定义主、次设备号
static struct class *led_class;
static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case LED_ON:
writel(0x00, led_data);
printk("open Led!\n");
return 0;
case LED_OFF:
writel(0xFF, led_data);
printk("close Led!\n");
return 0;
default:
return -EINVAL;
}
}
static int led_open(struct inode *inode, struct file *file)
{
//初始化控制寄存器
led_config = (volatile unsigned int *)ioremap(LEDCON, 4); //物理地址转换为虚拟地址
writel(0x00011000, led_config);
led_data = (volatile unsigned int *)ioremap(LEDDAT, 4);
//writel(0x00000018, led_data);
return 0;
}
static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = led_ioctl,
.open = led_open,
.release = NULL,
};
//注册函数
static int __init led_init(void)
{
int ret = 0;
cdev_init(&cdev, &led_fops);
alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME); //动态分配设备编号
ret = cdev_add(&cdev, devno, 1); //向内核注册cdev
//自动注册驱动至/dev/目录
led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class)){
printk("Err: failed in led-class.\n");
return -1;
}
device_create(led_class, NULL, devno, NULL, DEVICE_NAME);
return ret;
}
//注销函数
static void __exit led_exit(void)
{
cdev_del(&cdev); //注销cdev
unregister_chrdev_region(devno, 1); //释放设备号
class_destroy(led_class);
iounmap(led_config);
iounmap(led_data);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jerry.Gou");
MODULE_DESCRIPTION("TQ210 led driver");
led.h
#define LED_MAGIC 'L'
#define LED_ON _IO(LED_MAGIC, 1)
#define LED_OFF _IO(LED_MAGIC, 0)
Makefile
obj-m := led.o
KDIR := /root/code/Kernel_3.0.80_stable
all:
@make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
@rm -rf *.o *.ko *.order *.symvers *.bak .*.cmd *.mod.o *.mod.c .tmp_versions
cp:
@make clean
@make
cp *.ko /root/code/rootfs/Drive/
测试程序
led_test.c
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#define LED_MAGIC 'L'
#define LED_ON _IO(LED_MAGIC, 0)
#define LED_OFF _IO(LED_MAGIC, 1)
//测试LED的点亮、熄灭功能
int main(int argc, char **argv)
{
int fd;
int val;
fd = open("/dev/tqled", O_RDWR);
if(fd < 0)
{
printf("can't open led!\n");
}
if(argc != 2)
{
printf("Usage :\n");
printf("%s <on|off>\n", argv[0]);
return 0;
}
val = atoi(argv[1]); //字符串转化为整数
if (val == 1)
ioctl(fd, LED_ON);
else
ioctl(fd, LED_OFF);
return 0;
}
Makefile
objs := led_test.o
test:$(objs)
@arm-linux-gcc -o test $^
dep_files := $(foreach f,$(objs),.$(f).d)
dep_files := $(wildcard $(dep_files))
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
@arm-linux-gcc -Wp,-MD,.$@.d -c -o $@ $<
cp:
cp test /root/code/rootfs/Drive/led_test
clean:
rm *.o test