嵌入式面试真题学习笔记系列
嵌入式面试真题学习笔记系列 1. I2C SDA 被拉低死锁后的软件恢复 (个人博客链接) 2. RTOS 优先级翻转与实时任务阻塞的通用治理 (个人博客链接) 3. 不可恢复异常后的通用崩溃快照、调用栈保存与离线分析架构 (个人博客链接) 4. 低速 Flash 与 1MB SRAM 下的通用缓存架构设计 (个人博客链接) 5. 单硬件 Timer 下的高精度多路软件定时器架构设计 (个人博客链接) 6. 固定周期后台事件导致实时链路瞬态扰动的定位与自动化测试 (个人博客链接) 7. 多中断源竞争下关键实时事件丢失的系统化诊断与中断架构设计 (个人博客链接) 8. 多源信号时间戳偏差的补偿与重同步架构 (个人博客链接) 9. 嵌入式设备休眠电流异常的通用定位与低功耗治理 (个人博客链接) 10. 电源纹波影响 ADC 电量采样的软件滤波 (个人博客链接) 11. 资源受限系统中的分层低功耗与低延迟唤醒架构设计 (个人博客链接) 12. 资源受限设备中的低功耗短时事件识别架构 (个人博客链接) 13. 资源受限长期运行系统的确定性内存管理与内存池架构设计 (个人博客链接) 14....
canopen学习笔记系列
canopen学习笔记系列 1. CANopen TIME/SYNC 运行流程 (个人博客链接) (CSDN链接) 2. CANopen CiA 协议全景:核心内容、重点与组合关系 (个人博客链接) 3. CANopen Emergency: 搞懂 EM 运行流程 (个人博客链接) (CSDN链接) 4. CANopen MPDO:动态对象寻址 (个人博客链接) 5. CANopen NMT:搞懂 NMT 运行流程 (个人博客链接) (CSDN链接) 6. CANopen PDO 运行流程 (个人博客链接) (CSDN链接) 7. CANopen 搞懂 SDO client/server 运行流程 (个人博客链接) (CSDN链接) 8. CANopen 网络拓扑限制 (个人博客链接) 9. CANopene Heartbeat运行流程 (个人博客链接) (CSDN链接) 10. CANopenEditor 从新建工程到导出 EDS OD (个人博客链接) [11. CANopenNode CO_new() 与 `CO_config](<.&...
Lely CANopen NMT Heartbeat、srv与cfg 机制源码学习
Lely CANopen NMT Heartbeat、srv与cfg 机制源码学习 @[toc] 本文把以下六个内部文件放在同一条运行链上分析: 123456src/co/nmt_hb.csrc/co/nmt_hb.hsrc/co/nmt_srv.csrc/co/nmt_srv.hsrc/co/nmt_cfg.csrc/co/nmt_cfg.h 它们并不是三套彼此独立的协议实现,而是 co_nmt_t 周围的三类内部组件: nmt_hb:针对一个远端 Node-ID 维护 Heartbeat consumer 的接收、超时和状态事件; nmt_srv:根据本节点当前 NMT 状态装配或拆除 SDO、PDO、SYNC、TIME、EMCY、LSS 服务; nmt_cfg:在主站 boot slave 流程中,执行恢复默认值、文本 DCF、concise DCF 和用户扩展配置。 先建立一个总的心智模型: 12345co_nmt_t├─ 管本节点 NMT 状态机与主站启动策略├─ 通过 co_nmt_srv 管本节点协议服务生命周期├─ 为每个被监控远端节点创建 co_nmt...
Lely CANopen NMT Boot Slave:从 `nmt_boot.c` 看主站如何识别、配置并启动从站
Lely CANopen NMT Boot Slave:从 nmt_boot.c 看主站如何识别、配置并启动从站 @[toc] 1. 先给出核心判断nmt_boot.c 实现的不是普通从站侧 NMT 状态机,也不是简单地发送一条 Start Remote Node 命令。它是 NMT manager 针对一个远端从站执行的启动编排状态机。 对每个被管理的从站,它把多种已有服务串成一条完整链路: 1234567891011121314151617主站 DCF 中的从站声明 ↓确认该节点是否允许/需要 boot ↓通过 Client-SDO 校验设备类型与 Identity ↓通过 Heartbeat 或 Node Guarding 判断节点状态 ↓必要时发送 Reset Communication 并等待 boot-up ↓按配置决定是否检查、停止、清除和下载程序 ↓比较配置日期/时间,必要时调用 configuration request ↓启动 Heartbeat/Node Guarding 错误控制 ↓向 co_nmt_t...
Lely CANopen:CSDO&SSDO 客户端服务器 SDO 状态机、分段与块传输机制
Lely CANopen:CSDO/SSDO 客户端服务器 SDO 状态机、分段与块传输机制 @[toc] 一句话结论Lely 将 SDO 实现拆成客户端和服务器两个事件驱动状态机: co_csdo_t 主动发起远程上传或下载,负责构造请求帧、等待响应、维护超时、toggle、块序号、CRC、进度与完成回调; co_ssdo_t 被动接收客户端请求,负责解析命令、定位对象字典、调用 co_sub_dn_ind()/co_sub_up_ind(),并生成成功响应或 SDO abort; 两者都依赖 can_net_t 的 receiver、timer 和 send callback,本身不创建线程,也不直接操作 SocketCAN; 快速传输只有初始化帧,分段传输每帧最多携带 7 字节并交替 toggle bit,块传输以最多 127 个 segment 组成一个 block,通过 ackseq、blksize 和可选 CRC 实现 Go-Back-N 式恢复; CSDO 的完成回调在状态机回到空闲态后触发,因此回调中可以提交下一次请求;SSDO 没有服务...
Lely CANopen:RPDO&TPDO 运行期收发、SYNC、事件与定时器机制原理和运行流程
Lely CANopen:RPDO/TPDO 运行期收发、SYNC、事件与定时器机制原理和运行流程 @[toc] 源码基线:lely-industries/lely-core,提交 620d1858eb8520dbc3dc5e1a7314565becd54199,查阅时间为 2026-07-30。 本文核心分析以下文件: 123456include/lely/co/rpdo.hinclude/lely/co/rpdo.hppsrc/co/rpdo.cinclude/lely/co/tpdo.hinclude/lely/co/tpdo.hppsrc/co/tpdo.c 前置文章已经说明 co_pdo_dn()、co_pdo_up()、PDO 映射校验、位级编解码以及对象字典 indication 桥接。本文不重复展开这些基础算法,而是集中分析 RPDO/TPDO 服务对象如何注册 CAN 接收器、维护运行期参数、处理 SYNC、事件定时器、接收超时、同步窗口、抑制时间、RTR 和用户回调。 事实边界:函数、字段、条件分支和调用链来自上述源码;并发风险、生...
Lely CANopen `coapp Device` 本地 SDO PDO 读写、远程对象映射与运行机制
Lely CANopen coapp::Device:本地 SDO/PDO 读写、远程对象映射与运行机制 @[toc] 1. 先给出最关键的结论理解 Device 时,必须先把“本地读写”“远程读写”“SDO”“PDO”分开: Device 本质上是 co_dev_t 的 C++ 所有权与访问封装。 Device::Read()、Device::Write() 是对本地对象字典执行一次“本地 SDO 请求”,不会发送 CAN 帧。 Device::Get()、Device::Set() 是直接访问本地对象字典值,绕过 SDO 访问权限、范围检查和下载/上传回调。 Device::RpdoRead() 并不会通过 CAN 去读取远程节点,而是把“远程 TPDO 对象地址”转换为本地 RPDO 映射对象,再读取本地缓存值。 Device::TpdoWrite() 也不会执行远程 SDO 下载,而是把“远程 RPDO 对象地址”转换为本地 TPDO 映射对象,再写入本地待发送值。 真正通过 CAN 总线访问远程对象字典的是 co_csdo_t / l...
Lely CANopen:co_dev 设备对象字典与 DCF 和 PDO 事件机制
Lely CANopen:co_dev 设备对象字典与 EDS/DCF 解析、concise DCF 和 PDO 事件机制 @[toc] 一句话结论Lely 的 co_dev_t 不是协议状态机,也不是简单的 EDS 文件句柄,而是 CANopen 设备描述在运行期的根对象: 它保存 Node-ID、网络号、设备名称、身份信息、支持的位速率、LSS 和 dummy PDO 类型等设备级元数据; 它用一棵以 16 位索引为 key 的红黑树管理全部 co_obj_t,每个 co_obj_t 再管理自己的 co_sub_t; dcf.c 先把 EDS/DCF 的 INI 文本解析为通用配置树,再逐层创建 co_dev_t → co_obj_t → co_sub_t; $NODEID + n 不只是文本替换,解析器会记录相应 flag,co_dev_set_id() 在 Node-ID 改变时遍历整棵对象字典并按差值修正相关值; 文本 EDS/DCF 与 concise DCF 是两种完全不同的格式:前者描述设备结构和元数据,后者是用于参数配置的一组...
Lely CANopen:can_net、io_can_net设计原理
Lely CANopen:can_net、io_can_net 与 CAN channel 的分层关系,以及 TX/RX Ring 的设计原理@[toc] 一句话结论Lely 中容易混淆的几个对象,实际处于不同层次: can_net_t 是纯内存中的 CAN 逻辑调度核心,负责协议定时器、CAN-ID 接收分发和发送回调;它不知道 SocketCAN、文件描述符、poll、executor 或真实 CAN 控制器。 io_can_chan_t 是抽象 CAN 通道接口;src/io2/linux/can_chan.c 是它在 Linux SocketCAN 上的具体后端,负责文件描述符、收发操作、I/O 就绪事件和写确认。 io_can_net_t 是桥接层,把 can_net_t、io_timer_t、io_tqueue_t 和 io_can_chan_t 连接起来,使同步的协议核心能够运行在异步 I/O 框架上。 lely::io::CanNet 只是 io_can_net_t* 的 C++ RAII 包装,不是另一套独立实现;核心机制仍然...
Lely CANopen:io_tqueue 与 pheap 的实现原理、运行流程
Lely CANopen:io_tqueue 与 pheap 的实现原理、运行流程及其与 Timer、can_net 的关系 @[toc] 一句话结论io_tqueue 是一个“多路逻辑定时器复用器”: 上层可以同时提交很多个不同绝对截止时间的 io_tqueue_wait; 中间用 pheap 维护“当前最早到期”的等待; 下层始终只占用 一个 io_timer_t; 底层 Timer 到期时,再回到 io_tqueue 批量完成所有 value <= now 的等待。 它与 can_net 串起来之后,又形成“两级最早截止时间压缩”: 123456789很多 can_timer_t ↓can_net.timer_heap ↓ 选出协议层最早一个io_tqueue.queue ↓ 再与其他 I/O 等待一起排序一个 io_timer_t ↓Linux timerfd / poll / executor 1. 为什么需要 io_tqueue如果没有 io_tqueue,最直观的设计是: 1234每一个逻辑等待 → 一个 io_tim...







