Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Kernel
一个诡异的问题(线程不挂起也不运行)
发布于 2015-05-29 10:56:17 浏览:3153
订阅该版
[tocm] 首先声明我的RTT版本是比较低级的是 ```c #define RT_VERSION 4L /**< major version number */ #define RT_SUBVERSION 0L /**< minor version number */ ``` 好吧我承认比现在2.0的要落伍好多,不过我借助此版本已经调好了许多问题,不愿意放弃治疗,故而.... 当然本人是保守派,不爱换编译环境更不爱换版本。 言归正传 首先做了2测试 ## 测试一: 线程分配 1、TCPIP线程、 2、开ETX/RX线程, 3、然后再开一个TCP的应用连接接收PC数据线程。 4、开一个10ms UDP广播线程 5、开一个专门发回PC的线程 OK 建立连接开始测试,无论怎么玩都没问题,当然在此之前LWIP还是有点问题,修改后OK。 连续数据收发一个月不会有问题。 ## 测试二: 在以上线程都不变的情况下,增加一个线程用来RF无线的发送。同时增加一个外部中断 开始测试网络数据转无线。 测试发现有时候运行5分钟左右网络死掉,永远不会在连接。 于是开始DEBUG 发现并不是死机,是内存耗尽了。总内存是30K左右,使用了30K,导致了以太网中断后再也不能分配到PBUF。而一直在哪里。于是开始猜测难道有内存泄露的地方?找了一会发现,这仅仅是个表面现象。这个问题有更深层的原因,于是再次debug,发现并不是有内存泄露的地方,而是TCPIP的主线程停止运行。PBUF没有释放的地方,那么问题来了!!为什么TCPIP主线程停止运行???? 第一步 开始找TCP/IP线程运行的依据,当然是由下到上找。流程:以太网中断->发邮箱给ERX线程,ERX线程开始处理判断是否是一个IP包,是发邮箱给TCP/IP主线程。OK,大概流程这样 这样的话就是说要找到ERX的发送时的邮箱,于是找到发送TCPMSG的代码 `if (rt_mb_send(mbox, (rt_uint32_t)msg) == RT_EOK) return ERR_OK;` 一个邮箱进入邮箱后就是RTT的通用方法了,只是句柄不同。 请看如下代码 ```c /* resume suspended thread */ if( !rt_list_isempty(&mb->parent.suspend_thread) ) { rt_ipc_object_resume(&(mb->parent)); /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK; } ``` 这个代码是判断挂起链表是否为空,空的话地址就是一样的嘛,空表示没有挂起的线程会不执行调度程序。也就是说会不切换线程。不空才会调度优先级高的切换之。 正常情况下是会有挂起线程在链表中的。因为在RCV邮箱的时候线程会主动让出。以等待邮箱。 可是这里我测试的却是 “空” 这就导致了TCPIP线程一直无法激活(最起码底层的上不来。上层的邮箱即使发下来吊用没有。)也就直接导致LWIP的不工作,这就是自然的了, 那么问题突然转向变成了;“为什么线程挂起链表为空” 为什么呢?为空肯定是没有线程挂起了?(这里忽略异常修改的情况,一般情况下不可能异常修改的。) 要知道只要线程挂起了肯定这个挂起链表不会为空!无论是持有信号量还是邮箱,都是要挂起的,当然非空邮箱是例外 比如 ```c /* mailbox is empty */ while (mb->entry == 0) ``` 如果邮箱不空就不会挂起来了。但是这又很难解释为何比他优先级低的以太网接收线程还是可以运行的。他没挂起优先级比接收线程还高,却不能运行。只要找到这个问题就离搞定不远了。 问题还得持续的搞下去呀!!! 开始是网络不工作`->`内存增长异常`->`TCPIP没有运行导致PBUF没有FREE.`->`为什么TCPIP不运行`->`发送邮箱的时候没有就绪的线程`->`TCPIP优先级大于RX线程为毛不运行? 再或者不运行你挂起,为毛挂起表中没有你? 最后就是TCPIP线程即不再挂起表中,自己也不运行,任凭优先级比他低的RX呼呼的跑,值得注意的是所有的线程中只有空闲线程和RX线程还有中断是活动的,其他的貌似全部不能动弹。 还需要大量的测试。 此问题还在进一步审理中。请路过打什么指点一二。早日康复啊!
查看更多
13
个回答
默认排序
按发布时间排序
pangwei
2015-05-29
这家伙很懒,什么也没写!
最好先上传你的ipc.c文件
小ARM菜菜
2015-05-29
这家伙很懒,什么也没写!
>最好先上传你的ipc.c文件 没问题 ```c /* * File : ipc.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * [http://www.rt-thread.org/license/LICENSE](http://www.rt-thread.org/license/LICENSE) * * Change Logs: * Date Author Notes * 2006-03-14 Bernard the first version * 2006-04-25 Bernard implement semaphore * 2006-05-03 Bernard add RT_IPC_DEBUG * modify the type of IPC waiting time to rt_int32_t * 2006-05-10 Bernard fix the semaphore take bug and add IPC object * 2006-05-12 Bernard implement mailbox and message queue * 2006-05-20 Bernard implement mutex * 2006-05-23 Bernard implement fast event * 2006-05-24 Bernard implement event * 2006-06-03 Bernard fix the thread timer init bug * 2006-06-05 Bernard fix the mutex release bug * 2006-06-07 Bernard fix the message queue send bug * 2006-08-04 Bernard add hook support * 2009-05-21 Yi.qiu fix the sem release bug * 2009-07-18 Bernard fix the event clear bug * 2009-09-09 Bernard remove fast event and fix ipc release bug * 2009-10-10 Bernard change semaphore and mutex value to unsigned value * 2009-10-25 Bernard change the mb/mq receive timeout to 0 if the * re-calculated delta tick is a negative number. * 2009-12-16 Bernard fix the rt_ipc_object_suspend issue when IPC flag * is RT_IPC_FLAG_PRIO * 2010-01-20 mbbill remove rt_ipc_object_decrease function. * 2010-04-20 Bernard move memcpy outside interrupt disable in mq * 2010-10-26 yi.qiu add module support in rt_mp_delete and rt_mq_delete * 2010-11-10 Bernard add IPC reset command implementation. */ #include
#include
#include "kservice.h" /* #define RT_IPC_DEBUG */ #ifdef RT_USING_HOOK extern void (*rt_object_trytake_hook)(struct rt_object* object); extern void (*rt_object_take_hook)(struct rt_object* object); extern void (*rt_object_put_hook)(struct rt_object* object); #endif /** * @addtogroup IPC */ /*@{*/ /** * This function will initialize an IPC object * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc) { /* init ipc object */ rt_list_init(&(ipc->suspend_thread)); return RT_EOK; } /** * This function will suspend a thread for a specified IPC object and put the * thread into suspend queue of IPC object * * @param ipc the IPC object * @param thread the thread object to be suspended * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_suspend(struct rt_ipc_object *ipc, struct rt_thread *thread) { /* suspend thread */ rt_thread_suspend(thread); switch (ipc->parent.flag) { case RT_IPC_FLAG_FIFO: rt_list_insert_before(&(ipc->suspend_thread), &(thread->tlist)); break; case RT_IPC_FLAG_PRIO: { struct rt_list_node* n; struct rt_thread* sthread; /* find a suitable position */ for (n = ipc->suspend_thread.next; n != &(ipc->suspend_thread); n = n->next) { sthread = rt_list_entry(n, struct rt_thread, tlist); /* find out */ if (thread->current_priority < sthread->current_priority) { /* insert this thread before the sthread */ rt_list_insert_before(&(sthread->tlist), &(thread->tlist)); break; } } /* not found a suitable position, append to the end of suspend_thread list */ if (n == &(ipc->suspend_thread)) rt_list_insert_before(&(ipc->suspend_thread), &(thread->tlist)); } break; } return RT_EOK; } /** * This function will resume a thread from an IPC object: * - remove the thread from suspend queue of IPC object * - put the thread into system ready queue * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_resume(struct rt_ipc_object* ipc) { struct rt_thread *thread; /* get thread entry */ thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist); #ifdef RT_IPC_DEBUG rt_kprintf("resume thread:%s ", thread->name); #endif /* resume it */ rt_thread_resume(thread); return RT_EOK; } /** * This function will resume all suspended threads in an IPC object. * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */ rt_inline rt_err_t rt_ipc_object_resume_all(struct rt_ipc_object* ipc) { struct rt_thread* thread; register rt_ubase_t temp; /* wakeup all suspend threads */ while (!rt_list_isempty(&(ipc->suspend_thread))) { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* * resume thread * In rt_thread_resume function, it will remove current thread from * suspend list */ rt_thread_resume(thread); /* enable interrupt */ rt_hw_interrupt_enable(temp); } return RT_EOK; } #ifdef RT_USING_SEMAPHORE /** * This function will initialize a semaphore and put it under control of resource * management. * * @param sem the semaphore object * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the operation status, RT_EOK on successful */ rt_err_t rt_sem_init (rt_sem_t sem, const char* name, rt_uint32_t value, rt_uint8_t flag) { RT_ASSERT(sem != RT_NULL); /* init object */ rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name); /* init ipc object */ rt_ipc_object_init(&(sem->parent)); /* set init value */ sem->value = value; /* set parent */ sem->parent.parent.flag = flag; return RT_EOK; } /** * This function will detach a semaphore from resource management * * @param sem the semaphore object * * @return the operation status, RT_EOK on successful * * @see rt_sem_delete */ rt_err_t rt_sem_detach (rt_sem_t sem) { RT_ASSERT(sem != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(sem->parent)); /* detach semaphore object */ rt_object_detach(&(sem->parent.parent)); return RT_EOK; } #ifdef RT_USING_HEAP /** * This function will create a semaphore from system resource * * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the created semaphore, RT_NULL on error happen * * @see rt_sem_init */ rt_sem_t rt_sem_create (const char* name, rt_uint32_t value, rt_uint8_t flag) { rt_sem_t sem; /* allocate object */ sem = (rt_sem_t) rt_object_allocate(RT_Object_Class_Semaphore, name); if (sem == RT_NULL) return sem; /* init ipc object */ rt_ipc_object_init(&(sem->parent)); /* set init value */ sem->value = value; /* set parent */ sem->parent.parent.flag = flag; return sem; } /** * This function will delete a semaphore object and release the memory * * @param sem the semaphore object * * @return the error code * * @see rt_sem_detach */ rt_err_t rt_sem_delete (rt_sem_t sem) { RT_ASSERT(sem != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(sem->parent)); /* delete semaphore object */ rt_object_delete(&(sem->parent.parent)); return RT_EOK; } #endif /** * This function will take a semaphore, if the semaphore is unavailable, the * thread shall wait for a specified time. * * @param sem the semaphore object * @param time the waiting time * * @return the error code */ rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time) { register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(sem != RT_NULL); #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(sem->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); #ifdef RT_IPC_DEBUG rt_kprintf("thread %s take sem:%s, which value is: %d ", rt_thread_self()->name, ((struct rt_object*)sem)->name, sem->value); #endif if (sem->value > 0) { /* semaphore is available */ sem->value --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } else { /* no waiting, return with timeout */ if (time == 0 ) { rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* semaphore is unavailable, push to suspend list */ /* get current thread */ thread = rt_thread_self(); /* reset thread error number */ thread->error = RT_EOK; #ifdef RT_IPC_DEBUG rt_kprintf("sem take: suspend thread - %s ", thread->name); #endif /* suspend thread */ rt_ipc_object_suspend(&(sem->parent), thread); /* has waiting time, start thread timer */ if (time > 0) { #ifdef RT_IPC_DEBUG rt_kprintf("set thread:%s to timer list ", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { return thread->error; } } } #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(sem->parent.parent)); #endif return RT_EOK; } /** * This function will try to take a semaphore and immediately return * * @param sem the semaphore object * * @return the error code */ rt_err_t rt_sem_trytake(rt_sem_t sem) { return rt_sem_take(sem, 0); } /** * This function will release a semaphore, if there are threads suspended on * semaphore, it will be waked up. * * @param sem the semaphore object * * @return the error code */ rt_err_t rt_sem_release(rt_sem_t sem) { register rt_base_t temp; register rt_bool_t need_schedule; #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(sem->parent.parent)); #endif need_schedule = RT_FALSE; /* disable interrupt */ temp = rt_hw_interrupt_disable(); #ifdef RT_IPC_DEBUG rt_kprintf("thread %s releases sem:%s, which value is: %d ", rt_thread_self()->name, ((struct rt_object*)sem)->name, sem->value); #endif if ( !rt_list_isempty(&sem->parent.suspend_thread) ) { /* resume the suspended thread */ rt_ipc_object_resume(&(sem->parent)); need_schedule = RT_TRUE; } else sem->value ++; /* increase value */ /* enable interrupt */ rt_hw_interrupt_enable(temp); /* resume a thread, re-schedule */ if (need_schedule == RT_TRUE) rt_schedule(); return RT_EOK; } /** * This function can get or set some extra attributions of a semaphore object. * * @param sem the semaphore object * @param cmd the execution command * @param arg the execution argument * * @return the error code */ rt_err_t rt_sem_control(rt_sem_t sem, rt_uint8_t cmd, void* arg) { rt_ubase_t level; RT_ASSERT(sem != RT_NULL); if (cmd == RT_IPC_CMD_RESET) { rt_uint32_t value; /* get value */ value = (rt_uint32_t)arg; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* resume all waiting thread */ rt_ipc_object_resume_all(&sem->parent); /* set new value */ sem->value = (rt_uint16_t)value; /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_EOK; } return -RT_ERROR; } #endif /* end of RT_USING_SEMAPHORE */ #ifdef RT_USING_MUTEX /** * This function will initialize a mutex and put it under control of resource * management. * * @param mutex the mutex object * @param name the name of mutex * @param flag the flag of mutex * * @return the operation status, RT_EOK on successful */ rt_err_t rt_mutex_init (rt_mutex_t mutex, const char* name, rt_uint8_t flag) { RT_ASSERT(mutex != RT_NULL); /* init object */ rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name); /* init ipc object */ rt_ipc_object_init(&(mutex->parent)); mutex->value = 1; mutex->owner = RT_NULL; mutex->original_priority = 0xFF; mutex->hold = 0; /* set flag */ mutex->parent.parent.flag = flag; return RT_EOK; } /** * This function will detach a mutex from resource management * * @param mutex the mutex object * * @return the operation status, RT_EOK on successful * * @see rt_mutex_delete */ rt_err_t rt_mutex_detach (rt_mutex_t mutex) { RT_ASSERT(mutex != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(mutex->parent)); /* detach semaphore object */ rt_object_detach(&(mutex->parent.parent)); return RT_EOK; } #ifdef RT_USING_HEAP /** * This function will create a mutex from system resource * * @param name the name of mutex * @param flag the flag of mutex * * @return the created mutex, RT_NULL on error happen * * @see rt_mutex_init */ rt_mutex_t rt_mutex_create (const char* name, rt_uint8_t flag) { struct rt_mutex *mutex; /* allocate object */ mutex = (rt_mutex_t) rt_object_allocate(RT_Object_Class_Mutex, name); if (mutex == RT_NULL) return mutex; /* init ipc object */ rt_ipc_object_init(&(mutex->parent)); mutex->value = 1; mutex->owner = RT_NULL; mutex->original_priority = 0xFF; mutex->hold = 0; /* set flag */ mutex->parent.parent.flag = flag; return mutex; } /** * This function will delete a mutex object and release the memory * * @param mutex the mutex object * * @return the error code * * @see rt_mutex_detach */ rt_err_t rt_mutex_delete (rt_mutex_t mutex) { RT_ASSERT(mutex != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(mutex->parent)); /* delete semaphore object */ rt_object_delete(&(mutex->parent.parent)); return RT_EOK; } #endif /** * This function will take a mutex, if the mutex is unavailable, the * thread shall wait for a specified time. * * @param mutex the mutex object * @param time the waiting time * * @return the error code */ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time) { register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(mutex != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get current thread */ thread = rt_thread_self(); #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mutex->parent.parent)); #endif #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: current thread %s, mutex value: %d, hold: %d ", thread->name, mutex->value, mutex->hold); #endif /* reset thread error */ thread->error = RT_EOK; if (mutex->owner == thread) { /* it's the same thread */ mutex->hold ++; } else { /* in initialization status, the value is 1. Therefore, if the * value is great than 1, which indicates the mutex is avaible. */ if (mutex->value > 0) { /* mutex is available */ mutex->value --; /* set mutex owner and original priority */ mutex->owner = thread; mutex->original_priority = thread->current_priority; mutex->hold ++; } else { /* no waiting, return with timeout */ if (time == 0 ) { /* set error as timeout */ thread->error = -RT_ETIMEOUT; /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* mutex is unavailable, push to suspend list */ #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: suspend thread: %s ", thread->name); #endif /* change the owner thread priority of mutex */ if (thread->current_priority < mutex->owner->current_priority) { /* change the owner thread priority */ rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &thread->current_priority); } /* suspend current thread */ rt_ipc_object_suspend(&(mutex->parent), thread); /* has waiting time, start thread timer */ if (time > 0) { #ifdef RT_IPC_DEBUG rt_kprintf("mutex_take: start the timer of thread:%s ", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { /* return error */ return thread->error; } else { /* the mutex is taken successfully. */ /* disable interrupt */ temp = rt_hw_interrupt_disable(); } } } } /* enable interrupt */ rt_hw_interrupt_enable(temp); #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(mutex->parent.parent)); #endif return RT_EOK; } /** * This function will release a mutex, if there are threads suspended on mutex, * it will be waked up. * * @param mutex the mutex object * * @return the error code */ rt_err_t rt_mutex_release(rt_mutex_t mutex) { register rt_base_t temp; struct rt_thread* thread; rt_bool_t need_schedule; need_schedule = RT_FALSE; /* get current thread */ thread = rt_thread_self(); /* disable interrupt */ temp = rt_hw_interrupt_disable(); #ifdef RT_IPC_DEBUG rt_kprintf("mutex_release:current thread %s, mutex value: %d, hold: %d ", thread->name, mutex->value, mutex->hold); #endif #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mutex->parent.parent)); #endif /* mutex only can be released by owner */ if (thread != mutex->owner) { thread->error = -RT_ERROR; /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_ERROR; } /* decrease hold */ mutex->hold --; /* if no hold */ if (mutex->hold == 0) { /* change the owner thread to original priority */ if (mutex->original_priority != mutex->owner->current_priority) { rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &(mutex->original_priority)); } /* wakeup suspended thread */ if( !rt_list_isempty(&mutex->parent.suspend_thread) ) { /* get suspended thread */ thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist); #ifdef RT_IPC_DEBUG rt_kprintf("mutex_release: resume thread: %s ", thread->name); #endif /* set new owner and priority */ mutex->owner = thread; mutex->original_priority = thread->current_priority; mutex->hold ++; /* resume thread */ rt_ipc_object_resume(&(mutex->parent)); need_schedule = RT_TRUE; } else { /* increase value */ mutex->value ++; /* clear owner */ mutex->owner = RT_NULL; mutex->original_priority = 0xff; } } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* perform a schedule */ if (need_schedule == RT_TRUE) rt_schedule(); return RT_EOK; } /** * This function can get or set some extra attributions of a mutex object. * * @param mutex the mutex object * @param cmd the execution command * @param arg the execution argument * * @return the error code */ rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_uint8_t cmd, void* arg) { return -RT_ERROR; } #endif /* end of RT_USING_MUTEX */ #ifdef RT_USING_EVENT /** * This function will initialize an event and put it under control of resource * management. * * @param event the event object * @param name the name of event * @param flag the flag of event * * @return the operation status, RT_EOK on successful */ rt_err_t rt_event_init(rt_event_t event, const char* name, rt_uint8_t flag) { RT_ASSERT(event != RT_NULL); /* init object */ rt_object_init(&(event->parent.parent), RT_Object_Class_Event, name); /* set parent flag */ event->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(event->parent)); /* init event */ event->set = 0; return RT_EOK; } /** * This function will detach an event object from resource management * * @param event the event object * * @return the operation status, RT_EOK on successful */ rt_err_t rt_event_detach(rt_event_t event) { /* parameter check */ RT_ASSERT(event != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all(&(event->parent)); /* detach event object */ rt_object_detach(&(event->parent.parent)); return RT_EOK; } #ifdef RT_USING_HEAP /** * This function will create an event object from system resource * * @param name the name of event * @param flag the flag of event * * @return the created event, RT_NULL on error happen */ rt_event_t rt_event_create (const char* name, rt_uint8_t flag) { rt_event_t event; /* allocate object */ event = (rt_event_t) rt_object_allocate(RT_Object_Class_Event, name); if (event == RT_NULL) return event; /* set parent */ event->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(event->parent)); /* init event */ event->set = 0; return event; } /** * This function will delete an event object and release the memory * * @param event the event object * * @return the error code */ rt_err_t rt_event_delete (rt_event_t event) { /* parameter check */ RT_ASSERT(event != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all(&(event->parent)); /* delete event object */ rt_object_delete(&(event->parent.parent)); return RT_EOK; } #endif /** * This function will send an event to the event object, if there are threads * suspended on event object, it will be waked up. * * @param event the event object * @param set the event set * * @return the error code */ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set) { struct rt_list_node *n; struct rt_thread *thread; register rt_ubase_t level; register rt_base_t status; rt_bool_t need_schedule; /* parameter check */ RT_ASSERT(event != RT_NULL); if (set == 0) return -RT_ERROR; need_schedule = RT_FALSE; #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(event->parent.parent)); #endif /* disable interrupt */ level = rt_hw_interrupt_disable(); /* set event */ event->set |= set; if( !rt_list_isempty(&event->parent.suspend_thread) ) { /* search thread list to resume thread */ n = event->parent.suspend_thread.next; while (n != &(event->parent.suspend_thread)) { /* get thread */ thread = rt_list_entry(n, struct rt_thread, tlist); status = -RT_ERROR; if (thread->event_info & RT_EVENT_FLAG_AND) { if ((thread->event_set & event->set) == thread->event_set) { /* received an AND event */ status = RT_EOK; } } else if (thread->event_info & RT_EVENT_FLAG_OR) { if (thread->event_set & event->set) { /* save recieved event set */ thread->event_set = thread->event_set & event->set; /* received an OR event */ status = RT_EOK; } } /* move node to the next */ n = n->next; /* condition is satisfied, resume thread */ if (status == RT_EOK) { /* clear event */ if (thread->event_info & RT_EVENT_FLAG_CLEAR) event->set &= ~thread->event_set; /* resume thread, and thread list breaks out */ rt_thread_resume(thread); /* need do a scheduling */ need_schedule = RT_TRUE; } } } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ if (need_schedule == RT_TRUE) rt_schedule(); return RT_EOK; } /** * This function will receive an event from event object, if the event is unavailable, * the thread shall wait for a specified time. * * @param event the fast event object * @param set the interested event set * @param option the receive option * @param timeout the waiting time * @param recved the received event * * @return the error code */ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, rt_uint8_t option, rt_int32_t timeout, rt_uint32_t* recved) { struct rt_thread *thread; register rt_ubase_t level; register rt_base_t status; /* parameter check */ RT_ASSERT(event != RT_NULL); if (set == 0) return -RT_ERROR; /* init status */ status = -RT_ERROR; /* get current thread */ thread = rt_thread_self(); /* reset thread error */ thread->error = RT_EOK; #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(event->parent.parent)); #endif /* disable interrupt */ level = rt_hw_interrupt_disable(); /* check event set */ if (option & RT_EVENT_FLAG_AND) { if ((event->set & set) == set) status = RT_EOK; } else if (option & RT_EVENT_FLAG_OR) { if (event->set & set) status = RT_EOK; } if (status == RT_EOK) { /* set received event */ *recved = (event->set & set); /* received event */ if (option & RT_EVENT_FLAG_CLEAR) event->set &= ~set; } else if (timeout == 0) { /* no waiting */ thread->error = -RT_ETIMEOUT; } else { /* fill thread event info */ thread->event_set = set; thread->event_info = option; /* put thread to suspended thread list */ rt_ipc_object_suspend(&(event->parent), thread); /* if there is a waiting timeout, active thread timer */ if (timeout > 0) { /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ rt_schedule(); if (thread->error != RT_EOK) { /* return error */ return thread->error; } /* received an event, disable interrupt to protect */ level = rt_hw_interrupt_disable(); /* set received event */ *recved = thread->event_set; } /* enable interrupt */ rt_hw_interrupt_enable(level); #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(event->parent.parent)); #endif return thread->error; } /** * This function can get or set some extra attributions of an event object. * * @param event the event object * @param cmd the execution command * @param arg the execution argument * * @return the error code */ rt_err_t rt_event_control (rt_event_t event, rt_uint8_t cmd, void* arg) { rt_ubase_t level; RT_ASSERT(event != RT_NULL); if (cmd == RT_IPC_CMD_RESET) { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* resume all waiting thread */ rt_ipc_object_resume_all(&event->parent); /* init event set */ event->set = 0; /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_EOK; } return -RT_ERROR; } #endif /* end of RT_USING_EVENT */ #ifdef RT_USING_MAILBOX /** * This function will initialize a mailbox and put it under control of resource * management. * * @param mb the mailbox object * @param name the name of mailbox * @param msgpool the begin address of buffer to save received mail * @param size the size of mailbox * @param flag the flag of mailbox * * @return the operation status, RT_EOK on successful */ rt_err_t rt_mb_init(rt_mailbox_t mb, const char* name, void* msgpool, rt_size_t size, rt_uint8_t flag) { RT_ASSERT(mb != RT_NULL); /* init object */ rt_object_init(&(mb->parent.parent), RT_Object_Class_MailBox, name); /* set parent flag */ mb->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(mb->parent)); /* init mailbox */ mb->msg_pool = msgpool; mb->size = size; mb->entry = 0; mb->in_offset = 0; mb->out_offset = 0; return RT_EOK; } /** * This function will detach a mailbox from resource management * * @param mb the mailbox object * * @return the operation status, RT_EOK on successful */ rt_err_t rt_mb_detach(rt_mailbox_t mb) { /* parameter check */ RT_ASSERT(mb != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all(&(mb->parent)); /* detach mailbox object */ rt_object_detach(&(mb->parent.parent)); return RT_EOK; } #ifdef RT_USING_HEAP /** * This function will create a mailbox object from system resource * * @param name the name of mailbox * @param size the size of mailbox * @param flag the flag of mailbox * * @return the created mailbox, RT_NULL on error happen */ rt_mailbox_t rt_mb_create (const char* name, rt_size_t size, rt_uint8_t flag) { rt_mailbox_t mb; /* allocate object */ mb = (rt_mailbox_t) rt_object_allocate(RT_Object_Class_MailBox, name); if (mb == RT_NULL) return mb; /* set parent */ mb->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(mb->parent)); /* init mailbox */ mb->size = size; mb->msg_pool = rt_malloc(mb->size * sizeof(rt_uint32_t)); if (mb->msg_pool == RT_NULL) { /* delete mailbox object */ rt_object_delete(&(mb->parent.parent)); return RT_NULL; } mb->entry = 0; mb->in_offset = 0; mb->out_offset = 0; return mb; } /** * This function will delete a mailbox object and release the memory * * @param mb the mailbox object * * @return the error code */ rt_err_t rt_mb_delete (rt_mailbox_t mb) { /* parameter check */ RT_ASSERT(mb != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all(&(mb->parent)); #ifdef RT_USING_MODULE /* the mb object belongs to an application module */ if(mb->parent.parent.flag & RT_OBJECT_FLAG_MODULE) rt_module_free(mb->parent.parent.module_id, mb->msg_pool); else #endif /* free mailbox pool */ rt_free(mb->msg_pool); /* delete mailbox object */ rt_object_delete(&(mb->parent.parent)); return RT_EOK; } #endif /** * This function will send a mail to mailbox object, if there are threads suspended * on mailbox object, it will be waked up. * * @param mb the mailbox object * @param value the mail * * @return the error code */ rt_err_t rt_mb_send (rt_mailbox_t mb, rt_uint32_t value) { register rt_ubase_t temp; /* parameter check */ RT_ASSERT(mb != RT_NULL); #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mb->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* mailbox is full */ if (mb->entry == mb->size) { /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_EFULL; } /* set ptr */ mb->msg_pool[mb->in_offset] = value; /* increase input offset */ ++ mb->in_offset; mb->in_offset %= mb->size; /* increase message entry */ mb->entry ++; /* resume suspended thread */ if( !rt_list_isempty(&mb->parent.suspend_thread) ) { rt_ipc_object_resume(&(mb->parent)); /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK; } /* enable interrupt */ rt_hw_interrupt_enable(temp); return RT_EOK; } /** * This function will receive a mail from mailbox object, if there is no mail in * mailbox object, the thread shall wait for a specified time. * * @param mb the mailbox object * @param value the received mail will be saved in * @param timeout the waiting time * * @return the error code */ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout) { struct rt_thread *thread; register rt_ubase_t temp; rt_uint32_t tick_delta; /* parameter check */ RT_ASSERT(mb != RT_NULL); tick_delta = 0; #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mb->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get current thread */ thread = rt_thread_self(); /* mailbox is empty */ while (mb->entry == 0) { /* reset error number in thread */ thread->error = RT_EOK; /* no waiting, return timeout */ if (timeout == 0) { /* enable interrupt */ rt_hw_interrupt_enable(temp); thread->error = -RT_ETIMEOUT; return -RT_ETIMEOUT; } /* suspend current thread */ rt_ipc_object_suspend(&(mb->parent), thread); /* has waiting time, start thread timer */ if (timeout > 0) { /* get the start tick of timer */ tick_delta = rt_tick_get(); #ifdef RT_IPC_DEBUG rt_kprintf("mb_recv: start timer of thread:%s ", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* re-schedule */ rt_schedule(); /* resume from suspend state */ if (thread->error != RT_EOK) { /* return error */ return thread->error; } /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* re-calculate timeout tick */ if (timeout > 0) { tick_delta = rt_tick_get() - tick_delta; timeout -= tick_delta; if (timeout < 0) timeout = 0; } } /* fill ptr */ *value = mb->msg_pool[mb->out_offset]; /* increase output offset */ ++mb->out_offset; mb->out_offset %= mb->size; /* decrease message entry */ mb->entry --; /* enable interrupt */ rt_hw_interrupt_enable(temp); #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(mb->parent.parent)); #endif return RT_EOK; } /** * This function can get or set some extra attributions of a mailbox object. * * @param mb the mailbox object * @param cmd the execution command * @param arg the execution argument * * @return the error code */ rt_err_t rt_mb_control(rt_mailbox_t mb, rt_uint8_t cmd, void* arg) { rt_ubase_t level; RT_ASSERT(mb != RT_NULL); if (cmd == RT_IPC_CMD_RESET) { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* resume all waiting thread */ rt_ipc_object_resume_all(&mb->parent); /* re-init mailbox */ mb->entry = 0; mb->in_offset = 0; mb->out_offset = 0; /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_EOK; } return -RT_ERROR; } #endif /* end of RT_USING_MAILBOX */ #ifdef RT_USING_MESSAGEQUEUE struct rt_mq_message { struct rt_mq_message* next; }; /** * This function will initialize a message queue and put it under control of resource * management. * * @param mq the message object * @param name the name of message queue * @param msgpool the beginning address of buffer to save messages * @param msg_size the maximum size of message * @param pool_size the size of buffer to save messages * @param flag the flag of message queue * * @return the operation status, RT_EOK on successful */ rt_err_t rt_mq_init(rt_mq_t mq, const char* name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag) { struct rt_mq_message* head; register rt_base_t temp; /* parameter check */ RT_ASSERT(mq != RT_NULL); /* init object */ rt_object_init(&(mq->parent.parent), RT_Object_Class_MessageQueue, name); /* set parent flag */ mq->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(mq->parent)); /* set messasge pool */ mq->msg_pool = msgpool; /* get correct message size */ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); mq->max_msgs = pool_size / (mq->msg_size + sizeof(struct rt_mq_message)); /* init message list */ mq->msg_queue_head = RT_NULL; mq->msg_queue_tail = RT_NULL; /* init message empty list */ mq->msg_queue_free = RT_NULL; for (temp = 0; temp < mq->max_msgs; temp ++) { head = (struct rt_mq_message*)((rt_uint8_t*)mq->msg_pool + temp * (mq->msg_size + sizeof(struct rt_mq_message))); head->next = mq->msg_queue_free; mq->msg_queue_free = head; } /* the initial entry is zero */ mq->entry = 0; return RT_EOK; } /** * This function will detach a message queue object from resource management * * @param mq the message queue object * * @return the operation status, RT_EOK on successful */ rt_err_t rt_mq_detach(rt_mq_t mq) { /* parameter check */ RT_ASSERT(mq != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all((struct rt_ipc_object*)mq); /* detach message queue object */ rt_object_detach(&(mq->parent.parent)); return RT_EOK; } #ifdef RT_USING_HEAP /** * This function will create a message queue object from system resource * * @param name the name of message queue * @param msg_size the size of message * @param max_msgs the maximum number of message in queue * @param flag the flag of message queue * * @return the created message queue, RT_NULL on error happen */ rt_mq_t rt_mq_create (const char* name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag) { struct rt_messagequeue* mq; struct rt_mq_message* head; register rt_base_t temp; /* allocate object */ mq = (rt_mq_t) rt_object_allocate(RT_Object_Class_MessageQueue, name); if (mq == RT_NULL) return mq; /* set parent */ mq->parent.parent.flag = flag; /* init ipc object */ rt_ipc_object_init(&(mq->parent)); /* init message queue */ /* get correct message size */ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); mq->max_msgs = max_msgs; /* allocate message pool */ mq->msg_pool = rt_malloc((mq->msg_size + sizeof(struct rt_mq_message))* mq->max_msgs); if (mq->msg_pool == RT_NULL) { rt_mq_delete(mq); return RT_NULL; } /* init message list */ mq->msg_queue_head = RT_NULL; mq->msg_queue_tail = RT_NULL; /* init message empty list */ mq->msg_queue_free = RT_NULL; for (temp = 0; temp < mq->max_msgs; temp ++) { head = (struct rt_mq_message*)((rt_uint8_t*)mq->msg_pool + temp * (mq->msg_size + sizeof(struct rt_mq_message))); head->next = mq->msg_queue_free; mq->msg_queue_free = head; } /* the initial entry is zero */ mq->entry = 0; return mq; } /** * This function will delete a message queue object and release the memory * * @param mq the message queue object * * @return the error code */ rt_err_t rt_mq_delete (rt_mq_t mq) { /* parameter check */ RT_ASSERT(mq != RT_NULL); /* resume all suspended thread */ rt_ipc_object_resume_all(&(mq->parent)); #ifdef RT_USING_MODULE /* the mq object belongs to an application module */ if(mq->parent.parent.flag & RT_OBJECT_FLAG_MODULE) rt_module_free(mq->parent.parent.module_id, mq->msg_pool); else #endif /* free message queue pool */ rt_free(mq->msg_pool); /* delete message queue object */ rt_object_delete(&(mq->parent.parent)); return RT_EOK; } #endif /** * This function will send a message to message queue object, if there are threads * suspended on message queue object, it will be waked up. * * @param mq the message queue object * @param buffer the message * @param size the size of buffer * * @return the error code */ rt_err_t rt_mq_send (rt_mq_t mq, void* buffer, rt_size_t size) { register rt_ubase_t temp; struct rt_mq_message *msg; /* greater than one message size */ if (size > mq->msg_size) return -RT_ERROR; #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mq->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get a free list, there must be an empty item */ msg = (struct rt_mq_message*)mq->msg_queue_free; /* message queue is full */ if (msg == RT_NULL) { /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_EFULL; } /* move free list pointer */ mq->msg_queue_free = msg->next; /* enable interrupt */ rt_hw_interrupt_enable(temp); /* copy buffer */ rt_memcpy(msg + 1, buffer, size); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* link msg to message queue */ if (mq->msg_queue_tail != RT_NULL) { /* if the tail exists, */ ((struct rt_mq_message*)mq->msg_queue_tail)->next = msg; } /* the msg is the new tail of list, the next shall be NULL */ msg->next = RT_NULL; /* set new tail */ mq->msg_queue_tail = msg; /* if the head is empty, set head */ if (mq->msg_queue_head == RT_NULL)mq->msg_queue_head = msg; /* increase message entry */ mq->entry ++; /* resume suspended thread */ if( !rt_list_isempty(&mq->parent.suspend_thread) ) { rt_ipc_object_resume(&(mq->parent)); /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK; } /* enable interrupt */ rt_hw_interrupt_enable(temp); return RT_EOK; } /** * This function will send urgently a message to message queue object, which means * the message will be inserted to the head of message queue. If there are threads * suspended on message queue object, it will be waked up. * * @param mq the message queue object * @param buffer the message * @param size the size of buffer * * @return the error code */ rt_err_t rt_mq_urgent(rt_mq_t mq, void* buffer, rt_size_t size) { register rt_ubase_t temp; struct rt_mq_message *msg; /* greater than one message size */ if (size > mq->msg_size) return -RT_ERROR; #ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mq->parent.parent)); #endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* get a free list, there must be an empty item */ msg = (struct rt_mq_message*)mq->msg_queue_free; /* message queue is full */ if (msg == RT_NULL) { /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_EFULL; } /* move free list pointer */ mq->msg_queue_free = msg->next; /* enable interrupt */ rt_hw_interrupt_enable(temp); /* copy buffer */ rt_memcpy(msg + 1, buffer, size); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* link msg to the beginning of message queue */ msg->next = mq->msg_queue_head; mq->msg_queue_head = msg; /* if there is no tail */ if (mq->msg_queue_tail == RT_NULL) mq->msg_queue_tail = msg; /* increase message entry */ mq->entry ++; /* resume suspended thread */ if( !rt_list_isempty(&mq->parent.suspend_thread) ) { rt_ipc_object_resume(&(mq->parent)); /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK; } /* enable interrupt */ rt_hw_interrupt_enable(temp); return RT_EOK; } /** * This function will receive a message from message queue object, if there is no * message in message queue object, the thread shall wait for a specified time. * * @param mq the message queue object * @param buffer the received message will be saved in * @param size the size of buffer * @param timeout the waiting time * * @return the error code */ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeout) { struct rt_thread *thread; register rt_ubase_t temp; struct rt_mq_message *msg; rt_uint32_t tick_delta; #ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mq->parent.parent)); #endif tick_delta = 0; /* get current thread */ thread = rt_thread_self(); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* message queue is empty */ while (mq->entry == 0) { /* reset error number in thread */ thread->error = RT_EOK; /* no waiting, return timeout */ if (timeout == 0) { /* enable interrupt */ rt_hw_interrupt_enable(temp); thread->error = -RT_ETIMEOUT; return -RT_ETIMEOUT; } /* suspend current thread */ rt_ipc_object_suspend(&(mq->parent), thread); /* has waiting time, start thread timer */ if (timeout > 0) { /* get the start tick of timer */ tick_delta = rt_tick_get(); #ifdef RT_IPC_DEBUG rt_kprintf("set thread:%s to timer list ", thread->name); #endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* re-schedule */ rt_schedule(); /* recv message */ if (thread->error != RT_EOK) { /* return error */ return thread->error; } /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* re-calculate timeout tick */ if (timeout > 0) { tick_delta = rt_tick_get() - tick_delta; timeout -= tick_delta; if (timeout < 0) timeout = 0; } } /* get message from queue */ msg = (struct rt_mq_message*) mq->msg_queue_head; /* move message queue head */ mq->msg_queue_head = msg->next; /* reach queue tail, set to NULL */ if (mq->msg_queue_tail == msg) mq->msg_queue_tail = RT_NULL; /* decrease message entry */ mq->entry --; /* enable interrupt */ rt_hw_interrupt_enable(temp); /* copy message */ rt_memcpy(buffer, msg + 1, size > mq->msg_size? mq->msg_size : size); /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* put message to free list */ msg->next = (struct rt_mq_message*)mq->msg_queue_free; mq->msg_queue_free = msg; /* enable interrupt */ rt_hw_interrupt_enable(temp); #ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(mq->parent.parent)); #endif return RT_EOK; } /** * This function can get or set some extra attributions of a message queue object. * * @param mq the message queue object * @param cmd the execution command * @param arg the execution argument * * @return the error code */ rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void* arg) { rt_ubase_t level; struct rt_mq_message *msg; RT_ASSERT(mq != RT_NULL); if (cmd == RT_IPC_CMD_RESET) { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* resume all waiting thread */ rt_ipc_object_resume_all(&mq->parent); /* release all message in the queue */ while (mq->msg_queue_head != RT_NULL) { /* get message from queue */ msg = (struct rt_mq_message*) mq->msg_queue_head; /* move message queue head */ mq->msg_queue_head = msg->next; /* reach queue tail, set to NULL */ if (mq->msg_queue_tail == msg) mq->msg_queue_tail = RT_NULL; /* put message to free list */ msg->next = (struct rt_mq_message*)mq->msg_queue_free; mq->msg_queue_free = msg; } /* clean entry */ mq->entry = 0; /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_EOK; } return -RT_ERROR; } #endif /* end of RT_USING_MESSAGEQUEUE */ /*@}*/ ```
小ARM菜菜
2015-05-29
这家伙很懒,什么也没写!
最新进展,是在ERX中加入list_thread();之后进入那种故障之后查看线程,发现TCPIP线程状态为挂起。这证明IPC的状态说谎了。
小ARM菜菜
2015-05-29
这家伙很懒,什么也没写!
目前只要找到TCP/IP线程错误的挂在那个IPC上。一般情况下要挂在ERX上面才好,这样才可以驱动后面的。收发。错就错在不该挂到别的地方,且锁死了。找到这个挂在那里的是个问题。TCPIP的邮箱是3个,收发信号量2个,用于socket的每个一个。都有可能挂在上面。估计要一个一个找了。这可能还是网上说的那个问题,TCPIP死锁,
小ARM菜菜
2015-05-30
这家伙很懒,什么也没写!
我把TCPIP线程和网络的应用线程的优先级调整后OK。 这个问题可能就是之前有人说的TCPIP线程挂起在op_comple这信号上,造成的死锁 至于到底是不是我还需要验证。 不国有一点肯定 1、必须尽最快的速度取走TCP/IP发给上层的邮箱,不要让TCPIP挂起在这个邮箱上,而是要让TCP/IP挂起在ERX投递的邮箱上面。 2、这样的话就是应用线程必须高于TCPIP线程。TCPIP高于ERX/etx。 这样一旦TCPIP投递给APP,APP第一时间处理完毕释放信号,转而挂起到ERX投递邮箱处。就不会出现锁死的问题。 反正现在调整后OK了 后续一定要找到到底是谁导致了死锁。尅肯定的是一定是TCPIP和APP接口的地方有问题。
sync
2019-02-28
这家伙很懒,什么也没写!
>我把TCPIP线程和网络的应用线程的优先级调整后OK。 >这个问题可能就是之前有人说的TCPIP线程挂起在op_comple ... 我也遇到tcpip线程超时挂起问题,挂起后不会再继续执行,导致erx接收的数据,不停的申请内存,最后就是tcpip_inpkt函数里面的 ```c msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); ``` 这句会申请内存失败 因为tcpip线程始终无法执行。 不知道如何处理了。。。。
fhqmcu
认证专家
2019-03-03
个人博客:https://blog.csdn.net/fhqlongteng
最近我好像也遇到你的这个问题,系统版本为4.0.0,使用的是at_socket模块, `at_client.c`中的`client_parser`线程,处于就绪状态,它请求的信号量也有值,但是无法运行,但是这个线程不能被调试器调度,线程无法运行了。正在查找定位程序的问题。 ``` list_thread msh />list_thread thread pri status sp stack size max used left tick error -------- --- ------- ---------- ---------- ------ ---------- --- one_net 10 suspend 0x000003fc 0x00000800 57% 0x00000006 000 decoder 10 suspend 0x000000ac 0x00000400 16% 0x00000002 000 tshell 20 running 0x00000104 0x00001000 12% 0x00000001 000 at_clnt 9 ready 0x00000090 0x00000600 18% 0x00000002 000 ---就是这个线程,无法被操作系统调试运行了。 tidle0 31 ready 0x00000044 0x00000100 35% 0x00000018 000 main 10 suspend 0x00000130 0x00000800 21% 0x0000000e 000 ```
独角戏
2019-03-05
这家伙很懒,什么也没写!
哈哈,好多人出现这个问题
独角戏
2019-03-05
这家伙很懒,什么也没写!
我上一周折腾了一周
独角戏
2019-03-05
这家伙很懒,什么也没写!
[https://www.rt-thread.org/qa/thread-10257-1-1.html](https://www.rt-thread.org/qa/thread-10257-1-1.html) 可以参考这个帖子,重新从git下载rttthread
撰写答案
登录
注册新账号
关注者
0
被浏览
3.2k
关于作者
小ARM菜菜
这家伙很懒,什么也没写!
提问
10
回答
55
被采纳
0
关注TA
发私信
相关问题
1
请教cpu使用率分析
2
选择FreeRTOS, 还是RT-Thread。
3
thread heap stack overflow ?
4
rtt消息队列delay问题
5
释放被删除线程的内存地方在哪里啊
6
请教:各线程结束后,释放其中的内存的连续性问题
7
STM32F103中断关于信号量、邮箱问题
8
RTT中的线程栈大小如何控制
9
关于线程由执行态变为挂起态的代码实现,,,
10
rt_malloc(rt_size_t size)内存分配函数最小分配尺寸问题
推荐文章
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
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
2
RT-Thread EtherKit开源以太网硬件正式发布
3
如何在master上的BSP中添加配置yml文件
4
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
5
RT-Thread 发布 EtherKit开源以太网硬件!
热门标签
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
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
MicroPython
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
19
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
6
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部