硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2327|回复: 10
收起左侧

[CAN/FDCAN] 【视频教程】RTX5/FreeRTOS全家桶源码工程综合实战模板集成CANopen组件(2024-10-30)

  [复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2024-10-30 01:19:50 | 显示全部楼层 |阅读模式
【前言】

之前的视频教程分享了两期CANopen的专题,配套的例子都是基于裸机的,为了方便大家在OS下使用,本期视频带OS下的支持。

CANopen协议栈专题,实战方式系统了解NMT,PDO,SDO,时间戳,同步报文,紧急报文等(2023-10-17)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=121438

CANopen协议栈专题,CANopen主从机组网实战,CAN词典工具使用方法以及吃透PDO玩法(2023-11-01)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=121619

【视频】

https://www.bilibili.com/video/BV1zHSaYQEYx/



【简介】

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

第1期:RTX5全家桶源码综合模板发布,含FreeRTOS内核版本,将其打造成直接面向实际项目应用的综合框架
https://www.armbbs.cn/forum.php?mod=viewthread&tid=124516

第2期:RTX5源码全家桶集成emWin6.40,  Modbus主从,含FreeRTOS版, 探讨一种移植第3方组件通用方法以及使用注意事项
https://www.armbbs.cn/forum.php?mod=viewthread&tid=125509

第3期:手把手AppWizard轻松制作一个emWin滑动主界面控制框架,任意跳转控制(2024-09-06)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=125613

第4期:【授人以渔】CMSIS-RTOS V2封装层专题视频,一期视频将常用配置和用法梳理清楚,适用于RTX5和FreeRTOS(2024-09-28)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=125907

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

2.png

30c344ca114592da2fdcb069fb362994678329477.png



3、移植CANopenNode协议栈到RTOS两个关键地方的处理

(1)开关中断的处理,裸机版的移植在开关中断的处理地方非常"暴力",直接就是大范围的全局开关中断处理,非常不合理

[C] 纯文本查看 复制代码
/* (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)


[C] 纯文本查看 复制代码
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中断,且支持嵌套调用

[C] 纯文本查看 复制代码
/* (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执行一次的任务里面:

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*        函 数 名: AppTaskCANopen
*        功能说明: CANopen处理任务。
*        形    参: 无
*        返 回 值: 无
*   优 先 级: osPriorityNormal6  
*********************************************************************************************************
*/
extern void DemoCANFD(void);
void AppTaskCANopen(void *argument)
{
        const uint16_t usFrequency = 1; /* 延迟周期 */
        uint32_t tick;
        
        DemoCANFD();

        /* 获取当前时间 */
        tick = osKernelGetTickCount(); 
        
    while(1)
    {
                /* CAN处理 */
                canopen_app_process(); 
                canopen_app_interrupt();
                
                /* 相对延迟 */
                tick += usFrequency;                          
                osDelayUntil(tick);
    }
}


工程目录

1、集成了CMSIS6.10,CMSIS-Driver,CMSIS-DSP,CMSIS-Viwer,CMSIS-Compiler,CMSIS-RTOS V2,CMSIS-FreeRTOS,CMSIS-RTX,CMSIS-MbedTLS等,全部采用的当前最新版。
2、网络协议栈,单网络协议栈同时管理DM9000和DM9162双网口。
3、文件系统,同时管理外挂U盘,NAND Flash和SD卡。
4、USB协议栈,RL-USB同时外挂USB FS和USB HS两个USB外设,USB FS接口用于外接电脑,实现SD卡和NAND模拟U盘,USB HS用于外挂U盘设备。
5、加密算法库使用的CMSIS-mbedTLS。
6、BSP外设驱动,部分是采用的CMSIS-Driver,其他都采用我们自己设计的。
7、Modbus  RTU主从。
8、emWin6.46。
9、CANopen。

3.png

注意事项

使用的CANFD1,注意V7开发板上的跳线帽设置。另外就是如果使用了CANFD1引脚后,不能再使用MicroUSB的Device端口了



参考资料
1、案例下载,本次功能升级将emWin升级到最新的6.46版本。

FreeRTOS All In One(2024-10-30 V3.0).7z (30.53MB)
RTX5 All In One(2024-10-30 V3.0).7z (29.38MB)

2、RTX5全家桶源码综合模板发布V2.0,含FreeRTOS内核版本,将其打造成直接面向实际项目应用的综合框架(2024-08-30)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=124516

3、H7-TOOL的CAN/CANFD助手CANopen协议解析操作说明V1.1,持续更新(2023-12-04)
https://www.armbbs.cn/forum.php?mod=viewthread&tid=120863

评分

参与人数 2金币 +30 收起 理由
snibelyh + 20 很给力!
Vxworks + 10

查看全部评分

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
 楼主| 发表于 2024-10-30 01:58:46 | 显示全部楼层
更新完毕
回复

使用道具 举报

0

主题

110

回帖

110

积分

初级会员

积分
110
发表于 2024-10-30 15:15:38 | 显示全部楼层
辛苦,谢谢分享。
回复

使用道具 举报

1

主题

10

回帖

13

积分

新手上路

积分
13
发表于 2024-11-5 14:39:44 | 显示全部楼层
辛苦,谢谢分享!请教下大佬,LLS协议有了解么,挺实用的
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
 楼主| 发表于 2024-11-5 15:09:47 | 显示全部楼层
aqtcwangwy 发表于 2024-11-5 14:39
辛苦,谢谢分享!请教下大佬,LLS协议有了解么,挺实用的

这个里面也集成了,但是我一直没用,后面我试试。
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2024-11-9 11:34:08 | 显示全部楼层
这个can发送的驱动要改一下,按照他原来的驱动,如果同一个同步帧之后同步传输4个tpdo就会有一个发不出去,因为stm32的can的邮箱就3个,第四个会报溢出错误,然后就丢包发不出去。解决办法就是改一下发送驱动,在发送完成之后加一个检测邮箱fifo的函数,或者延时一段时间。就ok了。可以在网上查一下。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
 楼主| 发表于 2024-11-9 15:21:45 | 显示全部楼层
北铭 发表于 2024-11-9 11:34
这个can发送的驱动要改一下,按照他原来的驱动,如果同一个同步帧之后同步传输4个tpdo就会有一个发不出去, ...

谢谢,不过你搞错了,我们这个是CANFD,没有邮箱,是64个FIFO,并且底层的驱动我做了发送完成检测,你应该看错代码部分了,我们是CANFD的部分,不是经典CAN的部分。
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2024-11-10 17:54:29 | 显示全部楼层
eric2013 发表于 2024-11-9 15:21
谢谢,不过你搞错了,我们这个是CANFD,没有邮箱,是64个FIFO,并且底层的驱动我做了发送完成检测,你应 ...

我用的f4没有canfd。但针对经典can它确实有这个问题,而且canopenNode_stm32的github里面的也有人向官方提出这些问题,但是官方好像没有做出改动。如果发送3个以上的tpdo就会丢包。我发出来也是因为不是所有人都用canfd。
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
 楼主| 发表于 2024-11-11 09:11:43 | 显示全部楼层
北铭 发表于 2024-11-10 17:54
我用的f4没有canfd。但针对经典can它确实有这个问题,而且canopenNode_stm32的github里面的也有人向官方 ...

谢谢。
回复

使用道具 举报

12

主题

43

回帖

79

积分

初级会员

积分
79
发表于 2025-2-22 22:08:24 | 显示全部楼层
硬汉老师,这个专题的视频教程后续还会更新吗,期待一下这个BOOT+APP的教程
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
 楼主| 发表于 2025-2-23 06:11:12 | 显示全部楼层
frankff 发表于 2025-2-22 22:08
硬汉老师,这个专题的视频教程后续还会更新吗,期待一下这个BOOT+APP的教程

继续更新,下一个是文件系统专题。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-25 20:37 , Processed in 0.331822 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表