1 /*
2  * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the
12  *       distribution.
13  *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "os_queue.h"
31 #include "os_util.h"
32 
33 
34 /**
35  * @brief Create and initialize a queue object
36  * @param[in] queue Pointer to the queue object
37  * @param[in] queueLen The maximum number of items that the queue can hold at
38  *                     any one time.
39  * @param[in] itemSize The size, in bytes, of each data item that can be stored
40  *                     in the queue.
41  * @retval OS_Status, OS_OK on success
42  */
OS_QueueCreate(OS_Queue_t * queue,uint32_t queueLen,uint32_t itemSize)43 OS_Status OS_QueueCreate(OS_Queue_t *queue, uint32_t queueLen, uint32_t itemSize)
44 {
45 //  OS_HANDLE_ASSERT(!OS_QueueIsValid(queue), queue->handle);
46 
47     queue->handle = rt_mq_create("os_mq", itemSize, queueLen, RT_IPC_FLAG_FIFO);
48 
49     OS_DBG("%s(), handle %p\n", __func__, queue->handle);
50 
51     if (queue->handle == NULL) {
52         OS_ERR("err %"OS_HANDLE_F"\n", queue->handle);
53         return OS_FAIL;
54     }
55     queue->itemSize = itemSize;
56     return OS_OK;
57 }
58 
59 /**
60  * @brief Delete the queue object
61  * @param[in] queue Pointer to the queue object
62  * @retval OS_Status, OS_OK on success
63  */
OS_QueueDelete(OS_Queue_t * queue)64 OS_Status OS_QueueDelete(OS_Queue_t *queue)
65 {
66     rt_err_t ret;
67 
68     OS_HANDLE_ASSERT(OS_QueueIsValid(queue), queue->handle);
69     OS_DBG("%s(), handle %p\n", __func__, queue->handle);
70 
71     ret = rt_mq_delete(queue->handle);
72     if (ret != RT_EOK) {
73         OS_ERR("rt_mq_delete(%p) return %ld\n", queue->handle, ret);
74     }
75 
76     OS_QueueSetInvalid(queue);
77     return OS_OK;
78 }
79 
80 /**
81  * @brief Send (write) an item to the back of the queue
82  * @param[in] queue Pointer to the queue object
83  * @param[in] item Pointer to the data to be copied into the queue.
84  *                 The size of each item the queue can hold is set when the
85  *                 queue is created, and that many bytes will be copied from
86  *                 item into the queue storage area.
87  * @param[in] waitMS The maximum amount of time the thread should remain in the
88  *                   blocked state to wait for space to become available on the
89  *                   queue, should the queue already be full.
90  *                   OS_WAIT_FOREVER for waiting forever, zero for no waiting.
91  * @retval OS_Status, OS_OK on success
92  */
OS_QueueSend(OS_Queue_t * queue,const void * item,OS_Time_t waitMS)93 OS_Status OS_QueueSend(OS_Queue_t *queue, const void *item, OS_Time_t waitMS)
94 {
95     rt_err_t ret;
96 
97     OS_HANDLE_ASSERT(OS_QueueIsValid(queue), queue->handle);
98 
99     if (waitMS == 0) {
100         ret = rt_mq_send(queue->handle, item, queue->itemSize);
101         if (ret != RT_EOK) {
102             return OS_FAIL;
103         }
104     } else if (waitMS == OS_WAIT_FOREVER) {
105         while (1) {
106             ret = rt_mq_send(queue->handle, item, queue->itemSize);
107             if (ret == RT_EOK) {
108                 break;
109             } else if (ret == -RT_EFULL) {
110                 OS_MSleep(1);
111             } else {
112                 OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
113                 return OS_FAIL;
114             }
115         }
116     } else {
117         rt_tick_t endTick = rt_tick_get() + OS_CalcWaitTicks(waitMS);
118         while (OS_TimeBeforeEqual(rt_tick_get(), endTick)) {
119             ret = rt_mq_send(queue->handle, item, queue->itemSize);
120             if (ret == RT_EOK) {
121                 break;
122             } else if (ret == -RT_EFULL) {
123                 OS_MSleep(1);
124             } else {
125                 OS_DBG("%s() fail @ %d\n", __func__, __LINE__);
126                 return OS_FAIL;
127             }
128         }
129     }
130 
131     return OS_OK;
132 }
133 
134 /**
135  * @brief Receive (read) an item from the queue
136  * @param[in] queue Pointer to the queue object
137  * @param[in] item Pointer to the memory into which the received data will be
138  *                 copied. The length of the buffer must be at least equal to
139  *                 the queue item size which is set when the queue is created.
140  * @param[in] waitMS The maximum amount of time the thread should remain in the
141  *                   blocked state to wait for data to become available on the
142  *                   queue, should the queue already be empty.
143  *                   OS_WAIT_FOREVER for waiting forever, zero for no waiting.
144  * @retval OS_Status, OS_OK on success
145  */
OS_QueueReceive(OS_Queue_t * queue,void * item,OS_Time_t waitMS)146 OS_Status OS_QueueReceive(OS_Queue_t *queue, void *item, OS_Time_t waitMS)
147 {
148     rt_err_t ret;
149 
150     OS_HANDLE_ASSERT(OS_QueueIsValid(queue), queue->handle);
151 
152     ret = rt_mq_recv(queue->handle, item, queue->itemSize, OS_CalcWaitTicks(waitMS));
153     if (ret < 0) {
154         OS_DBG("%s() fail @ %d, %"OS_TIME_F" ms\n", __func__, __LINE__, (unsigned int)waitMS);
155         return OS_FAIL;
156     }
157 
158     return OS_OK;
159 }
160