📄 ipc.c.svn-base
字号:
/* parameter check */ RT_ASSERT(mb != RT_NULL);#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(); /* mailbox is empty */ if (mb->entry == 0) { /* get current thread */ thread = rt_thread_self(); /* 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) {#ifdef IPC_DEBUG rt_kprintf("set thread:%s to timer list\n", 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) /* maybe return RT_ETIMEOUT */ return thread->error; /* disable interrupt */ temp = rt_hw_interrupt_disable(); } /* 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 cmd, void* arg){ return RT_EOK;}#endif /* end of RT_USING_MAILBOX */#ifdef RT_USING_MESSAGEQUEUEstruct 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 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*)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 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 * 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*)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)); /* free mailbox pool */ rt_free(mq->msg_pool); /* delete mailbox 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; /* copy buffer */ rt_memcpy(msg + 1, buffer, size); /* 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 (mq->parent.suspend_thread_count > 0) { rt_ipc_object_resume(&(mq->parent)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); 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; /* copy buffer */ rt_memcpy(msg + 1, buffer, size); /* 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 (mq->parent.suspend_thread_count > 0) { rt_ipc_object_resume(&(mq->parent)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); 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 timeout){ struct rt_thread *thread; register rt_ubase_t temp; struct rt_mq_message *msg;#ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mq->parent.parent));#endif /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* mailbox is empty */ if (mq->entry == 0) { /* get current thread */ thread = rt_thread_self(); /* 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) {#ifdef IPC_DEBUG rt_kprintf("set thread:%s to timer list\n", 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) /* maybe return a RT_ETIMEOUT */ return thread->error; /* disable interrupt */ temp = rt_hw_interrupt_disable(); } /* 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; /* copy message */ rt_memcpy(buffer, msg + 1, size > mq->msg_size? mq->msg_size : size); /* put message to free list */ msg->next = (struct rt_mq_message*)mq->msg_queue_free; mq->msg_queue_free = msg; /* decrease message entry */ mq->entry --; /* 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 cmd, void* arg){ return RT_EOK;}#endif /* end of RT_USING_MESSAGEQUEUE *//** * @ingroup SystemInit * This function will init IPC module. */void rt_system_ipc_init(){ /* nothing to be done */}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -