Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
内核线程调度
20
rt_thread_resume failed
发布于 2021-08-14 15:22:01 浏览:1125
订阅该版
[tocm] ### **最终目的:** - 通过无线接收数据(中断中接收),然后将数据通过mqtt发送出去,并将数据更新至显示屏 ### **实现方法** - 参照rtthread系统中 **rt_slist_t**结构创建一个单向链表,每个要显示的数据都会放置在这个链表的末端,称为显示缓冲区。 - 创建显示屏刷新任务**thread_screen_refresh**:显示屏使用迪文串口屏,每屏最多显示 9 条数据,要显示的这9条数据定义为结构体数组,称为显存,显示屏固定 7s 间隔将当前显存更新与显示屏。 - 创建显示缓存链表数据检查任务**thread_screen_datacheck**:数据通过中断接收时会产生一个 rt_tick_get(); 并将这个数据放置在链表的末端,这个线程的功能是,如果这个 tick 和当前 tick 相比大于10s;就是说这条数据的第一条收到了,超过10s第二条还没有收到,我会把这个数据从链表中删除。 - 创建显示屏缓存链表数据写入任务**thread_screen_datawrite**:中断接收通过消息队里将要添加到链表末端的数据结构传输给此线程,通过这个线程写入到链表末端。 ### **流程图** - 说的比较乱,我画个图说明一下。 ![0.png](https://oss-club.rt-thread.org/uploads/20210814/e9bc4ff993eec2afbfd3a02f45af3a49.png.webp) ### **线程代码** - **数据写入** ``` C static void thread_screen_datawrite(void* param) { DisList_Type_Def temp_datawrite; while(1) { if(rt_mq_recv(p_mq_details_write, &temp_datawrite, sizeof(DisList_Type_Def), RT_WAITING_FOREVER) == RT_EOK) { /* write data */ if(write_listdata_dis(p_displaylist_ctrl, &temp_datawrite) == RT_ERROR) { LOG_E("Write dis data error"); } } else { rt_thread_delay(RT_TICK_PER_SECOND); } } } ``` - **数据检查** ``` C static void thread_screen_datacheck(void* param) { while (1) { if(p_displaylist_ctrl->dislist_store != RT_NULL) { delete_listdata_dis(p_displaylist_ctrl); rt_thread_delay(RT_TICK_PER_SECOND * 3); } else { rt_thread_delay(RT_TICK_PER_SECOND * 3); } } } ``` - **显示刷新** ``` C // 定时器发送 sem 刷新 void callbakfunc_timer_refreshdetails(void* param) { rt_sem_t p_sem_refreshdetails = param; rt_sem_release(p_sem_refreshdetails); } static void thread_screen_refresh(void* param) { while (1) { if(rt_sem_take(&sem_display_refresh, RT_WAITING_FOREVER) != RT_EOK) { LOG_E("sem_display_refresh take failed !"); rt_thread_delay(RT_TICK_PER_SECOND); } display_clear(); refresh_details_mem(); refresh_details(); refresh_basicinfo(p_displaylist_ctrl->dislist_pagenum, p_system_time, netdev_default, p_mqttsend_devicestatus->client_param->mqtt_client_state); } } ``` ### **显示结构体** ``` C /* display state union */ typedef union { rt_uint8_t uc; struct { rt_uint8_t b_chiptypeexist : 1; rt_uint8_t b_nameexist : 1; rt_uint8_t b_distanceexist : 1; rt_uint8_t b_voltageexist : 1; rt_uint8_t b_chiptype : 1; rt_uint8_t b_flagsos : 1; rt_uint8_t b_flagcall : 1; rt_uint8_t b_rev0:1; }param; }DisplayState_Type_Def; /* display content struct */ typedef struct { rt_slist_t dis_list; DisplayState_Type_Def dis_state; rt_uint8_t dis_tagvol; rt_uint16_t dis_tagid; rt_uint32_t dis_tagdistance; rt_tick_t generate_tick; char dis_tagname[DISPLAY_NAME_MAX]; rt_uint8_t tagname_len; }DisList_Type_Def; /* display ctrl struct */ typedef struct { DisList_Type_Def* dislist_store; DisList_Type_Def* dislist_read; rt_mp_t p_mempool_display; rt_uint8_t dislist_pagenum; rt_mutex_t muctexlock_dislist; }DisCtrl_Type_Def; ``` ### **应用接口代码** - **初始化** ``` C rt_err_t ini_listdata_dis(DisCtrl_Type_Def* param_displayctrl, rt_mp_t param_displaymempoll) { /* check param is rt_null */ RT_ASSERT(param_displayctrl); RT_ASSERT(param_displaymempoll); return ini_var_list(param_displayctrl, param_displaymempoll); } ``` - **写入** ``` C rt_err_t write_listdata_dis(DisCtrl_Type_Def* param_displayctrl, DisList_Type_Def* param_listdata_w) { DisList_Type_Def* cur_finddata = RT_NULL; /* check param is rt_null */ RT_ASSERT(param_displayctrl); RT_ASSERT(param_listdata_w); /* 1. find --------------------------------------------------------------*/ if(param_displayctrl->dislist_store != RT_NULL) { cur_finddata = find_data_list(param_displayctrl, param_listdata_w); } /* 2. change ----------------------------------------------------------- */ if(cur_finddata) { return change_data_list(param_displayctrl, cur_finddata, param_listdata_w); } /* 3. add -------------------------------------------------------------- */ return write_data_list(param_displayctrl, param_listdata_w); } ``` - **读取** ``` C DisList_Type_Def* read_listdata_dis(DisCtrl_Type_Def* param_displayctrl) { /* check param is rt_null */ RT_ASSERT(param_displayctrl); return read_data_list(param_displayctrl); } ``` - **删除** ``` C rt_err_t delete_listdata_dis(DisCtrl_Type_Def* param_displayctrl) { /* check param is rt_null */ RT_ASSERT(param_displayctrl); return delete_data_list(param_displayctrl); } ``` ### **链表操作代码** - **初始化** ``` C rt_err_t ini_var_list(DisCtrl_Type_Def* param_displayctrl, rt_mp_t param_displaymempoll) { param_displayctrl->dislist_store = RT_NULL; param_displayctrl->dislist_read = RT_NULL; param_displayctrl->p_mempool_display = param_displaymempoll; param_displayctrl->dislist_pagenum = 0x01; param_displayctrl->muctexlock_dislist = rt_mutex_create("muctexlock_dislist", RT_IPC_FLAG_FIFO); if(param_displayctrl->muctexlock_dislist == RT_NULL) { LOG_E("muctexlock_dislist init failed"); return RT_ERROR; } else { return RT_EOK; } } void ini_var_listdetails(DisList_Type_Def* param_listdata_w) { rt_slist_init(&(param_listdata_w->dis_list)); param_listdata_w->dis_state.uc = 0x00; param_listdata_w->dis_tagdistance = 0x00; param_listdata_w->dis_tagid = 0x00; rt_memset(param_listdata_w->dis_tagname, 0x20, DISPLAY_NAME_MAX); param_listdata_w->dis_tagvol = 0x00; param_listdata_w->generate_tick = 0x00; param_listdata_w->tagname_len = 0x00; } ``` - **查找** ``` C DisList_Type_Def* find_data_list(DisCtrl_Type_Def* param_displayctrl, DisList_Type_Def* param_listdata_w) { rt_base_t level; rt_slist_t *node = RT_NULL; DisList_Type_Def* temp_finddata = RT_NULL; // rt_mutex_take(param_displayctrl->muctexlock_dislist, RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); for (node = &(param_displayctrl->dislist_store->dis_list); node; node = rt_slist_next(node)) { temp_finddata = rt_slist_entry(node, DisList_Type_Def, dis_list); if(temp_finddata && tagid_cmp(temp_finddata, param_listdata_w)) { // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return temp_finddata; } } // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return RT_NULL; } ``` - **更新** ``` C rt_err_t change_data_list(DisCtrl_Type_Def* param_displayctrl, DisList_Type_Def* param_listdata_cur, DisList_Type_Def* param_listdata_w) { rt_base_t level; // rt_mutex_take(param_displayctrl->muctexlock_dislist, RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); /* chiptype */ if(param_listdata_w->dis_state.param.b_chiptypeexist) { param_listdata_cur->dis_state.param.b_chiptype = param_listdata_w->dis_state.param.b_chiptype; param_listdata_cur->dis_state.param.b_chiptypeexist = param_listdata_w->dis_state.param.b_chiptypeexist; } /* voltage */ if((param_listdata_cur->dis_tagvol != param_listdata_w->dis_tagvol) && (param_listdata_w->dis_state.param.b_voltageexist)) { param_listdata_cur->dis_tagvol = param_listdata_w->dis_tagvol; param_listdata_cur->dis_state.param.b_voltageexist = param_listdata_w->dis_state.param.b_voltageexist; } /* name */ if((!param_listdata_cur->dis_state.param.b_nameexist) && (param_listdata_w->dis_state.param.b_nameexist)) { rt_memcpy(param_listdata_cur->dis_tagname, param_listdata_w->dis_tagname, param_listdata_w->tagname_len); param_listdata_cur->dis_state.param.b_nameexist = param_listdata_w->dis_state.param.b_nameexist; param_listdata_cur->tagname_len = param_listdata_w->tagname_len; } /* distance */ if((param_listdata_cur->dis_tagdistance != param_listdata_w->dis_tagdistance) && (param_listdata_w->dis_state.param.b_distanceexist)) { param_listdata_cur->dis_tagdistance = param_listdata_w->dis_tagdistance; param_listdata_cur->dis_state.param.b_distanceexist = param_listdata_w->dis_state.param.b_distanceexist; } /* sos and call */ param_listdata_cur->dis_state.param.b_flagsos = param_listdata_w->dis_state.param.b_flagsos; param_listdata_cur->dis_state.param.b_flagcall = param_listdata_w->dis_state.param.b_flagcall; /* tick */ param_listdata_cur->generate_tick = param_listdata_w->generate_tick; // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return RT_EOK; } ``` - **写入** ``` C rt_err_t write_data_list(DisCtrl_Type_Def* param_displayctrl, DisList_Type_Def* param_listdata_w) { rt_base_t level; DisList_Type_Def* temp_writedata = RT_NULL; /* malloc mempool */ temp_writedata = (DisList_Type_Def*)rt_mp_alloc(param_displayctrl->p_mempool_display, RT_WAITING_NO); if(temp_writedata == RT_NULL) { return RT_ERROR; } /* init store detail */ ini_var_listdetails(temp_writedata); /* copy memory details */ rt_memcpy(temp_writedata, param_listdata_w, sizeof(DisList_Type_Def)); // rt_mutex_take(param_displayctrl->muctexlock_dislist, RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); if(param_displayctrl->dislist_store == RT_NULL) { param_displayctrl->dislist_store = temp_writedata; param_displayctrl->dislist_read = temp_writedata; } else { /* tail insertion */ rt_slist_append(&(param_displayctrl->dislist_store->dis_list), &(temp_writedata->dis_list)); } // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return RT_EOK; } ``` - **读取** ``` C DisList_Type_Def* read_data_list(DisCtrl_Type_Def* param_displayctrl) { rt_base_t level; rt_slist_t *node = RT_NULL; DisList_Type_Def* temp_readdata = RT_NULL; /* check store and read */ if((param_displayctrl->dislist_store == RT_NULL) || (param_displayctrl->dislist_read == RT_NULL)) { return RT_NULL; } // rt_mutex_take(param_displayctrl->muctexlock_dislist, RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); /* read one struct disdata */ node = &(param_displayctrl->dislist_read->dis_list); if(node) { temp_readdata = rt_slist_entry(node, DisList_Type_Def, dis_list); if(temp_readdata) { // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return temp_readdata; } } // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return RT_NULL; } ``` - **删除** ``` C rt_err_t delete_data_list(DisCtrl_Type_Def* param_displayctrl) { rt_base_t level; rt_slist_t *node = RT_NULL; DisList_Type_Def* temp_deletedata = RT_NULL; // rt_mutex_take(param_displayctrl->muctexlock_dislist, RT_WAITING_FOREVER); level = rt_hw_interrupt_disable(); /* delete disdata */ for(node = &(param_displayctrl->dislist_store->dis_list); node; node = rt_slist_next(node)) { temp_deletedata = rt_slist_entry(node, DisList_Type_Def, dis_list); if((temp_deletedata) && tick_cmp(rt_tick_get(), temp_deletedata)) { /* check store */ if(param_displayctrl->dislist_store == temp_deletedata && rt_slist_next(¶m_displayctrl->dislist_store->dis_list) == RT_NULL) { param_displayctrl->dislist_store = RT_NULL; } /* delete */ else { rt_slist_remove(&(param_displayctrl->dislist_store->dis_list), &(temp_deletedata->dis_list)); } /* check read */ if(param_displayctrl->dislist_read == temp_deletedata) { param_displayctrl->dislist_read = param_displayctrl->dislist_store; } /* free memory */ rt_mp_free(temp_deletedata); } } // rt_mutex_release(param_displayctrl->muctexlock_dislist); rt_hw_interrupt_enable(level); return RT_EOK; } ``` ### **详细信息** ![2.png](https://oss-club.rt-thread.org/uploads/20210814/d0a5aa943e292cb4939e3a820bee9e9e.png) ## **问题阐述** - **说明:**中断产生的数据会很快 - 说不定什么时候就报错,错误内容如下 ```C (rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread) assertion failed at function:rt_thread_resume, line number:770 ``` - 未添加显示相关的三个线程时,程序可稳定运行,昨晚添加后今天来了一看就有这个问题了,试着修改了 开关中断还是不行。 - 各位路过的大神,停下脚步帮帮我吧,疫情如此别出去七夕了,为国家减轻点负担,写代码最安全。
查看更多
出出啊
2021-08-14
恃人不如自恃,人之为己者不如己之自为也
不看前边的,最后这个错误,明显告诉我们,你的系统内存被污染了,有内存溢出的地方。某些内存数据被非法写坏了。 极有可能是数据传输给界面线程时出错了。鉴于代码太多,一时难看出来是哪儿内存溢出了。 如果内存还充足,先把各个线程栈翻倍。 `write_listdata_dis` 函数调用了仨操作链表的函数 `find_data_list` `change_data_list` `write_data_list` ,虽然三个函数内部都有关中断保护,但是在这仨函数之间切换时没有中断保护。这是很危险的。 刚开始判断链表非空,后面俩函数没有判断链表是否空。 定时器发送 sem 刷新部分,用 mdelay 替换到定时器也是可以的 在线程里,数据保护,没必要使用关中断,用 `rt_enter_critical` 和 `rt_exit_critical` 进入临界区代替比较好。 find_data_list 中比较两条数据的时间,比较的是第一条,还是上一条?
2
个回答
默认排序
按发布时间排序
小小李sunny
2021-08-14
这家伙很懒,什么也没写!
当要进行thread_resume操作时,发现这个要操作的对象并不是一个正常、合法的线程。 建议单步调试一下,看具体是操作哪个对象的时候发生的错误,然后重点排查这个对象是否被修改,或者出现异常。
撰写答案
登录
注册新账号
关注者
0
被浏览
1.1k
关于作者
zhujie
这家伙很懒,什么也没写!
提问
27
回答
13
被采纳
2
关注TA
发私信
相关问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
简单两步配置RTT源码阅读环境 vsc+clangd
2
恩智浦[FRDM-MCXN947]初探 之 ADC与DAC
3
LVGL使用字库IC芯片显示中文
4
基于STM32H750和Rt-Thread的CANFD通信实现的记录(一)
5
freemodbus主机在freertos的适配,参考rtthread例程
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部