0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

深度剖析U-Boot ADC Uclass:从架构到实战的全维度解析

jf_44130326 来源:Linux1024 作者:Linux1024 2026-04-26 07:08 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

嵌入式开发中,ADC(模数转换)是连接模拟世界与数字系统的关键桥梁,而U-Boot作为嵌入式领域的经典引导程序,其ADC子系统的设计堪称分层架构与通用化设计的典范。本文将从架构、流程、数据流到实战开发,全方位拆解U-Boot ADC Uclass的设计精髓,帮你吃透这一核心子系统。

一、架构概览:三层架构,职责分明

wKgZO2ntScqAG0DpAAAenv0DoD8720.png

U-Boot的ADC子系统基于DM(Driver Model)驱动模型构建,采用清晰的三层架构,让不同层级各司其职:

应用层开发者只需调用标准化API(如adc_channel_single_shot),无需关注底层硬件细节;

Uclass层(核心):封装统一接口、通道合法性检查、电源管理、超时处理等通用逻辑,是整个子系统的“中枢”;

驱动层:针对不同硬件(如瑞芯微saradc)实现寄存器操作、硬件初始化等专属逻辑;

硬件层:ADC外设的物理寄存器与模拟采样电路。

核心数据结构:撑起整个子系统的骨架

1.平台数据结构adc_uclass_platdata

存储ADC的核心配置信息,包括数据格式、精度掩码、超时时间、电源信息等,是Uclass层与驱动层交互的关键:

