summaryrefslogtreecommitdiff
path: root/firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c')
-rw-r--r--firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c b/firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c
new file mode 100644
index 0000000..3054812
--- /dev/null
+++ b/firmware/memory_chip_gone/Middlewares/ST/STM32_WPAN/utilities/stm_queue.c
@@ -0,0 +1,383 @@
+/**
+ ******************************************************************************
+ * @file stm_queue.c
+ * @author MCD Application Team
+ * @brief Queue management
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2018-2021 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "utilities_common.h"
+
+#include "stm_queue.h"
+
+/* Private define ------------------------------------------------------------*/
+/* Private typedef -------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+#define MOD(X,Y) (((X) >= (Y)) ? ((X)-(Y)) : (X))
+
+/* Private variables ---------------------------------------------------------*/
+/* Global variables ----------------------------------------------------------*/
+/* Extern variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Public functions ----------------------------------------------------------*/
+
+/**
+ * @brief Initilaiilze queue structure .
+ * @note This function is used to initialize the global queue structure.
+ * @param q: pointer on queue structure to be initialised
+ * @param queueBuffer: pointer on Queue Buffer
+ * @param queueSize: Size of Queue Buffer
+ * @param elementSize: Size of an element in the queue. if =0, the queue will manage variable sizze elements
+ * @retval always 0
+ */
+int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionFlags)
+{
+ q->qBuff = queueBuffer;
+ q->first = 0;
+ q->last = 0; /* queueSize-1; */
+ q->byteCount = 0;
+ q->elementCount = 0;
+ q->queueMaxSize = queueSize;
+ q->elementSize = elementSize;
+ q->optionFlags = optionFlags;
+
+ if ((optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG) && q-> elementSize)
+ {
+ /* can not deal with splitting at the end of buffer with fixed size element */
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * @brief Add element to the queue .
+ * @note This function is used to add one or more element(s) to the Circular Queue .
+ * @param q: pointer on queue structure to be handled
+ * @param X; pointer on element(s) to be added
+ * @param elementSize: Size of element to be added to the queue. Only used if the queue manage variable size elements
+ * @param nbElements: number of elements in the in buffer pointed by x
+ * @retval pointer on last element just added to the queue, NULL if the element to be added do not fit in the queue (too big)
+ */
+uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements)
+{
+
+ uint8_t* ptr = NULL; /* fct return ptr to the element freshly added, if no room fct return NULL */
+ uint16_t curElementSize = 0; /* the size of the element currently stored at q->last position */
+ uint8_t elemSizeStorageRoom = 0 ; /* Indicate the header (which contain only size) of element in case of varaibale size element (q->elementsize == 0) */
+ uint32_t curBuffPosition; /* the current position in the queue buffer */
+ uint32_t i; /* loop counter */
+ uint32_t NbBytesToCopy = 0, NbCopiedBytes = 0 ; /* Indicators for copying bytes in queue */
+ uint32_t eob_free_size; /* Eof End of Quque Buffer Free Size */
+ uint8_t wrap_will_occur = 0; /* indicate if a wrap around will occurs */
+ uint8_t wrapped_element_eob_size; /* In case of Wrap around, indicate size of parta of element that fit at thened of the queuue buffer */
+ uint16_t overhead = 0; /* In case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG or CIRCULAR_QUEUE_NO_WRAP_FLAG options,
+ indcate the size overhead that will be generated by adding the element with wrap management (split or no wrap ) */
+
+
+ elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
+ /* retrieve the size of last element sored: the value stored at the beginning of the queue element if element size is variable otherwise take it from fixed element Size member */
+ if (q->byteCount)
+ {
+ curElementSize = (q->elementSize == 0) ? q->qBuff[q->last] + ((q->qBuff[MOD((q->last+1), q->queueMaxSize)])<<8) + 2 : q->elementSize;
+ }
+ /* if queue element have fixed size , reset the elementSize arg with fixed element size value */
+ if (q->elementSize > 0)
+ {
+ elementSize = q->elementSize;
+ }
+
+ eob_free_size = (q->last >= q->first) ? q->queueMaxSize - (q->last + curElementSize) : 0;
+
+ /* check how many bytes of wrapped element (if anay) are at end of buffer */
+ wrapped_element_eob_size = (((elementSize + elemSizeStorageRoom )*nbElements) < eob_free_size) ? 0 : (eob_free_size % (elementSize + elemSizeStorageRoom));
+ wrap_will_occur = wrapped_element_eob_size > elemSizeStorageRoom;
+
+ overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)) ? wrapped_element_eob_size : overhead;
+ overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)) ? elemSizeStorageRoom : overhead;
+
+
+ /* Store now the elements if ennough room for all elements */
+ if (elementSize && ((q->byteCount + ((elementSize + elemSizeStorageRoom )*nbElements) + overhead) <= q->queueMaxSize))
+ {
+ /* loop to add all elements */
+ for (i=0; i < nbElements; i++)
+ {
+ q->last = MOD ((q->last + curElementSize),q->queueMaxSize);
+ curBuffPosition = q->last;
+
+ /* store the element */
+ /* store first the element size if element size is variable */
+ if (q->elementSize == 0)
+ {
+ q->qBuff[curBuffPosition++]= elementSize & 0xFF;
+ curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
+ q->qBuff[curBuffPosition++]= (elementSize & 0xFF00) >> 8 ;
+ curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
+ q->byteCount += 2;
+ }
+
+ /* Identify number of bytes of copy takeing account possible wrap, in this case NbBytesToCopy will contains size that fit at end of the queue buffer */
+ NbBytesToCopy = MIN((q->queueMaxSize-curBuffPosition),elementSize);
+ /* check if no wrap (NbBytesToCopy == elementSize) or if Wrap and no spsicf option;
+ In this case part of data will copied at the end of the buffer and the rest a the beginning */
+ if ((NbBytesToCopy == elementSize) || ((NbBytesToCopy < elementSize) && (q->optionFlags == CIRCULAR_QUEUE_NO_FLAG)))
+ {
+ /* Copy First part (or emtire buffer ) from current position up to the end of the buffer queue (or before if enough room) */
+ memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
+ /* Adjust bytes count */
+ q->byteCount += NbBytesToCopy;
+ /* Wrap */
+ curBuffPosition = 0;
+ /* set NbCopiedBytes bytes with ampount copied */
+ NbCopiedBytes = NbBytesToCopy;
+ /* set the rest to copy if wrao , if no wrap will be 0 */
+ NbBytesToCopy = elementSize - NbBytesToCopy;
+ /* set the current element Size, will be used to calaculate next last position at beginning of loop */
+ curElementSize = (elementSize) + elemSizeStorageRoom ;
+ }
+ else if (NbBytesToCopy) /* We have a wrap to manage */
+ {
+ /* case of CIRCULAR_QUEUE_NO_WRAP_FLAG option */
+ if (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)
+ {
+ /* if element size are variable and NO_WRAP option, Invalidate end of buffer setting 0xFFFF size*/
+ if (q->elementSize == 0)
+ {
+ q->qBuff[curBuffPosition-2] = 0xFF;
+ q->qBuff[curBuffPosition-1] = 0xFF;
+ }
+ q->byteCount += NbBytesToCopy; /* invalid data at the end of buffer are take into account in byteCount */
+ /* No bytes coped a the end of buffer */
+ NbCopiedBytes = 0;
+ /* all element to be copied at the begnning of buffer */
+ NbBytesToCopy = elementSize;
+ /* Wrap */
+ curBuffPosition = 0;
+ /* if variable size element, invalidate end of buffer setting OxFFFF in element header (size) */
+ if (q->elementSize == 0)
+ {
+ q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
+ q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
+ q->byteCount += 2;
+ }
+
+ }
+ /* case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG option */
+ else if (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)
+ {
+ if (q->elementSize == 0)
+ {
+ /* reset the size of current element to the nb bytes fitting at the end of buffer */
+ q->qBuff[curBuffPosition-2] = NbBytesToCopy & 0xFF;
+ q->qBuff[curBuffPosition-1] = (NbBytesToCopy & 0xFF00) >> 8 ;
+ /* copy the bytes */
+ memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
+ q->byteCount += NbBytesToCopy;
+ /* set the number of copied bytes */
+ NbCopiedBytes = NbBytesToCopy;
+ /* set rest of data to be copied to begnning of buffer */
+ NbBytesToCopy = elementSize - NbBytesToCopy;
+ /* one element more dur to split in 2 elements */
+ q->elementCount++;
+ /* Wrap */
+ curBuffPosition = 0;
+ /* Set new size for rest of data */
+ q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
+ q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
+ q->byteCount += 2;
+ }
+ else
+ {
+ /* Should not occur */
+ /* can not manage split Flag on Fixed size element */
+ /* Buffer is corrupted */
+ return NULL;
+ }
+ }
+ curElementSize = (NbBytesToCopy) + elemSizeStorageRoom ;
+ q->last = 0;
+ }
+
+ /* some remaining byte to copy */
+ if (NbBytesToCopy)
+ {
+ memcpy(&q->qBuff[curBuffPosition],&x[(i*elementSize)+NbCopiedBytes],NbBytesToCopy);
+ q->byteCount += NbBytesToCopy;
+ }
+
+ /* One more element */
+ q->elementCount++;
+ }
+
+ ptr = q->qBuff + (MOD((q->last+elemSizeStorageRoom ),q->queueMaxSize));
+ }
+ /* for Breakpoint only...to remove */
+ else
+ {
+ return NULL;
+ }
+ return ptr;
+}
+
+
+/**
+ * @brief Remove element from the queue and copy it in provided buffer
+ * @note This function is used to remove and element from the Circular Queue .
+ * @param q: pointer on queue structure to be handled
+ * @param elementSize: Pointer to return Size of element to be removed
+ * @param buffer: destination buffer where to copy element
+ * @retval Pointer on removed element. NULL if queue was empty
+ */
+uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
+{
+ return NULL;
+}
+
+
+
+/**
+ * @brief Remove element from the queue.
+ * @note This function is used to remove and element from the Circular Queue .
+ * @param q: pointer on queue structure to be handled
+ * @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
+ * @retval Pointer on removed element. NULL if queue was empty
+ */
+uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize)
+{
+ uint8_t elemSizeStorageRoom = 0;
+ uint8_t* ptr= NULL;
+ elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
+ uint16_t eltSize = 0;
+ if (q->byteCount > 0)
+ {
+ /* retrieve element Size */
+ eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
+
+ if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
+ {
+ if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
+ ((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
+ {
+ /* all data from current position up to the end of buffer are invalid */
+ q->byteCount -= (q->queueMaxSize - q->first);
+ /* Adjust first element pos */
+ q->first = 0;
+ /* retrieve the right size after the wrap [if variable size element] */
+ eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
+ }
+ }
+
+ /* retrieve element */
+ ptr = q->qBuff + (MOD((q->first + elemSizeStorageRoom), q->queueMaxSize));
+
+ /* adjust byte count */
+ q->byteCount -= (eltSize + elemSizeStorageRoom) ;
+
+ /* Adjust q->first */
+ if (q->byteCount > 0)
+ {
+ q->first = MOD((q->first+ eltSize + elemSizeStorageRoom ), q->queueMaxSize);
+ }
+ /* adjust element count */
+ --q->elementCount;
+ }
+ if (elementSize != NULL)
+ {
+ *elementSize = eltSize;
+ }
+ return ptr;
+}
+
+
+/**
+ * @brief "Sense" first element of the queue, without removing it and copy it in provided buffer
+ * @note This function is used to return a pointer on the first element of the queue without removing it.
+ * @param q: pointer on queue structure to be handled
+ * @param elementSize: Pointer to return Size of element to be removed
+ * @param buffer: destination buffer where to copy element
+ * @retval Pointer on sensed element. NULL if queue was empty
+ */
+
+uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
+{
+ return NULL;
+}
+
+
+/**
+ * @brief "Sense" first element of the queue, without removing it.
+ * @note This function is used to return a pointer on the first element of the queue without removing it.
+ * @param q: pointer on queue structure to be handled
+ * @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
+ * @retval Pointer on sensed element. NULL if queue was empty
+ */
+uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize)
+{
+ uint8_t elemSizeStorageRoom = 0;
+ uint8_t* x= NULL;
+ elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
+ uint16_t eltSize = 0;
+ uint32_t FirstElemetPos = 0;
+
+ if (q->byteCount > 0)
+ {
+ FirstElemetPos = q->first;
+ eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
+
+ if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
+ {
+ if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
+ ((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
+
+ {
+ /* all data from current position up to the end of buffer are invalid */
+ FirstElemetPos = 0; /* wrap to the begiining of buffer */
+
+ /* retrieve the right size after the wrap [if variable size element] */
+ eltSize = (q->elementSize == 0) ? q->qBuff[FirstElemetPos]+ ((q->qBuff[MOD((FirstElemetPos+1), q->queueMaxSize)])<<8) : q->elementSize;
+ }
+ }
+ /* retrieve element */
+ x = q->qBuff + (MOD((FirstElemetPos + elemSizeStorageRoom), q->queueMaxSize));
+ }
+ if (elementSize != NULL)
+ {
+ *elementSize = eltSize;
+ }
+ return x;
+}
+
+/**
+ * @brief Check if queue is empty.
+ * @note This function is used to to check if the queue is empty.
+ * @param q: pointer on queue structure to be handled
+ * @retval TRUE (!0) if the queue is empyu otherwise FALSE (0)
+ */
+int CircularQueue_Empty(queue_t *q)
+{
+ int ret=FALSE;
+ if (q->byteCount <= 0)
+ {
+ ret=TRUE;
+ }
+ return ret;
+}
+
+int CircularQueue_NbElement(queue_t *q)
+{
+ return q->elementCount;
+}