9.20 作业

基于gpio子系统编写LED灯的驱动,编写应用程序测试

led.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include <linux/cdev.h>
#include "head.h"

struct gpio_desc *led_gpios[3];
unsigned int major = 0;
unsigned int minor = 0;
char *devname = "led";
int dfnum = 3; // 驱动文件数量
struct cdev *cdev;
struct class *cls;
struct device *dev;

void led_on_off(int count, unsigned int flag)
{
    switch (flag)
    {
    case LEDX_OFF:
        gpiod_set_value(led_gpios[count], 0);
        break;
    case LEDX_ON:
        gpiod_set_value(led_gpios[count], 1);
        break;
    case LEDX_REV:
        gpiod_set_value(led_gpios[count], !gpiod_get_value(led_gpios[count]));
        break;
    }
}

// 封装操作方法
int led_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    file->private_data = (void *)MINOR(inode->i_rdev);
    return 0;
}
ssize_t led_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
    return 0;
}
ssize_t led_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
    return 0;
}
long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    unsigned int min = (int)file->private_data;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    led_on_off(min - minor, cmd);
    return 0;
}
int led_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
// 定义一个操作方法结构体对象并且初始化
struct file_operations fops = {
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .release = led_close,
    .unlocked_ioctl = led_ioctl,
};

static int __init mycdev_init(void)
{
    struct device_node *dnode;
    int i, j;

    cdev = cdev_alloc();
    if (!cdev)
    {
        printk("字符设备驱动对象申请空间失败\n");
        goto out1;
    }
    printk("字符设备驱动对象申请空间成功\n");
    cdev_init(cdev, &fops);

    if (major)
    {
        if (register_chrdev_region(MKDEV(major, minor), dfnum, devname))
        {
            printk("静态申请设备号失败\n");
            goto out2;
        }
        printk("静态申请设备号成功\n");
    }
    else
    {
        unsigned int dnub;
        if (alloc_chrdev_region(&dnub, minor, dfnum, devname))
        {
            printk("动态申请设备号失败\n");
            goto out2;
        }
        printk("动态申请设备号成功\n");
        major = MAJOR(dnub);
    }

    if (cdev_add(cdev, MKDEV(major, minor), dfnum))
    {
        printk("注册驱动失败\n");
        goto out3;
    }
    printk("注册驱动成功\n");

    cls = class_create(THIS_MODULE, devname);
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        goto out4;
    }
    printk("向上提交目录成功\n");

    for (i = 0; i < dfnum; i++)
    {
        dev = device_create(cls, NULL, MKDEV(major, minor + i), NULL, "%s%d", devname, i);
        if (IS_ERR(cls))
        {
            printk("向上提交设备节点信息失败\n");
            goto out5;
        }
        printk("向上提交设备节点信息成功\n");
    }

    dnode = of_find_node_by_name(NULL, "myled");
    if (dnode == NULL)
    {
        printk("设备树节点解析失败\n");
        goto out5;
    }
    printk("设备树节点解析成功\n");

    for (j = 0; j < 3; j++)
    {
        led_gpios[j] = gpiod_get_from_of_node(dnode, "led-gpios", j, GPIOD_OUT_LOW, NULL);
        if (IS_ERR(led_gpios[j]))
        {
            printk("解析GPIO失败\n");
            goto out6;
        }
        printk("解析GPIO成功\n");

        gpiod_set_value(led_gpios[j], 1);
    }

    return 0;

out6:
    for (j--; j >= 0; j--)
    {
        gpiod_put(led_gpios[j]);
    }
out5:
    for (i--; i >= 0; i--)
    {
        device_destroy(cls, MKDEV(major, minor + i));
    }
    class_destroy(cls);
out4:
    cdev_del(cdev);
out3:
    unregister_chrdev_region(MKDEV(major, minor), dfnum);
out2:
    kfree(cdev);
out1:
    return -1;
}

