【视频】
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执行一次的任务里面: