完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在调试程序时发现,CAN和serial线程里面都调用rt_device_write函数会导致rt_device_write函数卡死。CAN是用中断接收和发送,serialDMA接收,轮询发送。会不会就是两个线程之间会有影响呢,导致rt_device_write堵死呢?程序本身不会死掉,运行灯还一直运行,但是serial和can会死掉 |
|
相关推荐
11个回答
|
|
|
|
|
|
两个线程之间没有交互,但是会访问同一块共享内存。不过我加了互斥量了
|
|
|
|
我最新的调试记录又出现一个新的问题,就是CAN调用这个函数的时候,返回值SIZE为0的情况下,数据依旧可以发送成功
|
|
|
|
CAN文件里面有两个CAN线程,rx线程接收放入共享内存,tx通过定时器,定时向从机广播上传数据。
serial文件里面就一个接收线程,接收到数据通过消息队列给到数据解析线程,然后根据解析出来的命令将can数据上传 |
|
|
|
如果用的drv_can.c的话,发送是在_can_sendmsg函数中完成的。它把buf赋值给了pmsg。
struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; 而, struct rt_can_msg是用位域做的。发送数据size为0,还能发送,有可能是buf部分数据没有清除,这个倒不奇怪。 |
|
|
|
出现线程不再被调度的情况,在 4.0.2 版本上是存在的,其它版本出现这个问题的可能就是线程控制块的数据被意外修改了。
可以研究一下我那个 od_mem 。仔细检查线程控制块里的两个 list tlist 指针是不是变了。 另一方面,可以写个终端命令,单独启动那些不再被调度的线程。这样操作看看是不是能让线程恢复工作。 |
|
|
|
我昨天又遇到一个新情况,就是can发送数据前几次是发送成功的,rt_device_write的size返回值是正确的,但是过一段时间,size 返回值就为0了,但是数据可以正常的发送出去。我看了论坛有好几个贴友都出现这个问题了
|
|
|
|
还有一个情况是size返回值判断那地方,如果我把if里面的输出语句注释掉,程序会卡死在rt_device_write这里面,如果我取消注释,程序就能够正常运行```
static void can_tx_thread(void *parameter) { struct rt_can_msg msg = {0}; rt_size_t size; while(1) { rt_sem_take(&timer0_sem,RT_WAITING_FOREVER); if(rt_mutex_take(&rx_can1_mutex, RT_WAITING_NO) == RT_EOK) { if((tmp_msg_can1.lcd_write_blade[3] == 0x02) && ((tmp_msg_can1.lcd_write_blade[4] - 1) == Switch_load(1, led_Switch))) { LOG_E("lcd_write_blade success...n"); msg.id = (tmp_msg_can1.lcd_write_blade[5] + 0x100); // ID 为 0x78 msg.ide = RT_CAN_STDID; // 标准格式 msg.rtr = RT_CAN_DTR; // 数据帧 msg.len = 2; // 数据长度为 8 msg.data[0] = tmp_msg_can1.lcd_write_blade[6]; //待发送的 8 字节数据 msg.data[1] = tmp_msg_can1.lcd_write_blade[7]; msg.data[2] = 0; msg.data[3] = 0; msg.data[4] = 0; msg.data[5] = 0; msg.data[6] = 0; msg.data[7] = 0; // 发送一帧 CAN 数据 rt_mutex_release(&rx_can1_mutex); size = rt_device_write(can_dev, 0, &msg, sizeof(msg)); if (size == 0) { rt_kprintf("lcd write can failed!n"); } rt_memset(tmp_msg_can1.lcd_write_blade, 0, 10); } else if ((tmp_msg_can1.lcd_write_blade[3] == 0x03) && ((tmp_msg_can1.lcd_write_blade[4] - 1) == Switch_load(1, led_Switch))) { LOG_E("many lcd write balde sucess...n"); msg.id = 0x91; // ID 为 0x78 msg.ide = RT_CAN_STDID; // 标准格式 msg.rtr = RT_CAN_DTR; // 数据帧 msg.len = 2; // 数据长度为 8 msg.data[0] = tmp_msg_can1.lcd_write_blade[5]; //待发送的 8 字节数据 msg.data[1] = tmp_msg_can1.lcd_write_blade[6]; msg.data[2] = 0; msg.data[3] = 0; msg.data[4] = 0; msg.data[5] = 0; msg.data[6] = 0; msg.data[7] = 0; // 发送一帧 CAN 数据 rt_mutex_release(&rx_can1_mutex); size = rt_device_write(can_dev, 0, &msg, sizeof(msg)); if (size == 0) { rt_kprintf("lcd write can lot size failed!n"); } rt_memset(tmp_msg_can1.lcd_write_blade, 0, 10); } } if(rt_mutex_take(&rx_cdm_mutex, RT_WAITING_FOREVER) == RT_EOK) { msg.id = 0x90; // ID 为 0x78 msg.ide = RT_CAN_STDID; // 标准格式 msg.rtr = RT_CAN_DTR; // 数据帧 msg.len = 8; // 数据长度为 8 msg.data[0] = (modbus_cdm.cdm_reginput_rev[0] >> 8 & 0xff); //待发送的 8 字节数据 msg.data[1] = modbus_cdm.cdm_reginput_rev[0] & 0xff; msg.data[2] = (modbus_cdm.cdm_reginput_rev[1] >> 8 & 0xff); msg.data[3] = modbus_cdm.cdm_reginput_rev[1] & 0xff; msg.data[4] = 0; msg.data[5] = 0; msg.data[6] = 0; msg.data[7] = 0; // 发送一帧 CAN 数据 rt_mutex_release(&rx_cdm_mutex); size = rt_device_write(can_dev, 0, &msg, sizeof(msg)); if (size == 0) { rt_kprintf("%dn",Switch_load(1, led_Switch)); rt_kprintf("cdm write can1 data failed!n"); } else { rt_kprintf("%dn",Switch_load(1, led_Switch)); rt_kprintf("cdm write can1 data success...!n"); } } } } ``` |
|
|
|
rt_kprintf 在你这里应该是起到的延时效果了
你得检查一下什么地方会返回0了,还有在什么时候会返回0。会不会是上次的数据还没有传输完,又 write 造成后面这次直接返回0了? 加 rt_kprintf 能正常运行可能就是前后两次发送冲突了。 |
|
|
|
rt_device_write的函数很简单的,断言,判断ref_count, 调用dev->write函数。代码如下所示:
serial和can死掉,那就是这两个外设的写操作死掉了,建议再深入去查一下原因,更加准确说明现象、提供详细的log等。在drv_usart.h/drv_can.c中具体的写操作函数中找原因。 rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); if (dev->ref_count == 0) { rt_set_errno(-RT_ERROR); return 0; } /* call device_write interface */ if (device_write != RT_NULL) { return device_write(dev, pos, buffer, size); } /* set error code */ rt_set_errno(-RT_ENOSYS); return 0; } |
|
|
|
uart 和 can,rt_device_write只是写入环形缓冲区,返回0就是有剩余数据没发出去没空间写了,卡死应该是发出去导致没有收到完成信号量,死等。
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
788 浏览 0 评论
4271 浏览 0 评论
如何使用python调起UDE STK5.2进行下载自动化下载呢?
2529 浏览 0 评论
开启全新AI时代 智能嵌入式系统快速发展——“第六届国产嵌入式操作系统技术与产业发展论坛”圆满结束
2929 浏览 0 评论
获奖公布!2024 RT-Thread全球巡回线下培训火热来袭!报名提问有奖!
31479 浏览 11 评论
72917 浏览 21 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 12:22 , Processed in 0.817977 second(s), Total 90, Slave 73 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号