1.驱动程序
//-------------------------------------
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <asm/arch/regs-gpio.h>
#define LED1 0x01
#define LED2 0x02
#define LED3 0x04
#define LED4 0x08
static int matrix_led_major = 0;
static unsigned char led_status = 0;
static void set_led_status(unsigned char status)
{
unsigned char led_status_changed;
led_status_changed = led_status ^ (status & 0x0F);
led_status = status & 0x0F;
if(led_status_changed != 0x00)
{
if(led_status_changed & LED1)
{
if(led_status & LED1)
s3c2410_gpio_setpin(S3C2410_GPF4,0);
else
s3c2410_gpio_setpin(S3C2410_GPF4,1);
}
if(led_status_changed & LED2)
{
if(led_status & LED2)
s3c2410_gpio_setpin(S3C2410_GPF5,0);
else
s3c2410_gpio_setpin(S3C2410_GPF5,1);
}
if(led_status_changed & LED3)
{
if(led_status & LED3)
s3c2410_gpio_setpin(S3C2410_GPF6,0);
else
s3c2410_gpio_setpin(S3C2410_GPF6,1);
}
if(led_status_changed & LED4)
{
if(led_status & LED4)
s3c2410_gpio_setpin(S3C2410_GPF7,0);
else
s3c2410_gpio_setpin(S3C2410_GPF7,1);
}
}
}
static int matrix_led_open(struct inode *inode,struct file *filp)
{
return 0;
}
static int matrix_led_release(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t matrix_led_read(struct file *filp,char *buff,size_t count,loff_t *offp)
{
copy_to_user(buff,(char *)&led_status,sizeof(unsigned char));
return sizeof(unsigned char);
}
static ssize_t matrix_led_write(struct file *filp,const char *buff,size_t count,loff_t *offp)
{
unsigned char status;
if(count == 1)
{
if(copy_from_user(&status,buff,sizeof(unsigned char)))
return -EFAULT;
set_led_status(status);
return sizeof(unsigned char);
}
else
return -EFAULT;
}
static struct file_operations matrix_led_fops = {
.owner = THIS_MODULE,
.open = matrix_led_open,
.read = matrix_led_read,
.write = matrix_led_write,
.release = matrix_led_release,
};
static int __init matrix_led_init(void)
{
int ret;
ret = register_chrdev(0,"led",&matrix_led_fops);
if(ret < 0)
{
printk("matrix_led: can't get major number\n");
return ret;
}
matrix_led_major = ret;
#ifdef CONFIG_DEVFS_FS
ret = devfs_mk_cdev(MKDEV(matrix_led_major,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,"led");
if(ret)
{
unregister_chrdev(matrix_led_major,"led");
printk("matrix_led: can't make char device fo devfs\n");
return ret;
}
#endif
s3c2410_gpio_cfgpin(S3C2410_GPB7,S3C2410_GPB7_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB8,S3C2410_GPB8_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB9,S3C2410_GPB9_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB10,S3C2410_GPB10_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB7,1);
s3c2410_gpio_setpin(S3C2410_GPB8,1);
s3c2410_gpio_setpin(S3C2410_GPB9,1);
s3c2410_gpio_setpin(S3C2410_GPB10,1);
led_status = 0x00;
printk("led: the matrix led initialized\n");
return 0;
}
static void __exit matrix_led_exit(void)
{
set_led_status(~(LED1 | LED2 | LED3 | LED4));
#ifdef CONFIG_DEVFS_FS
//devfs_remove("led/%d",0);
devfs_remove("led");
#endif
unregister_chrdev(matrix_led_major,"led");
printk("led: the matrix led driver exit\n");
}
module_init(matrix_led_init);
module_exit(matrix_led_exit);
MODULE_ALIAS("matrix_led");
MODULE_DESCRIPTION("The Matrix LED Driver");
MODULE_AUTHOR("jjj.<jjjstudio@163.com>");
MODULE_LICENSE("GPL");
2.驱动程序 Makefile
ifneq ($(KERNELRELEASE),)
obj-m :=led.o
else
KERNELDIR ?=/2.6.14
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
endif
3.测试程序
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/delay.h>
//#include <linux/dela2y.h>^M
#include <linux/fcntl.h>
#include <linux/kernel.h>
int main(int argc, char** argv)
{ int fd;
unsigned char i = 0;
unsigned char status;
fd = open("/dev/led",O_RDWR);
if(fd < 0)
{
printf("Can't open the matrix led drivers!\n");
return fd;
}
while(1)
{
i = (i+1)&0x0F;
write(fd,&i,1);
if(read(fd,&status,1) != 0)
printf("led status: %25x\n",status);
usleep(1000000);
// msleep(1000);
}
close(fd);
return 0;
}
4.测试程序 Makefile
CFLAGS = -O -Wall
CC = arm-linux-gcc
LD = arm-linux-ld
all:kd
kd: kd.c
$(CC) $(CFLAGS) -o kd kd.c
clean:
rm -f *.o *~ kd
1. 把写好的驱动程序led.c,COPY到DRIVERS –>CHAR 目录下面。
2. 在该目录下的Makefile 中适当位置加入一行obj-$(CONFIG_LIUDEFANG) += led.o 意思是如果LIUDEFANG 配置为Y 则编绎led.c 的连接文件led.o
3. 在该目录下的Kconfig 文件中加入菜单项
menu "Character devices"
config LIUDEFANG
<tab> bool "my led test ! liudefang"
4. 《这一步不加也没事啊》在该目录下的mem.c 中加入驱动程序的初始化程序这样进入系统后就可以直接
#ifdef CONFIG_LIUDEFANG
extern int __init matrix_led_init(void);
#endif
#ifdef CONFIG_LIUDEFANG
int __init matrix_led_init();
#endif
更多详情,