1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491 */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
5 /* This program is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 2 of the License, or */
8 /* (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* You may also obtain this software under a propriety license from Microchip. */
19 /* Please contact Microchip for further information. */
20 /*------------------------------------------------------------------------------------------------*/
24 * \brief Implementation of class CTransceiver
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
34 #include "ucs_transceiver.h"
38 /*------------------------------------------------------------------------------------------------*/
39 /* Internal prototypes */
40 /*------------------------------------------------------------------------------------------------*/
41 static void Trcv_OnTxStatusInternal(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status);
43 /*------------------------------------------------------------------------------------------------*/
45 /*------------------------------------------------------------------------------------------------*/
46 /*! \brief Constructor of class CTransceiver
47 * \param self The instance
48 * \param fifo_ptr Reference to the dedicated port message FIFO
49 * \param def_src_addr Source address that is preset in Tx message object
50 * \param ucs_user_ptr User reference that needs to be passed in every callback function
51 * \param trace_id ID specifies FIFO in traces if multiple transceivers are running
53 void Trcv_Ctor(CTransceiver *self, CPmFifo *fifo_ptr, uint16_t def_src_addr, void *ucs_user_ptr, uint8_t trace_id)
55 MISC_MEM_SET(self, 0, sizeof(*self));
56 self->fifo_ptr = fifo_ptr;
57 self->tx_def_src = def_src_addr;
58 self->ucs_user_ptr = ucs_user_ptr;
59 self->own_id = trace_id;
60 Pool_Ctor(&self->tx_msg_pool, self->tx_msgs, TRCV_SIZE_TX_POOL, ucs_user_ptr);
61 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (fifo_ptr != NULL));
64 /*! \brief Assigns a function of another class to receive messages
65 * \details The assigned function is responsible to call Trcv_RxReleaseMsg() it has finished to process it
66 * \param self The instance
67 * \param callback_fptr Callback function
68 * \param inst_ptr The instance of the receiver class
70 void Trcv_RxAssignReceiver(CTransceiver *self, Trcv_RxCompleteCb_t callback_fptr, void *inst_ptr)
72 self->rx_complete_fptr = callback_fptr;
73 self->rx_complete_inst = inst_ptr;
76 /*! \brief Assigns a function of another class to filter Rx messages
77 * \details The assigned function is responsible to discard or pass Rx messages
78 * \param self The instance
79 * \param callback_fptr Callback function
80 * \param inst_ptr The instance of the filter class
82 void Trcv_RxAssignFilter(CTransceiver *self, Trcv_RxFilterCb_t callback_fptr, void *inst_ptr)
84 self->rx_filter_fptr = callback_fptr;
85 self->rx_filter_inst = inst_ptr;
88 /*! \brief Releases an Rx message which was received by the assigned receiver
89 * \param self The instance
90 * \param tel_ptr Reference to the received message
92 void Trcv_RxReleaseMsg(CTransceiver *self, Msg_MostTel_t *tel_ptr)
94 CMessage *msg_ptr = (CMessage*)(void*)tel_ptr;
95 bool check_ok = !Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)); /* message object shall not be part of a list */
96 /* because it was provided in an earlier step */
97 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", check_ok);
100 Fifo_RxReleaseMsg(self->fifo_ptr, msg_ptr);
104 /*! \brief Retrieves a message object from the pool
105 * \param self The instance
106 * \param size Size of the message in bytes. Valid range: 0..45.
107 * \return Reference to the Msg_MostTel_t structure if a message is available.
110 extern Msg_MostTel_t* Trcv_TxAllocateMsg(CTransceiver *self, uint8_t size)
112 const uint8_t TRCV_CTRL_MAX_SIZE = 45U; /* replace by PMS constant in future */
113 CMessage *handle = NULL;
114 Msg_MostTel_t *tel_ptr = NULL;
116 if (size <= TRCV_CTRL_MAX_SIZE)
118 handle = Pool_GetMsg(&self->tx_msg_pool);
122 Msg_Cleanup(handle); /* reset headers and fields */
123 Msg_ReserveHeader(handle, PMP_PM_MAX_SIZE_HEADER + ENC_MAX_SIZE_CONTENT);
124 tel_ptr = Msg_GetMostTel(handle); /* return public struct of the message object */
125 tel_ptr->tel.tel_id = 0U;
126 tel_ptr->tel.tel_len = size;
127 tel_ptr->tel.tel_cnt = 0U;
128 tel_ptr->source_addr = self->tx_def_src;
135 /*! \brief Returns a message object to the transceiver pool a message was allocated from
136 * \param tel_ptr Reference to the message object which needs to be returned.
138 void Trcv_TxReleaseMsg(Msg_MostTel_t *tel_ptr)
140 CMessage* msg_ptr = (CMessage*)(void*)tel_ptr; /* avoid MISRA-C warning by converting to "void*" */
141 bool check_ok = !Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)); /* message object shall not be part of a list */
142 TR_ASSERT(0U, "[TRCV]", check_ok); /* because it was provided in an earlier step */
146 Pool_ReturnMsg(msg_ptr);
150 /*! \brief Prepares a message object for re-transmission
151 * \param tel_ptr Reference to the Tx message object which needs
154 void Trcv_TxReuseMsg(Msg_MostTel_t *tel_ptr)
156 CMessage* msg_ptr = (CMessage*)(void*)tel_ptr;
157 TR_ASSERT(0U, "[TRCV]", (!Dln_IsNodePartOfAList(Msg_GetNode(msg_ptr)))); /* message object shall not be part of a list */
158 /* because it was provided in an earlier step */
159 Msg_Cleanup(msg_ptr); /* reset headers and fields */
160 Msg_ReserveHeader(msg_ptr, PMP_PM_MAX_SIZE_HEADER + ENC_MAX_SIZE_CONTENT);
163 /*! \brief Transmits a given message object to the INIC
164 * \details After completed transmission the message object is released automatically
165 * \param self The instance
166 * \param tel_ptr Reference to the message object
168 void Trcv_TxSendMsg(CTransceiver *self, Msg_MostTel_t *tel_ptr)
172 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL));
173 msg_ptr = (CMessage*)(void*)tel_ptr;
175 TR_INFO((self->ucs_user_ptr, "[TRCV]", "Trcv_TxSendMsg(): FIFO: %u, MSG(tgt:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self->own_id, tel_ptr->destination_addr, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type));
176 Msg_SetTxStatusHandler(msg_ptr, &Trcv_OnTxStatusInternal, self); /* just release the message */
177 Fifo_Tx(self->fifo_ptr, msg_ptr, false);
180 /*! \brief Transmits a given message object to the INIC with a dedicated result callback
181 * \param self The instance
182 * \param tel_ptr Reference to the message object
183 * \param callback_fptr Callback function which is invoked after message transmission has finished.
184 * Must be \c NULL to avoid that a callback function is invoked. In this case
185 * the message object is freed internally. Hence, the message object must
186 * not provide external payload.
187 * \param inst_ptr Reference to the instance which is invoked with callback_fptr. Has to be \c
188 * NULL if callback_fptr is \c NULL.
189 * \note The provided callback function is responsible to free the message object by calling
190 * Trcv_TxReleaseMsg() or to reuse the message object by calling Trcv_TxReuseMsg() before
191 * passing it to one of the transmit functions again.
193 void Trcv_TxSendMsgExt(CTransceiver *self, Msg_MostTel_t *tel_ptr, Msg_TxStatusCb_t callback_fptr, void *inst_ptr)
197 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL));
198 msg_ptr = (CMessage*)(void*)tel_ptr;
200 if (callback_fptr == NULL)
202 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (inst_ptr == NULL));
203 callback_fptr = &Trcv_OnTxStatusInternal;
207 TR_INFO((self->ucs_user_ptr, "[TRCV]", "Trcv_TxSendMsgExt(): FIFO: %u, MSG(tgt:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self->own_id, tel_ptr->destination_addr, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type));
208 Msg_SetTxStatusHandler(msg_ptr, callback_fptr, inst_ptr);
209 Fifo_Tx(self->fifo_ptr, msg_ptr, false);
212 /*! \brief Transmits a given message object to the INIC bypassing all other messages in the FIFO
213 * \param self The instance
214 * \param tel_ptr Reference to the message object
215 * \param callback_fptr Callback function which is invoked after message transmission has finished.
216 * Must be \c NULL to avoid that a callback function is invoked. In this case
217 * the message object is freed internally. Hence, the message object must
218 * not provide external payload.
219 * \param inst_ptr Reference to the instance which is invoked
220 * \note The provided callback function is responsible to free the message object by calling
221 * Trcv_TxReleaseMsg() or to reuse the message object by calling Trcv_TxReuseMsg() before
222 * passing it to one of the transmit functions again.
224 void Trcv_TxSendMsgBypass(CTransceiver *self, Msg_MostTel_t *tel_ptr, Msg_TxStatusCb_t callback_fptr, void *inst_ptr)
228 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (tel_ptr != NULL));
229 msg_ptr = (CMessage*)(void*)tel_ptr;
231 if (callback_fptr == NULL)
233 TR_ASSERT(self->ucs_user_ptr, "[TRCV]", (inst_ptr == NULL));
234 callback_fptr = &Trcv_OnTxStatusInternal;
238 Msg_SetTxStatusHandler(msg_ptr, callback_fptr, inst_ptr);
239 Fifo_Tx(self->fifo_ptr, msg_ptr, true);
242 /*! \brief Callback function which is invoked instead of an external callback
243 * as soon as channel transmission was finished in PMS.
244 * \param self The instance
245 * \param tel_ptr Reference to the message object
246 * \param status Transmission status
248 static void Trcv_OnTxStatusInternal(void *self, Msg_MostTel_t *tel_ptr, Ucs_MsgTxStatus_t status)
250 Trcv_TxReleaseMsg(tel_ptr);
255 /*! \brief Internal callback function which is intended to be
256 * invoked by the port message channel on completed reception.
257 * \param self The instance
258 * \param tel_ptr Reference to the message object
260 void Trcv_RxOnMsgComplete(void *self, CMessage *tel_ptr)
262 CTransceiver *self_ = (CTransceiver*)self;
263 bool discard = false;
265 TR_INFO((self_->ucs_user_ptr, "[TRCV]", "Trcv_RxOnMsgComplete(): FIFO: %u, MSG(src:0x%04X, id:%02X.%01X.%04X.%01X)", 6U, self_->own_id, tel_ptr->pb_msg.source_addr, tel_ptr->pb_msg.id.fblock_id, tel_ptr->pb_msg.id.instance_id, tel_ptr->pb_msg.id.function_id, tel_ptr->pb_msg.id.op_type));
266 if (self_->rx_filter_fptr != NULL)
268 discard = self_->rx_filter_fptr(self_->rx_filter_inst, Msg_GetMostTel(tel_ptr));
271 if ((self_->rx_complete_fptr != NULL) && (discard == false))
273 /* the assigned Rx function is responsible to release the message */
274 self_->rx_complete_fptr(self_->rx_complete_inst, Msg_GetMostTel(tel_ptr));
278 Fifo_RxReleaseMsg(self_->fifo_ptr, tel_ptr);
287 /*------------------------------------------------------------------------------------------------*/
289 /*------------------------------------------------------------------------------------------------*/