makefile 文件
模式一:
obj-m += my_led.o
# specify flags for the module compilation
# EXTRA_CFLAGS=-g -O0
KERNEL_DIR = /work/linuxkernel/linux-2.6.25
PWD = $(shell pwd)
build:kernel_modules
kernel_modules:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
$(RM) *.o *.ko *.mod.c Module.symvers Module.markers modules.order
============================================================================
模式二:
ifeq ($(KERNEL_DIR),)
KERNEL_DIR ?= /work/linuxkernel/linux-2.6.25
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ *.ko *.mod.c Module.*
else
obj-m := my_led.o
endif
(ps:make modules_install 命令可以将模块安装的操作系统)
============================================================================
.h 文件:
#ifndef MY_LED_H
#define MY_LED_H
#include
//*the cmd of leds
#define MY_LED_TYPE 'g'
#define CMD_LED_OFF _IO(MY_LED_TYPE,0)
#define CMD_LED_ON _IO(MY_LED_TYPE,1)
#define CMD_BLINK _IO(MY_LED_TYPE,2)
//the name of device
#define DEVICE_NAME "hyy_led"
//the state of LED
#define LED_OFF 1
#define LED_ON 0
//error processing
#define error(...) do {\
printk("********************************************************\n");\
printk("error located %s : %d :%s\n",__FILE__,__LINE__,__FUNCTION__);\
printk(__VA_ARGS__);\
printk("********************************************************\n");\
}while(0)
#define DEBUG_MSG
//debug message print
#ifdef DEBUG_MSG
#define pdeg(...) printk(__VA_ARGS__),printk("(function:%s line: %d) \n",__FUNCTION__,__LINE__);
#else
#define pdeg(...) NULL
#endif
#endif /*MY_LED_H*/
============================================================================
.c文件:
/*
* this is just a led driver test
* just for fun and train
*
* author : hyy
* time : 2012-08-31 11:21:20
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "my_led.h"
static int led_major = 0;
static int led_minor = 0;
static int b_flg = 0;
struct cdev *led_device;
struct class *myclass;
static struct tast_struct * led_th=NULL;
unsigned int GpioId;
static unsigned long led_table[] =
{
((0x02DC << 16) | (2)),//GPIO2_2_GPIO,//MFP_PIN_GPIO2_2,//blue
((0x02E0 << 16) | (3)),//GPIO3_2_GPIO,//MFP_PIN_GPIO3_2,//yellow
((0x02E4 << 16) | (4)),//GPIO4_2_GPIO,//MFP_PIN_GPIO4_2,//green
((0x02E8 << 16) | (5)),//GPIO5_2_GPIO,//MFP_PIN_GPIO5_2,//red
((0x04E0 << 16) | (83)),//GPIO83_GPIO,//MFP_PIN_GPIO83,//keypad backlight
};
static int blink_led(int i)
{
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_ON);
msleep(125);
gpio_direction_output(GpioId,LED_OFF);
msleep(125);
gpio_direction_output(GpioId,LED_ON);
msleep(125);
gpio_direction_output(GpioId,LED_OFF);
msleep(125);
}
// kthread exce function
static int led_abcd(void *data)
{
int i=0;
while(!kthread_should_stop()){
for (i=0 ; i<5 ; i++ ) {
blink_led(i);
}
}
return 0;
}
int light_release(struct inode *inode, struct file *filp)
{
return 0;
}
int light_open(struct inode *inode, struct file *filp)
{
return 0;
}
int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int i = 0;
if (arg > 5 && arg < 0 ) {
error("arg must in 0 ~ 5\n");
return -EINVAL;
}
switch(cmd) {
case CMD_LED_OFF:
if (arg == 5 ) {
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_OFF);
}
}else {
GpioId = mfp_to_gpio(led_table[arg]);
gpio_direction_output(GpioId,LED_OFF);
}
break;
case CMD_LED_ON:
if (arg == 5 ) {
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_ON);
}
}else {
GpioId = mfp_to_gpio(led_table[arg]);
gpio_direction_output(GpioId,LED_ON);
}
break;
case CMD_BLINK:
if (arg == 5 ) {
if (!b_flg){
led_th = kthread_run(&led_abcd,NULL,"led kernel thread");
if (led_th == NULL ) {
error("create kernel thread failed!\n");
return -1;
}
b_flg = 1;
}else {
if (led_th ) {
kthread_stop(led_th);
led_th = NULL;
}
error("b_flg = %d\t led_th = %d\n",b_flg,led_th);
b_flg = 0;
}
} else {
blink_led(arg);
}
break;
default:
printk("error argument!\n");
return -EINVAL;
}
return 0;
}
struct file_operations light_fops = {
.owner = THIS_MODULE,
.ioctl = light_ioctl,
.open = light_open,
.release = light_release,
};
static void __exit light_exit (void)
{
dev_t devno = MKDEV(led_major,led_minor);
if (led_device){
cdev_del(led_device);
kfree(led_device);
led_device = NULL;
}
device_destroy(myclass,devno);
class_destroy(myclass);
unregister_chrdev_region(devno,1);
// free the kthread
if (led_th ) {
kthread_stop(led_th);
led_th = NULL;
}
return;
}
static int __init light_init(void)
{
int result = 0;
int i, GpioId ;
dev_t dev = 0;
result = alloc_chrdev_region(&dev,led_minor,1,DEVICE_NAME);
led_major = MAJOR(dev);
if (result < 0){
error(KERN_WARNING "wfet_kb:can`t get major %d\n",led_major);
return result;
}
led_device = kmalloc(sizeof(struct cdev), GFP_KERNEL);
if (!led_device) {
result = -ENOMEM;
unregister_chrdev_region(dev, 1);
return result;
}
memset(led_device, 0, sizeof(struct cdev));
cdev_init(led_device, &light_fops);
led_device->owner = THIS_MODULE;
result = cdev_add(led_device,dev,1);
if (result) {
error(KERN_NOTICE "Error %d adding LED device, major_%d",result, MAJOR(dev));
kfree(led_device);
led_device = NULL;
unregister_chrdev_region(dev, 1);
return result;
}
/*create device file*/
myclass = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(myclass) ) {
error("Err: failed in in creating class\n");
return -1;
}
device_create(myclass,NULL,MKDEV(led_major,led_minor),DEVICE_NAME);
for (i = 0 ; i <5 ; i++ ) {
GpioId = mfp_to_gpio(led_table[i]);
gpio_direction_output(GpioId,LED_OFF);
}
return 0;
}
module_init(light_init);
module_exit(light_exit);
MODULE_AUTHOR("hyy");
MODULE_LICENSE("GPL"); //任意版本的GUN公共许可权
/*
MODULE_LICENSE("GPL V2"); //GPL版本2许可权
MODULE_LICENSE("GPL and additional rights"); //GPL及其附加许可权
MODULE_LICENSE("Dual BSD/GPL"); //BSD/GPL双重许可权
MODULE_LICENSE("Dual MPL/GPL"); //MPL/GPL双重许可权
MODULE_LICENSE("Proprietary"); //专有许可权
*/
Makefile.txt my_led.h.txt my_led.c.txt
阅读(1002) | 评论(0) | 转发(1) |