static void __exit mycdev_exit(void)
{
    int i;

    del_timer(&timer);

    for (i = 0; i < 3; i++)
    {
        gpiod_set_value(led_gpios[i], 0);
        gpiod_put(led_gpios[i]);

        device_destroy(cls, MKDEV(major, minor + i));
    }

    class_destroy(cls);

    cdev_del(cdev);

    unregister_chrdev_region(MKDEV(major, minor), dfnum);

    kfree(cdev);
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

head.h

#ifndef __HEAD_H__
#define __HEAD_H__

#define LEDX_ON _IO('l',1)
#define LEDX_OFF _IO('l',0)
#define LEDX_REV _IO('l',2)

#endif

test.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "head.h"

int main()
{
    int fd[3];
    for (int i = 0; i < 3; i++)
    {
        char path[128] = {0};
        snprintf(path, sizeof(path), "/dev/led%d", i);
        fd[i] = open(path, O_RDWR);
        if (fd[i] < 0)
        {
            printf("文件打开失败\n");
            return -1;
        }
    }

    for (int i = 0;; i++)
    {
        ioctl(fd[i % 3], LEDX_REV);
        sleep(1);
    }

    for (int i = 0; i < 3; i++)
    {
        close(fd[i]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: IAR for ARM是一款用于开发基于ARM处理器的嵌入式系统的集成开发环境。9.20是该软件的版本号。该软件提供了丰富的开发工具,包括编译器、调试器、性能分析器、代码优化器等,用于方便地开发ARM芯片的软件系统。 IAR for ARM的编译器支持ICC、EC++和Asm三种编程语言,能够生成高效、可靠、可移植的代码。它还提供了一系列调试工具,如 J-Link调试器和I-jet调试器,可以帮助开发人员快速调试和测试程序。 此外,IAR for ARM 9.20还提供了多种优化策略,包括大小优化、速度优化、调试优化等,可根据实际需求进行选择,从而使软件系统更加高效和可靠。此外,该软件还支持多种ARM处理器和外围器件,可适用于广泛的嵌入式系统开发。 总之,IAR for ARM 9.20是一款功能强大的嵌入式系统开发工具,可以大大提高开发效率和代码质量,方便开发人员进行ARM芯片的软件开发。 ### 回答2: IAR for ARM是一款可以支持现在市场上绝大多数ARM微处理器的专业编译软件,其最新版本是9.20版。它具有强大的编译能力和高度优化的代码生成功能,可以使ARM微处理器的性能得到最大的发挥。 IAR for ARM 9.20版相比较以往版本,具有更加快速、更稳定和更精确的代码调试功能,同时支持多核调试。另外,该版本还提供了丰富的代码库以及系统级的软件组件,方便用户更快速地开发ARM平台的应用程序。 除此之外,IAR for ARM 9.20还可以集成其他常用的开发工具,比如GIT、SVN等,使得团队协作更加便捷,同时也提高了软件开发的效率和可靠性。总之,IAR for ARM 9.20是一个适用于ARM平台开发的全面且强大的编译工具。 ### 回答3: IAR for ARM 9.20是一款面向ARM处理器的编译器。它支持从ARM7到Cortex-M架构,提供了一系列完整的开发工具链,包括C/C++编译器、链接器、调试器等。其性能强大,对代码进行了高度优化,能够让开发者在ARM处理器上开发高效的嵌入式应用程序。它可以在多种操作系统上运行,例如Windows、Linux和MacOS等。此外,IAR for ARM 9.20还具有高度集成的调试器功能,支持实时观察变量的值,跟踪程序的执行路径,并且能够快速定位错误。同时,该编译器还提供了丰富的编译器选项和优化技术,可以灵活地为不同的应用程序和目标处理器进行优化。总之,IAR for ARM 9.20是一款可靠的ARM处理器编译器,能够为嵌入式开发者提供高效的开发工具和丰富的优化选项。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值