Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/inc/tx_queue.h
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/inc/tx_queue.h	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/inc/tx_queue.h	(revision 65)
@@ -0,0 +1,175 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    tx_queue.h                                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the ThreadX queue management component,           */
+/*    including all data types and external references.  It is assumed    */
+/*    that tx_api.h and tx_port.h have already been included.             */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef TX_QUEUE_H
+#define TX_QUEUE_H
+
+
+/* Define queue control specific data definitions.  */
+
+#define TX_QUEUE_ID                             ((ULONG) 0x51554555)
+
+
+/* Determine if in-line component initialization is supported by the
+   caller.  */
+#ifdef TX_INVOKE_INLINE_INITIALIZATION
+
+/* Yes, in-line initialization is supported, remap the queue initialization
+   function.  */
+
+#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+#define _tx_queue_initialize() \
+                    _tx_queue_created_ptr =                          TX_NULL;     \
+                    _tx_queue_created_count =                        TX_EMPTY
+#else
+#define _tx_queue_initialize() \
+                    _tx_queue_created_ptr =                          TX_NULL;     \
+                    _tx_queue_created_count =                        TX_EMPTY;    \
+                    _tx_queue_performance_messages_sent_count =      ((ULONG) 0); \
+                    _tx_queue_performance__messages_received_count = ((ULONG) 0); \
+                    _tx_queue_performance_empty_suspension_count =   ((ULONG) 0); \
+                    _tx_queue_performance_full_suspension_count =    ((ULONG) 0); \
+                    _tx_queue_performance_timeout_count =            ((ULONG) 0)
+#endif
+#define TX_QUEUE_INIT
+#else
+
+/* No in-line initialization is supported, use standard function call.  */
+VOID        _tx_queue_initialize(VOID);
+#endif
+
+
+/* Define the message copy macro. Note that the source and destination
+   pointers must be modified since they are used subsequently.  */
+
+#ifndef TX_QUEUE_MESSAGE_COPY
+#define TX_QUEUE_MESSAGE_COPY(s, d, z)          \
+                    *(d)++ = *(s)++;            \
+                    if ((z) > ((UINT) 1))       \
+                    {                           \
+                        while (--(z))           \
+                        {                       \
+                            *(d)++ =  *(s)++;   \
+                         }                      \
+                    }
+#endif
+
+
+/* Define internal queue management function prototypes.  */
+
+VOID        _tx_queue_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence);
+
+
+/* Queue management component data declarations follow.  */
+
+/* Determine if the initialization function of this component is including
+   this file.  If so, make the data definitions really happen.  Otherwise,
+   make them extern so other functions in the component can access them.  */
+
+#ifdef TX_QUEUE_INIT
+#define QUEUE_DECLARE
+#else
+#define QUEUE_DECLARE extern
+#endif
+
+
+/* Define the head pointer of the created queue list.  */
+
+QUEUE_DECLARE  TX_QUEUE *   _tx_queue_created_ptr;
+
+
+/* Define the variable that holds the number of created queues. */
+
+QUEUE_DECLARE  ULONG        _tx_queue_created_count;
+
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+/* Define the total number of messages sent.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance_messages_sent_count;
+
+
+/* Define the total number of messages received.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance__messages_received_count;
+
+
+/* Define the total number of queue empty suspensions.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance_empty_suspension_count;
+
+
+/* Define the total number of queue full suspensions.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance_full_suspension_count;
+
+
+/* Define the total number of queue full errors.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance_full_error_count;
+
+
+/* Define the total number of queue timeouts.  */
+
+QUEUE_DECLARE  ULONG        _tx_queue_performance_timeout_count;
+
+
+#endif
+
+
+/* Define default post queue delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h).  */
+
+#ifndef TX_QUEUE_DELETE_PORT_COMPLETION
+#define TX_QUEUE_DELETE_PORT_COMPLETION(q)
+#endif
+
+
+#endif
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_cleanup.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_cleanup.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_cleanup.c	(revision 65)
@@ -0,0 +1,227 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _tx_queue_cleanup                                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function processes queue timeout and thread terminate          */
+/*    actions that require the queue data structures to be cleaned        */
+/*    up.                                                                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    thread_ptr                        Pointer to suspended thread's     */
+/*                                        control block                   */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_thread_system_resume          Resume thread service             */
+/*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    _tx_thread_timeout                Thread timeout processing         */
+/*    _tx_thread_terminate              Thread terminate processing       */
+/*    _tx_thread_wait_abort             Thread wait abort processing      */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+VOID  _tx_queue_cleanup(TX_THREAD  *thread_ptr, ULONG suspension_sequence)
+{
+
+#ifndef TX_NOT_INTERRUPTABLE
+TX_INTERRUPT_SAVE_AREA
+#endif
+
+TX_QUEUE            *queue_ptr;
+UINT                suspended_count;
+TX_THREAD           *next_thread;
+TX_THREAD           *previous_thread;
+
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+    /* Disable interrupts to remove the suspended thread from the queue.  */
+    TX_DISABLE
+
+    /* Determine if the cleanup is still required.  */
+    if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_queue_cleanup))
+    {
+
+        /* Check for valid suspension sequence.  */
+        if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
+        {
+
+            /* Setup pointer to queue control block.  */
+            queue_ptr =  TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+
+            /* Check for NULL queue pointer.  */
+            if (queue_ptr != TX_NULL)
+            {
+
+                /* Is the queue ID valid?  */
+                if (queue_ptr -> tx_queue_id == TX_QUEUE_ID)
+                {
+
+                    /* Determine if there are any thread suspensions.  */
+                    if (queue_ptr -> tx_queue_suspended_count != TX_NO_SUSPENSIONS)
+                    {
+#else
+
+                        /* Setup pointer to queue control block.  */
+                        queue_ptr =  TX_VOID_TO_QUEUE_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
+#endif
+
+                        /* Yes, we still have thread suspension!  */
+
+                        /* Clear the suspension cleanup flag.  */
+                        thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
+
+                        /* Decrement the suspended count.  */
+                        queue_ptr -> tx_queue_suspended_count--;
+
+                        /* Pickup the suspended count.  */
+                        suspended_count =  queue_ptr -> tx_queue_suspended_count;
+
+                        /* Remove the suspended thread from the list.  */
+
+                        /* See if this is the only suspended thread on the list.  */
+                        if (suspended_count == TX_NO_SUSPENSIONS)
+                        {
+
+                            /* Yes, the only suspended thread.  */
+
+                            /* Update the head pointer.  */
+                            queue_ptr -> tx_queue_suspension_list =  TX_NULL;
+                        }
+                        else
+                        {
+
+                            /* At least one more thread is on the same suspension list.  */
+
+                            /* Update the links of the adjacent threads.  */
+                            next_thread =                                   thread_ptr -> tx_thread_suspended_next;
+                            previous_thread =                               thread_ptr -> tx_thread_suspended_previous;
+                            next_thread -> tx_thread_suspended_previous =   previous_thread;
+                            previous_thread -> tx_thread_suspended_next =   next_thread;
+
+                            /* Determine if we need to update the head pointer.  */
+                            if (queue_ptr -> tx_queue_suspension_list == thread_ptr)
+                            {
+
+                                /* Update the list head pointer.  */
+                                queue_ptr -> tx_queue_suspension_list =         next_thread;
+                            }
+                        }
+
+                        /* Now we need to determine if this cleanup is from a terminate, timeout,
+                           or from a wait abort.  */
+                        if (thread_ptr -> tx_thread_state == TX_QUEUE_SUSP)
+                        {
+
+                            /* Timeout condition and the thread still suspended on the queue.
+                               Setup return error status and resume the thread.  */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+                            /* Increment the total timeouts counter.  */
+                            _tx_queue_performance_timeout_count++;
+
+                            /* Increment the number of timeouts on this queue.  */
+                            queue_ptr -> tx_queue_performance_timeout_count++;
+#endif
+
+                            /* Setup return status.  */
+                            if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
+                            {
+
+                                /* Queue full timeout!  */
+                                thread_ptr -> tx_thread_suspend_status =  TX_QUEUE_FULL;
+                            }
+                            else
+                            {
+
+                                /* Queue empty timeout!  */
+                                thread_ptr -> tx_thread_suspend_status =  TX_QUEUE_EMPTY;
+                            }
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+                            /* Resume the thread!  */
+                            _tx_thread_system_ni_resume(thread_ptr);
+#else
+
+                            /* Temporarily disable preemption.  */
+                            _tx_thread_preempt_disable++;
+
+                            /* Restore interrupts.  */
+                            TX_RESTORE
+
+                            /* Resume the thread!  */
+                            _tx_thread_system_resume(thread_ptr);
+
+                            /* Disable interrupts.  */
+                            TX_DISABLE
+#endif
+                        }
+#ifndef TX_NOT_INTERRUPTABLE
+                    }
+                }
+            }
+        }
+    }
+
+    /* Restore interrupts.  */
+    TX_RESTORE
+#endif
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_create.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_create.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_create.c	(revision 65)
@@ -0,0 +1,172 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _tx_queue_create                                    PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function creates a message queue.  The message size and depth  */
+/*    of the queue is specified by the caller.                            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    name_ptr                          Pointer to queue name             */
+/*    message_size                      Size of each queue message        */
+/*    queue_start                       Starting address of the queue area*/
+/*    queue_size                        Number of bytes in the queue      */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    TX_SUCCESS                        Successful completion status      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+                        VOID *queue_start, ULONG queue_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT            capacity;
+UINT            used_words;
+TX_QUEUE        *next_queue;
+TX_QUEUE        *previous_queue;
+
+
+    /* Initialize queue control block to all zeros.  */
+    TX_MEMSET(queue_ptr, 0, (sizeof(TX_QUEUE)));
+
+    /* Setup the basic queue fields.  */
+    queue_ptr -> tx_queue_name =             name_ptr;
+
+    /* Save the message size in the control block.  */
+    queue_ptr -> tx_queue_message_size =  message_size;
+
+    /* Determine how many messages will fit in the queue area and the number
+       of ULONGs used.  */
+    capacity =    (UINT) (queue_size / ((ULONG) (((ULONG) message_size) * (sizeof(ULONG)))));
+    used_words =  capacity * message_size;
+
+    /* Save the starting address and calculate the ending address of
+       the queue.  Note that the ending address is really one past the
+       end!  */
+    queue_ptr -> tx_queue_start =  TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+    queue_ptr -> tx_queue_end =    TX_ULONG_POINTER_ADD(queue_ptr -> tx_queue_start, used_words);
+
+    /* Set the read and write pointers to the beginning of the queue
+       area.  */
+    queue_ptr -> tx_queue_read =   TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+    queue_ptr -> tx_queue_write =  TX_VOID_TO_ULONG_POINTER_CONVERT(queue_start);
+
+    /* Setup the number of enqueued messages and the number of message
+       slots available in the queue.  */
+    queue_ptr -> tx_queue_available_storage =  (UINT) capacity;
+    queue_ptr -> tx_queue_capacity =           (UINT) capacity;
+
+    /* Disable interrupts to put the queue on the created list.  */
+    TX_DISABLE
+
+    /* Setup the queue ID to make it valid.  */
+    queue_ptr -> tx_queue_id =  TX_QUEUE_ID;
+
+    /* Place the queue on the list of created queues.  First,
+       check for an empty list.  */
+    if (_tx_queue_created_count == TX_EMPTY)
+    {
+
+        /* The created queue list is empty.  Add queue to empty list.  */
+        _tx_queue_created_ptr =                   queue_ptr;
+        queue_ptr -> tx_queue_created_next =      queue_ptr;
+        queue_ptr -> tx_queue_created_previous =  queue_ptr;
+    }
+    else
+    {
+
+        /* This list is not NULL, add to the end of the list.  */
+        next_queue =      _tx_queue_created_ptr;
+        previous_queue =  next_queue -> tx_queue_created_previous;
+
+        /* Place the new queue in the list.  */
+        next_queue -> tx_queue_created_previous =  queue_ptr;
+        previous_queue -> tx_queue_created_next =  queue_ptr;
+
+        /* Setup this queues's created links.  */
+        queue_ptr -> tx_queue_created_previous =  previous_queue;
+        queue_ptr -> tx_queue_created_next =      next_queue;
+    }
+
+    /* Increment the created queue count.  */
+    _tx_queue_created_count++;
+
+    /* Optional queue create extended processing.  */
+    TX_QUEUE_CREATE_EXTENSION(queue_ptr)
+
+    /* If trace is enabled, register this object.  */
+    TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_QUEUE, queue_ptr, name_ptr, queue_size, message_size)
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_CREATE, queue_ptr, message_size, TX_POINTER_TO_ULONG_CONVERT(queue_start), queue_size, TX_TRACE_QUEUE_EVENTS)
+
+    /* Log this kernel call.  */
+    TX_EL_QUEUE_CREATE_INSERT
+
+    /* Restore interrupts.  */
+    TX_RESTORE
+
+    /* Return TX_SUCCESS.  */
+    return(TX_SUCCESS);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_receive.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_receive.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_receive.c	(revision 65)
@@ -0,0 +1,488 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _tx_queue_receive                                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function receives a message from the specified queue. If there */
+/*    are no messages in the queue, this function waits according to the  */
+/*    option specified.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    destination_ptr                   Pointer to message destination    */
+/*                                        **** MUST BE LARGE ENOUGH TO    */
+/*                                             HOLD MESSAGE ****          */
+/*    wait_option                       Suspension option                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    status                            Completion status                 */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_thread_system_resume          Resume thread routine             */
+/*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */
+/*    _tx_thread_system_suspend         Suspend thread routine            */
+/*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _tx_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD       *thread_ptr;
+ULONG           *source;
+ULONG           *destination;
+UINT            size;
+UINT            suspended_count;
+TX_THREAD       *next_thread;
+TX_THREAD       *previous_thread;
+UINT            status;
+
+
+    /* Default the status to TX_SUCCESS.  */
+    status =  TX_SUCCESS;
+
+    /* Disable interrupts to receive message from queue.  */
+    TX_DISABLE
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+    /* Increment the total messages received counter.  */
+    _tx_queue_performance__messages_received_count++;
+
+    /* Increment the number of messages received from this queue.  */
+    queue_ptr -> tx_queue_performance_messages_received_count++;
+
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_RECEIVE, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(destination_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
+
+    /* Log this kernel call.  */
+    TX_EL_QUEUE_RECEIVE_INSERT
+
+    /* Pickup the thread suspension count.  */
+    suspended_count =  queue_ptr -> tx_queue_suspended_count;
+
+    /* Determine if there is anything in the queue.  */
+    if (queue_ptr -> tx_queue_enqueued != TX_NO_MESSAGES)
+    {
+
+        /* Determine if there are any suspensions.  */
+        if (suspended_count == TX_NO_SUSPENSIONS)
+        {
+
+            /* There is a message waiting in the queue and there are no suspensi.  */
+
+            /* Setup source and destination pointers.  */
+            source =       queue_ptr -> tx_queue_read;
+            destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+            size =         queue_ptr -> tx_queue_message_size;
+
+            /* Copy message. Note that the source and destination pointers are
+               incremented by the macro.  */
+            TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+            /* Determine if we are at the end.  */
+            if (source == queue_ptr -> tx_queue_end)
+            {
+
+                /* Yes, wrap around to the beginning.  */
+                source =  queue_ptr -> tx_queue_start;
+            }
+
+            /* Setup the queue read pointer.   */
+            queue_ptr -> tx_queue_read =  source;
+
+            /* Increase the amount of available storage.  */
+            queue_ptr -> tx_queue_available_storage++;
+
+            /* Decrease the enqueued count.  */
+            queue_ptr -> tx_queue_enqueued--;
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+        }
+        else
+        {
+
+            /* At this point we know the queue is full.  */
+
+            /* Pickup thread suspension list head pointer.  */
+            thread_ptr =  queue_ptr -> tx_queue_suspension_list;
+
+            /* Now determine if there is a queue front suspension active.   */
+
+            /* Is the front suspension flag set?  */
+            if (thread_ptr -> tx_thread_suspend_option == TX_TRUE)
+            {
+
+                /* Yes, a queue front suspension is present.  */
+
+                /* Return the message associated with this suspension.  */
+
+                /* Setup source and destination pointers.  */
+                source =       TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+                destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+                size =         queue_ptr -> tx_queue_message_size;
+
+                /* Copy message. Note that the source and destination pointers are
+                   incremented by the macro.  */
+                TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+                /* Message is now in the caller's destination. See if this is the only suspended thread
+                   on the list.  */
+                suspended_count--;
+                if (suspended_count == TX_NO_SUSPENSIONS)
+                {
+
+                    /* Yes, the only suspended thread.  */
+
+                    /* Update the head pointer.  */
+                    queue_ptr -> tx_queue_suspension_list =  TX_NULL;
+                }
+                else
+                {
+
+                    /* At least one more thread is on the same expiration list.  */
+
+                    /* Update the list head pointer.  */
+                    next_thread =                            thread_ptr -> tx_thread_suspended_next;
+                    queue_ptr -> tx_queue_suspension_list =  next_thread;
+
+                    /* Update the links of the adjacent threads.  */
+                    previous_thread =                              thread_ptr -> tx_thread_suspended_previous;
+                    next_thread -> tx_thread_suspended_previous =  previous_thread;
+                    previous_thread -> tx_thread_suspended_next =  next_thread;
+                }
+
+                /* Decrement the suspension count.  */
+                queue_ptr -> tx_queue_suspended_count =  suspended_count;
+
+                /* Prepare for resumption of the first thread.  */
+
+                /* Clear cleanup routine to avoid timeout.  */
+                thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
+
+                /* Put return status into the thread control block.  */
+                thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+                /* Resume the thread!  */
+                _tx_thread_system_ni_resume(thread_ptr);
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+#else
+
+                /* Temporarily disable preemption.  */
+                _tx_thread_preempt_disable++;
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+
+                /* Resume thread.  */
+                _tx_thread_system_resume(thread_ptr);
+#endif
+            }
+            else
+            {
+
+                /* At this point, we know that the queue is full and there
+                   are one or more threads suspended trying to send another
+                   message to this queue.  */
+
+                /* Setup source and destination pointers.  */
+                source =       queue_ptr -> tx_queue_read;
+                destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(destination_ptr);
+                size =         queue_ptr -> tx_queue_message_size;
+
+                /* Copy message. Note that the source and destination pointers are
+                   incremented by the macro.  */
+                TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+                /* Determine if we are at the end.  */
+                if (source == queue_ptr -> tx_queue_end)
+                {
+
+                    /* Yes, wrap around to the beginning.  */
+                    source =  queue_ptr -> tx_queue_start;
+                }
+
+                /* Setup the queue read pointer.   */
+                queue_ptr -> tx_queue_read =  source;
+
+                /* Disable preemption.  */
+                _tx_thread_preempt_disable++;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+
+                /* Interrupts are enabled briefly here to keep the interrupt
+                   lockout time deterministic.  */
+
+                /* Disable interrupts again.  */
+                TX_DISABLE
+#endif
+
+                /* Decrement the preemption disable variable.  */
+                _tx_thread_preempt_disable--;
+
+                /* Setup source and destination pointers.  */
+                source =       TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+                destination =  queue_ptr -> tx_queue_write;
+                size =         queue_ptr -> tx_queue_message_size;
+
+                /* Copy message. Note that the source and destination pointers are
+                   incremented by the macro.  */
+                TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+                /* Determine if we are at the end.  */
+                if (destination == queue_ptr -> tx_queue_end)
+                {
+
+                    /* Yes, wrap around to the beginning.  */
+                    destination =  queue_ptr -> tx_queue_start;
+                }
+
+                /* Adjust the write pointer.  */
+                queue_ptr -> tx_queue_write =  destination;
+
+                /* Pickup thread pointer.  */
+                thread_ptr =  queue_ptr -> tx_queue_suspension_list;
+
+                /* Message is now in the queue.  See if this is the only suspended thread
+                   on the list.  */
+                suspended_count--;
+                if (suspended_count == TX_NO_SUSPENSIONS)
+                {
+
+                  /* Yes, the only suspended thread.  */
+
+                    /* Update the head pointer.  */
+                    queue_ptr -> tx_queue_suspension_list =  TX_NULL;
+                }
+                else
+                {
+
+                    /* At least one more thread is on the same expiration list.  */
+
+                    /* Update the list head pointer.  */
+                    next_thread =                            thread_ptr -> tx_thread_suspended_next;
+                    queue_ptr -> tx_queue_suspension_list =  next_thread;
+
+                    /* Update the links of the adjacent threads.  */
+                    previous_thread =                               thread_ptr -> tx_thread_suspended_previous;
+                    next_thread -> tx_thread_suspended_previous =   previous_thread;
+                    previous_thread -> tx_thread_suspended_next =   next_thread;
+                }
+
+                /* Decrement the suspension count.  */
+                queue_ptr -> tx_queue_suspended_count =  suspended_count;
+
+                /* Prepare for resumption of the first thread.  */
+
+                /* Clear cleanup routine to avoid timeout.  */
+                thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
+
+                /* Put return status into the thread control block.  */
+                thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+                /* Resume the thread!  */
+                _tx_thread_system_ni_resume(thread_ptr);
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+#else
+
+                /* Temporarily disable preemption.  */
+                _tx_thread_preempt_disable++;
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+
+                /* Resume thread.  */
+                _tx_thread_system_resume(thread_ptr);
+#endif
+            }
+        }
+    }
+
+    /* Determine if the request specifies suspension.  */
+    else if (wait_option != TX_NO_WAIT)
+    {
+
+        /* Determine if the preempt disable flag is non-zero.  */
+        if (_tx_thread_preempt_disable != ((UINT) 0))
+        {
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */
+            status =  TX_QUEUE_EMPTY;
+        }
+        else
+        {
+
+            /* Prepare for suspension of this thread.  */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+            /* Increment the total queue empty suspensions counter.  */
+            _tx_queue_performance_empty_suspension_count++;
+
+            /* Increment the number of empty suspensions on this queue.  */
+            queue_ptr -> tx_queue_performance_empty_suspension_count++;
+#endif
+
+            /* Pickup thread pointer.  */
+            TX_THREAD_GET_CURRENT(thread_ptr)
+
+            /* Setup cleanup routine pointer.  */
+            thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_queue_cleanup);
+
+            /* Setup cleanup information, i.e. this queue control
+               block and the source pointer.  */
+            thread_ptr -> tx_thread_suspend_control_block =    (VOID *) queue_ptr;
+            thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) destination_ptr;
+            thread_ptr -> tx_thread_suspend_option =           TX_FALSE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+            /* Increment the suspension sequence number, which is used to identify
+               this suspension event.  */
+            thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+            /* Setup suspension list.  */
+            if (suspended_count == TX_NO_SUSPENSIONS)
+            {
+
+                /* No other threads are suspended.  Setup the head pointer and
+                   just setup this threads pointers to itself.  */
+                queue_ptr -> tx_queue_suspension_list =         thread_ptr;
+                thread_ptr -> tx_thread_suspended_next =        thread_ptr;
+                thread_ptr -> tx_thread_suspended_previous =    thread_ptr;
+            }
+            else
+            {
+
+                /* This list is not NULL, add current thread to the end. */
+                next_thread =                                   queue_ptr -> tx_queue_suspension_list;
+                thread_ptr -> tx_thread_suspended_next =        next_thread;
+                previous_thread =                               next_thread -> tx_thread_suspended_previous;
+                thread_ptr -> tx_thread_suspended_previous =    previous_thread;
+                previous_thread -> tx_thread_suspended_next =   thread_ptr;
+                next_thread -> tx_thread_suspended_previous =   thread_ptr;
+            }
+
+            /* Increment the suspended thread count.  */
+            queue_ptr -> tx_queue_suspended_count =  suspended_count + ((UINT) 1);
+
+            /* Set the state to suspended.  */
+            thread_ptr -> tx_thread_state =    TX_QUEUE_SUSP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+            /* Call actual non-interruptable thread suspension routine.  */
+            _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+#else
+
+            /* Set the suspending flag.  */
+            thread_ptr -> tx_thread_suspending =  TX_TRUE;
+
+            /* Setup the timeout period.  */
+            thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option;
+
+            /* Temporarily disable preemption.  */
+            _tx_thread_preempt_disable++;
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Call actual thread suspension routine.  */
+            _tx_thread_system_suspend(thread_ptr);
+#endif
+
+            /* Return the completion status.  */
+            status =  thread_ptr -> tx_thread_suspend_status;
+        }
+    }
+    else
+    {
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Immediate return, return error completion.  */
+        status =  TX_QUEUE_EMPTY;
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_send.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_send.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_queue_send.c	(revision 65)
@@ -0,0 +1,428 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _tx_queue_send                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function places a message into the specified queue.  If there  */
+/*    is no room in the queue, this function waits according to the       */
+/*    option specified.                                                   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    source_ptr                        Pointer to message source         */
+/*    wait_option                       Suspension option                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    status                            Completion status                 */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_thread_system_resume          Resume thread routine             */
+/*    _tx_thread_system_ni_resume       Non-interruptable resume thread   */
+/*    _tx_thread_system_suspend         Suspend thread routine            */
+/*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _tx_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD       *thread_ptr;
+ULONG           *source;
+ULONG           *destination;
+UINT            size;
+UINT            suspended_count;
+TX_THREAD       *next_thread;
+TX_THREAD       *previous_thread;
+UINT            status;
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+VOID            (*queue_send_notify)(struct TX_QUEUE_STRUCT *notify_queue_ptr);
+#endif
+
+
+    /* Default the status to TX_SUCCESS.  */
+    status =  TX_SUCCESS;
+
+    /* Disable interrupts to place message in the queue.  */
+    TX_DISABLE
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+    /* Increment the total messages sent counter.  */
+    _tx_queue_performance_messages_sent_count++;
+
+    /* Increment the number of messages sent to this queue.  */
+    queue_ptr -> tx_queue_performance_messages_sent_count++;
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    TX_TRACE_IN_LINE_INSERT(TX_TRACE_QUEUE_SEND, queue_ptr, TX_POINTER_TO_ULONG_CONVERT(source_ptr), wait_option, queue_ptr -> tx_queue_enqueued, TX_TRACE_QUEUE_EVENTS)
+
+    /* Log this kernel call.  */
+    TX_EL_QUEUE_SEND_INSERT
+
+    /* Pickup the thread suspension count.  */
+    suspended_count =  queue_ptr -> tx_queue_suspended_count;
+
+    /* Determine if there is room in the queue.  */
+    if (queue_ptr -> tx_queue_available_storage != TX_NO_MESSAGES)
+    {
+
+        /* There is room for the message in the queue.  */
+
+        /* Determine if there are suspended on this queue.  */
+        if (suspended_count == TX_NO_SUSPENSIONS)
+        {
+
+            /* No suspended threads, simply place the message in the queue.  */
+
+            /* Reduce the amount of available storage.  */
+            queue_ptr -> tx_queue_available_storage--;
+
+            /* Increase the enqueued count.  */
+            queue_ptr -> tx_queue_enqueued++;
+
+            /* Setup source and destination pointers.  */
+            source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+            destination =  queue_ptr -> tx_queue_write;
+            size =         queue_ptr -> tx_queue_message_size;
+
+            /* Copy message. Note that the source and destination pointers are
+               incremented by the macro.  */
+            TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+            /* Determine if we are at the end.  */
+            if (destination == queue_ptr -> tx_queue_end)
+            {
+
+                /* Yes, wrap around to the beginning.  */
+                destination =  queue_ptr -> tx_queue_start;
+            }
+
+            /* Adjust the write pointer.  */
+            queue_ptr -> tx_queue_write =  destination;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Pickup the notify callback routine for this queue.  */
+            queue_send_notify =  queue_ptr -> tx_queue_send_notify;
+#endif
+
+            /* No thread suspended, just return to caller.  */
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Determine if a notify callback is required.  */
+            if (queue_send_notify != TX_NULL)
+            {
+
+                /* Call application queue send notification.  */
+                (queue_send_notify)(queue_ptr);
+            }
+#endif
+        }
+        else
+        {
+
+            /* There is a thread suspended on an empty queue. Simply
+               copy the message to the suspended thread's destination
+               pointer.  */
+
+            /* Pickup the head of the suspension list.  */
+            thread_ptr =  queue_ptr -> tx_queue_suspension_list;
+
+            /* See if this is the only suspended thread on the list.  */
+            suspended_count--;
+            if (suspended_count == TX_NO_SUSPENSIONS)
+            {
+
+                /* Yes, the only suspended thread.  */
+
+                /* Update the head pointer.  */
+                queue_ptr -> tx_queue_suspension_list =  TX_NULL;
+            }
+            else
+            {
+
+                /* At least one more thread is on the same expiration list.  */
+
+                /* Update the list head pointer.  */
+                queue_ptr -> tx_queue_suspension_list =  thread_ptr -> tx_thread_suspended_next;
+
+                /* Update the links of the adjacent threads.  */
+                next_thread =                            thread_ptr -> tx_thread_suspended_next;
+                queue_ptr -> tx_queue_suspension_list =  next_thread;
+
+                /* Update the links of the adjacent threads.  */
+                previous_thread =                               thread_ptr -> tx_thread_suspended_previous;
+                next_thread -> tx_thread_suspended_previous =   previous_thread;
+                previous_thread -> tx_thread_suspended_next =   next_thread;
+            }
+
+            /* Decrement the suspension count.  */
+            queue_ptr -> tx_queue_suspended_count =  suspended_count;
+
+            /* Prepare for resumption of the thread.  */
+
+            /* Clear cleanup routine to avoid timeout.  */
+            thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
+
+            /* Setup source and destination pointers.  */
+            source =       TX_VOID_TO_ULONG_POINTER_CONVERT(source_ptr);
+            destination =  TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
+            size =         queue_ptr -> tx_queue_message_size;
+
+            /* Copy message. Note that the source and destination pointers are
+               incremented by the macro.  */
+            TX_QUEUE_MESSAGE_COPY(source, destination, size)
+
+            /* Put return status into the thread control block.  */
+            thread_ptr -> tx_thread_suspend_status =  TX_SUCCESS;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Pickup the notify callback routine for this queue.  */
+            queue_send_notify =  queue_ptr -> tx_queue_send_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+            /* Resume the thread!  */
+            _tx_thread_system_ni_resume(thread_ptr);
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+#else
+
+            /* Temporarily disable preemption.  */
+            _tx_thread_preempt_disable++;
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Resume thread.  */
+            _tx_thread_system_resume(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Determine if a notify callback is required.  */
+            if (queue_send_notify != TX_NULL)
+            {
+
+                /* Call application queue send notification.  */
+                (queue_send_notify)(queue_ptr);
+            }
+#endif
+        }
+    }
+
+    /* At this point, the queue is full. Determine if suspension is requested.  */
+    else if (wait_option != TX_NO_WAIT)
+    {
+
+        /* Determine if the preempt disable flag is non-zero.  */
+        if (_tx_thread_preempt_disable != ((UINT) 0))
+        {
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */
+            status =  TX_QUEUE_FULL;
+        }
+        else
+        {
+
+            /* Yes, prepare for suspension of this thread.  */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+            /* Increment the total number of queue full suspensions.  */
+            _tx_queue_performance_full_suspension_count++;
+
+            /* Increment the number of full suspensions on this queue.  */
+            queue_ptr -> tx_queue_performance_full_suspension_count++;
+#endif
+
+            /* Pickup thread pointer.  */
+            TX_THREAD_GET_CURRENT(thread_ptr)
+
+            /* Setup cleanup routine pointer.  */
+            thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_queue_cleanup);
+
+            /* Setup cleanup information, i.e. this queue control
+               block and the source pointer.  */
+            thread_ptr -> tx_thread_suspend_control_block =    (VOID *) queue_ptr;
+            thread_ptr -> tx_thread_additional_suspend_info =  (VOID *) source_ptr;
+            thread_ptr -> tx_thread_suspend_option =           TX_FALSE;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+            /* Increment the suspension sequence number, which is used to identify
+               this suspension event.  */
+            thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+            /* Setup suspension list.  */
+            if (suspended_count == TX_NO_SUSPENSIONS)
+            {
+
+                /* No other threads are suspended.  Setup the head pointer and
+                   just setup this threads pointers to itself.  */
+                queue_ptr -> tx_queue_suspension_list =         thread_ptr;
+                thread_ptr -> tx_thread_suspended_next =        thread_ptr;
+                thread_ptr -> tx_thread_suspended_previous =    thread_ptr;
+            }
+            else
+            {
+
+                /* This list is not NULL, add current thread to the end. */
+                next_thread =                                   queue_ptr -> tx_queue_suspension_list;
+                thread_ptr -> tx_thread_suspended_next =        next_thread;
+                previous_thread =                               next_thread -> tx_thread_suspended_previous;
+                thread_ptr -> tx_thread_suspended_previous =    previous_thread;
+                previous_thread -> tx_thread_suspended_next =   thread_ptr;
+                next_thread -> tx_thread_suspended_previous =   thread_ptr;
+            }
+
+            /* Increment the suspended thread count.  */
+            queue_ptr -> tx_queue_suspended_count =  suspended_count + ((UINT) 1);
+
+            /* Set the state to suspended.  */
+            thread_ptr -> tx_thread_state =    TX_QUEUE_SUSP;
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Pickup the notify callback routine for this queue.  */
+            queue_send_notify =  queue_ptr -> tx_queue_send_notify;
+#endif
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+            /* Call actual non-interruptable thread suspension routine.  */
+            _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+#else
+
+            /* Set the suspending flag.  */
+            thread_ptr -> tx_thread_suspending =  TX_TRUE;
+
+            /* Setup the timeout period.  */
+            thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option;
+
+            /* Temporarily disable preemption.  */
+            _tx_thread_preempt_disable++;
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Call actual thread suspension routine.  */
+            _tx_thread_system_suspend(thread_ptr);
+#endif
+
+#ifndef TX_DISABLE_NOTIFY_CALLBACKS
+
+            /* Determine if a notify callback is required.  */
+            if (thread_ptr -> tx_thread_suspend_status == TX_SUCCESS)
+            {
+
+                /* Determine if there is a notify callback.  */
+                if (queue_send_notify != TX_NULL)
+                {
+
+                    /* Call application queue send notification.  */
+                    (queue_send_notify)(queue_ptr);
+                }
+            }
+#endif
+
+            /* Return the completion status.  */
+            status =  thread_ptr -> tx_thread_suspend_status;
+        }
+    }
+    else
+    {
+
+        /* Otherwise, just return a queue full error message to the caller.  */
+
+#ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
+
+        /* Increment the number of full non-suspensions on this queue.  */
+        queue_ptr -> tx_queue_performance_full_error_count++;
+
+        /* Increment the total number of full non-suspensions.  */
+        _tx_queue_performance_full_error_count++;
+#endif
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Return error completion.  */
+        status =  TX_QUEUE_FULL;
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_create.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_create.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_create.c	(revision 65)
@@ -0,0 +1,239 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_initialize.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _txe_queue_create                                   PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the queue create function call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    name_ptr                          Pointer to queue name             */
+/*    message_size                      Size of each queue message        */
+/*    queue_start                       Starting address of the queue area*/
+/*    queue_size                        Number of bytes in the queue      */
+/*    queue_control_block_size          Size of queue control block       */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    TX_QUEUE_ERROR                    Invalid queue pointer             */
+/*    TX_PTR_ERROR                      Invalid starting address of queue */
+/*    TX_SIZE_ERROR                     Invalid message queue size        */
+/*    status                            Actual completion status          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_queue_create                  Actual queue create function      */
+/*    _tx_thread_system_preempt_check   Check for preemption              */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size,
+                        VOID *queue_start, ULONG queue_size, UINT queue_control_block_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+UINT            status;
+ULONG           i;
+TX_QUEUE        *next_queue;
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD       *thread_ptr;
+#endif
+
+
+    /* Default status to success.  */
+    status =  TX_SUCCESS;
+
+    /* Check for an invalid queue pointer.  */
+    if (queue_ptr == TX_NULL)
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+
+    /* Now check for a valid control block size.  */
+    else if (queue_control_block_size != (sizeof(TX_QUEUE)))
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+    else
+    {
+
+        /* Disable interrupts.  */
+        TX_DISABLE
+
+        /* Increment the preempt disable flag.  */
+        _tx_thread_preempt_disable++;
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Next see if it is already in the created list.  */
+        next_queue =   _tx_queue_created_ptr;
+        for (i = ((ULONG) 0); i < _tx_queue_created_count; i++)
+        {
+
+            /* Determine if this queue matches the queue in the list.  */
+            if (queue_ptr == next_queue)
+            {
+
+                break;
+            }
+            else
+            {
+
+                /* Move to the next queue.  */
+                next_queue =  next_queue -> tx_queue_created_next;
+            }
+        }
+
+        /* Disable interrupts.  */
+        TX_DISABLE
+
+        /* Decrement the preempt disable flag.  */
+        _tx_thread_preempt_disable--;
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Check for preemption.  */
+        _tx_thread_system_preempt_check();
+
+        /* At this point, check to see if there is a duplicate queue.  */
+        if (queue_ptr == next_queue)
+        {
+
+            /* Queue is already created, return appropriate error code.  */
+            status =  TX_QUEUE_ERROR;
+        }
+
+        /* Check the starting address of the queue.  */
+        else if (queue_start == TX_NULL)
+        {
+
+            /* Invalid starting address of queue.  */
+            status =  TX_PTR_ERROR;
+        }
+
+        /* Check for an invalid message size - less than 1.  */
+        else if (message_size < TX_1_ULONG)
+        {
+
+            /* Invalid message size specified.  */
+            status =  TX_SIZE_ERROR;
+        }
+
+        /* Check for an invalid message size - greater than 16.  */
+        else if (message_size > TX_16_ULONG)
+        {
+
+            /* Invalid message size specified.  */
+            status =  TX_SIZE_ERROR;
+        }
+
+        /* Check on the queue size.  */
+        else if ((queue_size/(sizeof(ULONG))) < message_size)
+        {
+
+            /* Invalid queue size specified.  */
+            status =  TX_SIZE_ERROR;
+        }
+        else
+        {
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+
+            /* Pickup thread pointer.  */
+            TX_THREAD_GET_CURRENT(thread_ptr)
+
+            /* Check for invalid caller of this function.  First check for a calling thread.  */
+            if (thread_ptr == &_tx_timer_thread)
+            {
+
+                /* Invalid caller of this function, return appropriate error code.  */
+                status =  TX_CALLER_ERROR;
+            }
+#endif
+
+            /* Check for interrupt call.  */
+            if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+            {
+
+                /* Now, make sure the call is from an interrupt and not initialization.  */
+                if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
+                {
+
+                    /* Invalid caller of this function, return appropriate error code.  */
+                    status =  TX_CALLER_ERROR;
+                }
+            }
+        }
+    }
+
+    /* Determine if everything is okay.  */
+    if (status == TX_SUCCESS)
+    {
+
+        /* Call actual queue create function.  */
+        status =  _tx_queue_create(queue_ptr, name_ptr, message_size, queue_start, queue_size);
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_receive.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_receive.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_receive.c	(revision 65)
@@ -0,0 +1,162 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _txe_queue_receive                                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the queue receive function call. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    destination_ptr                   Pointer to message destination    */
+/*                                        **** MUST BE LARGE ENOUGH TO    */
+/*                                             HOLD MESSAGE ****          */
+/*    wait_option                       Suspension option                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    TX_QUEUE_ERROR                    Invalid queue pointer             */
+/*    TX_PTR_ERROR                      Invalid destination pointer (NULL)*/
+/*    TX_WAIT_ERROR                     Invalid wait option               */
+/*    status                            Actual completion status          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_queue_receive                 Actual queue receive function     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option)
+{
+
+UINT        status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD   *current_thread;
+#endif
+
+
+    /* Default status to success.  */
+    status =  TX_SUCCESS;
+
+    /* Check for an invalid queue pointer.  */
+    if (queue_ptr == TX_NULL)
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+
+    /* Now check for invalid queue ID.  */
+    else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+
+    /* Check for an invalid destination for message.  */
+    else if (destination_ptr == TX_NULL)
+    {
+
+        /* Null destination pointer, return appropriate error.  */
+        status =  TX_PTR_ERROR;
+    }
+    else
+    {
+
+        /* Check for a wait option error.  Only threads are allowed any form of
+           suspension.  */
+        if (wait_option != TX_NO_WAIT)
+        {
+
+            /* Is the call from an ISR or Initialization?  */
+            if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+            {
+
+                /* A non-thread is trying to suspend, return appropriate error code.  */
+                status =  TX_WAIT_ERROR;
+            }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+            else
+            {
+
+                /* Pickup thread pointer.  */
+                TX_THREAD_GET_CURRENT(current_thread)
+
+                /* Is the current thread the timer thread?  */
+                if (current_thread == &_tx_timer_thread)
+                {
+
+                    /* A non-thread is trying to suspend, return appropriate error code.  */
+                    status =  TX_WAIT_ERROR;
+                }
+            }
+#endif
+        }
+    }
+
+    /* Determine if everything is okay.  */
+    if (status == TX_SUCCESS)
+    {
+
+        /* Call actual queue receive function.  */
+        status =  _tx_queue_receive(queue_ptr, destination_ptr, wait_option);
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_send.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_send.c	(revision 65)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/txe_queue_send.c	(revision 65)
@@ -0,0 +1,160 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Queue                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_timer.h"
+#include "tx_thread.h"
+#include "tx_queue.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _txe_queue_send                                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the queue send function call.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    queue_ptr                         Pointer to queue control block    */
+/*    source_ptr                        Pointer to message source         */
+/*    wait_option                       Suspension option                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    TX_QUEUE_ERROR                    Invalid queue pointer             */
+/*    TX_PTR_ERROR                      Invalid source pointer - NULL     */
+/*    TX_WAIT_ERROR                     Invalid wait option               */
+/*    status                            Actual completion status          */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_queue_send                    Actual queue send function        */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option)
+{
+
+UINT        status;
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+TX_THREAD   *current_thread;
+#endif
+
+
+    /* Default status to success.  */
+    status =  TX_SUCCESS;
+
+    /* Check for an invalid queue pointer.  */
+    if (queue_ptr == TX_NULL)
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+
+    /* Now check for invalid queue ID.  */
+    else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID)
+    {
+
+        /* Queue pointer is invalid, return appropriate error code.  */
+        status =  TX_QUEUE_ERROR;
+    }
+
+    /* Check for an invalid source for message.  */
+    else if (source_ptr == TX_NULL)
+    {
+
+        /* Null source pointer, return appropriate error.  */
+        status =  TX_PTR_ERROR;
+    }
+    else
+    {
+
+        /* Check for a wait option error.  Only threads are allowed any form of
+           suspension.  */
+        if (wait_option != TX_NO_WAIT)
+        {
+
+            /* Is the call from an ISR or Initialization?  */
+            if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0))
+            {
+
+                /* A non-thread is trying to suspend, return appropriate error code.  */
+                status =  TX_WAIT_ERROR;
+            }
+
+#ifndef TX_TIMER_PROCESS_IN_ISR
+            else
+            {
+
+                /* Pickup thread pointer.  */
+                TX_THREAD_GET_CURRENT(current_thread)
+
+                /* Is the current thread the timer thread?  */
+                if (current_thread == &_tx_timer_thread)
+                {
+
+                    /* A non-thread is trying to suspend, return appropriate error code.  */
+                    status =  TX_WAIT_ERROR;
+                }
+            }
+#endif
+        }
+    }
+
+    /* Determine if everything is okay.  */
+    if (status == TX_SUCCESS)
+    {
+
+        /* Call actual queue send function.  */
+        status =  _tx_queue_send(queue_ptr, source_ptr, wait_option);
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
+
