多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

CANopenNode 设备支持与移植指南:硬件抽象接口、空白模板与全平台驱动生态

CANopenNode 设备支持与移植指南:硬件抽象接口、空白模板与全平台驱动生态 嵌入式通信【免费下载链接】CANopenNodeCANopen protocol stack项目地址https://gitcode.com/gh_mirrors/ca/CANopenNode点击查看免费下载CANopenNode 是一套用 ANSI C 编写、面向对象方式实现的 CANopen 协议栈CiA 301 / DS-301但它刻意将协议栈核心与具体硬件驱动彻底分离主仓库不包含任何针对某款芯片的驱动代码所有硬件相关文件都由外部独立工程提供。本文以仓库内的 doc/deviceSupport.md 为主体结合 301/CO_driver.h 与 example 目录下的空白驱动模板系统讲解 CANopenNode 的设备接口规范、最小可编译工程的用法、驱动开发者推荐的移植工作流程以及当前社区已确认支持的 Linux、STM32、PIC、Analog Devices、Zephyr 等各类平台清单帮助读者快速完成自有硬件的移植接入。一、设计理念协议栈与硬件驱动彻底分离CANopenNode 可以运行在数量众多的设备上从简单的 16 位微控制器到 PC 计算机存在大量不同硬件、不同开发工具、不同开发者维护的实现。正如 doc/deviceSupport.md 开头所述单个项目维护者不可能持续跟进所有硬件接口的更新因此所有硬件相关文件都不属于 CANopenNode 主项目。这种设计带来的直接好处是协议栈核心与硬件无关301目录下的 NMT、PDO、SDO、Emergency、SYNC、TIME、LSS 等协议模块以及storage、303LED、304SRDO/GFC、305LSS、309ASCII gateway等扩展模块都只依赖一个统一的驱动抽象层。从源码结构看每个设备移植工程只需要向 CANopenNode 提供三个接口文件见 301/CO_driver.h 的 Hardware interface of CANopenNode 一节文件职责是否属于主仓库CO_driver.h声明通用驱动函数与类型被 CANopenNode 的每个 .c 文件包含是位于 301/CO_driver.hCO_driver_target.h定义微控制器特定的类型声明与必要宏否由各设备工程提供本仓库提供空模板CO_driver.c实现CO_driver.h中声明的函数否由各设备工程提供本仓库提供空模板本仓库仅在example目录中提供了两个基本为空的模板文件保证CANopenNode/example能在任何系统上编译通过但编译出的程序没有连接真实 CAN 硬件不可直接使用。完整的设备接口文档集中在 301/CO_driver.h 中。二、设备接口规范驱动层到底要实现什么以 301/CO_driver.h 为权威依据一个完整的 CAN 驱动必须实现以下核心数据结构与函数。2.1 三个核心数据结构CO_CANrx_t接收帧配置对象包含标准 CAN 标识符identbit 0..10 为 IDbit 11 为 RTR、掩码mask、绑定的 CANopen 对象指针object以及回调函数指针pCANrx_callback。CO_CANtx_t发送帧配置对象包含按 CAN 模块对齐的标识符ident、帧长度DLC、8 字节数据data[8]以及两个关键标志bufferFull上一帧是否仍在缓冲中与syncFlag同步 PDO 标志防止同步帧在同步窗口外发出。CO_CANmodule_t完整 CAN 模块对象聚合了rxArray/txArray及其大小、CANerrorStatus错误状态位域、CANnormal运行模式标志、useCANrxFilters硬件过滤器使用标志、bufferInhibitFlag、firstCANtxMessage、CANtxCount等。2.2 必须实现的函数清单301/CO_driver.h 声明了以下关键驱动函数空白实现可参考 example/CO_driver_blank.c函数作用与要点CO_CANsetConfigurationMode(CANptr)请求 CAN 进入配置停止模式并等待完成CO_CANsetNormalMode(CANmodule)请求 CAN 进入正常运行模式置CANnormal trueCO_CANmodule_init(...)初始化 CAN 模块对象与硬件寄存器必须在通信复位阶段、配置模式下调用。合法位速率kbps为 10、20、50、125、250、500、800、1000非法值默认回落为 125CO_CANmodule_disable(CANmodule)程序退出时关闭 CAN 模块CO_CANrxBufferInit(...)配置接收缓冲设置标识符与掩码并绑定对象与回调。同一标识符下索引最小者优先CO_CANtxBufferInit(...)配置发送缓冲设置标识符、RTR、帧长与syncFlag返回待填充数据的缓冲指针CO_CANsend(CANmodule, buffer)发送 CAN 帧若硬件发送缓冲空闲则直接复制否则置bufferFull等待 TX 中断发送CO_CANclearPendingSyncPDOs(...)同步窗口超时后清空所有挂起的同步 TPDOCO_CANmodule_process(CANmodule)周期性调用计算CANerrorStatus错误位域CO_CANinterrupt(CANmodule)中断入口接收中断做标识符匹配并调用CANrx_callback快速预处理发送中断按索引顺序发送排队帧接收侧的回调机制尤其重要CAN 帧先由硬件或软件过滤中断/实时线程根据 11 位 CAN-ID 与掩码判定归属的 CANopen 对象然后调用对应的CANrx_callback()快速提取数据供普通线程稍后处理。CO_CANrxMsg_readIdent()、CO_CANrxMsg_readDLC()、CO_CANrxMsg_readData()是目标平台需以内联函数或宏方式提供的帧读取辅助函数。2.3 错误状态与返回值约定驱动层的CO_CANmodule_process()需要按 301/CO_driver.h 的位域约定上报错误收发错误计数器 ≥ 96 进入 warning 级≥ 128 进入 passive 级发送计数器 ≥ 256 进入 bus off。位域包括CO_CAN_ERRTX_WARNING、CO_CAN_ERRTX_PASSIVE、CO_CAN_ERRTX_BUS_OFF、CO_CAN_ERRTX_OVERFLOW、CO_CAN_ERRTX_PDO_LATE、CO_CAN_ERRRX_WARNING、CO_CAN_ERRRX_PASSIVE、CO_CAN_ERRRX_OVERFLOW等。函数统一返回CO_ReturnError_t枚举定义见 301/CO_driver.h包括CO_ERROR_NO、CO_ERROR_ILLEGAL_ARGUMENT、CO_ERROR_ILLEGAL_BAUDRATE、CO_ERROR_TX_OVERFLOW、CO_ERROR_TX_PDO_WINDOW等 20 余种方便上层协议模块与应用程序统一处理。2.4 多线程与 RTOS 移植的关键宏CANopenNode 原生支持多线程裸机下表现为不同优先级的中断。驱动模板必须在CO_driver_target.h中定义以下同步宏CO_LOCK_CAN_SEND/CO_UNLOCK_CAN_SEND保护CO_CANsend()临界区CO_LOCK_EMCY/CO_UNLOCK_EMCY保护CO_errorReport()/CO_errorReset()CO_LOCK_OD/CO_UNLOCK_OD保护对象字典OD读写防止实时线程与主线程并发访问CO_FLAG_READ/CO_FLAG_SET/CO_FLAG_CLEAR接收新帧标志的读写配合内存屏障CO_MemoryBarrier()防止编译器优化乱序。example/CO_driver_target.h提供了全部为空实现的模板Zephyr、FreeRTOS、Mbed-os 等 RTOS 移植则需用互斥量、信号量或关调度实现这些宏这通常是移植工作量最大的部分之一。三、空白模板example 目录——任何系统上都能编译的最小工程example 目录不包含任何特定设备接口它本身就是驱动模板与最小应用示例的结合体可作为新移植工程的起点。目录内的文件职责如下文件职责example/CO_driver_blank.c空白驱动实现每个函数只有骨架与参数校验寄存器操作留空example/CO_driver_target.h空白目标定义CO_LITTLE_ENDIAN、基础类型、三个数据结构、空同步宏example/main_blank.c完整的主程序流程模板见下文example/OD.c / example/OD.h由 CANopenEditor 等外部工具生成的对象字典example/CO_storageBlank.c /.h非易失存储的空白实现example/Makefile使用 gcc 编译的 Makefile目标产物canopennode_blankexample/DS301_profile.edsDS301 设备描述文件EDS供组态工具使用编译验证非常简单需要 gcc 环境在仓库根目录执行cd example makeexample/Makefile 将CO_driver_blank.c、CO_storageBlank.c与301、303、305、storage目录下的协议模块以及CANopen.c、OD.c、main_blank.c一并编译链接-Wall开告警、-g开调试信息还预留了CO_USE_GLOBALS与CO_MULTIPLE_OD两个可选宏的开关位。example/main_blank.c 演示了标准初始化与运行流程这是每个真实移植工程主程序的骨架CO_new()分配并创建 CANopen 对象也可用CO_USE_GLOBALS改用全局变量进入通信复位循环CO_CANsetConfigurationMode()→CO_CANmodule_disable()→CO_CANinit()CAN 与位速率→CO_LSSinit()LSS 从站地址与待定 node-ID/位速率→CO_CANopenInit()NMT、SDO server/client、Emergency 等→CO_CANopenInitPDO()PDO 映射→CO_CANsetNormalMode()普通线程循环调用CO_process()处理所有异步对象实时线程tmrTask_thread典型 1 ms 周期依次调用CO_process_SYNC()、CO_process_RPDO()、CO_process_TPDO()并在CO_LOCK_OD/CO_UNLOCK_OD保护下执行CO_CAN1InterruptHandler()是 CAN 接收/发送中断入口的占位。Node-ID 与位速率在模板中以pendingNodeId默认 10与pendingBitRate默认 125 kbps体现注释明确说明真实设备应从拨码开关或非易失存储读取并可由 LSS 从站配置——这正是把 LSSCiA 305用于在线改节点地址与波特率的接入点相关实现见 305/CO_LSSslave.c。四、驱动开发者推荐工作流程官方七步法doc/deviceSupport.md 专门为希望共享与协作的驱动开发者给出了推荐流程这是社区长期实践沉淀的移植方法论建立独立的设备 demo 工程仓库在 Git 托管平台创建你自己的设备专用仓库引入 CANopenNode 核心将 CANopenNode 作为 git 子模块加入工程例如git submodule add https://gitcode.com/gh_mirrors/ca/CANopenNode原始文档建议添加上游仓库地址使用镜像地址同样可以完成子模块引入引入后 CANopenNode 核心代码保持不动便于后续升级。添加具体驱动与工程文件编写CO_driver_target.h与CO_driver.c并加入应用代码、对象字典、构建脚本撰写良好的 README.md描述你的工程、所用 demo 板、开发工具与用法可选准备 CANopenDemo 设备并运行测试在 CANopenDemo 仓库中提供 demoDevice利用其教程与测试工具验证移植正确性分享成果在 doc/deviceSupport.md 中新增设备条目并提交 Pull Request或在 CANopenNode 的 issues 中为新设备创建 issue申请成为项目开发者将你的工作贡献并入 CANopenNode 项目成为其开发者共同提升代码质量与功能完整性。文档同时指出目前最新、最完整的参考实现是 CANopenLinux 与 CANopenPIC面向 PIC32 裸机移植时可优先参考这两个工程example目录则是最小化的通用模板。五、社区已确认的设备支持清单以下是 doc/deviceSupport.md 记录的设备/平台支持现状信息以文档记录为准工程托管于各自独立仓库此处仅列出关键事实。5.1 主流活跃端口平台说明CANopenNode 版本状态特性工具 / 硬件LinuxsocketCAN与 Linux 内核 socketCAN 集成带主站命令接口文档明确说明其接口属于本项目体系v4.0活跃参考实现OD 存储、错误计数器、主站功能SDO client、LSS master、NMT masterLinux PC、树莓派等STM32STM32 微控制器集成v4.0———PIC32 / dsPIC30 / dsPIC33Microchip 16/32 位 PIC 系列最完整参考实现之一v4.0活跃参考实现PIC32 OD 存储、PIC32 SDO client demo、错误计数器MPLAB XExplorer 16、Max32 板已知最小资源示例dsPIC30F401116 位RAM 不足 2KB4 TPDO 4 RPDOAnalog Devices MAX32662 / MAX32690ADI MAX32xx 系列集成v4.0看似稳定LED 指示灯、错误计数器Maxim Micros SDKMAX32662-EVKIT、MAX32690-EVKIT信息更新于 2023-02-17Zephyr RTOSZephyr 官方模块级集成含示例工程v1.3稳定OD 存储、LED 指示灯、Program Download、Zephyr SDO server demoZephyr SDK任意带 CAN 接口且支持 Zephyr 的开发板信息更新于 2025-11-13Mbed-os RTOS STM32F091RC、L496ZGMbed-os 集成—稳定OD 存储、LED 指示灯、GPIOMbed CLIgcc 7STM32 Nucleo F091RC 等带 CAN 的开发板信息更新于 2020-01-215.2 社区贡献端口平台说明CANopenNode 版本状态特性Kinetis K20NXP ArmTeensy3面向 Teensy3 的驱动配套 readme 文档v1.02017-08-01看似稳定错误计数器信息更新于 2020-03-02S32DSNXP S32 Design StudioArm / PowerPC支持 S32K144EVB-Q100、DEVKIT-MPC5748G 等评估板文档随驱动附送v1.02017-08-01看似稳定错误计数器信息更新于 2020-03-02ESP32社区多次讨论2023-03、2020-07CANopenNode_ESP32作为 ESP-IDF 组件为便于维护直接使用未修改的 CANopenNode 核心另有配套示例工程—社区维护基于 ESP-IDF 框架FreeRTOSNeuberger 版基于 v1.3-master 分支的 FreeRTOS 移植2020-06-23v1.3社区维护多线程移植参考STM32CubeMX HALAtollic Studio 的 demo 工程在 Nucleo STM32L452xx 板上测试通过2019-05-03—社区维护基于 STM32CubeMX HAL 库K64F FreeRTOSKinetis SDKKinetis SDK 平台的 FreeRTOS 移植2018-02-13—社区维护—LPC1768MBED2016 年发布的 CANopenNode v1.0 时代示例v1.0历史最早一批 MBED 移植5.3 历史端口v1.0 时代文档还记录了已不再活跃的历史实现供参考与追溯RTOS eCos2013、Atmel SAM3X、ST STM32、NXP LPC177x_8x、Freescale MCF5282均为 CANopenNode v1.0 时代、BECK IPC Embedded Web-Controller SC2432015 年最后一次发布、ADI ADSP-CM408 混合信号控制器2014 年贡献、Microchip PIC18F2006 年最后一次发布以及最初属于 CANopenNode 的旧版 Object Dictionary Editor依赖极老版本的 Firefox 运行。这些条目印证了 CANopenNode 自 2006 年以来在多代硬件上的持续演进。六、设备特性与仓库源码的对应关系文档中反复出现的设备特性都能在当前仓库中找到对应的协议实现模块这为移植后的功能验收提供了明确抓手文档提到的特性仓库中的实现位置OD 存储自动或由标准 CANopen 命令触发storage/CO_storage.c 与 example/CO_storageBlank.c通过 OD 对象 1010h/1011h 子索引配合 CRC 校验实现非易失保存/恢复错误计数器 / Emergency301/CO_Emergency.c 配合驱动层CO_CANmodule_process()的CANerrorStatus位域主站功能SDO client、LSS master、NMT master301/CO_SDOclient.c、305/CO_LSSmaster.c、301/CO_NMT_Heartbeat.cLED 指示灯CiA 303-3303/CO_LEDs.cCANopen 状态红绿双色指示节点地址/波特率在线配置305/CO_LSSslave.c 与 main_blank.c 中的pendingNodeId/pendingBitRate网关 / 外部访问309/CO_gateway_ascii.cCiA 309-3 ASCII 命令接口所有模块的全局协调入口在 CANopen.hCO_new()、CO_CANinit()、CO_CANopenInit()、CO_CANopenInitPDO()、CO_process()等构成了与平台无关的初始化—运行契约而 301/CO_config.h 则负责各模块的编译期裁剪如是否启用 SDO client、LSS、LED 等设备移植时可按需裁剪以节省资源——这也是 PIC 端能做到RAM 不足 2KB的重要原因。七、移植新设备的关键检查点综合 doc/deviceSupport.md、301/CO_driver.h 与 example 模板移植一个新平台时建议按以下顺序自检类型与字节序在CO_driver_target.h中正确声明CO_LITTLE_ENDIAN或CO_BIG_ENDIANCANopen 本身为小端定义bool_t、CO_CANrx_t、CO_CANtx_t、CO_CANmodule_tCAN 初始化与位速率实现CO_CANmodule_init()支持文档规定的 8 种位速率非法值回落 125收发路径实现CO_CANrxBufferInit()/CO_CANtxBufferInit()/CO_CANsend()接收侧提供CO_CANrxMsg_readIdent/DLC/Data并实现CO_CANinterrupt()的匹配分发与发送队列同步与临界区按目标平台裸机中断优先级或 RTOS 互斥量落实CO_LOCK_*与CO_FLAG_*宏周期处理保证CO_CANmodule_process()、CO_process()及 1 ms 级实时线程SYNC/RPDO/TPDO按文档要求的调用节奏运行工程闭环以example为起点编写应用与 OD先在任意系统上通过make编译再移植驱动接入真实总线最后参照第五节特性清单逐项验证。按照文档的定位CANopenNode 是一个开放移植生态而非封闭实现官方维护 Linux 接口其他控制器接口由独立工程承载并通过 doc/deviceSupport.md 持续登记新设备。对开发者而言最务实的路径是——以 example 空白模板为本、以 CANopenLinux 与 CANopenPIC 为参照、按官方七步法提交自己的移植成果让 CANopen 协议栈在你的硬件上稳定运行并回馈到整个社区。赞分享嵌入式通信【免费下载链接】CANopenNodeCANopen protocol stack项目地址https://gitcode.com/gh_mirrors/ca/CANopenNode点击查看免费下载相关推荐GsonFactory最佳实践避免这些坑让你的解析更高效GsonFactory最佳实践避免这些坑让你的解析更高效 在Android开发中Json解析是每个开发者都会遇到的基础任务但你是否经常遇到因为后台数据格式移动开发序列化F´ 新平台移植指南Toolchain、平台文件、Fw::Types、硬件驱动与 OSAL 五步移植法F´ 新平台移植指南Toolchain、平台文件、Fw::Types、硬件驱动与 OSAL 五步移植法 F´F Prime是一个面向飞行软件与嵌入式系统的嵌入式系统编程Dogecoin 内嵌 LevelDB 的 port 平台抽象层解析接口设计、默认实现与跨平台移植指南Dogecoin 内嵌 LevelDB 的 port 平台抽象层解析接口设计、默认实现与跨平台移植指南 本文围绕 src/leveldb/port/READM区块链上一篇Docker快速部署AntSK从容器配置到模型挂载完整教程下一篇如何自定义量化NVIDIA-Nemotron-3-Nano-30B-A3B-OptiQ-4bitmlx-optiq高级配置教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表