summaryrefslogtreecommitdiff
path: root/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/apollo2/libraries/drivers/hal/am_hal_queue.c')
-rw-r--r--bsp/apollo2/libraries/drivers/hal/am_hal_queue.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c
new file mode 100644
index 0000000000..66a9846c29
--- /dev/null
+++ b/bsp/apollo2/libraries/drivers/hal/am_hal_queue.c
@@ -0,0 +1,286 @@
+//*****************************************************************************
+//
+// am_hal_queue.c
+//! @file
+//!
+//! @brief Functions for implementing a queue system.
+//!
+//! @addtogroup Miscellaneous2 Software Features (MISC)
+//! @ingroup apollo2hal
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Copyright (c) 2017, Ambiq Micro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// This is part of revision 1.2.9 of the AmbiqSuite Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "am_mcu_apollo.h"
+
+//*****************************************************************************
+//
+//! @brief Initializes a queue.
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvData - Pointer to a memory location to be used for data storage.
+//! @param ui32ItemSize - Number of bytes per item in the queue.
+//! @param ui32ArraySize - Number of bytes in the data array.
+//!
+//! This function initializes the members of a queue structure and attaches it
+//! to an array of memory that it can use for storage. This function should be
+//! called before the queue is used.
+//!
+//! In this example, we are creating a queue that can hold 1024 32-bit
+//! integers. The integers themselves will be stored in the array named
+//! pui32WorkingSpace, while information about the queue itself will be stored
+//! in sDataQueue.
+//!
+//! @note The caller should not modify any of the members of am_hal_queue_t
+//! structures. The queue API will handle these members in a thread-safe way.
+//!
+//! @note The queue will remember what size data is in it. Other queue API
+//! functions will perform transfers in units of "items" where one "item" is
+//! the number of bytes you specify in the \e ui32ItemSize argument upon
+//! initialization.
+//!
+//! Example usage:
+//!
+//! @code
+//!
+//! //
+//! // Declare a queue structure and an array of bytes we can use to store
+//! // data.
+//! //
+//! am_hal_queue_t sDataQueue;
+//! uint32_t pui32WorkingSpace[1024];
+//!
+//! //
+//! // Attach the queue structure to the working memory.
+//! //
+//! am_hal_queue_init(&sDataQueue, pui8WorkingSpace, sizeof(uint32_t)
+//! sizeof(pui32WorkingSpace));
+//!
+//! @endcode
+//!
+//! The am_hal_queue_from_array macro is a convenient shorthand for this
+//! operation. The code below does the same thing as the code above.
+//!
+//! @code
+//!
+//! //
+//! // Declare a queue structure and an array of bytes we can use to store
+//! // data.
+//! //
+//! am_hal_queue_t sDataQueue;
+//! uint32_t pui32WorkingSpace[1024];
+//!
+//! //
+//! // Attach the queue structure to the working memory.
+//! //
+//! am_hal_queue_from_array(&sDataQueue, pui8WorkingSpace);
+//!
+//! @endcode
+//
+//*****************************************************************************
+void
+am_hal_queue_init(am_hal_queue_t *psQueue, void *pvData, uint32_t ui32ItemSize,
+ uint32_t ui32ArraySize)
+{
+ psQueue->ui32WriteIndex = 0;
+ psQueue->ui32ReadIndex = 0;
+ psQueue->ui32Length = 0;
+ psQueue->ui32Capacity = ui32ArraySize;
+ psQueue->ui32ItemSize = ui32ItemSize;
+ psQueue->pui8Data = (uint8_t *) pvData;
+}
+
+//*****************************************************************************
+//
+//! @brief Adds an item to the Queue
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvSource - Pointer to the data to be added.
+//! @param ui32NumItems - Number of items to be added.
+//!
+//! This function will copy the data pointed to by pvSource into the queue. The
+//! \e ui32NumItems term specifies the number of items to be copied from \e
+//! pvSource. The size of an "item" depends on how the queue was initialized.
+//! Please see am_hal_queue_init() for more information on this.
+//!
+//! @return true if the add operation was successful, or false if the queue
+//! didn't have enough space.
+//
+//*****************************************************************************
+bool
+am_hal_queue_item_add(am_hal_queue_t *psQueue, const void *pvSource, uint32_t ui32NumItems)
+{
+ uint32_t i;
+ uint8_t *pui8Source;
+ uint32_t ui32Bytes = ui32NumItems * psQueue->ui32ItemSize;
+ bool bSuccess = false;
+ uint32_t ui32Primask;
+
+ pui8Source = (uint8_t *) pvSource;
+
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ //
+ // Check to make sure that the buffer isn't already full
+ //
+ if ( am_hal_queue_space_left(psQueue) >= ui32Bytes )
+ {
+ //
+ // Loop over the bytes in the source array.
+ //
+ for ( i = 0; i < ui32Bytes; i++ )
+ {
+ //
+ // Write the value to the buffer.
+ //
+ psQueue->pui8Data[psQueue->ui32WriteIndex] = pui8Source[i];
+
+ //
+ // Advance the write index, making sure to wrap if necessary.
+ //
+ psQueue->ui32WriteIndex = ((psQueue->ui32WriteIndex + 1) %
+ psQueue->ui32Capacity);
+ }
+
+ //
+ // Update the length value appropriately.
+ //
+ psQueue->ui32Length += ui32Bytes;
+
+ //
+ // Report a success.
+ //
+ bSuccess = true;
+ }
+ else
+ {
+ //
+ // The buffer can't fit the amount of data requested. Return a
+ // failure.
+ //
+ bSuccess = false;
+ }
+
+ am_hal_interrupt_master_set(ui32Primask);
+
+ return bSuccess;
+}
+
+//*****************************************************************************
+//
+//! @brief Removes an item from the Queue
+//!
+//! @param psQueue - Pointer to a queue structure.
+//! @param pvDest - Pointer to the data to be added.
+//! @param ui32NumItems - Number of items to be added.
+//!
+//! This function will copy the data from the queue into the memory pointed to
+//! by pvDest. The \e ui32NumItems term specifies the number of items to be
+//! copied from the queue. The size of an "item" depends on how the queue was
+//! initialized. Please see am_hal_queue_init() for more information on this.
+//!
+//! @return true if we were able to pull the requested number of items from the
+//! queue, or false if the queue didn't have that many items to pull.
+//
+//*****************************************************************************
+bool
+am_hal_queue_item_get(am_hal_queue_t *psQueue, void *pvDest, uint32_t ui32NumItems)
+{
+ uint32_t i;
+ uint8_t *pui8Dest;
+ uint32_t ui32Bytes = ui32NumItems * psQueue->ui32ItemSize;
+ bool bSuccess = false;
+ uint32_t ui32Primask;
+
+ pui8Dest = (uint8_t *) pvDest;
+
+ ui32Primask = am_hal_interrupt_master_disable();
+
+ //
+ // Check to make sure that the buffer isn't empty
+ //
+ if ( am_hal_queue_data_left(psQueue) >= ui32Bytes )
+ {
+ //
+ // Loop over the bytes in the destination array.
+ //
+ for ( i = 0; i < ui32Bytes; i++ )
+ {
+ //
+ // Grab the next value from the buffer.
+ //
+ pui8Dest[i] = psQueue->pui8Data[psQueue->ui32ReadIndex];
+
+ //
+ // Advance the read index, wrapping if needed.
+ //
+ psQueue->ui32ReadIndex = ((psQueue->ui32ReadIndex + 1) %
+ psQueue->ui32Capacity);
+ }
+
+ //
+ // Adjust the length value to reflect the change.
+ //
+ psQueue->ui32Length -= ui32Bytes;
+
+ //
+ // Report a success.
+ //
+ bSuccess = true;
+ }
+ else
+ {
+ //
+ // If the buffer didn't have enough data, just return false.
+ //
+ bSuccess = false;
+ }
+
+ am_hal_interrupt_master_set(ui32Primask);
+
+ return bSuccess;
+}
+
+//*****************************************************************************
+//
+// End Doxygen group.
+//! @}
+//
+//*****************************************************************************