龙芯技术社区
直播中

jf_48561352

未满1年用户 30经验值
擅长:嵌入式技术
私信 关注
[2K系列]

【龙芯2K0300蜂鸟板试用】3 gpio控制led字符驱动

led点灯是最常用的也是最简单的驱动程序,在linux内核当中,应该有现成的配置和驱动,但它是通过控制/sys属性,而不是/dev属性,本文基于字符驱动,通过控制/dev实现

硬件电路

板子上有3个LED灯,只有一个用户可以控制,其余2个分别是底板和核心板上的电源指示灯,用户LED灯的原理图如下所示
image.png

即D1灯,通过GPIO85控制其的亮灭,当GPIO85输出低电平时,LED点亮,反之亦然。

配置驱动

设备树配置

在设备树中,默认配置用户led为心跳灯,如下所示

leds {
		compatible = "gpio-leds";

		led1 {
			label = "led1";
			gpios = <&gpio 85 GPIO_ACTIVE_LOW>;
			linux,default-trigger = "heartbeat";
			default-state = "on";
		};

	};

对应的驱动,位于drivers/leds/leds-gpio.c,

在此将默认dts配置注释,增加如下设备树配置信息

gpio_led{
		compatible = "lx,gpio-led";
		label = "led";
		gpios = <&gpio 85 GPIO_ACTIVE_LOW>;
		status = "ok";
	};

驱动代码

平台驱动

定义平台驱动,设置compatible 与设备树相同,引脚probe函数lx_led_probe

static const struct of_device_id led_ids[] = {
    { .compatible = "lx,gpio-led"},
    { /* sentinel */ }
};

 
struct platform_driver lx_gpio_led_driver = {
    .probe = lx_led_probe,
    .driver = {
            .name = "gpioled",
            .owner = THIS_MODULE,
            .of_match_table = led_ids,
    }
};

probe信息

主要3部分:解析设备树信息,字符设备cdev,class/device设备

static int lx_led_probe(struct platform_device *pdv)
{

	int ret = 0;  

	pr_info("match successed\n");

	led_device_node = of_find_node_by_path("/gpio_led");
	if(led_device_node == NULL)
	{
		pr_err( "it get led node failed! \n");
		return -1;
	}

	led = of_get_named_gpio(led_device_node, "gpios", 0);
	pr_info("led = %d\n",led);

	gpio_direction_output(led, 0);  


	ret = alloc_chrdev_region(&led_devno, 0, 1, "gpioled");
	if(ret < 0){
		pr_err("fail to alloc led_devno\n");
		goto alloc_err;
	}

	led_chr_dev.owner = THIS_MODULE;
	cdev_init(&led_chr_dev, &led_chr_dev_fops);

	ret = cdev_add(&led_chr_dev, led_devno, 1);
	if(ret < 0)
	{
		printk("fail to add cdev\n");
		goto add_err;
	}

	class_led = class_create(THIS_MODULE, "gpioled");
	device = device_create(class_led, NULL, led_devno, NULL, "gpioled");

	return 0;

add_err:
	unregister_chrdev_region(led_devno, 1);
	pr_err("egister_chrdev error! \n");
alloc_err:
	return -1;

}

读写控制

led主要通过输出0或1控制亮灭,故只需要实现write函数(或ioctl)

static ssize_t lx_led_dev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
	unsigned char value;  

	int error = copy_from_user(&value, buf, cnt);
	if(error < 0) {
		pr_err(" it get data error\n");
	    	return -1;
	}

	if(value)
	{
		gpio_direction_output(led, 1);  
	}
	else
	{
		gpio_direction_output(led, 0); 
	}

	return 1;
}
 
static struct file_operations  led_chr_dev_fops =
{
    .owner = THIS_MODULE,
    .open = lx_led_dev_open,
    .write = lx_led_dev_write,
};

应用测试

int main(int argc, char **argv)

{

int fd;

int status;


fd = open(“/dev/gpioled”, O_RDWR);
if (fd == -1)
{
printf("can not open file /dev/gpioled\\\\\\\\n");
return -1;
}

do
{
printf("please input:/0/1/q\\\\\\\\n");
scanf("%d",&status);
printf("%d\\\\\\\\n",status);
if (status == 0)
{
write(fd, &status, 1);
}
else if(status== 1)
{
write(fd, &status, 1);
}
else if(status==113) /*q==113*/
{
break;
}
else
{
printf("please error\\\\\\\\n");
}
} while(1);

close(fd);
return 0;

}

实验效果

终端控制

首先,加载ko文件
QQ_1724587199019.png

然后运行应用,分别输入1或0,控制led的状态
QQ_1724587220227.png

板卡显示

b3a1b103f77da2442682062083abf32a

更多回帖

发帖
×
20
完善资料,
赚取积分