gpio操作(LS1B)
1、一般gpio_request 封装了mem_request(),起保护作用,最后要调用mem_free之类的,主要是告诉内核这个地址被占用了。当其他地方调用同一地址gpio_request就会报告错误,改地址已被申请。在/proc/mem 可以看到有地址占用表描述。
这种用法的保护前提是大家都遵守先申请在访问,有一个地方没有遵守这个规则,这功能就失效了,就好比进程互斥,必须大家在访问临界资源的时候都先获取锁一样,其中一个没有遵守约定,代码报废;
2、__gpio_set_value 和 gpio_set_value的区别
一般的带有__这种操作的宏和函数是未保护的,对这种__操作的使用最好不用;主要是为了防止错误地址引用: __gpio_set_value是没有地址范围检测的,如果引用非法地址,有可能内核down掉;
//龙芯1b buzzer.c
#include <linux/fs.h>
#include <linux/module.h>
#include
<linux/kernel.h>
#include <linux/init.h>
#include
<linux/cdev.h>
#include <linux/io.h>
#include
<linux/errno.h>
#include <linux/platform_device.h>
#include
<linux/miscdevice.h>
#include <linux/gpio_keys.h>
#include
<asm/gpio.h>
#define DEVNAME "buzzer_gpio"
#define BUZZER_MINOR 123
MODULE_AUTHOR("liangqx
<liangqingxin-gz@loongson.cn>");
MODULE_DESCRIPTION("Drive the buzzer
through the gpio");
MODULE_LICENSE("GPL");
static int major;
module_param(major, int, 0);
static struct gpio_keys_platform_data *pkb = NULL;
static int buzzer_set_value(struct file *filp, const char __user
*buffer,
size_t count, loff_t *ppos)
{
char code[2];
int
port,value;
copy_from_user(code, buffer, (count < 2)?count:2);
value = code[0] - ‘0‘;
if(value >= pkb->nbuttons) return -ENOMEM;
port = pkb->buttons[value].gpio;
value = code[1] -
‘0‘;
printk("prot is %d, value is
%d\n",port,value);
gpio_set_value_cansleep(port, value);
return count;
}
static int __devinit buzzer_gpio_probe(struct platform_device
*pdev)
{
struct gpio_keys_platform_data *pdata =
pdev->dev.platform_data;
int i;
pkb = pdata;
for(i = 0;i < pkb->nbuttons;i++)
{
gpio_request(pkb->buttons[i].gpio,"buzzer");
gpio_direction_output(pkb->buttons[i].gpio,
0);
}
return 0;
}
static const struct file_operations buzzer_fops = {
.owner =
THIS_MODULE,
.write = buzzer_set_value,
};
static struct miscdevice buzzer_misc_device =
{
BUZZER_MINOR,
"buzzer_gpio",
&buzzer_fops,
};
struct platform_driver buzzer_device_driver = {
.probe =
buzzer_gpio_probe,
.driver = {
.name = "buzzer_gpio",
}
};
static int __init
buzzer_init(void)
{
if(misc_register(&buzzer_misc_device)){
printk(KERN_WARNING
"buzzer:Couldn‘t register device 10, %d.\n", BUZZER_MINOR);
return
-EBUSY;
}
return platform_driver_register(&buzzer_device_driver);
}
static void __exit buzzer_exit(void)
{
int
i;
misc_deregister(&buzzer_misc_device);
for(i = 0;i <
pkb->nbuttons;i++){
gpio_free(pkb->buttons[i].gpio);
}
}
module_init(buzzer_init);
module_exit(buzzer_exit);