imx6q内核之信号量

56 篇文章 2 订阅

生气驱动代码

/*************************************************************************
	> File Name: led_drv.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Sat 18 Mar 2017 06:27:26 AM PDT
 ************************************************************************/

#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/device.h>
#include<linux/slab.h>
#include<asm/gpio.h>
#include<mach/iomux-mx6q.h>

#define SABRESD_GPIO_LED4	IMX_GPIO_NR(3, 21)

struct led{
	char name[10];
	int gpio;
	int data;
	int open_cnt;
	struct semaphore sema;
	dev_t led_dev_id;
	struct cdev led_cdev;
	struct class* led_cls;
	struct file_operations led_fops;
}*sabre_led = NULL;

static int led_open(struct inode* inodp, struct file* filp)
{
	// 获取信息量, 正常获取立刻返回,如果没有获取信息量,进程
	// 在此进入等待队列休眠,唤醒有两种方式:
	// 1. 正常获取信号量,函数返回0
	// 2. 收到信号引起的唤醒,返回非0
	if(down_interruptible(&sabre_led->sema)) {
		printk("wake up by signal\n");
		return -EINTR;
	}
	printk("opening sabre led......\n");
	gpio_set_value(sabre_led->gpio, 1);

	return 0;
}

static int led_close(struct inode* inodp, struct file* filp)
{
	printk("closing sabre led device\n");
	up(&sabre_led->sema); // 唤醒等待队列的休眠进程,释放信号量
	gpio_set_value(sabre_led->gpio, 0);

	return 0;
}

static int led_init(void)
{
	sabre_led = (struct led*)kmalloc(sizeof(struct led), GFP_KERNEL);
	if(NULL == sabre_led) {
		printk("kmalloc error\n");
		return -1;
	}
	
	sabre_led->led_fops.owner = THIS_MODULE,
	sabre_led->led_fops.open = led_open,
	sabre_led->led_fops.release = led_close;

	sabre_led->gpio = SABRESD_GPIO_LED4;
	strcpy(sabre_led->name, "led");
	gpio_request(sabre_led->gpio, sabre_led->name);
	gpio_direction_output(sabre_led->gpio, 0);

	// 1. 申请设备号
	alloc_chrdev_region(&sabre_led->led_dev_id, 0, 1, "leds");
	// 2. 初始化字符设备对象
	cdev_init(&sabre_led->led_cdev, &sabre_led->led_fops);
	// 3. 添加字符设备对象到内核
	cdev_add(&sabre_led->led_cdev, sabre_led->led_dev_id, 1);
	// 4. 自动创建设备文件
	sabre_led->led_cls = class_create(THIS_MODULE, "xxdk");
	device_create(sabre_led->led_cls, NULL, 
			sabre_led->led_dev_id, NULL, "sabre_led");
	// 初始化信号量为互斥信号量
	sema_init(&sabre_led->sema, 1);	

	return 0;
}

static void led_exit(void)
{
	gpio_set_value(sabre_led->gpio, 0);
	gpio_free(sabre_led->gpio);

	device_destroy(sabre_led->led_cls, sabre_led->led_dev_id);
	class_destroy(sabre_led->led_cls);

	cdev_del(&sabre_led->led_cdev);
	unregister_chrdev_region(sabre_led->led_dev_id, 1);

	kfree(sabre_led);
	sabre_led = NULL;
	printk("bye bye\n");

	return;
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");


生气测试代码

/*************************************************************************
	> File Name: led_test.c
	> Author: XXDK
	> Email: v.manstein@qq.com 
	> Created Time: Sat 18 Mar 2017 08:24:16 AM PDT
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>

int main()
{
	int fd;

	if((fd = open("/dev/sabre_led", O_RDWR)) < 0) {
		perror("open sabreled failed");

	}

	sleep(20);
	close(fd);

	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值