Linux休眠与唤醒中环形缓冲区

在进行休眠与唤醒实验是由于每次按下按键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;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值