imx6ull Linux使用设备树配置LED

原创 专注于无线通信的蓬勃 2023-01-27 17:45

我们基于寄存器的方式已经编写了LED驱动,实现点亮/熄灭LED,但是你有没有发现一个问题,就是假设LED修改了一个GPIO,那么需要对应的修改寄存器代码,非常繁琐,而且随着改板次数增加,那么会带来一个灾难性的重复性没有技术含量的重复工作的弊端。

在之前的文档我们已经介绍了LED寄存器实现方式:https://blog.csdn.net/XiaoXiaoPengBo/article/details/128684419?spm=1001.2014.3001.5501

并且我们之前文档也写过了设备树相关的概念内容:

https://blog.csdn.net/XiaoXiaoPengBo/article/details/128734828?spm=1001.2014.3001.5501

那么本节,我们就结合之前的内容把他利用起来!!!我们还是用之前的LED GPIO1_3

一. 修改设备树dts文件

1.修改dts文件内容

在根节点下增加一下内容

wireless_link_led{
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "wl_led";
    status = "ok";
    reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
            0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
            0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
            0X0209C000 0X04 /* GPIO1_DR_BASE */
            0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};

2.编译dts验证

make dtbs

二. 实现LED基于设备树的驱动

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>


#define LED_MAJOR        200
#define LED_NAME        "led"

static struct class *led_class;
struct device_node *led_nd;



static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;


static int led_open(struct inode *inode, struct file *filp)
{
    printk("led_open\r\n");
    return 0;
}


static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    printk("led_read\r\n");
    return 0;
}

static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    printk("led_write\r\n");
    int retvalue;
    u32 val = 0;
    unsigned char databuf[1];
    unsigned char ledstat;

    retvalue = copy_from_user(databuf, buf, cnt);
    if(retvalue < 0) {
        printk("kernel write failed!\r\n");
        return -EFAULT;
    }

    ledstat = databuf[0];

    printk("ledstat:%d\r\n",ledstat);

    if(ledstat == 1)
    {
        val = readl(GPIO1_DR);
        val &= ~(1 << 3);    
        writel(val, GPIO1_DR);
    }
    else if(ledstat == 0)
    {
        val = readl(GPIO1_DR);
        val|= (1 << 3);    
        writel(val, GPIO1_DR);
    }

    return 1;
}


static int led_release(struct inode *inode, struct file *filp)
{
    printk("led_release\r\n");
    return 0;
}



static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .release =     led_release,
};


static int __init led_driver_init(void)
{
    u8 index;
    u32 val = 0;
    int ret = 0;
    const char *str;
    u32 regdata[14];
    struct property *proper;
    printk("led_driver_init\r\n");

    led_nd = of_find_node_by_path("/wireless_link_led");
    if(led_nd)
        printk("led nd found\r\n");
    else
    {
        printk("led nd is not found\r\n");
        return -1;
    }

    proper = of_find_property(led_nd, "compatible", NULL);
    if(proper)
        printk("compatible = %s\r\n", (char*)proper->value);
    else
        printk("compatible property find failed\r\n");

    ret = of_property_read_string(led_nd, "status", &str);
    printk("of_property_read_string ret:%d\r\n",ret);
    if(ret >= 0)
        printk("status = %s\r\n",str);

    ret = of_property_read_u32_array(led_nd, "reg", regdata, 10);
    printk("of_property_read_string ret:%d\r\n",ret);

    printk("---------------------------\r\n");
    for(index = 0; index < 10; index  )
        printk("%#X ", regdata[index]);
    printk("\r\n---------------------------\r\n");

    IMX6U_CCM_CCGR1 = of_iomap(led_nd, 0);
    SW_MUX_GPIO1_IO03 = of_iomap(led_nd, 1);
    SW_PAD_GPIO1_IO03 = of_iomap(led_nd, 2);
    GPIO1_DR = of_iomap(led_nd, 3);
    GPIO1_GDIR = of_iomap(led_nd, 4);

    val = readl(IMX6U_CCM_CCGR1);
    val &= ~(3 << 26);
    val |= (3 << 26);
    writel(val, IMX6U_CCM_CCGR1);

    writel(5, SW_MUX_GPIO1_IO03);

    writel(0x10B0, SW_PAD_GPIO1_IO03);

    val = readl(GPIO1_GDIR);
    val &= ~(1 << 3);
    val |= (1 << 3);
    writel(val, GPIO1_GDIR);

    val = readl(GPIO1_DR);
    val |= (1 << 3);    
    writel(val, GPIO1_DR);
    
    ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
    if(ret < 0){
        printk("register chrdev failed!\r\n");
        return -EIO;
    }
    
    led_class = class_create(THIS_MODULE,"led_class");

    device_create(led_class,NULL,MKDEV(LED_MAJOR,0),NULL,"led"); /* /dev/led */
    
    return 0;
}

