1 //*****************************************************************************
2 //
3 //! @file am_hal_queue.h
4 //!
5 //! @brief Functions for implementing a queue system.
6 //!
7 //! @addtogroup Miscellaneous3 Queue - Software Features (MISC)
8 //! @ingroup apollo3p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 #ifndef AM_HAL_QUEUE_H
48 #define AM_HAL_QUEUE_H
49 
50 //*****************************************************************************
51 //
52 //! @brief A data structure that will operate as a queue.
53 //!
54 //! This data structure holds information necessary for operating a thread-safe
55 //! queue. When declaring a structure of type am_hal_queue_t, you will also need
56 //! to provide some working memory for the queue to use. For more information on
57 //! setting up and using the am_hal_queue_t structure, please see the
58 //! documentation for am_hal_queue_init().
59 //
60 //*****************************************************************************
61 typedef struct
62 {
63     volatile uint32_t ui32WriteIndex;
64     volatile uint32_t ui32ReadIndex;
65     volatile uint32_t ui32Length;
66     uint32_t ui32Capacity;
67     uint32_t ui32ItemSize;
68     uint8_t *pui8Data;
69 }
70 am_hal_queue_t;
71 
72 //*****************************************************************************
73 //
74 // Function-like macros.
75 //
76 //*****************************************************************************
77 
78 //
79 //! Returns true if the queue is empty.
80 //
81 #define am_hal_queue_empty(psQueue)                                           \
82     ((psQueue)->ui32Length == 0)
83 
84 //
85 //! Returns true if the queue is full.
86 //
87 #define am_hal_queue_full(psQueue)                                            \
88     ((psQueue)->ui32Length == (psQueue)->ui32Capacity)
89 
90 //
91 //! Returns the amount of space left in the queue (in bytes).
92 //
93 #define am_hal_queue_space_left(psQueue)                                      \
94     ((psQueue)->ui32Capacity - (psQueue)->ui32Length)
95 
96 //
97 //! Returns the number of configured items that will fit in the queue.
98 //
99 #define am_hal_queue_slots_left(psQueue)                                      \
100     (((psQueue)->ui32Capacity - (psQueue)->ui32Length)                        \
101      / (psQueue)->ui32ItemSize)
102 
103 //
104 //! Returns the amount of data in the queue (in bytes).
105 //
106 #define am_hal_queue_data_left(psQueue)                                       \
107     ((psQueue)->ui32Length)
108 
109 //
110 //! Returns the number of configured items left in the queue.
111 //
112 #define am_hal_queue_items_left(psQueue)                                      \
113     ((psQueue)->ui32Length / (psQueue)->ui32ItemSize)
114 
115 //
116 //! Can be used as a pointer to the next item to be read from the queue.
117 //
118 #define am_hal_queue_peek(psQueue)                                            \
119     ((void *) &((psQueue)->pui8Data[(psQueue)->ui32ReadIndex]))
120 
121 //
122 //! Can be used as a pointer to the next available slot in the queue memory.
123 //
124 #define am_hal_queue_next_slot(psQueue)                                       \
125     ((void *) &((psQueue)->pui8Data[(psQueue)->ui32WriteIndex]))
126 
127 //*****************************************************************************
128 //
129 //! Use this to make sure you get the size parameters right.
130 //
131 //*****************************************************************************
132 #define am_hal_queue_from_array(queue, array)                                 \
133     am_hal_queue_init((queue), (array), sizeof((array)[0]), sizeof(array))
134 
135 #ifdef __cplusplus
136 extern "C"
137 {
138 #endif
139 
140 //*****************************************************************************
141 //
142 // External function definitions.
143 //
144 //*****************************************************************************
145 //*****************************************************************************
146 //
147 //! @brief Initializes a queue.
148 //!
149 //! @param psQueue - Pointer to a queue structure.
150 //! @param pvData - Pointer to a memory location to be used for data storage.
151 //! @param ui32ItemSize - Number of bytes per item in the queue.
152 //! @param ui32ArraySize - Number of bytes in the data array.
153 //!
154 //! This function initializes the members of a queue structure and attaches it
155 //! to an array of memory that it can use for storage.\n
156 //! This function should be called before the queue is used.
157 //!
158 //! In this example, we are creating a queue that can hold 1024 32-bit
159 //! integers.\n
160 //! The integers themselves will be stored in the array named pui32WorkingSpace,
161 //! while information about the queue itself will be stored in sDataQueue.
162 //!
163 //! @note The caller should not modify any of the members of am_hal_queue_t
164 //! structures. The queue API will handle these members in a thread-safe way.
165 //! @par
166 //! @note The queue will remember what size data is in it. Other queue API
167 //! functions will perform transfers in units of "items" where one "item" is
168 //! the number of bytes you specify in the \e ui32ItemSize argument upon
169 //! initialization.
170 //!
171 //! Example usage:
172 //!
173 //! @code
174 //!
175 //! //
176 //! // Declare a queue structure and an array of bytes we can use to store
177 //! // data.
178 //! //
179 //! am_hal_queue_t sDataQueue;
180 //! uint32_t pui32WorkingSpace[1024];
181 //!
182 //! //
183 //! // Attach the queue structure to the working memory.
184 //! //
185 //! am_hal_queue_init(&sDataQueue, pui8WorkingSpace, sizeof(uint32_t)
186 //!                   sizeof(pui32WorkingSpace));
187 //!
188 //! @endcode
189 //!
190 //! The am_hal_queue_from_array macro is a convenient shorthand for this
191 //! operation. The code below does the same thing as the code above.
192 //!
193 //! @code
194 //!
195 //!
196 //! // Declare a queue structure and an array of bytes we can use to store
197 //! // data.
198 //! //
199 //! am_hal_queue_t sDataQueue;
200 //! uint32_t pui32WorkingSpace[1024];
201 //!
202 //! //
203 //! // Attach the queue structure to the working memory.
204 //! //
205 //! am_hal_queue_from_array(&sDataQueue, pui8WorkingSpace);
206 //!
207 //! @endcode
208 //
209 //*****************************************************************************
210 extern void am_hal_queue_init(am_hal_queue_t *psQueue, void *pvData, uint32_t ui32ItemSize, uint32_t ui32ArraySize);
211 
212 //*****************************************************************************
213 //
214 //! @brief Adds an item to the Queue
215 //!
216 //! @param psQueue - Pointer to a queue structure.
217 //! @param pvSource - Pointer to the data to be added.
218 //! @param ui32NumItems - Number of items to be added.
219 //!
220 //! This function will copy the data pointed to by pvSource into the queue. The
221 //! \e ui32NumItems term specifies the number of items to be copied from \e
222 //! pvSource. The size of an "item" depends on how the queue was initialized.
223 //! Please see am_hal_queue_init() for more information on this.
224 //!
225 //! @return true if the add operation was successful, or false if the queue
226 //! didn't have enough space.
227 //
228 //*****************************************************************************
229 extern bool am_hal_queue_item_add(am_hal_queue_t *psQueue, const void *pvSource, uint32_t ui32NumItems);
230 
231 //*****************************************************************************
232 //
233 //! @brief Removes an item from the Queue
234 //!
235 //! @param psQueue - Pointer to a queue structure.
236 //! @param pvDest - Pointer to the data to be added.
237 //! @param ui32NumItems - Number of items to be added.
238 //!
239 //! This function will copy the data from the queue into the memory pointed to
240 //! by pvDest. The \e ui32NumItems term specifies the number of items to be
241 //! copied from the queue. The size of an "item" depends on how the queue was
242 //! initialized.  Please see am_hal_queue_init() for more information on this.
243 //!
244 //! @return true if we were able to pull the requested number of items from the
245 //! queue, or false if the queue didn't have that many items to pull.
246 //
247 //*****************************************************************************
248 extern bool am_hal_queue_item_get(am_hal_queue_t *psQueue, void *pvDest, uint32_t ui32NumItems);
249 
250 #ifdef __cplusplus
251 }
252 #endif
253 
254 #endif // AM_HAL_QUEUE_H
255 
256 //*****************************************************************************
257 //
258 // End Doxygen group.
259 //! @}
260 //
261 //*****************************************************************************
262