summaryrefslogtreecommitdiffstats
path: root/ucs2-lib/src/ucs_amd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ucs2-lib/src/ucs_amd.c')
-rw-r--r--ucs2-lib/src/ucs_amd.c570
1 files changed, 570 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_amd.c b/ucs2-lib/src/ucs_amd.c
new file mode 100644
index 0000000..c4d3456
--- /dev/null
+++ b/ucs2-lib/src/ucs_amd.c
@@ -0,0 +1,570 @@
+/*------------------------------------------------------------------------------------------------*/
+/* UNICENS V2.1.0-3491 */
+/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
+/* */
+/* This program is free software: you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation, either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+/* */
+/* You may also obtain this software under a propriety license from Microchip. */
+/* Please contact Microchip for further information. */
+/*------------------------------------------------------------------------------------------------*/
+
+/*!
+ * \file
+ * \brief Implementation of Application Message Distributor
+ *
+ * \cond UCS_INTERNAL_DOC
+ * \addtogroup G_AMD
+ * @{
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* Includes */
+/*------------------------------------------------------------------------------------------------*/
+#include "ucs_amd.h"
+#include "ucs_misc.h"
+
+/*! \brief Priority of the Application Message Distribution */
+static const uint8_t AMD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */
+/*! \brief Event which starts the Rx message distribution */
+static const Srv_Event_t AMD_EV_NOTIFY_RX = 1U;
+/*! \brief Event triggers notification of messages in tx_notify_queue */
+static const Srv_Event_t AMD_EV_NOTIFY_TX = 2U;
+/*! \brief FBlockID of FBlock NetBlock */
+static const uint8_t AMD_FB_NETBLOCK = 1U;
+/*! \brief FBlockID of FBlock NetworkMaster */
+static const uint8_t AMD_FB_NETWORKMASTER = 2U;
+
+/*------------------------------------------------------------------------------------------------*/
+/* Internal prototypes */
+/*------------------------------------------------------------------------------------------------*/
+static void Amd_Service(void *self);
+static void Amd_OnAmsComplete(void* self, Ucs_AmsRx_Msg_t* msg_ptr);
+static void Amd_OnEvent(void *self, void *error_code_ptr);
+static void Amd_OnTerminateEvent(void *self, void *error_code_ptr);
+static void Amd_RxFlush(CAmd *self, CDlList *list_ptr);
+#ifdef AMD_TX_DISTRIB
+static bool Amd_TxIsRcmMsg(Ucs_AmsTx_Msg_t *msg_ptr);
+static bool Amd_TxReceiveInternal(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr);
+static void Amd_TxProcessNotifyQueue(CAmd *self);
+#endif
+
+/*------------------------------------------------------------------------------------------------*/
+/* Initialization */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Constructor of class CAmd
+ * \param self The instance
+ * \param base_ptr Reference to base services
+ * \param ams_ptr Reference to the AMS
+ */
+void Amd_Ctor(CAmd *self, CBase *base_ptr, CAms *ams_ptr)
+{
+ MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */
+
+ self->base_ptr = base_ptr;
+ self->ams_ptr = ams_ptr;
+
+ self->started = false;
+ Srv_Ctor(&self->service, AMD_SRV_PRIO, self, &Amd_Service); /* register service */
+ (void)Scd_AddService(&self->base_ptr->scd, &self->service);
+
+ Dl_Ctor(&self->pre_queue, self->base_ptr->ucs_user_ptr); /* init preprocessor queue */
+ Dl_Ctor(&self->rx_queue, self->base_ptr->ucs_user_ptr); /* init Rx queue */
+ /* register event observer */
+ Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Amd_OnEvent);
+ Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer);
+ /* register termination events */
+ Mobs_Ctor(&self->terminate_observer, self, EH_M_TERMINATION_EVENTS, &Amd_OnTerminateEvent);
+ Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->terminate_observer);
+
+ Ams_RxAssignReceiver(self->ams_ptr, &Amd_OnAmsComplete, self);
+}
+
+
+#ifdef AMD_TX_DISTRIB
+/*! \brief Constructor of class CAmd
+ * \param self The instance
+ * \param base_ptr Reference to base services
+ * \param ams_ptr Reference to the AMS
+ * \param pool_ptr Reference to the AMS message pool
+ * \param inic_ptr Reference to the INIC
+ * \param net_ptr Reference to the network management
+ */
+void Amd_Ctor(CAmd *self, CBase *base_ptr, CAms *ams_ptr, CAmsMsgPool *pool_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr)
+{
+ MISC_MEM_SET((void *)self, 0, sizeof(*self)); /* reset members to "0" */
+
+ self->base_ptr = base_ptr;
+ self->ams_ptr = ams_ptr;
+ self->pool_ptr = pool_ptr;
+ self->inic_ptr = inic_ptr;
+ self->net_ptr = net_ptr;
+
+ self->started = false;
+ Srv_Ctor(&self->service, AMD_SRV_PRIO, self, &Amd_Service); /* register service */
+ (void)Scd_AddService(&self->base_ptr->scd, &self->service);
+
+ Dl_Ctor(&self->tx_notify_queue, self->base_ptr->ucs_inst_id); /* init queues */
+ Dl_Ctor(&self->pre_queue, self->base_ptr->ucs_inst_id); /* init preprocessor queue */
+ Dl_Ctor(&self->rx_queue, self->base_ptr->ucs_inst_id); /* init Rx queue */
+ /* register event observer */
+ Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Amd_OnEvent);
+ Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer);
+ /* register termination events */
+ Mobs_Ctor(&self->terminate_observer, self, EH_M_TERMINATION_EVENTS, &Amd_OnTerminateEvent);
+ Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->terminate_observer);
+
+ Ams_RxAssignReceiver(self->ams_ptr, &Amd_OnAmsComplete, self);
+ Ams_TxAssignTrcvSelector(self->ams_ptr, &Amd_TxIsRcmMsg);
+}
+#endif
+
+/*! \brief Assigns a pre-processor callback function for Rx messages
+ * \details This function must be called during initialization time.
+ * The AMS shall not already run.
+ * \param self The instance
+ * \param callback_fptr Reference to the callback function
+ * \param inst_ptr Reference to the pre-processor
+ */
+void Amd_AssignPreprocessor(CAmd *self, Amd_RxMsgCompleteCb_t callback_fptr, void *inst_ptr)
+{
+ if (callback_fptr != NULL)
+ {
+ self->preprocess_fptr = callback_fptr;
+ self->preprocess_inst_ptr = inst_ptr;
+
+ self->first_receive_fptr = callback_fptr;
+ self->first_receive_inst_ptr = inst_ptr;
+ self->first_q_ptr = &self->pre_queue;
+ }
+}
+
+/*! \brief Assigns a receiver callback function for Rx messages
+ * \details This function must be called during initialization time.
+ * The AMS shall not already run.
+ * \param self The instance
+ * \param callback_fptr Reference to the callback function
+ * \param inst_ptr Reference to the receiver
+ */
+void Amd_AssignReceiver(CAmd *self, Amd_RxMsgCompleteCb_t callback_fptr, void *inst_ptr)
+{
+ if (callback_fptr != NULL)
+ {
+ self->receive_fptr = callback_fptr;
+ self->receive_inst_ptr = inst_ptr;
+
+ if (self->first_receive_fptr == NULL)
+ {
+ self->first_receive_fptr = callback_fptr;
+ self->first_receive_inst_ptr = inst_ptr;
+ self->first_q_ptr = &self->rx_queue;
+ }
+ }
+}
+
+/*! \brief Assigns as callback function which is able to read and modify the Rx message
+ * \param self The instance
+ * \param callback_fptr Reference to the callback function
+ * \param inst_ptr Reference to the instance (owner of the callback function)
+ */
+void Amd_RxAssignModificator(CAmd *self, Amd_RxModificationCb_t callback_fptr, void *inst_ptr)
+{
+ if (callback_fptr != NULL)
+ {
+ self->rx_modification_fptr = callback_fptr;
+ self->rx_modification_inst_ptr = inst_ptr;
+ }
+}
+
+/*! \brief Service function of CAmd
+ * \details The processing of the Rx queues shall be started asynchronously
+ * after the initialization has succeeded.
+ * \param self The instance
+ */
+static void Amd_Service(void *self)
+{
+ CAmd *self_ = (CAmd*)self;
+ Srv_Event_t event_mask;
+ Srv_GetEvent(&self_->service, &event_mask);
+
+ if((event_mask & AMD_EV_NOTIFY_RX) == AMD_EV_NOTIFY_RX) /* triggered on internal transmission */
+ {
+ Srv_ClearEvent(&self_->service, AMD_EV_NOTIFY_RX);
+ if ((self_->started != false) && (self_->first_receive_fptr != NULL))
+ {
+ uint16_t size = Dl_GetSize(self_->first_q_ptr);
+ if (size > 0U)
+ {
+ self_->first_receive_fptr(self_->first_receive_inst_ptr);
+ }
+ }
+ }
+
+#ifdef AMD_TX_DISTRIB
+ if((event_mask & AMD_EV_NOTIFY_TX) == AMD_EV_NOTIFY_TX) /* notify Tx distribution failure asynchronously */
+ {
+ Srv_ClearEvent(&self_->service, AMD_EV_NOTIFY_TX);
+ Amd_TxProcessNotifyQueue(self_);
+ }
+#endif
+}
+
+/*------------------------------------------------------------------------------------------------*/
+/* Events */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Callback function which is invoked on completed application message reception
+ * \param self The instance
+ * \param msg_ptr Reference to the completed application message
+ */
+static void Amd_OnAmsComplete(void *self, Ucs_AmsRx_Msg_t *msg_ptr)
+{
+ CAmd *self_ = (CAmd*)self;
+
+ if (self_->rx_modification_fptr != NULL)
+ {
+ self_->rx_modification_fptr(self_->rx_modification_inst_ptr, msg_ptr);
+ }
+
+ if (self_->first_receive_fptr != NULL)
+ {
+ Amsg_RxEnqueue(msg_ptr, self_->first_q_ptr);
+
+ if (self_->started != false)
+ {
+ self_->first_receive_fptr(self_->first_receive_inst_ptr);
+ }
+ }
+ else
+ {
+ Ams_RxFreeMsg(self_->ams_ptr, msg_ptr);
+ }
+}
+
+/*! \brief Callback function if an events leads to the termination of the MNS
+ * \param self The instance
+ * \param error_code_ptr Reference to the error code
+ */
+static void Amd_OnTerminateEvent(void *self, void *error_code_ptr)
+{
+ CAmd *self_ = (CAmd*)self;
+ MISC_UNUSED(error_code_ptr);
+
+ TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Starting AMD Cleanup", 0U));
+ Amd_RxFlush(self_, &self_->pre_queue);
+ Amd_RxFlush(self_, &self_->rx_queue);
+#ifdef AMD_TX_DISTRIB
+ Amd_TxProcessNotifyQueue(self_);
+#endif
+ TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Finished AMD Cleanup", 0U));
+}
+
+/*! \brief Callback function which is invoked if the initialization is complete
+ * \param self The instance
+ * \param error_code_ptr Reference to the error code
+ */
+static void Amd_OnEvent(void *self, void *error_code_ptr)
+{
+ CAmd *self_ = (CAmd*)self;
+ MISC_UNUSED(error_code_ptr);
+
+ TR_INFO((self_->base_ptr->ucs_user_ptr, "[AMD]", "Received init complete event", 0U));
+ self_->started = true;
+ Srv_SetEvent(&self_->service, AMD_EV_NOTIFY_RX);
+}
+
+/*! \brief Flushes a given application Rx message queue
+ * \param self The instance
+ * \param list_ptr Reference to a list containing application Rx message objects
+ */
+static void Amd_RxFlush(CAmd *self, CDlList *list_ptr)
+{
+ Ucs_AmsRx_Msg_t *msg_ptr;
+
+ for (msg_ptr = Amsg_RxDequeue(list_ptr); msg_ptr != NULL; msg_ptr = Amsg_RxDequeue(list_ptr))
+ {
+ Ams_RxFreeMsg(self->ams_ptr, msg_ptr);
+ }
+}
+
+/*------------------------------------------------------------------------------------------------*/
+/* Pre-processor methods */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Peeks the front-most application message from the preprocessing queue
+ * \param self The instance
+ * \return Returns a reference to the front-most application message or \c NULL if the queue
+ * is empty.
+ */
+Ucs_AmsRx_Msg_t* Amd_PrePeekMsg(CAmd *self)
+{
+ return (Ucs_AmsRx_Msg_t*)(void*)Amsg_RxPeek(&self->pre_queue);
+}
+
+/*! \brief Removes the front-most application message from the preprocessing queue and frees it
+ * \param self The instance
+ */
+void Amd_PreReleaseMsg(CAmd *self)
+{
+ Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->pre_queue);
+
+ if (msg_ptr != NULL)
+ {
+ Ams_RxFreeMsg(self->ams_ptr, msg_ptr);
+ }
+}
+
+/*! \brief Forwards the front-most application message from the preprocessing queue to the Rx queue
+ * \param self The instance
+ */
+void Amd_PreForwardMsg(CAmd *self)
+{
+ Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->pre_queue);
+
+ if (msg_ptr != NULL)
+ {
+ if (self->receive_fptr != NULL)
+ {
+ Amsg_RxEnqueue(msg_ptr, &self->rx_queue);
+ self->receive_fptr(self->receive_inst_ptr);
+ }
+ else
+ {
+ Ams_RxFreeMsg(self->ams_ptr, msg_ptr);
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------------------------*/
+/* Receiver methods */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Peeks the front-most application message from the Rx queue
+ * \param self The instance
+ * \return Returns a reference to the front-most application message or \c NULL if the queue
+ * is empty.
+ */
+Ucs_AmsRx_Msg_t* Amd_RxPeekMsg(CAmd *self)
+{
+ return (Ucs_AmsRx_Msg_t*)(void*)Amsg_RxPeek(&self->rx_queue);
+}
+
+/*! \brief Removes the front-most application message from the Rx queue and frees it
+ * \param self The instance
+ */
+void Amd_RxReleaseMsg(CAmd *self)
+{
+ Ucs_AmsRx_Msg_t *msg_ptr = Amsg_RxDequeue(&self->rx_queue);
+
+ if (msg_ptr != NULL)
+ {
+ Ams_RxFreeMsg(self->ams_ptr, msg_ptr);
+ }
+}
+
+/*! \brief Retrieves the number of messages which are appended to the Rx queue
+ * \param self The instance
+ * \return Returns the number of messages.
+ */
+uint16_t Amd_RxGetMsgCnt(CAmd *self)
+{
+ return Dl_GetSize(&self->rx_queue);
+}
+
+#ifdef AMD_TX_DISTRIB
+/*------------------------------------------------------------------------------------------------*/
+/* Transmitter methods */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Distributes a Tx message internally as Rx message
+ * \param self The instance
+ * \param msg_ptr The Tx message
+ * \param tx_complete_sia_fptr Single instance API callback function which is invoked as soon as
+ * the transmission was finished.
+ * \param tx_complete_fptr Multi instance callback function which is invoked as soon as
+ * the transmission was finished.
+ * \param tx_complete_inst_ptr Instance pointer which is referred when tx_complete_fptr is invoked.
+ * \return Returns \c UCS_RET_SUCCESS if the message accepted for transmission.
+ * Returns \c UCS_RET_ERR_PARAM if the message is refused due to invalid message attributes.
+ */
+Ucs_Return_t Amd_TxSendMsg(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr, Amsg_TxCompleteSiaCb_t tx_complete_sia_fptr,
+ Amsg_TxCompleteCb_t tx_complete_fptr, void* tx_complete_inst_ptr)
+{
+ Ucs_Return_t ret = UCS_RET_SUCCESS;
+ bool tx_internal = false;
+ bool tx_network = false;
+ bool tx_ignore_nw_failure = false;
+ bool tx_check_ni = true; /* if false, transmit to INIC even during NET_OFF */
+
+ if (Ams_TxIsValidMessage(msg_ptr) != false)
+ {
+ Net_IsOwnAddrResult_t addr_type = Net_IsOwnAddress(self->net_ptr, msg_ptr->destination_address);
+
+ TR_ASSERT(self->base_ptr->ucs_user_ptr, "[AMS]", (((tx_complete_sia_fptr != NULL) && (tx_complete_fptr != NULL)) == false));
+ Amsg_TxSetCompleteCallback(msg_ptr, tx_complete_sia_fptr, tx_complete_fptr, tx_complete_inst_ptr);
+
+ if (msg_ptr->destination_address == UCS_ADDR_INTERNAL)
+ {
+ tx_internal = true; /* do not forward internal messages to INIC */
+ }
+ else if ((msg_ptr->fblock_id == AMD_FB_NETBLOCK) || (msg_ptr->fblock_id == AMD_FB_NETWORKMASTER))
+ {
+ if (addr_type == NET_IS_OWN_ADDR_NODE) /* replace own node address by "1" to force INIC internal routing */
+ { /* do not replace multicast addresses (these are static and handled by INIC) */
+ Amsg_TxReplaceDestinationAddr(msg_ptr, MSG_ADDR_INIC);
+ }
+ else if ((addr_type == NET_IS_OWN_ADDR_GROUP) ||
+ (msg_ptr->destination_address == UCS_ADDR_BROADCAST_BLOCKING) ||
+ (msg_ptr->destination_address == UCS_ADDR_BROADCAST_UNBLOCKING))
+ {
+ tx_ignore_nw_failure = true;
+ }
+
+ tx_network = true; /* route FBlocks NB and NWM to INIC */
+ tx_check_ni = false; /* INIC performs checks independent from NI state */
+ }
+ else if ((msg_ptr->destination_address == UCS_ADDR_BROADCAST_BLOCKING) ||
+ (msg_ptr->destination_address == UCS_ADDR_BROADCAST_UNBLOCKING))
+ {
+ tx_internal = true; /* forward broadcast messages to INIC and distribute internally */
+ tx_network = true;
+ }
+ else
+ {
+ switch (addr_type)
+ {
+ case NET_IS_OWN_ADDR_NODE:
+ tx_internal = true;
+ break;
+ case NET_IS_OWN_ADDR_GROUP:
+ tx_internal = true;
+ tx_network = true;
+ break;
+ case NET_IS_OWN_ADDR_NONE:
+ default:
+ tx_network = true;
+ break;
+ }
+ }
+
+ if ((Inic_GetAvailability(self->inic_ptr) == UCS_NW_NOT_AVAILABLE) && (tx_check_ni == true))
+ {
+ tx_network = false; /* abort network transmission */
+ Amsg_TxUpdateResult(msg_ptr, UCS_MSG_STAT_ERROR_NA_OFF);
+ }
+
+ if (tx_internal != false)
+ {
+ if (Amd_TxReceiveInternal(self, msg_ptr) == false)
+ { /* internal transmission failed */
+ Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_ERRBUF);
+ }
+ else
+ { /* internal transmission succeeded */
+ Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_SUCCESS);
+ }
+ }
+ else if (tx_ignore_nw_failure != false)
+ { /* INIC routing will succeed while NW transmission fails */
+ Amsg_TxUpdateInternalResult(msg_ptr, AMSG_TX_INTRES_SUCCESS);
+ }
+
+ if (tx_network == false)
+ { /* enqueue message to notification queue and set event */
+ Amsg_TxEnqueue(msg_ptr, &self->tx_notify_queue);
+ Srv_SetEvent(&self->service, AMD_EV_NOTIFY_TX);
+ }
+ else
+ {
+ Ams_TxSendMsgDirect(self->ams_ptr, msg_ptr);
+ }
+ }
+ else
+ {
+ ret = UCS_RET_ERR_PARAM; /* invalid message parameters */
+ }
+
+ return ret;
+}
+
+/*! \brief Decides whether to root a message to MCM or RCM FIFO
+ * \param msg_ptr The Tx message object
+ * \return Returns \c true if a Tx message shall be routed to RCM FIFO, otherwise returns \c false.
+ */
+static bool Amd_TxIsRcmMsg(Ucs_AmsTx_Msg_t *msg_ptr)
+{
+ bool ret = false;
+ if (((msg_ptr->fblock_id == AMD_FB_NETBLOCK) && (msg_ptr->op_type <= UCS_OP_STARTACK)) /* is NB.Command */
+ || ((msg_ptr->fblock_id == AMD_FB_NETWORKMASTER) && (msg_ptr->op_type > UCS_OP_STARTACK))) /* or NWM.Report?*/
+ {
+ ret = true;
+ }
+
+ return ret;
+}
+
+/*! \brief Distributes a Tx message internally as Rx message
+ * \param self The instance
+ * \param msg_ptr The Tx message
+ * \return Returns \c true if the message distributed successfully.
+ * Returns \c false if the allocation of the Rx message has failed.
+ */
+static bool Amd_TxReceiveInternal(CAmd *self, Ucs_AmsTx_Msg_t *msg_ptr)
+{
+ bool ret = false;
+ Ucs_AmsRx_Msg_t *rx_ptr = Amsp_AllocRxObj(self->pool_ptr, msg_ptr->data_size);
+
+ if (rx_ptr != NULL)
+ {
+ uint16_t src_addr = UCS_ADDR_INTERNAL;
+ if (msg_ptr->destination_address != UCS_ADDR_INTERNAL)
+ {
+ src_addr = Inic_GetNodeAddress(self->inic_ptr);
+ }
+ Amsg_RxBuildFromTx(rx_ptr, msg_ptr, src_addr);
+ if (self->first_q_ptr != NULL)
+ {
+ Amsg_RxEnqueue(rx_ptr, self->first_q_ptr);
+ Srv_SetEvent(&self->service, AMD_EV_NOTIFY_RX);
+ ret = true;
+ }
+ else
+ {
+ Amsp_FreeRxObj(self->pool_ptr, rx_ptr);
+ TR_FAILED_ASSERT(self->base_ptr->ucs_user_ptr, "[AMD]");
+ }
+ }
+
+ return ret;
+}
+
+/*! \brief Notifies the transmission result for all messages in the tx_notify_queue
+ * \param self The instance
+ */
+static void Amd_TxProcessNotifyQueue(CAmd *self)
+{
+ Ucs_AmsTx_Msg_t *tx_ptr = NULL;
+
+ for (tx_ptr = Amsg_TxDequeue(&self->tx_notify_queue); tx_ptr != NULL; tx_ptr = Amsg_TxDequeue(&self->tx_notify_queue))
+ {
+ /* just just notify completion, the object is automatically freed to the pool */
+ Amsg_TxNotifyComplete(tx_ptr, Amsg_TxGetResultCode(tx_ptr), Amsg_TxGetResultInfo(tx_ptr));
+ }
+}
+#endif
+
+/*!
+ * @}
+ * \endcond
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* End of file */
+/*------------------------------------------------------------------------------------------------*/
+