static void __exit led_driver_exit(void)
{
    printk("led_driver_exit\r\n");

    iounmap(IMX6U_CCM_CCGR1);
    iounmap(SW_MUX_GPIO1_IO03);
    iounmap(SW_PAD_GPIO1_IO03);
    iounmap(GPIO1_DR);
    iounmap(GPIO1_GDIR);
    device_destroy(led_class,MKDEV(LED_MAJOR,0));
    class_destroy(led_class);
    unregister_chrdev(LED_MAJOR, LED_NAME);
}

module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL"); 

三. 实现APP验证程序

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>



int main(int argc, char *argv[])
{
    int fd;
    int ret;
    uint8_t led;
    fd  = open(argv[1], O_RDWR);

    if(!strcmp("led_on",argv[2]))
    {
        printf("led on\r\n");
        led = 1;
        write(fd,&led,sizeof(led));
    }

    if(!strcmp("led_off",argv[2]))
    {
        led = 0;
        printf("led on\r\n");
        write(fd,&led,sizeof(led));
    }

    
    close(fd);

    
}

四. 验证

点亮 LED灯 ./test_app /dev/led led_on

熄灭 LED灯 ./test_app /dev/led led_on

五.总结

其实到了这一步虽然不需要配对寄存器地址,但是代码还在编写寄存器代码,也就是说换了一个GPIO还是要修改代码,是的!!!别急,后续我们看了GPIO子系统以及pinctl子系统后相信会有答案!!!