structadc_uclass_platdata{ intdata_format;          // 数据格式(BIN/2S补码) unsignedintdata_mask;      // 数据掩码(决定ADC精度) unsignedintdata_timeout_us;   // 单通道超时时间 unsignedintmultidata_timeout_us; // 多通道超时时间 unsignedintchannel_mask;     // 可用通道掩码 structudevice*vdd_supply;    // VDD电源调节器 // 省略部分字段...};

2.驱动操作接口adc_ops

定义驱动层需实现的核心回调函数,是Uclass层与驱动层的“契约”:

structadc_ops { int(*start_channel)(structudevice *dev,intchannel); int(*start_channels)(structudevice *dev,unsignedintchannel_mask); int(*channel_data)(structudevice *dev,intchannel,unsignedint*data); // 省略部分接口...};

二、核心流程:从初始化到单次采样的完整链路

1.初始化流程:设备树到硬件就绪

ADC设备的初始化围绕设备树解析展开,核心是平台数据的填充与硬件初始化:

wKgZO2ntScqAHSVGAAFk3_F1J38146.png

2.单次采样:最常用的核心流程

adc_channel_single_shot是最常用的ADC采样API,其完整流程堪称“通用化设计”的典范:

wKgZO2ntScqAXeT-AAKuqoq16JY096.png

关键设计亮点:超时与轮询的通用化

adc_channel_data函数实现了“驱动层返回状态+ Uclass层处理轮询/超时”的解耦设计,让所有驱动复用同一套逻辑:

intadc_channel_data(structudevice *dev,intchannel,unsignedint*data){ structadc_uclass_platdata*uc_pdata =dev_get_uclass_platdata(dev); conststructadc_ops*ops =dev_get_driver_ops(dev); unsignedinttimeout_us = uc_pdata->data_timeout_us; intret; // 通道合法性检查  ret =check_channel(dev, channel, CHECK_NUMBER, __func__); if(ret)   returnret; // 轮询读取:驱动只需返回-EBUSY表示硬件忙 do{    ret = ops->channel_data(dev, channel, data);   if(!ret || ret != -EBUSY)     break;   sdelay(5);// 短延时,非udelay  }while(timeout_us--); returnret;}

三、数据流:从模拟信号到电压值的完整转换

ADC的核心是“模拟信号→数字值→电压值”的转换,其数据流路径清晰且通用:

wKgZO2ntScqAFrSyAAA4SgAZKt4193.png

实战:从原始值到电压的计算

拿到ADC原始值后,需结合参考电压计算实际电压(以12位ADC为例):

unsignedintadc_value;intvdd_uv, ret;//1. 读取ADC原始值ret = adc_channel_single_shot("saradc@2ae00000",0, &adc_value);if(ret) { printf("ADC读取失败:%dn", ret); return;}//2. 获取参考电压(如1.8V)ret = adc_vdd_value(dev, &vdd_uv);//3. 转换为电压(12位ADC最大值4095)intvoltage_uv = ((u64)adc_value * vdd_uv) /4095;printf("电压值:%duV(%dmV)n", voltage_uv, voltage_uv /1000);

注意:需用64位运算防止乘法溢出,避免精度损失!

四、多通道采样:优雅的降级策略

U-Boot ADC子系统对多通道采样做了人性化设计:优先使用硬件多通道(高效),若硬件不支持则自动降级为单通道逐个采样(兼容),且对上层应用完全透明:

intadc_channels_single_shot(constchar*name,unsignedintchannel_mask,              structadc_channel *channels){ structudevice*dev; intret;  ret =uclass_get_device_by_name(UCLASS_ADC, name, &dev); if(ret)   returnret; // 策略1:尝试硬件多通道  ret =adc_start_channels(dev, channel_mask); if(ret)   gototry_manual;  ret =adc_channels_data(dev, channel_mask, channels); if(ret)   returnret; return0;try_manual: // 策略2:降级为单通道逐个采样 if(ret != -ENOSYS)   returnret; return_adc_channels_single_shot(dev, channel_mask, channels);}

五、开发者实战指南:避坑+最佳实践

1.驱动开发:聚焦硬件,别重复造轮子

•channel_data只需返回状态:硬件忙返回-EBUSY,就绪则返回原始值,超时/轮询交给Uclass层;

•必须填充uclass_platdata:尤其是data_mask(精度)、channel_mask(有效通道)、data_timeout_us(超时时间);

•示例:正确的驱动层channel_data实现

staticintgood_channel_data(structudevice *dev,intchannel,unsignedint*data){ structrockchip_saradc_regs*regs = priv->regs; // 仅检查硬件状态,不做循环/延时 if(!(readl(®s->status) & DATA_READY))   return-EBUSY;  *data =readl(®s->data); return0;}

2.应用开发:细节决定成败

•设备名称要匹配:需与设备树中ADC节点的名称一致(如saradc@2ae00000);

•电压计算防溢出:优先用u64类型做乘法,再做除法;

•区分sdelay和udelay:sdelay是循环延时,非微秒级延时,精准延时需用udelay。

3.设备树配置:电源与通道

adc@2ae00000 {  compatible ="rockchip,saradc-v2";  reg = <0x2ae00000 0x100>; // 电源配置  vdd-supply = <&adc_vdd_reg>;  vdd-microvolts = <1800000>;// 1.8V参考电压 // 有效通道(0-3)  channel_mask = <0x0F>;};

六、Uclass设计的核心思想:通用化与解耦

U-Boot ADC Uclass的设计堪称嵌入式驱动设计的典范,核心思想可总结为:

设计模式 实现方式 核心优势
统一接口 adc_ops抽象层 多平台/多硬件兼容,上层API统一
策略分离 Uclass处理超时/轮询/电源 驱动层聚焦硬件,减少重复代码
优雅降级 多通道→单通道自动切换 最大化兼容性,对上层透明
可选功能 CONFIG_ADC_REQ_REGULATOR 按需开启电源管理,灵活配置
前置检查 check_channel通道校验 提前发现错误,避免硬件异常

总结

U-Boot ADC Uclass通过分层架构、通用化接口、优雅的降级策略,实现了“一次开发,多硬件兼容”的目标。对于开发者而言,无需关注底层硬件差异,只需调用标准化API即可完成ADC采样;对于驱动开发者,只需实现硬件专属逻辑,复用Uclass层的通用能力。

这种“通用逻辑上提,硬件逻辑下沉”的设计思路,不仅是U-Boot驱动模型的核心,更是嵌入式系统设计的通用准则。掌握这一设计思想,无论是开发新的ADC驱动,还是理解其他Uclass子系统(如I2C、SPI),都能触类旁通。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • adc
    adc
    +关注

    关注

    100

    文章

    7950

    浏览量

    556931
  • u-boot
    +关注

    关注

    0

    文章

    140

    浏览量

    39955
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    吃透RK3576 U-Boot.map文件!嵌入式开发调试、性能优化、代码裁剪全攻略

    作为嵌入式开发工程师,你是否曾被 U-Boot 启动崩溃、固件体积过大、启动速度慢等问题困扰?其实答案就藏在 U-Boot 构建过程中自动生成的U-Boot.map文件里!这篇文章带你
    的头像 发表于 04-27 07:11 475次阅读
    吃透RK3576 <b class='flag-5'>U-Boot</b>.map文件!嵌入式开发调试、性能优化、代码裁剪全攻略

    深度解析 RK 平台 U-Boot 环境变量(env):原理、配置与实战

    环境变量(env)是 U-Boot 的核心配置机制,无需重新编译即可灵活调整启动参数。在 Rockchip(RK)平台上,环境变量不仅继承了 U-Boot 的通用特性,还针对 RK 芯片架构做了大量
    的头像 发表于 04-27 07:11 486次阅读
    <b class='flag-5'>深度</b><b class='flag-5'>解析</b> RK 平台 <b class='flag-5'>U-Boot</b> 环境变量(env):原理、配置与<b class='flag-5'>实战</b>

    [T2080] : 将 u-boot 移植 Flash 时出错的原因?如何解决?

    Code warrior tool target tasks flash programmer window programmed and verified my RCW and u-boot
    发表于 04-21 07:27

    更新 U-boot 时出现的问题求解

    我在尝试更新 U-boot 时遇到问题。最初我无法启动 Fedora,但后来我读到了这并尝试更新 U-boot。但是,当我按照官方文档我卡在迷你机屏幕上,什么也做不了。我担心董事会来了 DOA......
    发表于 04-01 07:20

    更新固件后 U-boot 不运行怎么解决?

    我刷新了从这里下载的新fw_payload固件(u-boot 和 opensbi):用于 TF 卡兼容性的新 u-boot 二进制文件 -.现在它启动到 OpenSBI,但无法达到 U-boot。我
    发表于 03-25 08:17

    更新 SPL 和 U-Boot的提示和技巧

    U-Boot 和 SPL 文件并将它们加载到 U 盘上 7 连接将 USB 记忆棒连接到 VF2 板并将其安装在文件夹中 8 更新来自终端的固件 9 验证使用命令 cat /proc/mtd 并检查如下
    发表于 03-20 08:15

    深入解析U-Boot image.c:RK平台镜像处理核心逻辑

    在瑞芯微(RK)平台的嵌入式开发中,U-Boot作为核心的启动加载程序,负责完成镜像解析、校验、加载等关键流程。而image.c正是U-Boot中处理镜像(uImage)的核心文件,尤其针对RK平台
    的头像 发表于 02-24 16:46 1822次阅读
    深入<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b> image.c:RK平台镜像处理核心逻辑

    玩转U-Boot bdinfo:嵌入式bsp开发者的定制、扩展与裁剪实战指南

    作为嵌入式开发者,U-Boot 是我们调试、适配板卡的核心工具,而 bdinfo 命令更是板级信息调试的“利器”——它能直观打印内存布局、Flash 信息、网络配置、时钟频率等核心参数。但原厂
    的头像 发表于 02-24 15:26 851次阅读
    玩转<b class='flag-5'>U-Boot</b> bdinfo:嵌入式bsp开发者的定制、扩展与裁剪<b class='flag-5'>实战</b>指南

    U-Boot SPL核心文件spl.c深度解析启动流程调试优化

    解析 U-Boot 中 spl.c 文件的功能与作用,探讨其在系统调试和优化中的价值,并通过流程图和脑图帮助开发者快速掌握核心要点。
    的头像 发表于 02-05 14:08 483次阅读
    <b class='flag-5'>U-Boot</b> SPL核心文件spl.c<b class='flag-5'>深度</b><b class='flag-5'>解析</b>:<b class='flag-5'>从</b>启动流程<b class='flag-5'>到</b>调试优化

    深入解析U-Boot TPL代码:嵌入式启动的“第一棒”背后的秘密

    在嵌入式系统启动过程中,按下电源键操作系统开始运行,中间藏着一系列精密的初始化步骤。今天我们就来拆解 Rockchip 平台 U-Boot 中的 TPL(Tiny Program Loader)阶段核心代码tpl.c,看看这
    的头像 发表于 02-05 14:07 1310次阅读
    深入<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b> TPL代码:嵌入式启动的“第一棒”背后的秘密

    深入解析U-Boot命令处理核心文件:功能、调试与开发价值

    在嵌入式系统开发中,U-Boot 作为主流的引导加载程序,其命令处理、交互逻辑和自动启动流程是核心功能模块。本文将围绕command.c、cli.c和autoboot.c三个关键文件,核心
    的头像 发表于 02-03 15:44 1002次阅读
    深入<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b>命令处理核心文件:功能、调试与开发价值

    深入解析U-Boot核心文件board_f.c:知识点、调试要点与开发价值

    在嵌入式系统开发中,U-Boot 作为应用最广泛的引导程序,其底层初始化逻辑直接决定了硬件启动的稳定性与可靠性。
    的头像 发表于 02-03 15:38 869次阅读
    深入<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b>核心文件board_f.c:知识点、调试要点与开发价值

    解析Rockchip平台U-Boot核心文件:boot_rkimg.c到底做了什么?

    在嵌入式开发中,U-Boot 作为引导程序的 “中流砥柱”,负责初始化硬件、加载内核并启动系统。对于 Rockchip 平台的设备(如常见的开发板、智能终端),boot_rkimg.c 是 U-Boot 中专门处理启动流程的核心
    的头像 发表于 02-03 15:29 978次阅读
    <b class='flag-5'>解析</b>Rockchip平台<b class='flag-5'>U-Boot</b>核心文件:<b class='flag-5'>boot</b>_rkimg.c到底做了什么?

    深入理解 RK3506 U-Boot 重定位:代码原理

     U-Boot 代码初始加载地址(通常是片内 ROM 或 Flash)复制运行效率更高的片外 RAM,再切换执行环境 RAM 中运行。 本文将结合 
    的头像 发表于 11-28 07:05 1011次阅读
    深入理解 RK3506 <b class='flag-5'>U-Boot</b> 重定位:<b class='flag-5'>从</b>代码<b class='flag-5'>到</b>原理

    U-Boot 无法识别 NAND怎么解决?

    U-Boot 无法识别 NAND
    发表于 09-03 06:37