rt-thread H7 使用fdcan没有外接设备时或发送错误时线程被挂起的解决方案
一、问题查找
使用的开发版是硬石的H7芯片型号STM32H743IIT6,测试时发现如果外面没有连接CAN设备,程序调用CAN发送时会一直等待发送反馈,导致相关线程挂起。
在线仿真时发现是卡在can.c文件的168行_can_int_tx函数:rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);
代码如下:
rt_inline int _can_int_tx(struct rt_can_device *can, const struct rt_can_msg *data, int msgs)
{int size;struct rt_can_tx_fifo *tx_fifo;RT_ASSERT(can != RT_NULL);size = msgs;tx_fifo = (struct rt_can_tx_fifo *) can->can_tx;RT_ASSERT(tx_fifo != RT_NULL);while (msgs){rt_base_t level;rt_uint32_t no;rt_uint32_t result;struct rt_can_sndbxinx_list tx_tosnd = RT_NULL;rt_sem_take(&(tx_fifo->sem), RT_WAITING_FOREVER);level = rt_hw_interrupt_disable();tx_tosnd = rt_list_entry(tx_fifo->freelist.next, struct rt_can_sndbxinx_list, list);RT_ASSERT(tx_tosnd != RT_NULL);rt_list_remove(&tx_tosnd->list);rt_hw_interrupt_enable(level);no = ((rt_uint32_t)tx_tosnd - (rt_uint32_t)tx_fifo->buffer) / sizeof(struct rt_can_sndbxinx_list);tx_tosnd->result = RT_CAN_SND_RESULT_WAIT;if (can->ops->sendmsg(can, data, no) != RT_EOK){/ send failed. */level = rt_hw_interrupt_disable();rt_list_insert_after(&tx_fifo->freelist, &tx_tosnd->list);rt_hw_interrupt_enable(level);rt_sem_release(&(tx_fifo->sem));continue;}can->status.sndchange = 1;rt_completion_wait(&(tx_tosnd->completion), RT_WAITING_FOREVER);
说明一直在等待完成信号,而发送完成信号的地方在can.c文件的900行rt_hw_can_isr函数:rt_completion_done(&(tx_fifo->buffer[no].completion));
源码如下:
case RT_CAN_EVENT_TX_DONE:
case RT_CAN_EVENT_TX_FAIL:
{struct rt_can_tx_fifo *tx_fifo;rt_uint32_t no;no = event > > 8;tx_fifo = (struct rt_can_tx_fifo *) can- >can_tx;RT_ASSERT(tx_fifo != RT_NULL);if ((event & 0xff) == RT_CAN_EVENT_TX_DONE){tx_fifo- >buffer[no].result = RT_CAN_SND_RESULT_OK;}else{tx_fifo- >buffer[no].result = RT_CAN_SND_RESULT_ERR;}rt_completion_done(&(tx_fifo- >buffer[no].completion));break;
}
二、解决方案
看完can的驱动源码后想到如果can总线没有其他设备,CAN发送报文应该属于出错的情况,查看drv_fdcan.c文件中关于几种中断的处理,发现故障后的回调函数里没有调用rt_hw_can_isr。于是参考HAL_FDCAN_TxBufferCompleteCallback函数的处理方式,对HAL_FDCAN_ErrorCallback进行了如下处理。
源码如下:
void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
{rt_uint32_t tmp_u32Errcount;rt_uint32_t tmp_u32status;uint32_t ret = HAL_FDCAN_GetError(hfdcan);if(hfdcan->Instance == FDCAN1){#ifdef BSP_USING_FDCAN1//can1if( (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk)){//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;st_DrvCan1.device.status.errcode = 0xff;}else{tmp_u32Errcount = st_DrvCan1.fdcanHandle.Instance->ECR;tmp_u32status = st_DrvCan1.fdcanHandle.Instance->PSR;st_DrvCan1.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;st_DrvCan1.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;st_DrvCan1.device.status.lasterrtype = tmp_u32status&0x000000007;rt_hw_can_isr(&st_DrvCan1.device, RT_CAN_EVENT_TX_FAIL);}#endif / BSP_USING_FDCAN1 /}else{#ifdef BSP_USING_FDCAN2if( (ret & FDCAN_IT_ARB_PROTOCOL_ERROR) &&(hfdcan->Instance->CCCR & FDCAN_CCCR_INIT_Msk)){//hfdcan->Instance->CCCR |= FDCAN_CCCR_CCE_Msk;hfdcan->Instance->CCCR &= ~FDCAN_CCCR_INIT_Msk;st_DrvCan2.device.status.errcode = 0xff;}else{//can2tmp_u32Errcount = st_DrvCan2.fdcanHandle.Instance->ECR;tmp_u32status = st_DrvCan2.fdcanHandle.Instance->PSR;st_DrvCan2.device.status.rcverrcnt = (tmp_u32Errcount>>8)&0x000000ff;st_DrvCan2.device.status.snderrcnt = (tmp_u32Errcount)&0x000000ff;st_DrvCan2.device.status.lasterrtype = tmp_u32status&0x000000007;rt_hw_can_isr(&st_DrvCan2.device, RT_CAN_EVENT_TX_FAIL);}#endif / BSP_USING_FDCAN2 /}
}
经修改后测试发现一切正常,发送错误后就会进入错误处理,不会卡死发送线程。
相关文章:
rt-thread H7 使用fdcan没有外接设备时或发送错误时线程被挂起的解决方案
一、问题查找 使用的开发版是硬石的H7芯片型号STM32H743IIT6,测试时发现如果外面没有连接CAN设备,程序调用CAN发送时会一直等待发送反馈,导致相关线程挂起。 在线仿真时发现是卡在can.c文件的168行_can_int_tx函数:rt_co…...
exptern “C“的作用,在 C 和 CPP 中分别调用 openblas 中的 gemm 为例
openblas提供的sgemm有两种方式,一种是通过cblas,另一种是直接声明并调用 sgemm_ 其中,cblas方式是更正规调用方法; 1,调用openblas的 sgemm 的两种方式 1.1 c语言程序中使用 sgemm hello_sgemm.c #include <st…...
如何提前预防网络威胁
一、引言 随着信息技术的迅猛进步,网络安全议题愈发凸显,成为社会各界不可忽视的重大挑战。近年来,一系列网络安全事件的爆发,如同惊雷般震撼着个人、企业及国家的安全防线,揭示了信息安全保护的紧迫性与复杂性。每一…...
ProviderRpc发送服务二将远程调用来的信息反序列化后调用服务方的方法,并将服务方的结果返回给发送方
在Provider的实现中,OnMessage函数中,处理接收到的连接RPC请求。将接收到的RPC请求(包含请求的对象,请求方法和 请求参数),接收到这些信息之后进行反序列化。得到这些参数之后我们即将要做的事情是去调用相…...
Io 35
FIleinputStream字节输入 package File.io;import java.io.*;public class io1 {public static void main(String[] args) throws IOException {// InputStream is new FileInputStream(new File("C:\\Users\\SUI\\Desktop\\Java1\\one\\src\\kaishi"));//简化Input…...
java基础概念11-方法
一、什么是方法 方法(method)是程序中最小的执行单元。 方法中的程序,要不然就是一起执行,要不然就是一起不执行!!! 二、方法的定义 在Java中,方法定义的一般格式如下:…...
大模型应用中的思维树(Tree of Thought)是什么?
大模型应用中的思维树(Tree of Thought)是什么? 大模型,特别是基于GPT(Generative Pre-trained Transformer)架构的模型,在处理复杂任务时,通常需要依赖某种形式的推理和决策机制。…...
学习记录(11):训练图片分类的算法
文章目录 一、卷积神经网络(CNN)架构1. ResNet(Residual Networks)2. DenseNet(Densely Connected Convolutional Networks)3. EfficientNet4. MobileNet 二、变换器(Transformer)架…...
上网防泄密,这些雷区不要碰!九招教你如何防泄密
李明:“最近看到不少关于信息泄露的新闻,真是让人担忧。咱们在工作中,稍有不慎就可能触碰到泄密的雷区啊。” 王芳:“确实,网络安全无小事。尤其是我们这种经常需要处理敏感信息的岗位,更得小心谨慎。那你…...
数据库篇--八股文学习第十五天| 一条SQL查询语句是如何执行的?,事务的四大特性有哪些?,数据库的事务隔离级别有哪些?
1、一条SQL查询语句是如何执行的? 答: 连接器:连接器负责跟客户端建立连接、获取权限、维持和管理连接。查询缓存: MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以…...
elk + filebeat + kafka实验和RSync同步
elk filebeat kafka实验和RSync同步 elk filebeat kafka实验 filebeatkafkaELK实验的操作步骤: #在装有nginx的主机上解压filebeat压缩包 [roottest4 opt]# tar -xf filebeat-6.7.2-linux-x86_64.tar.gz #将解压后的压缩包更改名字 [roottest4 opt]# mv file…...
子类到底能继承父类中的哪些内容?
...
【超详细公式】曝光值(EV)、光圈(AV)、快门(TV)、感光度(SV)、照度(Lux)
文章目录 术语 E V A V T V − S V EV AV TV - SV EVAVTV−SV L u x 2.5 2 E V Lux 2.5 \times 2^{EV} Lux2.52EV通常环境光照度参照表 术语 术语全称中文名EVExposure Value曝光值AVAperture Value光圈值TVTime Value快门值SVSensitive Value感光值BVBrightness Value…...
【Java】增强for遍历集合。
增强for遍历 增强for底层就是迭代器。所有的单列集合和数组才能使用增强for遍历。 在循环过程中无法对集合中的元素进行修改。 package demo;import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;public class submit {public static void …...
【Qt】管理创建子项目
新建项目 打开是这样,无法添加子项目 pro添加 TEMPLATE subdirs有了 点击添加子项目 其他项目-子目录项目 (空的子项目,只有pro,无h、cpp) 子目录名字 直接创建子目录下子项目 选择有无界面或者其他类型项目 …...
力扣——238.移动零
题目 思路 利用双指针,先找到第一个为0的地方指向,指针2指向下一个,指针1之前是已经处理好的数据,指针2进行遍历,遇到非零则与指针1数据交换,然后指针1。 代码 class Solution { public:void moveZeroes(…...
编程的魅力
在数字化时代,编程已不仅仅是计算机科学家的专属领地,它正逐渐渗透到我们生活的每一个角落,成为连接现实与虚拟、创新与传统的重要桥梁。编程,这一门融合了逻辑、创造与解决问题的艺术,正以其独特的魅力引领着新一轮的…...
想提升跨境电商运营?浏览器多开为你助力!
在日常生活中,我们在使用浏览器访问网站时,可能会遇到一个尴尬的情况:无法同时登录一个网站的多个账号。对于跨境电商卖家来说,这种情况更为常见。例如,当我们需要在亚马逊管理店铺时,我们可能已经使用A账号…...
使用QML的ListView自制树形结构图TreeView
背景 感觉QML自带的TreeView不是很好用,用在文件路径树形结构比较多,但是想用在自己数据里,就不太方便了,所以自己做一个。 用‘ListView里迭代ListView’的方法,制作树形结构,成果图: 代码…...
2.MySQL面试题之索引
1. 为什么索引要用 B树来实现呢,而不是 B 树? MySQL 选择使用 B 树来实现索引,而不是 B 树,主要是基于以下几个原因: 1.1 数据存储和访问效率 B 树:在 B 树中,数据和索引都存储在每个节点中。…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