专注于无线通信的蓬勃 朝气蓬勃——不积跬步 无以至千里, 不积小流 无以成江海
评论 (0)
  • 在人工智能技术飞速发展的今天,语音交互正以颠覆性的方式重塑我们的生活体验。WTK6900系列语音识别芯片凭借其离线高性能、抗噪远场识别、毫秒级响应的核心优势,为智能家居领域注入全新活力。以智能风扇为起点,我们开启一场“解放双手”的科技革命,让每一缕凉风都随“声”而至。一、核心技术:精准识别,无惧环境挑战自适应降噪,听懂你的每一句话WTK6900系列芯片搭载前沿信号处理技术,通过自适应降噪算法,可智能过滤环境噪声干扰。无论是家中电视声、户外虫鸣声,还是厨房烹饪的嘈杂声,芯片均能精准提取有效指令,识
    广州唯创电子 2025-04-08 08:40 192浏览
  •   卫星图像智能测绘系统:地理空间数据处理的创新引擎   卫星图像智能测绘系统作为融合卫星遥感、地理信息系统(GIS)、人工智能(AI)以及大数据分析等前沿技术的综合性平台,致力于达成高精度、高效率的地理空间数据采集、处理与应用目标。借助自动化、智能化的技术路径,该系统为国土资源管理、城市规划、灾害监测、环境保护等诸多领域输送关键数据支撑。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉北京五木恒润卫星图像智能测绘系统。这些成功案例为卫星
    华盛恒辉l58ll334744 2025-04-08 16:19 86浏览
  • ## DL/T645-2007* 帧格式:* 帧起始字符:68H* 地址域:A0 A1 A2 A3 A4 A5* 帧起始字符:68H* 控制码:1字节* 主站:* 13H:请求读电能表通信地址* 11H:请求读电能表数据* 1CH:请求跳闸、合闸* 从站:* 91H:正常应答读电能表* 9CH:正常应答跳闸、合闸* 数据域长度:1字节* 数据域:DI0 DI1 DI2 DI3* 发送方:每字节+33H* 接收方:每字节-33H* 数据标识:* 电能量* 最大需量及发生时间* 变量* 事件记录*
    四毛打印店 2025-04-09 10:53 59浏览
  • HDMI从2.1版本开始采用FRL传输模式,和2.0及之前的版本不同。两者在物理层信号上有所区别,这就需要在一些2.1版本的电路设计上增加匹配电路,使得2.1版本的电路能够向下兼容2.0及之前版本。2.1版本的信号特性下面截取自2.1版本规范定义,可以看到2.1版本支持直流耦合和交流耦合,其共模电压和AVCC相关,信号摆幅在400mV-1200mV2.0及之前版本的信号特性HDMI2.0及之前版本采用TMDS信号物理层,其结构和参数如下:兼容设计根据以上规范定义,可以看出TMDS信号的共模电压范
    durid 2025-04-08 19:01 172浏览
  • 文/郭楚妤编辑/cc孙聪颖‍伴随贸易全球化的持续深入,跨境电商迎来蓬勃发展期,物流行业 “出海” 成为不可阻挡的必然趋势。加之国内快递市场渐趋饱和,存量竞争愈发激烈。在此背景下,国内头部快递企业为突破发展瓶颈,寻求新的增长曲线,纷纷将战略目光投向海外市场。2024 年,堪称中国物流企业出海进程中的关键节点,众多企业纷纷扬帆起航,开启海外拓展之旅。然而,在一片向好的行业发展表象下,部分跨境物流企业的经营状况却不容乐观。它们受困于激烈的市场竞争、不断攀升的运营成本,以及复杂的国际物流环境,陷入了微利
    华尔街科技眼 2025-04-09 15:15 93浏览
  • 在万物互联时代,智能化安防需求持续升级,传统报警系统已难以满足实时性、可靠性与安全性并重的要求。WT2003H-16S低功耗语音芯片方案,以4G实时音频传输、超低功耗设计、端云加密交互为核心,重新定义智能报警设备的性能边界,为家庭、工业、公共安防等领域提供高效、稳定的安全守护。一、技术内核:五大核心突破,构建全场景安防基座1. 双模音频传输,灵活应对复杂场景实时音频流传输:内置高灵敏度MIC,支持环境音实时采集,通过4G模块直接上传至云端服务器,响应速度低至毫秒级,适用于火灾警报、紧急呼救等需即
    广州唯创电子 2025-04-08 08:59 156浏览
  •   物质扩散与污染物监测系统:环境守护的关键拼图   一、物质扩散原理剖析   物质扩散,本质上是物质在浓度梯度、温度梯度或者压力梯度等驱动力的作用下,从高浓度区域向低浓度区域迁移的过程。在环境科学范畴,物质扩散作为污染物在大气、水体以及土壤中迁移的关键机制,对污染物的分布态势、浓度动态变化以及环境风险程度有着直接且重大的影响。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这些成功案例为物质
    华盛恒辉l58ll334744 2025-04-09 11:24 57浏览
  • 文/Leon编辑/侯煜‍就在小米SU7因高速交通事故、智驾性能受到质疑的时候,另一家中国领先的智驾解决方案供应商华为,低调地进行了一场重大人事变动。(详情见:雷军熬过黑夜,寄望小米SU7成为及时雨)4月4日上午,有网友发现余承东的职务发生了变化,华为官网、其个人微博认证信息为“常务董事,终端BG董事长”,不再包括“智能汽车解决方案BU董事长”。余承东的确不再兼任华为车BU董事长,但并非完全脱离华为的汽车业务,而是聚焦鸿蒙智行。据悉,华为方面寻求将车BU独立出去,但鸿蒙智行仍留在华为终端BG部门。
    华尔街科技眼 2025-04-09 15:28 93浏览
  •     根据 IEC术语,瞬态过电压是指持续时间几个毫秒及以下的过高电压,通常是以高阻尼(快速衰减)形式出现,波形可以是振荡的,也可以是非振荡的。    瞬态过电压的成因和机理,IEC 60664-1给出了以下四种:    1. 自然放电,最典型的例子是雷击,感应到电力线路上,并通过电网配电系统传输,抵达用户端;        2. 电网中非特定感性负载通断。例如热处理工厂、机加工工厂对
    电子知识打边炉 2025-04-07 22:59 157浏览
  •   卫星图像智能测绘系统全面解析   一、系统概述   卫星图像智能测绘系统是基于卫星遥感技术、图像处理算法与人工智能(AI)技术的综合应用平台,旨在实现高精度、高效率的地理空间数据获取、处理与分析。该系统通过融合多源卫星数据(如光学、雷达、高光谱等),结合AI驱动的智能算法,实现自动化、智能化的测绘流程,广泛应用于城市规划、自然资源调查、灾害监测等领域。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润卫星图像智能测绘系统
    华盛恒辉l58ll334744 2025-04-08 15:04 99浏览
  •   物质扩散与污染物监测系统软件:多领域环境守护的智能中枢   北京华盛恒辉物质扩散与污染物监测系统软件,作为一款融合了物质扩散模拟、污染物监测、数据分析以及可视化等多元功能的综合性工具,致力于为环境科学、公共安全、工业生产等诸多领域给予强有力的技术支撑。接下来,将从功能特性、应用场景、技术实现途径、未来发展趋势等多个维度对这类软件展开详尽介绍。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这
    华盛恒辉l58ll334744 2025-04-09 14:54 114浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