
物联网嵌入式操作系统实时系统【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址https://gitcode.com/GitHub_Trending/riot/RIOT点击查看免费下载导读本文围绕 RIOT OS 仓库中的tests/drivers/lpc1768_eth测试应用展开完整讲解如何为兼容的 LPC1768 开发板构建并烧录该以太网驱动测试程序深入剖析lpc1768_eth_link_up与lpc1768_eth_auto两个可选伪模块的作用与依赖关系并结合 eth_netdev.c 等源码揭示 netdev 驱动的初始化、收发、链路状态轮询与自动协商的底层实现以及如何通过ifconfig命令验证以太网接口是否正常就绪。测试应用定位它到底在测什么tests/drivers/lpc1768_eth/README.md将该目录明确定义为LPC1768 以太网驱动ethernet driver的测试应用Test application for the LPC1768 ethernet driver。它的核心目的不是演示完整的网络协议栈应用而是验证 LPC1768 片上 EMACEthernet Media Access Controller外设经 RIOT 的 netdev 抽象层封装后能否完成以下关键工作驱动模块能否被正确编译链接并自动初始化网卡接口能否成功注册到网络栈并通过ifconfig观察到接口处于 up 且已配置状态可选地链路状态检测link state与 PHY 自动协商auto-negotiation功能能否按预期工作。整个测试应用构建在 RIOT 提供的通用测试工具模块test_utils_netdev_eth_minimal之上因此不需要为测试编写繁重的网络协议处理逻辑只需要提供设备初始化入口即可。构建与烧录Makefile 逐行解读测试应用的 Makefile 结构非常精简其默认目标板为 Seeed Studio Arch ProBOARD ? seeeduino_arch-pro include ../Makefile.drivers_common USEMODULE test_utils_netdev_eth_minimal # the driver to test USEMODULE lpc1768_eth # uncomment to enable additional features # USEMODULE lpc1768_eth_link_up # USEMODULE lpc1768_eth_auto FEATURES_REQUIRED periph_eth FEATURES_REQUIRED cpu_lpc1768 INCLUDES -I$(APPDIR) include $(RIOTBASE)/Makefile.include各部分的含义如下配置项作用BOARD ? seeeduino_arch-pro默认目标板为 seeeduino_arch-pro该板在 Makefile.features 中声明了FEATURES_PROVIDED periph_eth可通过命令行BOARDxxx覆盖USEMODULE test_utils_netdev_eth_minimal引入最小化 netdev 以太网测试工具模块负责事件循环与接收帧打印USEMODULE lpc1768_eth被测驱动模块本身编译 cpu/lpc1768/drivers/eth 下的驱动源码USEMODULE lpc1768_eth_link_up/lpc1768_eth_auto可选增强特性默认被注释掉按需取消注释FEATURES_REQUIRED periph_eth强制要求目标板提供以太网外设支持FEATURES_REQUIRED cpu_lpc1768强制要求 CPU 为 LPC1768从构建系统层面确保驱动与外设匹配构建与烧录命令沿用 RIOT 标准流程# 在 tests/drivers/lpc1768_eth 目录下 make BOARDseeeduino_arch-pro flash也可以只编译不烧录make BOARDseeeduino_arch-pro由于测试应用依赖test_utils_netdev_eth_minimal正式运行前建议查阅该模块的 API 文档见 netdev_eth_minimal.h了解其接口约定。驱动模块的依赖自动解析lpc1768_eth并不是一个孤立的模块RIOT 的构建系统会在 cpu/lpc1768/Makefile.dep 中自动补齐它的运行依赖ifneq (,$(filter lpc1768_eth_auto,$(USEMODULE))) USEMODULE lpc1768_eth_link_up endif ifneq (,$(filter lpc1768_eth_link_up,$(USEMODULE))) USEMODULE ztimer_periodic endif ifneq (,$(filter lpc1768_eth,$(USEMODULE))) FEATURES_REQUIRED periph_eth FEATURES_REQUIRED periph_gpio USEMODULE iolist USEMODULE netdev_eth USEMODULE netdev_new_api USEMODULE ztimer_msec endif这里可以看到三条重要的依赖规则lpc1768_eth_auto隐含lpc1768_eth_link_up——自动协商必须以链路状态检测为前提这与 README 中 auto-negotiation (implieslpc1768_eth_link_up) 的说明完全一致lpc1768_eth_link_up会引入ztimer_periodic因为链路状态是通过周期性定时器轮询实现的lpc1768_eth本身依赖iolist收发数据描述、netdev_eth通用以太网 netdev 层、netdev_new_api新版 netdev API、ztimer_msec毫秒级定时并要求periph_eth与periph_gpio特性。两个可选伪模块链路检测与自动协商README 明确指出测试应用可以通过 Makefile 启用两个伪模块pseudo-modules二者都属于可选项默认不启用伪模块功能依赖lpc1768_eth_link_up启用链路状态定时器link state timer周期性轮询 PHY 链路状态链路 up/down 时发出事件ztimer_periodiclpc1768_eth_auto启用自动协商auto-negotiation隐含lpc1768_eth_link_up依赖链路状态事件特性在 lpc1768_eth_netdev.h 的驱动文档中对这两个特性有更详细的说明链路状态事件Link State Events启用lpc1768_eth_link_up后驱动会持续监测链路状态并在链路建立或断开时向上层发出NETDEV_EVENT_LINK_UP/NETDEV_EVENT_LINK_DOWN事件自动协商Link Auto Negotiation启用lpc1768_eth_auto后PHY 会自动协商链路速率与双工模式。驱动文档明确建议强烈推荐使用自动协商因为它可以避免由于链路双方配置不匹配而在 PHY 层引发各类通信问题同时该特性依赖链路状态事件特性。换言之lpc1768_eth_link_up解决的是链路通没通的感知问题lpc1768_eth_auto解决的是以什么速率和双工模式通信的适配问题。二者在测试中往往组合使用。运行与预期输出ifconfig 验证README 的 Expected output 一节描述了测试成功的验收标准应用运行后应自动完成以太网驱动的初始化。请使用ifconfig命令验证以太网接口已 up 且已配置。也就是说程序启动后不需要人工干预驱动初始化RIOT 的网络接口会自动初始化随后进入 shell。此时执行 ifconfig如果初始化成功输出中应能看到名为lpc1768_eth的接口条目接口名来自 auto_init_lpc1768_eth.c 中gnrc_netif_ethernet_create传入的lpc1768_eth其状态应显示接口已启用UP并且携带 MAC 地址等配置信息。若接口没有出现或状态异常则说明驱动初始化链路存在问题。从 main.c 可以看出程序启动时的完整流程与打印信息int main(void) { puts(Test application for LPC1768 ethernet peripheral); int res netdev_eth_minimal_init(); if (res) { puts(Error initializing devices); return 1; } /* start the shell */ puts(Initialization successful - starting the shell now); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }启动时依次输出 Test application for LPC1768 ethernet peripheral 与 Initialization successful - starting the shell now随后进入交互式 shell。如果设备初始化失败则会打印 Error initializing devices 并返回错误码。测试框架底层test_utils_netdev_eth_minimal 的协作契约README 提到本测试应用使用了test_utils_netdev_eth_minimal更多信息请参阅 API 文档。该工具模块的接口契约定义在 netdev_eth_minimal.h 中它要求测试应用提供两样东西设备初始化函数netdev_eth_minimal_init_devs(netdev_event_cb_t cb)由测试应用实现负责把被测驱动绑定到 netdev 实例上并完成硬件初始化设备数量宏NETDEV_ETH_MINIMAL_NUMOF定义在init_dev.h中。测试应用侧的实现位于 init_dev.h 与 main.c/* init_dev.h */ #define NETDEV_ETH_MINIMAL_NUMOF 1 /* main.c */ static netdev_t lpc1768_eth_netdev; int netdev_eth_minimal_init_devs(netdev_event_cb_t cb) { /* setup the specific driver */ lpc1768_eth_netdev_setup(lpc1768_eth_netdev); /* set the application-provided callback */ lpc1768_eth_netdev.event_callback cb; /* initialize the device driver */ int res lpc1768_eth_netdev.driver-init(lpc1768_eth_netdev); expect(!res); return 0; }这段代码演示了 RIOT netdev 驱动的标准使用姿势调用lpc1768_eth_netdev_setup()把静态netdev_t实例绑定到 LPC1768 EMAC 驱动注意setup 阶段不会触碰硬件把工具模块提供的事件回调cb赋给event_callback之后驱动的 ISR 事件都会通过它送达测试框架的事件循环调用driver-init()真正初始化外设硬件并用expect()断言初始化成功。工具模块侧的实现netdev_eth_minimal.c则负责注册事件线程、把驱动 ISR 桥接到事件循环、并在收到以太网帧时打印帧的目的地址、源地址以及 payload 的十六进制转储方便在 shell 中直接观察收到的原始以太网帧。驱动源码深度解读从 setup 到 ISR 的完整链路理解了测试框架后我们再下沉到驱动层。LPC1768 以太网驱动分为两层底层外设封装cpu/lpc1768/periph/eth.c对外暴露lpc1768_eth_*系列 API与 netdev 适配层eth_netdev.c。后者是本次测试真正驱动的对象。netdev 驱动方法表eth_netdev.c 末尾定义了完整的 netdev 驱动回调表const netdev_driver_t lpc1768_eth_driver { .send _send, .confirm_send _confirm_send, .recv _recv, .init _init, .isr _isr, .get _get, .set _set, };init初始化与链路策略的分支_init()的核心逻辑体现了两个伪模块对行为的影响见 eth_netdev.cstatic int _init(netdev_t *netdev) { eui48_t hwaddr; netdev_eui48_get(netdev, hwaddr); int res lpc1768_eth_init(hwaddr.uint8); if (res 0) { return res; } if (IS_USED(MODULE_LPC1768_ETH_LINK_UP)) { if (IS_USED(MODULE_LPC1768_ETH_AUTO)) { /* start auto-negotiation of the link speed */ lpc1768_eth_start_auto_negotiation(); } /* periodically wake the event loop to poll the link state */ ztimer_periodic_init(ZTIMER_MSEC, _link_timer, _link_timer_cb, netdev, CONFIG_LPC1768_ETH_LINK_POLL_MS); ztimer_periodic_start(_link_timer); } else { /* assume link is up */ netdev-event_callback(netdev, NETDEV_EVENT_LINK_UP); } return 0; }由此可以清晰看到硬件初始化前会通过netdev_eui48_get()获取/生成 EUI-48 格式的 MAC 地址未启用lpc1768_eth_link_up时驱动不做链路检测直接假设链路已 up立即发送NETDEV_EVENT_LINK_UP事件——这是最简运行模式启用后若同时启用了lpc1768_eth_auto会先调用lpc1768_eth_start_auto_negotiation()启动 PHY 自动协商异步执行然后启动一个周期为CONFIG_LPC1768_ETH_LINK_POLL_MS默认 1000ms的 ztimer 定时器周期性唤醒事件循环去轮询链路状态。ISR链路状态轮询与接收事件链路状态轮询并不直接在定时器回调里完成那样会阻塞中断上下文而是通过_link_timer_cb设置_link_check标志并调用netdev_trigger_event_isr()把实际检测推迟到事件循环线程上下文中执行。在_isr()中if (IS_USED(MODULE_LPC1768_ETH_LINK_UP) _link_check) { _link_check false; bool up lpc1768_eth_link_up(); if (up ! _link_state) { _link_state up; if (up) { if (IS_USED(MODULE_LPC1768_ETH_AUTO)) { /* complete auto-negotiation of the link */ lpc1768_eth_complete_auto_negotiation(); } netdev-event_callback(netdev, NETDEV_EVENT_LINK_UP); } else { netdev-event_callback(netdev, NETDEV_EVENT_LINK_DOWN); } } } /* receive if necessary */ if (lpc1768_eth_rx_pending()) { netdev-event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); }这里体现了驱动设计的两个细节边沿触发只有当链路状态发生跳变up→down 或 down→up时才发出事件避免每次轮询都向上层重复上报自动协商的完成时机当检测到链路从 down 变为 up 时若启用了自动协商会先调用lpc1768_eth_complete_auto_negotiation()把协商出的速率/双工参数落实到 MAC 寄存器再通知上层链路已就绪。底层 PHY 接口的语义定义在 periph/eth.h 中包括lpc1768_eth_link_up()读取 PHY 的 BMSR.LINK 位判断链路是否 uplpc1768_eth_start_auto_negotiation()通告 10/100 Mbps 半双工/全双工全部能力并重启 PHY 自动协商异步成功返回 0PHY 不支持时返回-EOPNOTSUPPlpc1768_eth_complete_auto_negotiation()等待 PHY 报告协商完成根据双方能力寄存器推导速率与双工并编程 SUPP、MAC2、Command、IPGT 等寄存器lpc1768_eth_tx_status()查询最近一次发送的状态返回已发送字节数或-EAGAIN仍在发送、-EBUSY碰撞中止、-EIO其他失败lpc1768_eth_set_link_speed()把静态配置或协商结果写入 MAC。get/set面向上层网络的选项接口_get()/_set()实现了上层网络栈通过netopt_t查询/配置驱动的标准途径见 eth_netdev.cNETOPT_ADDRESS读取/设置 MAC 地址6 字节NETOPT_LINK查询当前链路状态返回NETOPT_ENABLE/NETOPT_DISABLENETOPT_PROMISCUOUSMODE读取/开启混杂模式其他选项透传给netdev_eth_get/netdev_eth_set通用以太网层处理。这正是ifconfig命令能够读到接口 MAC、链路状态等信息所依赖的底层支撑。关键配置参数一览驱动相关的可调参数集中定义在 cpu/lpc1768/include/config.h 中均可通过 CFLAGS 覆盖配置宏默认值含义CONFIG_LPC1768_ETH_AN_TIMEOUT_MS5000UPHY 自动协商完成的超时时间毫秒CONFIG_LPC1768_ETH_LINK_POLL_MS1000U链路状态轮询间隔毫秒即 README 所述link state timer的周期CONFIG_LPC1768_ETH_PHY_TIMEOUT_MS1UPHY 操作超时毫秒属于绝对误差上限实际 PHY 操作通常只需数微秒CONFIG_LPC1768_ETH_RX_BUF_NUMOF4U接收缓冲区数量static_assert要求至少为 1CONFIG_LPC1768_ETH_TX_BUF_NUMOF4U发送缓冲区数量static_assert要求至少为 1例如若希望把链路轮询周期改为 500ms可在构建时传入make BOARDseeeduino_arch-pro CFLAGS-DCONFIG_LPC1768_ETH_LINK_POLL_MS500U从测试到产品驱动在系统中的自动初始化路径测试应用通过手动编写netdev_eth_minimal_init_devs()来完成设备注册而真实产品中只要在应用 Makefile 中声明USEMODULE lpc1768_ethRIOT 的自动初始化机制auto_init就会代为完成同样的工作。auto_init_lpc1768_eth.c 展示了完整的注册流程void auto_init_lpc1768_eth(void) { LOG_DEBUG([auto_init_netif] initializing lpc1768_eth\n); /* setup netdev device */ lpc1768_eth_netdev_setup(_netdev); /* initialize netdev - gnrc adapter state */ int res gnrc_netif_ethernet_create(_netif, _stack, GNRC_NETIF_STACKSIZE_DEFAULT, GNRC_NETIF_PRIO, lpc1768_eth, _netdev); if (res 0) { LOG_ERROR([auto_init_netif] Failed to create netif for lpc1768_eth device: %d\n, res); return; } }可以看到自动初始化同样调用lpc1768_eth_netdev_setup()完成 netdev 绑定然后通过gnrc_netif_ethernet_create()创建名为lpc1768_eth的 GNRC 网络接口并启动其线程。这也解释了为什么测试应用中netdev_eth_minimal_init_devs()能够只绑定、不实现完整协议栈——netdev 抽象将外设驱动与上层协议栈解耦同一份驱动既可服务于轻量测试框架也可服务于完整的 GNRC 网络栈。小结从构建配置、伪模块语义到驱动源码实现tests/drivers/lpc1768_eth这份测试应用虽然只有三个文件却完整覆盖了 RIOT 以太网驱动开发与验证的典型路径通过Makefile声明模块与特性、通过init_dev.h约定设备数量、通过netdev_eth_minimal_init_devs()完成驱动绑定最后用ifconfig验证接口状态。对于希望为其他 LPC1768 板卡验证以太网功能、或打算在自己的驱动上套用同一套测试框架的开发者而言它是一份非常合适的参考模板——复制目录、替换init_dev.h与netdev_eth_minimal_init_devs()中的绑定逻辑即可快速将测试迁移到新的以太网设备上。赞分享物联网嵌入式操作系统实时系统【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址https://gitcode.com/GitHub_Trending/riot/RIOT点击查看免费下载相关推荐RIOT OS 中 ADT7310 温度传感器驱动的测试应用实践编译、运行与源码解析RIOT OS 中 ADT7310 温度传感器驱动的测试应用实践编译、运行与源码解析 本篇技术指南围绕 RIOT 仓库中的 tests/drivers/adt物联网嵌入式操作系统实时系统RIOT 中 SCD30 CO2/温湿度传感器驱动测试应用深度解析从编译运行到源码原理RIOT 中 SCD30 CO2/温湿度传感器驱动测试应用深度解析从编译运行到源码原理 导读 本文围绕 RIOT 仓库中 tests/drivers/scd3物联网嵌入式操作系统实时系统Binci完全指南如何用Docker容器化你的开发工作流告别环境配置烦恼Binci完全指南如何用Docker容器化你的开发工作流告别环境配置烦恼 Binci是一款强大的开发工作流容器化工具它能够帮助开发者将开发环境和任务流程通物联网嵌入式操作系统实时系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考