专栏名称: 安富莱电子
由武汉安富莱电子有限公司负责维护。每周发布嵌入式周报,嵌入式领域最新消息和技术分享。内容原创。
目录
相关文章推荐
BioArt  ·  ​PNAS | ... ·  昨天  
生物学霸  ·  常用试剂----三光气 ·  2 天前  
生物制品圈  ·  诺诚健华首次启动口服 TYK2 变构抑制剂 ... ·  4 天前  
生信宝典  ·  微生物组-扩增子16S分析和可视化(2025.4) ·  3 天前  
51好读  ›  专栏  ›  安富莱电子

【视频教程】RTX5/FreeRTOS全家桶源码工程综合实战模板集成CANopen组件

安富莱电子  · 公众号  ·  · 2024-10-30 01:53

正文

【前言】
之前的视频教程分享了两期CANopen专题,配套的例子都是基于裸机的,为了方便大家在OS下使用,本期视频带来OS下的支持。
BSP视频教程第27期:CANopen协议栈专题,干货分享,实战方式系统了解NMT,PDO,SDO,时间戳,同步报文,紧急报文等
BSP视频教程第28期:CANopen协议栈专题,CANopen主从机组网实战,CAN词典工具使用方法以及吃透PDO玩法

【视频】

B站查看:
https://www.bilibili.com/video/BV1zHSaYQEYx

【简介】

1、针对RTX5/FreeRTOS源码全家桶模板,已经更新了4期视频,这是第5期,来一期添加CANopen组件的视频教程。

第1期: RTX5全家桶源码综合模板发布,含FreeRTOS内核版本,将其打造成直接面向实际项目应用的综合框架

第2期: RTX5源码全家桶集成emWin6, Modbus主从,含FreeRTOS版, 探讨一种移植第3方组件通用方法以及使用注意事项

第3期: 【视频教程】手把手AppWizard轻松制作一个emWin滑动主界面控制框架视频教程发布,任意跳转控制

第4期: 【授人以渔】CMSIS-RTOS V2封装层专题视频,一期视频将常用配置和用法梳理清楚,适用于RTX5和FreeRTOS


2、CANopen常用的NMT,PDO,SDO,时间戳,同步报文,紧急报文都支持

3、移植CANopenNode协议栈到RTOS两个关键地方的处理
(1)开关中断的处理,裸机版的移植在开关中断的处理地方非常"暴力",直接就是大范围的全局开关中断处理,非常不合理
/* (un)lock critical section in CO_CANsend() */#define CO_LOCK_CAN_SEND(CAN_MODULE)                                                                                   \    do {                                                                                                               \        (CAN_MODULE)->primask_send = __get_PRIMASK();                                                                  \        __disable_irq();                                                                                               \    } while (0)#define CO_UNLOCK_CAN_SEND(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_send)
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */#define CO_LOCK_EMCY(CAN_MODULE) \ do { \ (CAN_MODULE)->primask_emcy = __get_PRIMASK(); \ __disable_irq(); \ } while (0)#define CO_UNLOCK_EMCY(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_emcy)
/* (un)lock critical section when accessing Object Dictionary */#define CO_LOCK_OD(CAN_MODULE) \ do { \ (CAN_MODULE)->primask_od = __get_PRIMASK(); \ __disable_irq(); \ } while (0)#define CO_UNLOCK_OD(CAN_MODULE) __set_PRIMASK((CAN_MODULE)->primask_od)
canopen_app_interrupt(void) {    CO_LOCK_OD(CO->CANmodule);    if (!CO->nodeIdUnconfigured && CO->CANmodule->CANnormal) {        bool_t syncWas = false;        /* get time difference since last function call */        uint32_t timeDifference_us = 1000; // 1ms second
#if (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE syncWas = CO_process_SYNC(CO, timeDifference_us, NULL);#endif#if (CO_CONFIG_PDO) & CO_CONFIG_RPDO_ENABLE CO_process_RPDO(CO, syncWas, timeDifference_us, NULL);#endif#if (CO_CONFIG_PDO) & CO_CONFIG_TPDO_ENABLE CO_process_TPDO(CO, syncWas, timeDifference_us, NULL);#endif
/* Further I/O or nonblocking application code may go here. */ } CO_UNLOCK_OD(CO->CANmodule);}

现在修改为采用仅开关CAN中断,且支持嵌套调用

/* (un)lock critical section in CO_CANsend() */#define CO_LOCK_CAN_SEND(CAN_MODULE)                                                                   \    do {                                                                                               \                HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);                                                               \        (CAN_MODULE)->CriticalNesting++;                                                               \    } while(0)#define CO_UNLOCK_CAN_SEND(CAN_MODULE)                                                                 \    do {                                                                                               \                (CAN_MODULE)->CriticalNesting--;                                                                \                if((CAN_MODULE)->CriticalNesting == 0)                                                         \                {                                                                                              \                  HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);                                                               \                }                                                                                              \    } while(0)        
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */#define CO_LOCK_EMCY(CAN_MODULE) \ do { \ HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); \ (CAN_MODULE)->CriticalNesting++; \ } while(0)#define CO_UNLOCK_EMCY(CAN_MODULE) \ do { \ (CAN_MODULE)->CriticalNesting--; \ if((CAN_MODULE)->CriticalNesting == 0) \ { \ HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); \ } \ } while(0)
/* (un)lock critical section when accessing Object Dictionary */#define CO_LOCK_OD(CAN_MODULE) \ do { \ HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); \ (CAN_MODULE)->CriticalNesting++; \ } while (0)#define CO_UNLOCK_OD(CAN_MODULE) \ do { \ (CAN_MODULE)->CriticalNesting--; \ if((CAN_MODULE)->CriticalNesting == 0) \ { \ HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); \ } \ } while(0)
#endif

(2)函数canopen_app_process和canopen_app_interrupt的调用处理,我们这里直接将其放在1ms执行一次的任务里面:

/*






请到「今天看啥」查看全文