混杂设备驱动
在内核中定义了一个 misc
misc_register();
对于GPIO的操作:
1. 向内核申请 gpio
int gpio_request(unsigned gpio, const char * label)
gpio: 要申请操作的 gpio的编号, 所有的 GPIO从0开始,对应的 GPIO引脚都有一个Number: s5p6818
label: 给要申请的 gpio 一个名字
返回: 成功 返回0, 失败:其他值
在头文件(arm/arm/plat-s5p6818/common/cfg_type.h )中
驱动模块文件代码如下:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <cfg_type.h>
unsigned int led_gpio[]={
PAD_GPIO_B+26,
PAD_GPIO_C+11,
PAD_GPIO_C+7,
PAD_GPIO_C+12
};
char *led_name[]={"led1","led2","led3","led4"};
int led_open(struct inode *_inode, struct file *_file)
{
int i;
printk(KERN_INFO "led_open \n");
for(i=0;i<4;i++)
{
gpio_request(led_gpio[i], led_name[i]);
gpio_direction_output(led_gpio[i], 1);
}
return 0;
}
int led_close(struct inode *_inode, struct file *_file)
{
int i;
printk(KERN_INFO "led_close \n");
for(i=0;i<4;i++)
{
gpio_free(led_gpio[i]);
}
return 0;
}
long led_ioctl(struct file *_inode, unsigned int cmd, unsigned arg)
{
printk(KERN_INFO "led_ioctl \n");
if(arg >3 )
{
printk(KERN_INFO " error argument\n");
return -1;
}
switch(cmd)
{
case 0: //开LED
__gpio_set_value(led_gpio[arg], 0);
break;
case 1: //关LED
__gpio_set_value(led_gpio[arg], 1);
}
return 0;
}
// 操作 该设备驱动的 文件操作
struct file_operations ledfops={
.owner = THIS_MODULE,
.open = led_open,
.release = led_close,
.unlocked_ioctl = led_ioctl
};
struct miscdevice ledmisc ={
.minor = 255, // 内核动态分配次设备号
.name = "my_led", // 设备名
.fops = &ledfops,
};
int led_init(void)
{
printk(KERN_INFO "led init module\n");
//1. 注册一个Misc 混杂设备:主设备号10
misc_register(&ledmisc);
return 0;
}
void led_exit(void)
{
printk(KERN_INFO "led exit module\n");
misc_deregister(&ledmisc);
return ;
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("led module");
在Ubuntu下编译成模块。
连接板子后下载模块。
加载模块后可以在 /dev 下看到 my_led 已加载