欢迎访问宙启技术站
智能推送

全志A33 linux led驱动编程(附实测参考代码)

发布时间:2023-05-18 03:06:42

本文将介绍如何在全志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;

}