diff options
Diffstat (limited to 'bsp/apollo2/libraries/drivers/hal/am_hal_queue.c')
| -rw-r--r-- | bsp/apollo2/libraries/drivers/hal/am_hal_queue.c | 286 |
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. +//! @} +// +//***************************************************************************** |
