一 驱动实例
#include <linux/delay.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/suspend.h>
#include <linux/poll.h>
/*GPIO3_3:用于检测串口是否出现overrun状态*/
#define SERIAL_STATES_GPIO 67
/*导出符号让其他内核模块可见,然后还需要在相应的.h文件中声明(extern volatile unsigned long serial_states;)*/
volatile unsigned long serial_states;
EXPORT_SYMBOL_GPL(serial_states);
static int serial_states_open(struct inode *inode, struct file *file)
{
return 0;
}
static int serial_states_release(struct inode *inode, struct file *file)
{
/*note: releasing the wdt in NOWAYOUT-mode does not stop it */
return 0;
}
static int serial_states_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
if (!buf || count < 1)
return 0;
if (count > 4)
count = 4;
serial_states = 1;
if (copy_to_user(buf, (void*)&serial_states, count)) {
printk(KERN_ERR"serial_states copy_to_user failed.");
return -EFAULT;
}
return count;
}
static int serial_states_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
serial_states = 0;
return count;
}
static const struct file_operations serial_states_fops = {
.owner = THIS_MODULE,
.open = serial_states_open,
.release = serial_states_release,
.read = serial_states_read,
.write = serial_states_write,
};
static struct miscdevice serial_states_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "serial_states",
.fops = &serial_states_fops,
};
static int __init u9500_init(void)
{
int ret = -1;
/*注册misc设备*/
ret = misc_register(&serial_states_device);
if (ret != 0) {
printk(KERN_ERR "register serial_states_device miscdevice error");
goto err1;
}
/*判断该gpio是否有效*/
ret = gpio_is_valid(SERIAL_STATES_GPIO);
if (0 == ret) {
printk(KERN_ERR "serial states gpio is invalid!\n");
goto err2;
}
/*请求gpio:其他地方就不能用了*/
ret = gpio_request(SERIAL_STATES_GPIO, "serial_states_gpio");
if (0 != ret)
goto err2;
/*设置gpio方向,以及设置输出值*/
ret = gpio_direction_output(SERIAL_STATES_GPIO, 0);
if (0 != ret)
goto err3;
/*设置gpio输出值*/
gpio_set_value(SERIAL_STATES_GPIO, 0);
printk("serial states module probe sucsecc!\n");
return 0;
err3:
gpio_free(SERIAL_STATES_GPIO);
err2:
misc_deregister(&serial_states_device);
err1:
return ret;
}
module_init(u9500_init);
static void __exit u9500_exit(void)
{
int ret = -1;
ret = gpio_is_valid(SERIAL_STATES_GPIO);
if (0 == ret)
gpio_free(SERIAL_STATES_GPIO);
misc_deregister(&serial_states_device);
}
module_exit(u9500_exit);
MODULE_AUTHOR("vector");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("serial_states driver");
二 Makefile 实例
serialstates-objs := serial_states.o
obj-m := serialstates.o
PWD := $(shell pwd)
KDIR := /home/vec/mydisk1/soure/kernel/obj
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers