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 the UNICENS API.
27 /*------------------------------------------------------------------------------------------------*/
29 /*------------------------------------------------------------------------------------------------*/
30 #include "ucs_class.h"
32 #include "ucs_trace.h"
36 /*------------------------------------------------------------------------------------------------*/
38 /*------------------------------------------------------------------------------------------------*/
39 /*! \def UCS_NUM_INSTANCES
40 * \brief Number of API instances which can be created by function Ucs_CreateInstance().
41 * \details One API instance is used to communicate with one local INIC. In this case the application
42 * is connected to one network.
43 * It is possible access multiple networks by having multiple API instances. Each API instance
44 * requires communication with an exclusive INIC.
45 * Valid values: 1..10. Default Value: 1.
46 * \ingroup G_UCS_INIT_AND_SRV
48 #ifndef UCS_NUM_INSTANCES
49 # define UCS_NUM_INSTANCES 1
50 # define UCS_API_INSTANCES 1U /* default value */
51 #elif (UCS_NUM_INSTANCES > 10)
52 # define UCS_API_INSTANCES 10U
53 #elif (UCS_NUM_INSTANCES < 1)
54 # define UCS_API_INSTANCES 1U
56 # define UCS_API_INSTANCES ((uint8_t)UCS_NUM_INSTANCES)
59 /*! \cond UCS_INTERNAL_DOC
60 * \addtogroup G_UCS_CLASS
64 /*------------------------------------------------------------------------------------------------*/
65 /* Internal Prototypes */
66 /*------------------------------------------------------------------------------------------------*/
67 static bool Ucs_CheckInitData(const Ucs_InitData_t *init_ptr);
68 static void Ucs_Ctor(CUcs* self, uint8_t ucs_inst_id, void *api_user_ptr);
69 static void Ucs_InitComponents(CUcs* self);
70 static void Ucs_InitFactoryComponent(CUcs *self);
71 static void Ucs_InitBaseComponent(CUcs *self);
72 static void Ucs_InitPmsComponentConfig(CUcs *self);
73 static void Ucs_InitNetComponent(CUcs *self);
74 static void Ucs_InitLocalInicComponent(CUcs *self);
75 static void Ucs_InitRoutingComponent(CUcs *self);
76 static void Ucs_InitAtsClass(CUcs *self);
77 static void Ucs_InitExcComponent(CUcs *self);
78 static void Ucs_InitSysDiagComponent(CUcs *self);
79 static void Ucs_InitNodeDiscovery(CUcs *self);
80 static void Ucs_InitBackChannelDiagnosis(CUcs *self);
81 static void Ucs_InitProgramming(CUcs *self);
82 static void Ucs_InitManager(CUcs *self);
83 static void Ucs_InitResultCb(void *self, void *result_ptr);
84 static void Ucs_UninitResultCb(void *self, void *error_code_ptr);
85 static void Ucs_OnRxRcm(void *self, Msg_MostTel_t *tel_ptr);
86 static bool Ucs_OnRxMsgFilter(void *self, Msg_MostTel_t *tel_ptr);
87 static void Ucs_OnGetTickCount(void *self, void *tick_count_value_ptr);
88 static void Ucs_OnSetApplicationTimer(void *self, void *new_time_value_ptr);
89 static void Ucs_OnServiceRequest(void *self, void *result_ptr);
90 static void Ucs_OnGeneralError(void *self, void *result_ptr);
91 static void Ucs_Most_PortStatusCb(void *self, void *result_ptr);
92 static void Ucs_StartAppNotification(CUcs *self);
93 static void Ucs_StopAppNotification(CUcs *self);
94 static void Ucs_Inic_OnDeviceStatus(void *self, void *data_ptr);
95 static void Ucs_NetworkStartupResult(void *self, void *result_ptr);
96 static void Ucs_NetworkShutdownResult(void *self, void *result_ptr);
97 static void Ucs_NetworkForceNAResult(void *self, void *result_ptr);
98 static void Ucs_NetworkFrameCounterResult(void *self, void *result_ptr);
99 static void Ucs_NetworkStatus(void *self, void *result_ptr);
100 static void Ucs_InitPmsComponent(CUcs *self);
101 static void Ucs_InitPmsComponentApp(CUcs *self);
102 static void Ucs_InitAmsComponent(CUcs *self);
103 static void Ucs_AmsRx_Callback(void *self);
104 static void Ucs_AmsTx_FreedCallback(void *self, void *data_ptr);
105 static bool Ucs_McmRx_FilterCallback(void *self, Msg_MostTel_t *tel_ptr);
106 static Ucs_Nd_CheckResult_t Ucs_OnNdEvaluate(void *self, Ucs_Signature_t *signature_ptr);
107 static void Ucs_OnNdReport(void *self, Ucs_Nd_ResCode_t code, Ucs_Signature_t *signature_ptr);
109 /*------------------------------------------------------------------------------------------------*/
111 /*------------------------------------------------------------------------------------------------*/
112 extern Ucs_Inst_t* Ucs_CreateInstance(void)
114 static CUcs api_instances[UCS_API_INSTANCES];
115 static uint8_t next_index = 0U;
116 Ucs_Inst_t *inst_ptr = NULL;
118 if (next_index < UCS_API_INSTANCES)
120 CUcs *ucs_ptr = &api_instances[next_index];
121 ucs_ptr->ucs_inst_id = next_index + 1U; /* start with instance id "1" */
122 TR_INFO((ucs_ptr->ucs_user_ptr, "[API]", "Ucs_CreateInstance(): returns 0x%p", 1U, ucs_ptr));
123 inst_ptr = (Ucs_Inst_t*)(void*)ucs_ptr; /* convert API pointer to abstract data type */
128 TR_INFO((0U, "[API]", "Ucs_CreateInstance(): failed!", 0U));
135 /*------------------------------------------------------------------------------------------------*/
136 /* Initialization structure */
137 /*------------------------------------------------------------------------------------------------*/
138 extern Ucs_Return_t Ucs_SetDefaultConfig(Ucs_InitData_t *init_ptr)
140 Ucs_Return_t ret = UCS_RET_ERR_PARAM;
142 if (init_ptr != NULL)
144 MISC_MEM_SET(init_ptr, 0, sizeof(*init_ptr));
145 /* -- add default values here -- */
146 init_ptr->general.inic_watchdog_enabled = true;
147 init_ptr->ams.enabled = true;
148 init_ptr->network.status.notification_mask = 0xFFFFU; /* Initialize notification masks for NET callbacks */
149 init_ptr->mgr.packet_bw = MGR_PACKET_BW_DEFAULT;
150 init_ptr->mgr.enabled = false;
151 ret = UCS_RET_SUCCESS;
154 TR_INFO((0U, "[API]", "Ucs_SetDefaultConfig(init_ptr: 0x%p): called", 1U, init_ptr));
158 /*! \brief Checks if the given initialization data is valid
159 * \param init_ptr Reference to initialization data
160 * \return Returns \c true if the given initialization data is valid, otherwise \c false.
162 static bool Ucs_CheckInitData(const Ucs_InitData_t *init_ptr)
166 if ((init_ptr == NULL) || /* General NULL pointer checks */
167 (init_ptr->general.get_tick_count_fptr == NULL) ||
168 (init_ptr->lld.start_fptr == NULL) ||
169 (init_ptr->lld.stop_fptr == NULL) ||
170 (init_ptr->lld.tx_transmit_fptr == NULL)
173 TR_ERROR((0U, "[API]", "Initialization failed. Required initialization data contains a NULL pointer.", 0U));
176 else if (((init_ptr->general.set_application_timer_fptr == NULL) && (init_ptr->general.request_service_fptr != NULL)) ||
177 ((init_ptr->general.set_application_timer_fptr != NULL) && (init_ptr->general.request_service_fptr == NULL)))
179 TR_ERROR((0U, "[API]", "Initialization failed. To run UCS in event driven service mode, both callback functions must be assigned.", 0U));
182 else if ((init_ptr->mgr.enabled != false) && ((init_ptr->nd.eval_fptr != NULL) || (init_ptr->nd.report_fptr != NULL)))
184 TR_INFO((0U, "[API]", "Ambiguous initialization structure. NodeDiscovery callback functions are not effective if 'mgr.enabled' is 'true'.", 0U));
190 /*------------------------------------------------------------------------------------------------*/
191 /* Class initialization */
192 /*------------------------------------------------------------------------------------------------*/
193 /*! \brief Constructor of API. Values are reset, initialization must be triggered via Ucs_Init().
194 * \param self The instance
195 * \param ucs_inst_id The ID of the instance
196 * \param api_user_ptr The user reference for API callback functions
198 static void Ucs_Ctor(CUcs* self, uint8_t ucs_inst_id, void *api_user_ptr)
200 MISC_MEM_SET(self, 0, sizeof(*self)); /* reset memory and backup/restore instance id */
201 self->ucs_inst_id = ucs_inst_id;
202 self->ucs_user_ptr = api_user_ptr;
205 extern Ucs_Return_t Ucs_Init(Ucs_Inst_t* self, const Ucs_InitData_t *init_ptr, Ucs_InitResultCb_t init_result_fptr)
207 CUcs *self_ = (CUcs*)(void*)self;
208 Ucs_Return_t ret = UCS_RET_ERR_PARAM;
210 /* Note: "self_->ucs_inst_id" is already set to the correct value in Ucs_CreateInstance(), do not overwrite it */
211 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Init(init_ptr: 0x%p): called", 1U, init_ptr));
213 if (Ucs_CheckInitData(init_ptr))
215 Ucs_Ctor(self_, self_->ucs_inst_id, init_ptr->user_ptr);/* initialize object */
216 self_->init_result_fptr = init_result_fptr; /* backup result callback function */
218 self_->init_data = *init_ptr; /* backup init data */
219 Ucs_InitComponents(self_); /* call constructors and link all components */
220 /* create init-complete observer */
221 Sobs_Ctor(&self_->init_result_obs, self, &Ucs_InitResultCb);
222 Ats_Start(&self_->inic.attach, &self_->init_result_obs);/* Start attach process */
223 ret = UCS_RET_SUCCESS;
225 /* register observer related to Ucs_Stop() */
226 Mobs_Ctor(&self_->uninit_result_obs, self, (EH_E_UNSYNC_COMPLETE | EH_E_UNSYNC_FAILED), &Ucs_UninitResultCb);
230 extern void Ucs_Service(Ucs_Inst_t* self)
232 CUcs *self_ = (CUcs*)(void*)self;
233 bool pending_events = false;
235 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Service(): called", 0U));
236 Scd_Service(&self_->general.base.scd); /* Run the scheduler */
237 pending_events = Scd_AreEventsPending(&self_->general.base.scd); /* Check if events are still pending? */
239 if (pending_events != false) /* At least one event is pending? */
241 if (self_->general.request_service_fptr != NULL)
243 self_->general.request_service_fptr(self_->ucs_user_ptr); /* Trigger UCS service call immediately */
247 Tm_CheckForNextService(&self_->general.base.tm); /* If UCS timers are running: What is the next time that
248 * the timer management must be serviced again? */
251 extern void Ucs_ReportTimeout(Ucs_Inst_t* self)
253 CUcs *self_ = (CUcs*)(void*)self;
254 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_ReportTimeout(): called", 0U));
255 Tm_TriggerService(&self_->general.base.tm); /* Trigger TM service call */
258 extern Ucs_Return_t Ucs_Stop(Ucs_Inst_t* self, Ucs_StdResultCb_t stopped_fptr)
260 CUcs *self_ = (CUcs*)(void*)self;
261 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
263 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_Stop() called", 0U));
265 if ((self_->uninit_result_fptr == NULL) && (self_->init_complete != false))
267 if (stopped_fptr != NULL)
269 self_->uninit_result_fptr = stopped_fptr;
270 Eh_DelObsrvPublicError(&self_->general.base.eh);
271 Eh_AddObsrvInternalEvent(&self_->general.base.eh, &self_->uninit_result_obs);
272 ret_val = UCS_RET_SUCCESS;
273 Fifos_ConfigureSyncParams(&self_->fifos, FIFOS_UNSYNC_RETRIES, FIFOS_UNSYNC_TIMEOUT);
274 Fifos_Unsynchronize(&self_->fifos, true, false);
279 ret_val = UCS_RET_ERR_API_LOCKED; /* termination is already running */
285 /*------------------------------------------------------------------------------------------------*/
286 /* Connection Routing Management */
287 /*------------------------------------------------------------------------------------------------*/
288 Ucs_Return_t Ucs_Rm_Start(Ucs_Inst_t *self, Ucs_Rm_Route_t *routes_list, uint16_t list_size)
290 CUcs *self_ = (CUcs*)(void*)self;
292 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
294 if (self_->init_complete != false)
296 ret_val = Rtm_StartProcess (&self_->rtm, routes_list, list_size);
302 Ucs_Return_t Ucs_Rm_SetRouteActive (Ucs_Inst_t *self, Ucs_Rm_Route_t *route_ptr, bool active)
304 CUcs *self_ = (CUcs*)(void*)self;
306 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
308 if ((self_ != NULL) && (route_ptr != NULL))
310 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
311 if (self_->init_complete != false)
315 ret_val = Rtm_DeactivateRoute(&self_->rtm, route_ptr);
319 ret_val = Rtm_ActivateRoute(&self_->rtm, route_ptr);
327 Ucs_Return_t Ucs_Xrm_Stream_SetPortConfig(Ucs_Inst_t *self,
328 uint16_t destination_address,
330 Ucs_Stream_PortOpMode_t op_mode,
331 Ucs_Stream_PortOption_t port_option,
332 Ucs_Stream_PortClockMode_t clock_mode,
333 Ucs_Stream_PortClockDataDelay_t clock_data_delay,
334 Ucs_Xrm_Stream_PortCfgResCb_t result_fptr)
336 CUcs *self_ = (CUcs*)(void*)self;
337 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
341 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
342 if (self_->init_complete != false)
344 ret_val = Xrm_Stream_SetPortConfig(Fac_GetXrmLegacy(&self_->factory, destination_address, self_->init_data.rm.xrm.check_unmute_fptr),
357 Ucs_Return_t Ucs_Xrm_Stream_GetPortConfig(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index,
358 Ucs_Xrm_Stream_PortCfgResCb_t result_fptr)
360 CUcs *self_ = (CUcs*)(void*)self;
361 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
365 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
366 if (self_->init_complete != false)
368 ret_val = Xrm_Stream_GetPortConfig(Fac_GetXrmLegacy(&self_->factory, destination_address, self_->init_data.rm.xrm.check_unmute_fptr),
376 /*------------------------------------------------------------------------------------------------*/
377 /* Node Management */
378 /*------------------------------------------------------------------------------------------------*/
379 Ucs_Return_t Ucs_Rm_SetNodeAvailable(Ucs_Inst_t *self, Ucs_Rm_Node_t *node_ptr, bool available)
381 CUcs *self_ = (CUcs*)(void*)self;
382 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
384 if ((self_ != NULL) && (node_ptr != NULL))
386 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
387 if (self_->init_complete != false)
389 ret_val = Rtm_SetNodeAvailable(&self_->rtm, node_ptr, available);
396 bool Ucs_Rm_GetNodeAvailable (Ucs_Inst_t *self, Ucs_Rm_Node_t *node_ptr)
398 CUcs *self_ = (CUcs*)(void*)self;
399 bool ret_val = false;
401 if ((self_ != NULL) && (node_ptr != NULL))
403 ret_val = Rtm_GetNodeAvailable(&self_->rtm, node_ptr);
409 Ucs_Return_t Ucs_Rm_GetAttachedRoutes (Ucs_Inst_t *self, Ucs_Rm_EndPoint_t * ep_inst,
410 Ucs_Rm_Route_t * ls_found_routes[], uint16_t ls_size)
412 CUcs *self_ = (CUcs*)(void*)self;
413 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
417 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
418 if (self_->init_complete != false)
420 ret_val = Rtm_GetAttachedRoutes(&self_->rtm, ep_inst, ls_found_routes, ls_size);
427 uint16_t Ucs_Rm_GetConnectionLabel(Ucs_Inst_t *self, Ucs_Rm_Route_t *route_ptr)
429 uint16_t ret_value = 0U;
430 CUcs *self_ = (CUcs*)(void*)self;
432 if ((self_ != NULL) && (self_->init_complete != false) && (route_ptr != NULL))
434 ret_value = Rtm_GetConnectionLabel(&self_->rtm, route_ptr);
440 /*------------------------------------------------------------------------------------------------*/
441 /* Node Scripting Management */
442 /*------------------------------------------------------------------------------------------------*/
443 Ucs_Return_t Ucs_Ns_Run (Ucs_Inst_t *self, Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCb_t result_fptr)
445 CUcs *self_ = (CUcs*)(void*)self;
446 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
448 if ((self_ != NULL) && (node_ptr != NULL) && (node_ptr->signature_ptr != NULL))
450 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
451 if (self_->init_complete != false)
453 CNodeScriptManagement * nsm_inst = Fac_GetNsm(&self_->factory, node_ptr->signature_ptr->node_address);
455 ret_val = UCS_RET_ERR_NOT_AVAILABLE;
456 if (nsm_inst != NULL)
458 ret_val = Nsm_Run_Pb(nsm_inst, node_ptr, result_fptr);
466 /*------------------------------------------------------------------------------------------------*/
467 /* GPIO and I2C Peripheral Bus Interfaces */
468 /*------------------------------------------------------------------------------------------------*/
469 Ucs_Return_t Ucs_Gpio_CreatePort(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index, uint16_t debounce_time, Ucs_Gpio_CreatePortResCb_t result_fptr)
471 CUcs *self_ = (CUcs*)(void*)self;
472 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
476 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
477 if (self_->init_complete != false)
479 ret_val = Gpio_CreatePort(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr),
489 Ucs_Return_t Ucs_Gpio_SetPinMode(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle,
490 uint8_t pin, Ucs_Gpio_PinMode_t mode, Ucs_Gpio_ConfigPinModeResCb_t result_fptr)
492 CUcs *self_ = (CUcs*)(void*)self;
493 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
497 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
498 if (self_->init_complete != false)
500 ret_val = Gpio_SetPinModeConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr),
511 Ucs_Return_t Ucs_Gpio_GetPinMode(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, Ucs_Gpio_ConfigPinModeResCb_t result_fptr)
513 CUcs *self_ = (CUcs*)(void*)self;
514 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
518 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
519 if (self_->init_complete != false)
521 ret_val = Gpio_GetPinModeConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr),
530 Ucs_Return_t Ucs_Gpio_WritePort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle,
531 uint16_t mask, uint16_t data, Ucs_Gpio_PinStateResCb_t result_fptr)
533 CUcs *self_ = (CUcs*)(void*)self;
534 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
538 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
539 if (self_->init_complete != false)
541 ret_val = Gpio_SetPinStateConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr),
552 Ucs_Return_t Ucs_Gpio_ReadPort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t gpio_port_handle, Ucs_Gpio_PinStateResCb_t result_fptr)
554 CUcs *self_ = (CUcs*)(void*)self;
555 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
559 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
560 if (self_->init_complete != false)
562 ret_val = Gpio_GetPinStateConfig(Fac_GetGpio(&self_->factory, destination_address, self_->init_data.gpio.trigger_event_status_fptr),
571 Ucs_Return_t Ucs_I2c_CreatePort(Ucs_Inst_t *self, uint16_t destination_address, uint8_t index, Ucs_I2c_Speed_t speed,
572 uint8_t i2c_int_mask, Ucs_I2c_CreatePortResCb_t result_fptr)
574 CUcs *self_ = (CUcs*)(void*)self;
575 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
579 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
580 if (self_->init_complete != false)
582 ret_val = I2c_CreatePort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr),
593 Ucs_Return_t Ucs_I2c_WritePort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t port_handle, Ucs_I2c_TrMode_t mode, uint8_t block_count,
594 uint8_t slave_address, uint16_t timeout, uint8_t data_len, uint8_t * data_ptr,
595 Ucs_I2c_WritePortResCb_t result_fptr)
597 CUcs *self_ = (CUcs*)(void*)self;
598 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
602 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
603 if (self_->init_complete != false)
605 ret_val = I2c_WritePort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr),
620 Ucs_Return_t Ucs_I2c_ReadPort(Ucs_Inst_t *self, uint16_t destination_address, uint16_t port_handle, uint8_t slave_address, uint8_t data_len,
621 uint16_t timeout, Ucs_I2c_ReadPortResCb_t result_fptr)
623 CUcs *self_ = (CUcs*)(void*)self;
624 Ucs_Return_t ret_val = UCS_RET_ERR_PARAM;
628 ret_val = UCS_RET_ERR_NOT_INITIALIZED;
629 if (self_->init_complete != false)
631 ret_val = I2c_ReadPort(Fac_GetI2c(&self_->factory, destination_address, self_->init_data.i2c.interrupt_status_fptr),
643 /*------------------------------------------------------------------------------------------------*/
645 /*------------------------------------------------------------------------------------------------*/
646 /*! \brief Initializes all UCS core components
647 * \param self The instance
649 static void Ucs_InitComponents(CUcs* self)
651 Ucs_InitBaseComponent(self);
652 Ucs_InitFactoryComponent(self);
653 Ucs_InitLocalInicComponent(self);
654 Ucs_InitNetComponent(self);
655 Ucs_InitPmsComponent(self);
656 Ucs_InitAmsComponent(self);
657 Ucs_InitRoutingComponent(self);
658 Ucs_InitAtsClass(self);
660 Ucs_InitExcComponent(self);
661 Ucs_InitSysDiagComponent(self);
662 Ucs_InitNodeDiscovery(self);
663 Ucs_InitBackChannelDiagnosis(self);
664 Ucs_InitProgramming(self);
665 Ucs_InitManager(self); /* shall be called as last one due to re-configuration work */
668 /*! \brief Initializes the factory component
669 * \param self The instance
671 static void Ucs_InitFactoryComponent(CUcs *self)
673 Fac_InitData_t fac_init_data;
674 fac_init_data.base_ptr = &self->general.base;
675 fac_init_data.net_ptr = &self->net.inst;
676 fac_init_data.xrmp_ptr = &self->xrmp;
677 fac_init_data.icm_transceiver = &self->icm_transceiver;
678 fac_init_data.rcm_transceiver = &self->rcm_transceiver;
679 Fac_Ctor(&self->factory, &fac_init_data);
682 /*! \brief Initializes the the base component
683 * \param self The instance
685 static void Ucs_InitBaseComponent(CUcs *self)
687 Base_InitData_t base_init_data;
689 if (self->init_data.general.request_service_fptr != NULL) /* pointer may be NULL for termination */
691 self->general.request_service_fptr = self->init_data.general.request_service_fptr;
692 Sobs_Ctor(&self->general.service_request_obs, self, &Ucs_OnServiceRequest);
693 base_init_data.scd.service_request_obs_ptr = &self->general.service_request_obs;
697 base_init_data.scd.service_request_obs_ptr = NULL;
700 self->general.get_tick_count_fptr = self->init_data.general.get_tick_count_fptr;
701 Sobs_Ctor(&self->general.get_tick_count_obs, self, &Ucs_OnGetTickCount);
702 base_init_data.tm.get_tick_count_obs_ptr = &self->general.get_tick_count_obs;
703 if (self->init_data.general.set_application_timer_fptr != NULL)
705 self->general.set_application_timer_fptr = self->init_data.general.set_application_timer_fptr;
706 Sobs_Ctor(&self->general.set_application_timer_obs, self, &Ucs_OnSetApplicationTimer);
707 base_init_data.tm.set_application_timer_obs_ptr = &self->general.set_application_timer_obs;
711 base_init_data.tm.set_application_timer_obs_ptr = NULL;
713 base_init_data.ucs_inst_id = self->ucs_inst_id;
714 base_init_data.ucs_user_ptr = self->ucs_user_ptr;
715 Base_Ctor(&self->general.base, &base_init_data);
718 /*! \brief Initializes the port message service
719 * \param self The instance
721 static void Ucs_InitPmsComponent(CUcs *self)
723 CPmFifo * mcm_fifo_ptr = NULL;
725 if (self->init_data.ams.enabled == true)
727 mcm_fifo_ptr = &self->msg.mcm_fifo;
730 Ucs_InitPmsComponentConfig(self);
731 Ucs_InitPmsComponentApp(self);
733 Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, &self->icm_fifo, mcm_fifo_ptr, &self->rcm_fifo);
734 Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */
737 /*! \brief Initializes the port message service
738 * \param self The instance
740 static void Ucs_InitPmsComponentConfig(CUcs *self)
742 Pmch_InitData_t pmch_init_data;
743 Fifo_InitData_t icm_init;
744 Fifo_Config_t icm_config;
745 Fifo_InitData_t rcm_init;
746 Fifo_Config_t rcm_config;
748 /* Initialize port message service */
749 pmch_init_data.ucs_user_ptr = self->ucs_user_ptr;
750 pmch_init_data.tx_release_fptr = &Fifo_TxOnRelease;
751 pmch_init_data.lld_iface = self->init_data.lld;
752 Pmch_Ctor(&self->pmch, &pmch_init_data);
754 /* Initialize the ICM channel */
755 icm_init.base_ptr = &self->general.base;
756 icm_init.channel_ptr = &self->pmch;
757 icm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete;
758 icm_init.rx_cb_inst = &self->icm_transceiver;
759 icm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
760 icm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
761 icm_config.fifo_id = PMP_FIFO_ID_ICM;
762 icm_config.tx_wd_timeout = 0U;
763 icm_config.tx_wd_timer_value = 0U;
764 icm_config.rx_ack_timeout = 10U;
765 icm_config.rx_busy_allowed = 0xFU;
766 icm_config.rx_credits = PMCH_FIFO_CREDITS;
767 icm_config.rx_threshold = PMCH_FIFO_THRESHOLD;
768 if (self->init_data.general.inic_watchdog_enabled == false)
770 icm_config.rx_ack_timeout = 0U;
772 Fifo_Ctor(&self->icm_fifo, &icm_init, &icm_config);
774 /* Initialize the RCM channel */
775 rcm_init.base_ptr = &self->general.base;
776 rcm_init.channel_ptr = &self->pmch;
777 rcm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete;
778 rcm_init.rx_cb_inst = &self->rcm_transceiver;
779 rcm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
780 rcm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
781 rcm_config.fifo_id = PMP_FIFO_ID_RCM;
782 rcm_config.tx_wd_timeout = 10U; /* Watchdog timeout: 1s */
783 rcm_config.tx_wd_timer_value = 600U; /* Watchdog trigger every 600 ms */
784 rcm_config.rx_ack_timeout = 10U; /* Acknowledge timeout: 10 ms */
785 rcm_config.rx_busy_allowed = 0xFU;
786 rcm_config.rx_credits = PMCH_FIFO_CREDITS;
787 rcm_config.rx_threshold = PMCH_FIFO_THRESHOLD;
788 if (self->init_data.general.inic_watchdog_enabled == false)
790 /* Disable INIC watchdog */
791 rcm_config.tx_wd_timeout = 0U; /* Watchdog timeout: 0 -> infinite */
792 rcm_config.tx_wd_timer_value = 0U; /* Watchdog timer: 0 -> no timer */
793 rcm_config.rx_ack_timeout = 0U; /* Acknowledge timeout: 0 -> infinite */
795 Fifo_Ctor(&self->rcm_fifo, &rcm_init, &rcm_config);
797 Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, &self->icm_fifo, NULL/*MCM*/, &self->rcm_fifo);
798 Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */
801 /* initialize transceivers and set reference to FIFO instance */
802 Trcv_Ctor(&self->icm_transceiver, &self->icm_fifo, MSG_ADDR_EHC_CFG, self->ucs_user_ptr, PMP_FIFO_ID_ICM);
803 Trcv_RxAssignFilter(&self->icm_transceiver, &Ucs_OnRxMsgFilter, self);
804 Trcv_RxAssignReceiver(&self->icm_transceiver, &Inic_OnIcmRx, self->inic.local_inic);
805 Trcv_Ctor(&self->rcm_transceiver, &self->rcm_fifo, MSG_ADDR_EHC_CFG, self->ucs_user_ptr, PMP_FIFO_ID_RCM);
806 /* Assign RX filter and receiver function to the RCM transceiver */
807 Trcv_RxAssignFilter(&self->rcm_transceiver, &Ucs_OnRxMsgFilter, self);
808 Trcv_RxAssignReceiver(&self->rcm_transceiver, &Ucs_OnRxRcm, self);
811 /*! \brief Initializes the network management component
812 * \param self The instance
814 static void Ucs_InitNetComponent(CUcs *self)
816 Net_InitData_t net_init_data;
818 Sobs_Ctor(&self->net.startup_obs, self, &Ucs_NetworkStartupResult);
819 Sobs_Ctor(&self->net.shutdown_obs, self, &Ucs_NetworkShutdownResult);
820 Sobs_Ctor(&self->net.force_na_obs, self, &Ucs_NetworkForceNAResult);
821 Sobs_Ctor(&self->net.frame_counter_obs, self, &Ucs_NetworkFrameCounterResult);
822 net_init_data.base_ptr = &self->general.base;
823 net_init_data.inic_ptr = self->inic.local_inic;
824 Net_Ctor(&self->net.inst, &net_init_data);
827 /*! \brief Initializes the FBlock INIC
828 * \param self The instance
830 static void Ucs_InitLocalInicComponent(CUcs *self)
832 self->inic.local_inic = Fac_GetInic(&self->factory, UCS_ADDR_LOCAL_INIC);
833 Obs_Ctor(&self->inic.device_status_obs, self, &Ucs_Inic_OnDeviceStatus);
836 /*! \brief Initializes the Routing components
837 * \param self The instance
839 static void Ucs_InitRoutingComponent(CUcs *self)
841 Epm_InitData_t epm_init;
842 Rtm_InitData_t rtm_init;
844 /* Initialize the unique XRM Pool Instance */
845 Xrmp_Ctor(&self->xrmp);
847 /* Initialize the EndPoint Management Instance */
848 epm_init.base_ptr = &self->general.base;
849 epm_init.fac_ptr = &self->factory;
850 epm_init.res_debugging_fptr = self->init_data.rm.debug_resource_status_fptr;
851 epm_init.check_unmute_fptr = self->init_data.rm.xrm.check_unmute_fptr;
852 Epm_Ctor (&self->epm, &epm_init);
854 /* Initialize the Routes Management Instance */
855 rtm_init.base_ptr = &self->general.base;
856 rtm_init.epm_ptr = &self->epm;
857 rtm_init.net_ptr = &self->net.inst;
858 rtm_init.report_fptr = self->init_data.rm.report_fptr;
859 Rtm_Ctor(&self->rtm, &rtm_init);
862 /*! \brief Initializes the attach service
863 * \param self The instance
865 static void Ucs_InitAtsClass(CUcs *self)
867 Ats_InitData_t ats_init_data;
868 ats_init_data.base_ptr = &self->general.base;
869 ats_init_data.fifos_ptr = &self->fifos;
870 ats_init_data.inic_ptr = self->inic.local_inic;
871 ats_init_data.pme_ptr = &self->pme;
872 Ats_Ctor(&self->inic.attach, &ats_init_data);
875 /*! \brief Initializes the FBlock ExtendedNetworkControl API
876 * \param self The instance
878 static void Ucs_InitExcComponent(CUcs *self)
880 /* Create the FBlock ExtendedNetworkControl instance */
881 Exc_Ctor(&self->exc, &self->general.base, &self->rcm_transceiver);
884 /*! \brief Initializes the SystemDiagnosis component
885 * \param self The instance
887 static void Ucs_InitSysDiagComponent(CUcs *self)
889 /* Create the System Diagnosis instance */
890 SysDiag_Ctor(&self->sys_diag, self->inic.local_inic, &self->general.base, &self->exc);
894 static void Ucs_InitNodeDiscovery(CUcs *self)
896 Nd_InitData_t nd_init_data;
898 if (self->init_data.mgr.enabled == false)
900 nd_init_data.inst_ptr = self;
901 nd_init_data.report_fptr = &Ucs_OnNdReport;
902 nd_init_data.eval_fptr = &Ucs_OnNdEvaluate;
906 nd_init_data.inst_ptr = &self->nobs;
907 nd_init_data.report_fptr = &Nobs_OnNdReport;
908 nd_init_data.eval_fptr = &Nobs_OnNdEvaluate;
911 Nd_Ctor(&self->nd, self->inic.local_inic, &self->general.base, &self->exc, &nd_init_data);
915 static void Ucs_InitBackChannelDiagnosis(CUcs *self)
917 Bcd_Ctor(&self->bcd, self->inic.local_inic, &self->general.base, &self->exc);
920 static void Ucs_InitProgramming(CUcs *self)
922 Prg_Ctor(&self->prg, self->inic.local_inic, &self->general.base, &self->exc);
926 /*! \brief Initializes the Manager class
927 * \details This function shall be called as the latest initialization function since
928 * it may disable some of the conventional API.
929 * \param self The instance
931 static void Ucs_InitManager(CUcs *self)
933 if (self->init_data.mgr.enabled == true)
935 Mgr_Ctor(&self->mgr, &self->general.base, self->inic.local_inic, &self->net.inst, &self->nd, self->init_data.mgr.packet_bw);
936 Nobs_Ctor(&self->nobs, &self->general.base, &self->nd, &self->rtm, &self->init_data.mgr);
941 /*! \brief Callback function which announces the result of the attach process
942 * \param self The instance
943 * \param result_ptr Result of the initialization process. Result must be casted into data type
944 * Ucs_InitResult_t. Possible return values are shown in the table below.
945 * Result Code | Description
946 * ----------------------------- | ----------------------------------------------------
947 * UCS_INIT_RES_SUCCESS | Initialization succeeded
948 * UCS_INIT_RES_ERR_BUF_OVERFLOW | No message buffer available
949 * UCS_INIT_RES_ERR_PMS_INIT | PMS Initialization failed
950 * UCS_INIT_RES_ERR_INIC_VERSION | INIC device version check failed
951 * UCS_INIT_RES_ERR_DEV_ATT_CFG | Device attach failed due to an configuration error
952 * UCS_INIT_RES_ERR_DEV_ATT_PROC | Device attach failed due to a system error
953 * UCS_INIT_RES_ERR_NET_CFG | Network configuration failed
954 * UCS_INIT_RES_ERR_TIMEOUT | Initialization timeout occurred
956 static void Ucs_InitResultCb(void *self, void *result_ptr)
958 CUcs *self_ = (CUcs*)self;
959 Ucs_InitResult_t *result_ptr_ = (Ucs_InitResult_t *)result_ptr;
961 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_InitResultCb(): Ucs_Init() completed, internal event code: %u", 1U, *result_ptr_));
962 if (*result_ptr_ != UCS_INIT_RES_SUCCESS)
964 Ucs_StopAppNotification(self_);
967 if (self_->init_result_fptr != NULL)
969 self_->init_result_fptr(*result_ptr_, self_->ucs_user_ptr);
972 /* Start notification if initialization succeeded */
973 if (*result_ptr_ == UCS_INIT_RES_SUCCESS)
975 self_->init_complete = true;
976 Ucs_StartAppNotification(self_);
980 /*! \brief Callback function which announces the result of Ucs_Stop()
981 * \param self The instance
982 * \param error_code_ptr Reference to the error code
984 static void Ucs_UninitResultCb(void *self, void *error_code_ptr)
986 CUcs *self_ = (CUcs*)self;
987 uint32_t error_code = *((uint32_t *)error_code_ptr);
988 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_UninitResultCb(): Ucs_Stop() completed, internal event code: %u", 1U, error_code));
990 self_->init_complete = false;
991 Eh_DelObsrvInternalEvent(&self_->general.base.eh, &self_->uninit_result_obs);
993 Ucs_StopAppNotification(self_);
995 if (self_->uninit_result_fptr != NULL)
997 Ucs_StdResult_t result;
999 result.code = UCS_RES_SUCCESS;
1000 result.info_ptr = NULL;
1001 result.info_size = 0U;
1003 if (error_code != EH_E_UNSYNC_COMPLETE)
1005 result.code = UCS_RES_ERR_TIMEOUT;
1008 self_->uninit_result_fptr(result, self_->ucs_user_ptr);
1009 self_->uninit_result_fptr = NULL;
1013 /*! \brief Starts the notification after the initialization has succeeded
1014 * \param self The instance
1016 static void Ucs_StartAppNotification(CUcs *self)
1018 self->general.general_error_fptr = self->init_data.general.error_fptr; /* assign general error notification */
1019 Sobs_Ctor(&self->general.general_error_obs, self, &Ucs_OnGeneralError);
1020 Eh_AddObsrvPublicError(&self->general.base.eh, &self->general.general_error_obs);
1022 if (self->init_data.network.status.cb_fptr != NULL) /* Start notification of Network Status */
1024 self->net.status_fptr = self->init_data.network.status.cb_fptr;
1025 Mobs_Ctor(&self->net.status_obs,
1027 (uint32_t)self->init_data.network.status.notification_mask,
1028 &Ucs_NetworkStatus);
1029 Net_AddObserverNetworkStatus(&self->net.inst, &self->net.status_obs);
1032 if ((self->init_data.ams.tx.message_freed_fptr != NULL) && (self->msg.ams_tx_alloc_failed != false))
1034 self->msg.ams_tx_alloc_failed = false;
1035 self->init_data.ams.tx.message_freed_fptr(self->ucs_user_ptr);
1038 if (self->init_data.inic.power_state_fptr != NULL)
1040 self->inic.power_state = Inic_GetDevicePowerState(self->inic.local_inic); /* remember the current value */
1041 self->init_data.inic.power_state_fptr(self->inic.power_state, self->ucs_user_ptr);
1042 Inic_AddObsvrDeviceStatus(self->inic.local_inic, &self->inic.device_status_obs);
1045 if(self->init_data.rm.xrm.most_port_status_fptr != NULL) /* Initialize callback pointer for MOST port status callback */
1047 self->xrm.most_port_status_fptr = self->init_data.rm.xrm.most_port_status_fptr;
1048 Obs_Ctor(&self->xrm.most_port_status_obs, self, &Ucs_Most_PortStatusCb);
1049 Inic_AddObsrvMostPortStatus(self->inic.local_inic, &self->xrm.most_port_status_obs);
1053 /*! \brief Stops application events for timer management and event service
1054 * \param self The instance
1056 static void Ucs_StopAppNotification(CUcs *self)
1058 self->general.request_service_fptr = NULL; /* clear service request to avoid any pending events to be called again */
1059 Tm_StopService(&self->general.base.tm); /* stop timer service */
1062 /*------------------------------------------------------------------------------------------------*/
1063 /* Message Routing */
1064 /*------------------------------------------------------------------------------------------------*/
1065 /*! \brief Callback function to receive RCM Rx messages
1066 * \param self The UCS instance
1067 * \param tel_ptr The received RCM Rx message object
1068 * \return Returns \c true to discard the message and free it to the pool (no-pass).
1069 * Otherwise, returns \c false (pass).
1071 static void Ucs_OnRxRcm(void *self, Msg_MostTel_t *tel_ptr)
1073 CUcs *self_ = (CUcs*)self;
1075 if (tel_ptr->id.fblock_id == FB_EXC)
1077 Exc_OnRcmRxFilter(&(self_->exc), tel_ptr);
1079 else if (tel_ptr->id.fblock_id == FB_INIC)
1081 if (!Nsm_OnRcmRxFilter(Fac_FindNsm(&self_->factory, tel_ptr->source_addr), tel_ptr))
1083 CInic * inic_ptr = Fac_FindInic(&self_->factory, tel_ptr->source_addr);
1084 if (inic_ptr != NULL)
1086 Inic_OnRcmRxFilter(inic_ptr, tel_ptr);
1091 Trcv_RxReleaseMsg(&self_->rcm_transceiver, tel_ptr); /* free Rx telegram */
1094 /*! \brief Callback function which filters Control Rx messages
1095 * \param self The UCS instance
1096 * \param tel_ptr The received Rx message object
1097 * \return Returns \c true to discard the message and free it to the pool (no-pass).
1098 * Otherwise, returns \c false (pass).
1100 static bool Ucs_OnRxMsgFilter(void *self, Msg_MostTel_t *tel_ptr)
1102 CUcs *self_ = (CUcs*)self;
1103 bool ret = false; /* just pass - do not discard message */
1105 if (self_->rx_filter_fptr != NULL)
1107 ret = self_->rx_filter_fptr(tel_ptr, self_->ucs_user_ptr);
1112 if ((tel_ptr->id.op_type == UCS_OP_ERROR) || (tel_ptr->id.op_type == UCS_OP_ERRORACK))
1114 if (self_->init_data.general.debug_error_msg_fptr != NULL)
1116 self_->init_data.general.debug_error_msg_fptr(tel_ptr, self_->ucs_user_ptr);
1122 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_OnRxMsgFilter(): message discarded by unit test", 0U));
1128 /*------------------------------------------------------------------------------------------------*/
1129 /* Internal Observers / Basic API */
1130 /*------------------------------------------------------------------------------------------------*/
1131 /*! \brief Callback function which is invoked to request the current tick count value
1132 * \param self The instance
1133 * \param tick_count_value_ptr Reference to the requested tick count value. The pointer must
1134 * be casted into data type uint16_t.
1136 static void Ucs_OnGetTickCount(void *self, void *tick_count_value_ptr)
1138 CUcs *self_ = (CUcs*)self;
1139 *((uint16_t *)tick_count_value_ptr) = self_->general.get_tick_count_fptr(self_->ucs_user_ptr);
1142 /*! \brief Callback function which is invoked to start the application timer when the UNICENS service
1143 * is implemented event driven
1144 * \param self The instance
1145 * \param new_time_value_ptr Reference to the new timer value. The pointer must be casted into
1146 * data type uint16_t.
1148 static void Ucs_OnSetApplicationTimer(void *self, void *new_time_value_ptr)
1150 CUcs *self_ = (CUcs*)self;
1151 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_OnSetApplicationTimer(%d)", 1U, *((uint16_t *)new_time_value_ptr)));
1152 self_->general.set_application_timer_fptr(*((uint16_t *)new_time_value_ptr), self_->ucs_user_ptr);
1155 /*! \brief Callback function which is invoked to announce a request for service
1156 * \param self The instance
1157 * \param result_ptr Result pointer (not used)
1159 static void Ucs_OnServiceRequest(void *self, void *result_ptr)
1161 CUcs *self_ = (CUcs*)self;
1163 TR_ASSERT(self_->ucs_user_ptr, "[API]", self_->init_data.general.request_service_fptr != NULL);
1164 self_->general.request_service_fptr(self_->ucs_user_ptr); /* Call application callback */
1165 MISC_UNUSED(result_ptr);
1168 /*! \brief Callback function which announces a general error
1169 * \param self The instance
1170 * \param result_ptr Reference to the result. Must be casted into Eh_PublicErrorData_t.
1172 static void Ucs_OnGeneralError(void *self, void *result_ptr)
1174 CUcs *self_ = (CUcs*)self;
1175 Ucs_Error_t error_code = *((Ucs_Error_t *)result_ptr);
1177 self_->init_complete = false; /* General error occurred -> Lock UCS API */
1178 Ucs_StopAppNotification(self_);
1180 if (self_->general.general_error_fptr != NULL) /* callback is not assigned during initialization */
1182 self_->general.general_error_fptr(error_code, self_->ucs_user_ptr);
1186 /*! \brief Observer callback for Inic_MostPortStatus_Status/Error(). Casts the result and
1187 * invokes the application result callback.
1188 * \param self Instance pointer
1189 * \param result_ptr Reference to result
1191 static void Ucs_Most_PortStatusCb(void *self, void *result_ptr)
1193 CUcs *self_ = (CUcs*)self;
1194 if(self_->xrm.most_port_status_fptr != NULL)
1196 Inic_MostPortStatus_t status = *((Inic_MostPortStatus_t *)result_ptr);
1197 self_->xrm.most_port_status_fptr(status.most_port_handle,
1198 status.availability,
1200 status.freestreaming_bw,
1201 self_->ucs_user_ptr);
1205 /*------------------------------------------------------------------------------------------------*/
1207 /*------------------------------------------------------------------------------------------------*/
1208 /*! \brief Observer callback function for INICs device status
1209 * \param self The instance
1210 * \param data_ptr Pointer to structure Inic_DeviceStatus_t
1212 static void Ucs_Inic_OnDeviceStatus(void *self, void *data_ptr)
1214 CUcs *self_ = (CUcs*)self;
1215 Ucs_Inic_PowerState_t pws = ((Inic_DeviceStatus_t *)data_ptr)->power_state;
1217 if ((self_->init_data.inic.power_state_fptr != NULL) && (pws != self_->inic.power_state))
1219 self_->init_data.inic.power_state_fptr(pws, self_->ucs_user_ptr);
1222 self_->inic.power_state = pws;
1225 /*------------------------------------------------------------------------------------------------*/
1226 /* Network Management */
1227 /*------------------------------------------------------------------------------------------------*/
1228 Ucs_Return_t Ucs_Network_Startup(Ucs_Inst_t* self, uint16_t packet_bw, uint16_t forced_na_timeout,
1229 Ucs_StdResultCb_t result_fptr)
1231 CUcs *self_ = (CUcs*)(void*)self;
1233 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1234 if (self_->init_complete != false)
1236 ret_val = Inic_NwStartup(self_->inic.local_inic, forced_na_timeout,
1237 packet_bw, &self_->net.startup_obs);
1238 if (ret_val == UCS_RET_SUCCESS)
1240 self_->net.startup_fptr = result_fptr;
1246 /*! \brief Callback function which announces the result of Ucs_Network_Startup()
1247 * \param self The instance
1248 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
1250 static void Ucs_NetworkStartupResult(void *self, void *result_ptr)
1252 CUcs *self_ = (CUcs*)self;
1253 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
1255 if (self_->net.startup_fptr != NULL)
1257 self_->net.startup_fptr(result_ptr_->result, self_->ucs_user_ptr);
1261 Ucs_Return_t Ucs_Network_Shutdown(Ucs_Inst_t *self, Ucs_StdResultCb_t result_fptr)
1263 CUcs *self_ = (CUcs*)(void*)self;
1264 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1265 if (self_->init_complete != false)
1267 ret_val = Inic_NwShutdown(self_->inic.local_inic, &self_->net.shutdown_obs);
1268 if (ret_val == UCS_RET_SUCCESS)
1270 self_->net.shutdown_fptr = result_fptr;
1276 /*! \brief Callback function which announces the result of Ucs_Network_Shutdown()
1277 * \param self The instance
1278 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
1280 static void Ucs_NetworkShutdownResult(void *self, void *result_ptr)
1282 CUcs *self_ = (CUcs*)self;
1283 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
1285 if (self_->net.shutdown_fptr != NULL)
1287 self_->net.shutdown_fptr(result_ptr_->result, self_->ucs_user_ptr);
1291 Ucs_Return_t Ucs_Network_ForceNotAvailable(Ucs_Inst_t *self, bool force, Ucs_StdResultCb_t result_fptr)
1293 CUcs *self_ = (CUcs*)(void*)self;
1294 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1295 if (self_->init_complete != false)
1297 ret_val = Inic_NwForceNotAvailable(self_->inic.local_inic, force, &self_->net.force_na_obs);
1298 if (ret_val == UCS_RET_SUCCESS)
1300 self_->net.force_na_fptr = result_fptr;
1306 /*! \brief Callback function which announces the result of Network_ForceNotAvailable()
1307 * \param self The instance
1308 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
1310 static void Ucs_NetworkForceNAResult(void *self, void *result_ptr)
1312 CUcs *self_ = (CUcs*)self;
1313 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
1315 if (self_->net.force_na_fptr != NULL)
1317 self_->net.force_na_fptr(result_ptr_->result, self_->ucs_user_ptr);
1321 Ucs_Return_t Ucs_Network_GetFrameCounter(Ucs_Inst_t *self, uint32_t reference, Ucs_Network_FrameCounterCb_t result_fptr)
1323 CUcs *self_ = (CUcs*)(void*)self;
1324 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1325 if (self_->init_complete != false)
1327 ret_val = Inic_NwFrameCounter_Get(self_->inic.local_inic, reference, &self_->net.frame_counter_obs);
1328 if (ret_val == UCS_RET_SUCCESS)
1330 self_->net.frame_counter_fptr = result_fptr;
1337 /*! \brief Callback function which announces the result of Ucs_Network_GetFrameCounter()
1338 * \param self The instance
1339 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t and data_info
1340 * must be casted into Inic_FrameCounterStatus_t.
1342 static void Ucs_NetworkFrameCounterResult(void *self, void *result_ptr)
1344 CUcs *self_ = (CUcs*)self;
1346 if (self_->net.frame_counter_fptr != NULL)
1348 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
1350 uint32_t frame_counter;
1353 if (result_ptr_->data_info != NULL)
1355 Inic_FrameCounterStatus_t *frame_counter_result_data_ptr = (Inic_FrameCounterStatus_t *)result_ptr_->data_info;
1356 reference = frame_counter_result_data_ptr->reference;
1357 frame_counter = frame_counter_result_data_ptr->frame_counter;
1358 lock = frame_counter_result_data_ptr->lock;
1367 self_->net.frame_counter_fptr(reference, frame_counter, lock, result_ptr_->result, self_->ucs_user_ptr);
1371 /*! \brief Observer callback which monitors the network status
1372 * \param self The instance
1373 * \param result_ptr Reference to result. Must be casted into Net_NetworkStatusParam_t.
1375 static void Ucs_NetworkStatus(void *self, void *result_ptr)
1377 CUcs *self_ = (CUcs*)self;
1378 Net_NetworkStatusParam_t *result_ptr_ = (Net_NetworkStatusParam_t *)result_ptr;
1380 if (self_->net.status_fptr != NULL)
1382 self_->net.status_fptr( result_ptr_->change_mask,
1383 result_ptr_->events,
1384 result_ptr_->availability,
1385 result_ptr_->avail_info,
1386 result_ptr_->avail_trans_cause,
1387 result_ptr_->node_address,
1388 result_ptr_->node_position,
1389 result_ptr_->max_position,
1390 result_ptr_->packet_bw,
1391 self_->ucs_user_ptr);
1395 uint8_t Ucs_Network_GetNodesCount(Ucs_Inst_t *self)
1397 CUcs *self_ = (CUcs*)(void*)self;
1398 return Inic_GetNumberOfNodes(self_->inic.local_inic);
1402 /*------------------------------------------------------------------------------------------------*/
1403 /* Node Discovery */
1404 /*------------------------------------------------------------------------------------------------*/
1405 Ucs_Return_t Ucs_Nd_Start(Ucs_Inst_t* self)
1407 CUcs *self_ = (CUcs*)(void*)self;
1408 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1410 if (self_->init_complete != false)
1412 ret_val = Nd_Start(&self_->nd);
1418 Ucs_Return_t Ucs_Nd_Stop(Ucs_Inst_t* self)
1420 CUcs *self_ = (CUcs*)(void*)self;
1421 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1423 if (self_->init_complete != false)
1425 ret_val = Nd_Stop(&self_->nd);
1431 Ucs_Return_t Ucs_Nd_InitAll(Ucs_Inst_t* self)
1433 CUcs *self_ = (CUcs*)(void*)self;
1434 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1436 if (self_->init_complete != false)
1438 Nd_InitAll(&self_->nd);
1439 ret_val = UCS_RET_SUCCESS;
1445 /*! \brief Callback function to proxy the user callback for node evaluation
1446 * \param self The instance
1447 * \param signature_ptr Reference to the node signature
1448 * \return The evaluation return value which defines how to proceed with the node.
1450 static Ucs_Nd_CheckResult_t Ucs_OnNdEvaluate(void *self, Ucs_Signature_t *signature_ptr)
1452 CUcs *self_ = (CUcs*)(void*)self;
1453 Ucs_Nd_CheckResult_t ret_val = UCS_ND_CHK_UNKNOWN;
1455 if (self_->init_data.nd.eval_fptr != NULL)
1457 ret_val = self_->init_data.nd.eval_fptr(signature_ptr, self_->ucs_user_ptr);
1463 /*! \brief Callback function to proxy the user callback for node evaluation
1464 * \param self The instance
1465 * \param code The report code
1466 * \param signature_ptr Reference to the node signature or NULL if no signature applies.
1468 static void Ucs_OnNdReport(void *self, Ucs_Nd_ResCode_t code, Ucs_Signature_t *signature_ptr)
1470 CUcs *self_ = (CUcs*)(void*)self;
1472 if (self_->init_data.nd.report_fptr != NULL)
1474 self_->init_data.nd.report_fptr(code, signature_ptr, self_->ucs_user_ptr);
1479 /*------------------------------------------------------------------------------------------------*/
1480 /* BackChannel Diagnosis */
1481 /*------------------------------------------------------------------------------------------------*/
1482 Ucs_Return_t Ucs_Bcd_Start(Ucs_Inst_t* self, Ucs_Bcd_ReportCb_t report_fptr)
1484 CUcs *self_ = (CUcs*)(void*)self;
1485 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1487 if (report_fptr == NULL)
1489 ret_val = UCS_RET_ERR_PARAM;
1491 else if (self_->init_complete != false)
1493 Bcd_Start(&self_->bcd, report_fptr);
1494 ret_val = UCS_RET_SUCCESS;
1500 /*------------------------------------------------------------------------------------------------*/
1501 /* Programming service */
1502 /*------------------------------------------------------------------------------------------------*/
1503 Ucs_Return_t Ucs_Prog_Start(Ucs_Inst_t *self,
1505 Ucs_Signature_t *signature,
1506 Ucs_Prg_SessionType_t session_type,
1507 Ucs_Prg_Command_t* command_list,
1508 Ucs_Prg_ReportCb_t result_fptr)
1510 CUcs *self_ = (CUcs*)(void*)self;
1511 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1513 if (result_fptr == NULL)
1515 ret_val = UCS_RET_ERR_PARAM;
1517 else if (self_->init_complete != false)
1519 Prg_Start(&self_->prg, node_id, signature, session_type, command_list, result_fptr);
1520 ret_val = UCS_RET_SUCCESS;
1526 /*------------------------------------------------------------------------------------------------*/
1527 /* Message Handling */
1528 /*------------------------------------------------------------------------------------------------*/
1529 /*! \brief Initializes the port message service for application interface (MCM)
1530 * \param self The instance
1532 static void Ucs_InitPmsComponentApp(CUcs *self)
1534 Fifo_InitData_t mcm_init;
1535 Fifo_Config_t mcm_config;
1537 /* Initialize the MCM channel */
1538 mcm_init.base_ptr = &self->general.base;
1539 mcm_init.channel_ptr = &self->pmch;
1540 mcm_init.rx_cb_fptr = &Trcv_RxOnMsgComplete;
1541 mcm_init.rx_cb_inst = &self->msg.mcm_transceiver;
1542 mcm_init.tx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
1543 mcm_init.rx_encoder_ptr = Enc_GetEncoder(ENC_CONTENT_00);
1545 /* Enable INIC watchdog */
1546 mcm_config.fifo_id = PMP_FIFO_ID_MCM;
1547 mcm_config.tx_wd_timeout = 10U; /* Watchdog timeout: 1s */
1548 mcm_config.tx_wd_timer_value = 600U; /* Watchdog trigger every 600 ms */
1549 mcm_config.rx_ack_timeout = 10U; /* Acknowledge timeout: 10 ms */
1550 mcm_config.rx_busy_allowed = 0xFU;
1551 mcm_config.rx_credits = PMCH_MCM_CREDITS;
1552 mcm_config.rx_threshold = PMCH_MCM_THRESHOLD;
1553 if (self->init_data.general.inic_watchdog_enabled == false)
1555 /* Disable INIC watchdog */
1556 mcm_config.tx_wd_timeout = 0U; /* Watchdog timeout: 0 -> infinite */
1557 mcm_config.tx_wd_timer_value = 0U; /* Watchdog timer: 0 -> no timer */
1558 mcm_config.rx_ack_timeout = 0U; /* Acknowledge timeout: 0 -> infinite */
1560 Fifo_Ctor(&self->msg.mcm_fifo,&mcm_init, &mcm_config);
1562 Fifos_Ctor(&self->fifos, &self->general.base, &self->pmch, NULL, &self->msg.mcm_fifo, NULL);
1563 Pmev_Ctor(&self->pme, &self->general.base, &self->fifos); /* initialize event handler */
1566 /* initialize transceivers and set reference to FIFO instance */
1567 Trcv_Ctor(&self->msg.mcm_transceiver, &self->msg.mcm_fifo, MSG_ADDR_EHC_APP, self->ucs_user_ptr, PMP_FIFO_ID_MCM);
1568 Trcv_RxAssignFilter(&self->msg.mcm_transceiver, &Ucs_McmRx_FilterCallback, self);
1571 static void Ucs_InitAmsComponent(CUcs *self)
1573 Smm_Ctor(&self->msg.smm, self->ucs_user_ptr);
1574 (void)Smm_LoadPlugin(&self->msg.smm, &self->msg.ams_allocator, SMM_SIZE_RX_MSG);
1576 TR_ASSERT(self->ucs_user_ptr, "[API]", (self->msg.ams_allocator.alloc_fptr != NULL));
1577 TR_ASSERT(self->ucs_user_ptr, "[API]", (self->msg.ams_allocator.free_fptr != NULL));
1579 Amsp_Ctor(&self->msg.ams_pool, &self->msg.ams_allocator, self->ucs_user_ptr);
1580 Ams_Ctor(&self->msg.ams, &self->general.base, &self->msg.mcm_transceiver, NULL, &self->msg.ams_pool,
1582 Ams_TxSetDefaultRetries(&self->msg.ams, self->init_data.ams.tx.default_llrbc);
1584 Amd_Ctor(&self->msg.amd, &self->general.base, &self->msg.ams);
1585 Amd_AssignReceiver(&self->msg.amd, &Ucs_AmsRx_Callback, self);
1586 /* Amd_RxAssignModificator(&self->amd, &Mnsa_AmdRx_Modificator, self); */
1588 self->msg.ams_tx_alloc_failed = false;
1589 Obs_Ctor(&self->msg.ams_tx_freed_obs, self, &Ucs_AmsTx_FreedCallback);
1590 if (self->init_data.ams.tx.message_freed_fptr != NULL)
1592 Ams_TxAssignMsgFreedObs(&self->msg.ams, &self->msg.ams_tx_freed_obs);
1595 Cmd_Ctor(&self->msg.cmd, &self->general.base);
1598 extern Ucs_AmsTx_Msg_t* Ucs_AmsTx_AllocMsg(Ucs_Inst_t *self, uint16_t data_size)
1600 CUcs *self_ = (CUcs*)(void*)self;
1601 Ucs_AmsTx_Msg_t *ret_ptr = NULL;
1603 if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true))
1605 ret_ptr = Ams_TxGetMsg(&self_->msg.ams, data_size);
1608 self_->msg.ams_tx_alloc_failed = (ret_ptr == NULL) ? true : false;
1612 extern Ucs_Return_t Ucs_AmsTx_SendMsg(Ucs_Inst_t *self, Ucs_AmsTx_Msg_t *msg_ptr, Ucs_AmsTx_CompleteCb_t tx_complete_fptr)
1614 CUcs *self_ = (CUcs*)(void*)self;
1615 Ucs_Return_t ret_val = UCS_RET_ERR_NOT_INITIALIZED;
1617 if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true))
1619 ret_val = Ams_TxSendMsg(&self_->msg.ams, msg_ptr, NULL, tx_complete_fptr, self_->ucs_user_ptr);
1625 extern void Ucs_AmsTx_FreeUnusedMsg(Ucs_Inst_t *self, Ucs_AmsTx_Msg_t *msg_ptr)
1627 CUcs *self_ = (CUcs*)(void*)self;
1629 if (msg_ptr != NULL)
1631 Ams_TxFreeUnusedMsg(&self_->msg.ams, msg_ptr);
1635 extern Ucs_AmsRx_Msg_t* Ucs_AmsRx_PeekMsg(Ucs_Inst_t *self)
1637 CUcs *self_ = (CUcs*)(void*)self;
1638 Ucs_AmsRx_Msg_t *ret = NULL;
1640 if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true))
1642 ret = Amd_RxPeekMsg(&self_->msg.amd);
1648 extern void Ucs_AmsRx_ReleaseMsg(Ucs_Inst_t *self)
1650 CUcs *self_ = (CUcs*)(void*)self;
1652 if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true))
1654 Amd_RxReleaseMsg(&self_->msg.amd);
1658 extern uint16_t Ucs_AmsRx_GetMsgCnt(Ucs_Inst_t *self)
1660 CUcs *self_ = (CUcs*)(void*)self;
1663 if ((self_->init_complete != false) && (self_->init_data.ams.enabled == true))
1665 ret = Amd_RxGetMsgCnt(&self_->msg.amd);
1670 /*! \brief Callback function which announces that a new application message
1671 * is added to the Rx queue
1672 * \param self The instance
1674 static void Ucs_AmsRx_Callback(void *self)
1676 CUcs *self_ = (CUcs*)self;
1678 if (self_->init_data.ams.rx.message_received_fptr != NULL)
1680 self_->init_data.ams.rx.message_received_fptr(self_->ucs_user_ptr);
1684 /*! \brief Callback function which announces that the AMS Tx Pool provides again a Tx message object
1685 * after a prior allocation has failed.
1686 * \param self The instance
1687 * \param data_ptr Not used (always \c NULL)
1689 static void Ucs_AmsTx_FreedCallback(void *self, void *data_ptr)
1691 CUcs *self_ = (CUcs*)self;
1692 MISC_UNUSED(data_ptr);
1694 if ((self_->msg.ams_tx_alloc_failed != false) && (self_->init_complete != false))
1696 self_->msg.ams_tx_alloc_failed = false;
1697 self_->init_data.ams.tx.message_freed_fptr(self_->ucs_user_ptr);
1701 /*! \brief Callback function which filters MCM Rx messages
1702 * \param self The instance
1703 * \param tel_ptr The received Rx message object
1704 * \return Returns \c true to discard the message and free it to the pool (no-pass).
1705 * Otherwise, returns \c false (pass).
1707 static bool Ucs_McmRx_FilterCallback(void *self, Msg_MostTel_t *tel_ptr)
1709 CUcs *self_ = (CUcs*)self;
1710 bool ret = false; /* default: pass the message */
1712 if ((tel_ptr->id.fblock_id != MSG_DEF_FBLOCK_ID) || (tel_ptr->id.op_type != MSG_DEF_OP_TYPE) ||
1713 ((tel_ptr->id.function_id & (uint16_t)0x000FU) != MSG_DEF_FUNC_ID_LSN))
1715 TR_INFO((self_->ucs_user_ptr, "[API]", "Ucs_McmRx_FilterCallback(): discarding Rx message with signature %02X.%02X.%03X.%X ", 4U, tel_ptr->id.fblock_id, tel_ptr->id.instance_id, tel_ptr->id.function_id, tel_ptr->id.op_type));
1724 /*------------------------------------------------------------------------------------------------*/
1725 /* Message decoding */
1726 /*------------------------------------------------------------------------------------------------*/
1727 Ucs_Cmd_Return_t Ucs_Cmd_AddMsgIdTable(Ucs_Inst_t *self, Ucs_Cmd_MsgId_t *msg_id_tab_ptr)
1729 Ucs_Cmd_Return_t ret_val;
1730 CUcs *self_ = (CUcs*)(void*)self;
1732 if (msg_id_tab_ptr != NULL)
1734 ret_val = Cmd_AddMsgIdTable(&(self_->msg.cmd), msg_id_tab_ptr);
1738 ret_val = UCS_CMD_RET_ERR_NULL_PTR;
1745 Ucs_Cmd_Return_t Ucs_Cmd_RemoveMsgIdTable(Ucs_Inst_t *self)
1747 Ucs_Cmd_Return_t ret_val;
1748 CUcs *self_ = (CUcs*)(void*)self;
1750 ret_val = Cmd_RemoveMsgIdTable(&(self_->msg.cmd));
1756 Ucs_Cmd_Return_t Ucs_Cmd_DecodeMsg(Ucs_Inst_t *self, Ucs_AmsRx_Msg_t *msg_rx_ptr)
1758 Ucs_Cmd_Return_t ret_val;
1759 CUcs *self_ = (CUcs*)(void*)self;
1761 if(msg_rx_ptr != NULL)
1763 ret_val = Cmd_DecodeMsg(&(self_->msg.cmd), msg_rx_ptr);
1767 ret_val = UCS_CMD_RET_ERR_NULL_PTR;
1773 /*------------------------------------------------------------------------------------------------*/
1774 /* Unit tests only */
1775 /*------------------------------------------------------------------------------------------------*/
1776 extern void Ucs_AssignRxFilter(Ucs_Inst_t *self, Ucs_RxFilterCb_t callback_fptr)
1778 CUcs *self_ = (CUcs*)(void*)self;
1779 self_->rx_filter_fptr = callback_fptr;
1787 /*------------------------------------------------------------------------------------------------*/
1789 /*------------------------------------------------------------------------------------------------*/