在进行休眠与唤醒实验是由于每次按下按键g_key的值将会被覆盖,所以引入环形缓冲区来存放每次按下按键的数据
主要代码部分
//定环形缓冲区的大小为128
#define BUF_LEN 128
//定义环形缓冲区数组,存放按下按键的数据
static int g_keys[BUF_LEN];
//定义读写指针
static int r, w;
//创建函数寻找下一个位置,其实就是x+1。取余操作是为了防止越界
#define NEXT_POS(x) ((x+1)%BUF_LEN)
//判断数组是否为空
static int id_key_buf_empty(void)
{
return (r == w);
}
//判断数组是否满了
static int is_key_buf_full(void)
{
return (r == NEXT_POS(w));
}
//添加按键的数据:用写指针
static void put_key(int key)
{
if(!is_key_buf_full())
{
g_keys[w] = key;
w = NEXT_POS(w);
}
}
//得到按键的数据:用读指针
static int get_key(void)
{
int key = 0;
if(is_key_buf_empty())
{
key = g_keys[r];
r = NEXT_POS(r);
}
return key;
}
如果写一个数据
1.判断环形缓冲区数组是否满了
2.如果没有满,将此时的按键值写入到环形缓冲区数组中
3.将写指针指向下一个位置
如果读一个数据
1.判断环形缓冲区数组是否为空
2.如果不为空,将此时的按键值赋为当前读索引为r的下标对应的环形缓冲区数组的数据
3.将读指针指向下一个位置
在应用程调用read函数时,通过驱动函数
static ssize_t gpio_key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
int err;
int key;
wait_event_interruptible(gpio_key_wait, !is_key_buf_empty());
key = get_key();
err = copy_to_user(buf, &key, 4);
return 4;
}
只要环形缓冲区数组不为空。就一直处于唤醒状态,然后一直遍历数组中的值,直到其为空
在按键中断处理函数中调用put_key函数
static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
struct gpio_key *gpio_key = dev_id;
int val;
int key;
val = gpiod_get_value(gpio_key->gpiod);
printk("key %d %d\n", gpio_key->gpio, val);
key = (gpio_key->gpio << 8) | val;
put_key(key);
wake_up_interruptible(&gpio_key_wait);
return IRQ_HANDLED;
}