全志A33 linux led驱动编程(附实测参考代码)
本文将介绍如何在全志A33芯片开发板上编写Linux下的LED驱动程序,包括如何在Linux内核中添加驱动和如何使用用户空间程序控制LED。
首先,我们需要了解全志A33芯片的GPIO控制器,并确定LED连接到哪个GPIO上。在本例中,我们将使用PA0引脚来连接LED。
接下来,我们需要在Linux内核中添加LED驱动。为此,请按以下步骤操作:
1. 在内核源代码树中的driver目录下创建一个新目录leds。
2. 在leds目录下创建一个新文件leds-a33.c。
3. 将以下代码复制到leds-a33.c中:
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#define DRIVER_NAME "leds-a33"
static struct gpio_desc *led_gpiod;
static int leds_a33_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
led_gpiod = gpio_to_desc(of_get_named_gpio(node, "led-gpio", 0));
if (!led_gpiod)
return -EINVAL;
gpio_direction_output(led_gpiod, 0);
pr_info("%s: LED driver initialized
", DRIVER_NAME);
return 0;
}
static int leds_a33_remove(struct platform_device *pdev)
{
pr_info("%s: LED driver removed
", DRIVER_NAME);
gpio_set_value(led_gpiod, 0);
gpio_put(led_gpiod);
return 0;
}
static const struct of_device_id leds_a33_of_match[] = {
{ .compatible = "allwinner,sun8i-a33-leds",
.data = NULL },
{}
};
MODULE_DEVICE_TABLE(of, leds_a33_of_match);
static struct platform_driver leds_a33_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = leds_a33_of_match,
.owner = THIS_MODULE,
},
.probe = leds_a33_probe,
.remove = leds_a33_remove,
};
module_platform_driver(leds_a33_driver);
4. 上述代码包含一个leds_a33_probe函数,它在模块加载时被调用。该函数使用device tree(设备树)API获取LED连接的GPIO引脚,并将其设置为输出模式。此外,我们还定义了一个leds_a33_remove函数,在模块卸载时被调用。
5. 我们还需要在设备树中添加一个节点来描述LED。为此,请打开设备树文件,并添加以下内容:
&pio {
ledd: ledd@0 {
compatible = "allwinner,sun8i-a33-led";
reg = <0>;
led-gpio = <&pio 0 0 GPIO_ACTIVE_HIGH>;
};
};
上面的设备树节点中定义了一个名为ledd的LED,并将其连接到GPIO口0,pin0。
6. 编译内核,并将模块加载到开发板上。
7. 可以使用以下命令来测试LED是否工作:
echo 1 > /sys/class/leds/ledd/brightness
echo 0 > /sys/class/leds/ledd/brightness
当然,在用户空间使用ioctl等函数也可以控制LED的亮灭。
至此,我们已经成功地在全志A33开发板上编写了一个Linux LED驱动程序。以下是完整的测试代码,仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <linux/kd.h>
#include <sys/ioctl.h>
#define LED_DEV "/sys/class/leds/ledd/brightness"
void usage(char *argv0)
{
printf("Usage: %s <0|1>
", argv0);
}
int main(int argc, char **argv)
{
int status = -1, fd;
char *endptr = NULL;
long int value;
if (argc < 2) {
usage(argv[0]);
return -1;
}
errno = 0;
value = strtol(argv[1], &endptr, 10);
if (errno == ERANGE) {
perror("strtol");
return -1;
}
if (endptr == argv[1] || *endptr != '\0' || value < 0 || value > 1) {
usage(argv[0]);
return -1;
}
fd = open(LED_DEV, O_WRONLY);
if (fd < 0) {
perror("open");
return -1;
}
status = ioctl(fd, KDSETLED, value ? LED_CAP : LED_SCR);
close(fd);
return status;
}
