1.分层和分离的概念的示意图
App
--------------------------------------------------
input.c
--------------------------------------------------分层
/ \
/ \
/ 分离 \
button.c < ===== > evdev.c
硬件相关 纯软件(稳定)
2.bus_drv_dev模型
bus
--------------------------------------------------
/ \
device_add/ \ driver_register
/ 分离 \
devices < ===== > driver
硬件相关 比较稳定的代码
device_add: 1.把device放入bus的dev链表
2.从bus的drv链表取出每一个drv
用bus的match函数判断drv能否支持dev
3.若可以支持,调用drv的probe函数
driver_register: 1.把driver放入bus的drv链表
2.从bus的dev链表取出每一个dev
用bus的match函数判断dev能否支持drv
3.若可以支持,调用probe函数
注意:这只不过是一种左右建立联系的机制,devices和drivers都只不过是结构体而已
3.led驱动的分层分离实例
led_dev.c代码如下
-
//moudle.h 包含了大量加载模块需要的函数和符号的定义
-
#include <linux/module.h>
-
//kernel.h以便使用printk()等函数
-
#include <linux/kernel.h>
-
//fs.h包含常用的数据结构,如struct file等
-
#include <linux/fs.h>
-
//uaccess.h 包含copy_to_user(),copy_from_user()等函数
-
#include <linux/uaccess.h>
-
//io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
-
#include <linux/io.h>
-
#include <linux/miscdevice.h>
-
#include <linux/pci.h>
-
//init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
-
#include <linux/init.h>
-
#include <linux/delay.h>
-
#include <linux/device.h>
-
#include <linux/cdev.h>
-
#include <linux/gpio.h>
-
#include <linux/irq.h>
-
#include <linux/sched.h>
-
#include <linux/interrupt.h>
-
#include <linux/poll.h>
-
#include <linux/input.h>
-
#include <linux/pm.h>
-
#include <linux/sysctl.h>
-
#include <linux/proc_fs.h>
-
#include <linux/platform_device.h>
-
#include <linux/version.h>
-
#include <linux/types.h>
-
#include <linux/list.h>
-
#include <linux/timer.h>
-
#include <linux/serial_core.h>
-
-
//irq.h中断与并发请求事件
-
#include <asm/irq.h>
-
//下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
-
//#include <mach/gpio.h>
-
#include <mach/regs-gpio.h>
-
#include <plat/gpio-cfg.h>
-
#include <mach/hardware.h>
-
#include <mach/map.h>
-
-
-
/* 分配/设置/注册一个platform_device */
-
-
static struct resource led_resource[] = {
-
/*寄存器地址*/
-
[0] = {
-
.start = 0x7F008820,
-
.end = 0x7F008820 + 8 - 1,
-
.flags = IORESOURCE_MEM,
-
},
-
/*哪一位*/
-
[1] = {
-
.start = 0,
-
.end = 0,
-
.flags = IORESOURCE_IRQ,
-
}
-
};
-
-
static void led_release(struct device * dev)
-
{
-
}
-
-
static struct platform_device led_dev = {
-
.name = "myled",
-
.id = -1,
-
.num_resources = ARRAY_SIZE(led_resource),
-
.resource = led_resource,
-
.dev = {
-
.release = led_release,
-
},
-
};
-
-
static int led_dev_init(void)
-
{
-
platform_device_register(&led_dev);
-
return 0;
-
}
-
-
static void led_dev_exit(void)
-
{
-
platform_device_unregister(&led_dev);
-
}
-
-
module_init(led_dev_init);
-
module_exit(led_dev_exit);
-
-
MODULE_LICENSE("GPL");
led_drv.c代码如下
-
//moudle.h 包含了大量加载模块需要的函数和符号的定义
-
#include <linux/module.h>
-
//kernel.h以便使用printk()等函数
-
#include <linux/kernel.h>
-
//fs.h包含常用的数据结构,如struct file等
-
#include <linux/fs.h>
-
//uaccess.h 包含copy_to_user(),copy_from_user()等函数
-
#include <linux/uaccess.h>
-
//io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
-
#include <linux/io.h>
-
#include <linux/miscdevice.h>
-
#include <linux/pci.h>
-
//init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
-
#include <linux/init.h>
-
#include <linux/delay.h>
-
#include <linux/device.h>
-
#include <linux/cdev.h>
-
#include <linux/gpio.h>
-
#include <linux/irq.h>
-
#include <linux/sched.h>
-
#include <linux/interrupt.h>
-
#include <linux/poll.h>
-
#include <linux/input.h>
-
#include <linux/pm.h>
-
#include <linux/sysctl.h>
-
#include <linux/proc_fs.h>
-
#include <linux/platform_device.h>
-
-
//irq.h中断与并发请求事件
-
#include <asm/irq.h>
-
//下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
-
//#include <mach/gpio.h>
-
#include <mach/regs-gpio.h>
-
#include <plat/gpio-cfg.h>
-
#include <mach/hardware.h>
-
#include <mach/map.h>
-
-
-
static int major;
-
static struct class *cls;
-
static volatile unsigned long *gpio_con;
-
static volatile unsigned long *gpio_dat;
-
static int pin;
-
-
static int led_open(struct inode *inode, struct file *file)
-
{
-
/* 配置为输出 */
-
*gpio_con &= ~(0xE<<(pin*4));
-
-
return 0;
-
}
-
-
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
-
{
-
int val;
-
-
if( copy_from_user(&val, buf, count) ) // copy_to_user();
-
return -EFAULT;
-
-
if (val == 1)
-
{
-
// 点灯
-
*gpio_dat &= ~(1<<pin);
-
}
-
else
-
{
-
// 灭灯
-
*gpio_dat |= (1<<pin);
-
}
-
-
return 0;
-
}
-
-
-
static struct file_operations led_fops = {
-
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
-
.open = led_open,
-
.write = led_write,
-
};
-
-
static int led_probe(struct platform_device *pdev)
-
{
-
struct resource *res;
-
-
/* 根据platform_device的资源进行ioremap */
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
gpio_con = ioremap(res->start, res->end - res->start + 1);
-
gpio_dat = gpio_con + 1;
-
-
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-
pin = res->start;
-
-
/* 注册字符设备驱动程序 */
-
-
printk("led_probe, found led\n");
-
-
major = register_chrdev(0, "myled", &led_fops);
-
-
cls = class_create(THIS_MODULE, "myled");
-
-
device_create(cls, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */
-
-
return 0;
-
}
-
-
static int led_remove(struct platform_device *pdev)
-
{
-
/* 卸载字符设备驱动程序 */
-
/* iounmap */
-
printk("led_remove, remove led\n");
-
-
device_destroy(cls, MKDEV(major, 0));
-
class_destroy(cls);
-
unregister_chrdev(major, "myled");
-
iounmap(gpio_con);
-
-
printk("led_removed!\n");
-
-
return 0;
-
}
-
-
-
struct platform_driver led_drv = {
-
.probe = led_probe,
-
.remove = led_remove,
-
.driver = {
-
.name = "myled",
-
}
-
};
-
-
-
static int led_drv_init(void)
-
{
-
platform_driver_register(&led_drv);
-
return 0;
-
}
-
-
static void led_drv_exit(void)
-
{
-
platform_driver_unregister(&led_drv);
-
}
-
-
module_init(led_drv_init);
-
module_exit(led_drv_exit);
-
-
MODULE_LICENSE("GPL");
测试程序代码如下
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <stdio.h>
-
-
int main(int argc, char **argv)
-
{
-
int fd;
-
int val = 1;
-
fd = open("/dev/led", O_RDWR);
-
if (fd < 0)
-
{
-
printf("can't open!\n");
-
}
-
if (argc != 2)
-
{
-
printf("Usage :\n");
-
printf("%s \n", argv[0]);
-
return 0;
-
}
-
-
if (strcmp(argv[1], "on") == 0)
-
{
-
val = 1;
-
}
-
else
-
{
-
val = 0;
-
}
-
-
write(fd, &val, 4);
-
return 0;
-
}
测试:insmod led_drv.ko
insmod led_dev.ko
./led_test on
./led_test off
要修改哪个led只需修改led_dev.c中的led_resource[]的位就行了
阅读(1130) | 评论(0) | 转发(0) |