/*------------------------------------------------------------------------------------------------*/ /* 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 . */ /* */ /* You may also obtain this software under a propriety license from Microchip. */ /* Please contact Microchip for further information. */ /*------------------------------------------------------------------------------------------------*/ /*! * \file * \brief Implementation of the System Diagnosis class * \details Performs the System Diagnosis * * \cond UCS_INTERNAL_DOC * \addtogroup G_SYS_DIAG * @{ */ /*------------------------------------------------------------------------------------------------*/ /* Includes */ /*------------------------------------------------------------------------------------------------*/ #include "ucs_misc.h" #include "ucs_ret_pb.h" #include "ucs_sys_diag.h" /*#include "ucs_mnsa.h"*/ /*------------------------------------------------------------------------------------------------*/ /* Internal constants */ /*------------------------------------------------------------------------------------------------*/ #define SYS_DIAG_NUM_STATES 10U /*!< \brief Number of state machine states */ #define SYS_DIAG_NUM_EVENTS 17U /*!< \brief Number of state machine events */ #define SD_NUM_HELLO 10U /*!< \brief Number of Hello.Get Retries */ #define SD_TIMEOUT_HELLO 150U /*!< \brief timeout used for repeating Hello.Get messages */ #define SD_TIMEOUT_COMMAND 100U /*!< \brief timeout used for supervising INIC commands */ #define SD_TIMEOUT_CABLE_DIAGNOSIS 3000U /*!< \brief timeout used for supervising cable link diagnosis */ #define SD_DIAG_ADDR_BASE 0x0500U /*!< \brief Diagnosis Node Address of own node */ #define SD_WELCOME_SUCCESS 0U /*!< \brief Welcome.Result reports success */ #define SD_SIGNATURE_VERSION 1U /*!< \brief signature version used for System Diagnosis */ /*------------------------------------------------------------------------------------------------*/ /* Service parameters */ /*------------------------------------------------------------------------------------------------*/ /*! Priority of the System Diagnosis service used by scheduler */ static const uint8_t SD_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ /*! Main event for the System Diagnosis service */ static const Srv_Event_t SD_EVENT_SERVICE = 1U; /*------------------------------------------------------------------------------------------------*/ /* Internal enumerators */ /*------------------------------------------------------------------------------------------------*/ /*! \brief Possible events of the system diagnosis state machine */ typedef enum SysDiag_Events_ { SD_E_NIL = 0U, /*!< \brief NIL Event */ SD_E_STARTDIAG = 1U, /*!< \brief StartDiag API function was called */ SD_E_SD_RES_OK = 2U, /*!< \brief MOSTNetworkSystemDiagnosis.Result received */ SD_E_ABORT = 3U, /*!< \brief Application requires stop of System Diagnosis */ SD_E_HELLO_OK = 4U, /*!< \brief Hello.Status received */ SD_E_HELLO_RETRY = 5U, /*!< \brief Retry the Hello.Get command */ SD_E_HELLO_ALL_DONE = 6U, /*!< \brief All retries of the Hello.Get command are done */ SD_E_WELCOME = 7U, /*!< \brief Welcome.Result, may be Ok or NotOk*/ SD_E_ALL_DONE = 8U, /*!< \brief All branches and segments of the network were explored*/ SD_E_PORT_FOUND = 9U, /*!< \brief An unexplored port was found */ SD_E_PORT_ENABLED = 10U, /*!< \brief A port was succesful enabled */ SD_E_PORT_DISABLED = 11U, /*!< \brief A port was succesful disabled */ SD_E_BRANCH_FOUND = 12U, /*!< \brief Another branch was found */ SD_E_CABLE_LINK_RES = 13U, /*!< \brief The CableLinkDiagnosis reported a result */ SD_E_ERROR = 14U, /*!< \brief An error was detected */ SD_E_TIMEOUT = 15U, /*!< \brief An timeout has been occurred */ SD_E_NO_SUCCESS = 16U /*!< \brief Welcome result was NoSuccess */ } SysDiag_Events_t; /*! \brief States of the system diagnosis state machine */ typedef enum SysDiag_State_ { SD_S_IDLE = 0U, /*!< \brief Idle state */ SD_S_WAIT_DIAG = 1U, /*!< \brief System Diagnosis started */ SD_S_WAIT_HELLO = 2U, /*!< \brief Hello command sent */ SD_S_HELLO_TIMEOUT = 3U, /*!< \brief Hello command timed out */ SD_S_WAIT_WELCOME = 4U, /*!< \brief Welcome sent */ SD_S_NEXT_PORT = 5U, /*!< \brief Next port found to be tested */ SD_S_WAIT_ENABLE = 6U, /*!< \brief Port Enable sent */ SD_S_WAIT_DISABLE = 7U, /*!< \brief Port Disable sent */ SD_S_CABLE_LINK_DIAG = 8U, /*!< \brief Wait for CableL Link Diagnosis Result */ SD_S_END = 9U /*!< \brief Wait for System Diagnosis stop */ } SysDiag_State_t; /*------------------------------------------------------------------------------------------------*/ /* Internal prototypes */ /*------------------------------------------------------------------------------------------------*/ static void Sd_Service(void *self); static void Sd_SysDiagInit(void* self); static void Sd_SysDiagStart(void *self); static void Sd_SysDiagStop(void *self); static void Sd_SendHello(void *self); static void Sd_Error(void *self); static void Sd_ErrorWelcome(void *self); static void Sd_SendWelcome(void *self); static void Sd_CableLinkDiagnosis(void *self); static void Sd_CalcPort(void *self); static void Sd_AllDone(void *self); static void Sd_EnablePort(void *self); static void Sd_DisablePort(void *self); static void Sd_Finish(void *self); static void Sd_Abort(void *self); static void Sd_StopDiagFailed(void *self); static void Sd_HelloTimeout(void *self); static void Sd_SysDiagTimeout(void *self); static void Sd_WelcomeTimeout(void *self); static void Sd_EnablePortTimeout(void *self); static void Sd_DisablePortTimeout(void *self); static void Sd_CableLinkDiagnosisTimeout(void *self); static void Sd_SysDiagStartResultCb(void *self, void *result_ptr); static void Sd_SysDiagStopResultCb(void *self, void *result_ptr); static void Sd_HelloStatusCb(void *self, void *result_ptr); static void Sd_WelcomeResultCb(void *self, void *result_ptr); static void Sd_EnablePortResultCb(void *self, void *result_ptr); static void Sd_DisablePortResultCb(void *self, void *result_ptr); static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr); static void Sd_OnTerminateEventCb(void *self, void *result_ptr); static void Sd_TimerCb(void *self); /*------------------------------------------------------------------------------------------------*/ /* State transition table (used by finite state machine) */ /*------------------------------------------------------------------------------------------------*/ /*! \brief State transition table */ static const Fsm_StateElem_t sys_diag_trans_tab[SYS_DIAG_NUM_STATES][SYS_DIAG_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ { { /* State SD_S_IDLE */ /* SD_E_NIL */ {NULL, SD_S_IDLE }, /* SD_E_STARTDIAG */ {&Sd_SysDiagStart, SD_S_WAIT_DIAG }, /* SD_E_SD_RES_OK */ {NULL, SD_S_IDLE }, /* SD_E_ABORT */ {NULL, SD_S_IDLE }, /* SD_E_HELLO_OK */ {NULL, SD_S_IDLE }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_IDLE }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_IDLE }, /* SD_E_WELCOME */ {NULL, SD_S_IDLE }, /* SD_E_ALL_DONE */ {NULL, SD_S_IDLE }, /* SD_E_PORT_FOUND */ {NULL, SD_S_IDLE }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_IDLE }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_IDLE }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_IDLE }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_IDLE }, /* SD_E_ERROR */ {NULL, SD_S_IDLE }, /* SD_E_TIMEOUT */ {NULL, SD_S_IDLE }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_IDLE } }, { /* State SD_S_WAIT_DIAG */ /* SD_E_NIL */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_SD_RES_OK */ {&Sd_SendHello, SD_S_WAIT_HELLO }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DIAG }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_SysDiagTimeout, SD_S_END }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DIAG } }, { /* State SD_S_WAIT_HELLO*/ /* SD_E_NIL */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {&Sd_SendWelcome, SD_S_WAIT_WELCOME }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_WELCOME */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_HELLO }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_HelloTimeout, SD_S_HELLO_TIMEOUT }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_HELLO } }, { /* State SD_S_HELLO_TIMEOUT */ /* SD_E_NIL */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_STARTDIAG */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_SD_RES_OK */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_HELLO_RETRY */ {&Sd_SendHello, SD_S_WAIT_HELLO }, /* SD_E_HELLO_ALL_DONE */ {&Sd_CableLinkDiagnosis, SD_S_CABLE_LINK_DIAG }, /* SD_E_WELCOME */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_ALL_DONE */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_PORT_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {NULL, SD_S_HELLO_TIMEOUT }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_HELLO_TIMEOUT } }, { /* State SD_S_WAIT_WELCOME */ /* SD_E_NIL */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_WELCOME */ {&Sd_CalcPort, SD_S_NEXT_PORT }, /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_WELCOME }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_WelcomeTimeout, SD_S_END }, /* SD_E_NO_SUCCESS */ {&Sd_ErrorWelcome, SD_S_END } }, { /* State SD_S_NEXT_PORT */ /* SD_E_NIL */ {NULL, SD_S_NEXT_PORT }, /* SD_E_STARTDIAG */ {NULL, SD_S_NEXT_PORT }, /* SD_E_SD_RES_OK */ {NULL, SD_S_NEXT_PORT }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_NEXT_PORT }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_NEXT_PORT }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_NEXT_PORT }, /* SD_E_WELCOME */ {NULL, SD_S_NEXT_PORT }, /* SD_E_ALL_DONE */ {&Sd_AllDone, SD_S_END }, /* SD_E_PORT_FOUND */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_NEXT_PORT }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_NEXT_PORT }, /* SD_E_BRANCH_FOUND */ {&Sd_DisablePort, SD_S_WAIT_DISABLE }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_NEXT_PORT }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {NULL, SD_S_NEXT_PORT }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_NEXT_PORT } }, { /* State SD_S_WAIT_ENABLE */ /* SD_E_NIL */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_WELCOME */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_PORT_ENABLED */ {&Sd_SendHello, SD_S_WAIT_HELLO }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_ENABLE }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_EnablePortTimeout, SD_S_END }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_ENABLE } }, { /* State SD_S_WAIT_DISABLE */ /* SD_E_NIL */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_STARTDIAG */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_SD_RES_OK */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_WELCOME */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_ALL_DONE */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_PORT_FOUND */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_PORT_DISABLED */ {&Sd_EnablePort, SD_S_WAIT_ENABLE }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_WAIT_DISABLE }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_DisablePortTimeout, SD_S_END }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_WAIT_DISABLE } }, { /* State SD_S_CABLE_LINK_DIAG */ /* SD_E_NIL */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_STARTDIAG */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_SD_RES_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_ABORT */ {&Sd_Abort, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_WELCOME */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_ALL_DONE */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_PORT_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_CABLE_LINK_DIAG }, /* SD_E_CABLE_LINK_RES */ {&Sd_CalcPort, SD_S_NEXT_PORT }, /* SD_E_ERROR */ {&Sd_Error, SD_S_END }, /* SD_E_TIMEOUT */ {&Sd_CableLinkDiagnosisTimeout, SD_S_END }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_CABLE_LINK_DIAG } }, { /* State SD_S_END */ /* SD_E_NIL */ {NULL, SD_S_END }, /* SD_E_STARTDIAG */ {NULL, SD_S_END }, /* SD_E_SD_RES_OK */ {Sd_Finish, SD_S_IDLE }, /* SD_E_ABORT */ {NULL, SD_S_END }, /* SD_E_HELLO_OK */ {NULL, SD_S_END }, /* SD_E_HELLO_RETRY */ {NULL, SD_S_END }, /* SD_E_HELLO_ALL_DONE */ {NULL, SD_S_END }, /* SD_E_WELCOME */ {NULL, SD_S_END }, /* SD_E_ALL_DONE */ {NULL, SD_S_END }, /* SD_E_PORT_FOUND */ {NULL, SD_S_END }, /* SD_E_PORT_ENABLED */ {NULL, SD_S_END }, /* SD_E_PORT_DISABLED */ {NULL, SD_S_END }, /* SD_E_BRANCH_FOUND */ {NULL, SD_S_END }, /* SD_E_CABLE_LINK_RES */ {NULL, SD_S_END }, /* SD_E_ERROR */ {Sd_StopDiagFailed, SD_S_IDLE }, /* SD_E_TIMEOUT */ {Sd_StopDiagFailed, SD_S_IDLE }, /* SD_E_NO_SUCCESS */ {NULL, SD_S_END } } }; /*------------------------------------------------------------------------------------------------*/ /* Implementation */ /*------------------------------------------------------------------------------------------------*/ /*! \brief Constructor of class CSysDiag. * \param self Reference to CSysDiag instance * \param inic Reference to CInic instance * \param base Reference to CBase instance * \param exc Reference to CExc instance */ void SysDiag_Ctor(CSysDiag *self, CInic *inic, CBase *base, CExc *exc) { MISC_MEM_SET((void *)self, 0, sizeof(*self)); self->inic = inic; self->exc = exc; self->base = base; Fsm_Ctor(&self->fsm, self, &(sys_diag_trans_tab[0][0]), SYS_DIAG_NUM_EVENTS, SD_E_NIL); Sobs_Ctor(&self->sys_diag_start, self, &Sd_SysDiagStartResultCb); Sobs_Ctor(&self->sys_diag_stop, self, &Sd_SysDiagStopResultCb); Sobs_Ctor(&self->sys_hello, self, &Sd_HelloStatusCb); Sobs_Ctor(&self->sys_welcome, self, &Sd_WelcomeResultCb); Sobs_Ctor(&self->sys_enable_port, self, &Sd_EnablePortResultCb); Sobs_Ctor(&self->sys_disable_port, self, &Sd_DisablePortResultCb); Sobs_Ctor(&self->sys_cable_link_diagnosis, self, &Sd_CableLinkDiagnosisResultCb); /* register termination events */ Mobs_Ctor(&self->sys_terminate, self, EH_M_TERMINATION_EVENTS, &Sd_OnTerminateEventCb); Eh_AddObsrvInternalEvent(&self->base->eh, &self->sys_terminate); /* Initialize System Diagnosis service */ Srv_Ctor(&self->sd_srv, SD_SRV_PRIO, self, &Sd_Service); /* Add System Diagnosis service to scheduler */ (void)Scd_AddService(&self->base->scd, &self->sd_srv); } /*! \brief Service function of the System Diagnosis service. * \param self Reference to System Diagnosis object */ static void Sd_Service(void *self) { CSysDiag *self_ = (CSysDiag *)self; Srv_Event_t event_mask; Srv_GetEvent(&self_->sd_srv, &event_mask); if(SD_EVENT_SERVICE == (event_mask & SD_EVENT_SERVICE)) /* Is event pending? */ { Fsm_State_t result; Srv_ClearEvent(&self_->sd_srv, SD_EVENT_SERVICE); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); result = Fsm_Service(&self_->fsm); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", (result != FSM_STATE_ERROR)); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "FSM -> %d", 1U, self_->fsm.current_state)); MISC_UNUSED(result); } } /*! \brief Starts the System Diagnosis State machine * * \param *self Reference to System Diagnosis object * \param *obs_ptr Observer pointer * \return UCS_RET_SUCCESS Operation successful * \return UCS_RET_ERR_API_LOCKED System Diagnosis was already started * \return UCS_RET_ERR_BUFFER_OVERFLOW Invalid observer */ Ucs_Return_t SysDiag_Run(CSysDiag *self, CSingleObserver *obs_ptr) { Ucs_Return_t ret_val = UCS_RET_SUCCESS; if (self->startup_locked == false) { Ssub_Ret_t ret_ssub; ret_ssub = Ssub_AddObserver(&self->sysdiag, obs_ptr); if (ret_ssub != SSUB_UNKNOWN_OBSERVER) /* obs_ptr == NULL ? */ { self->startup_locked = true; Sd_SysDiagInit(self); Fsm_SetEvent(&self->fsm, SD_E_STARTDIAG); Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Run", 0U)); } else { ret_val = UCS_RET_ERR_BUFFER_OVERFLOW; /* obs_ptr was invalid */ } } else { ret_val = UCS_RET_ERR_API_LOCKED; } return ret_val; } /*! \brief Aborts the System Diagnosis State machine * * \param *self Reference to System Diagnosis object * \return UCS_RET_SUCCESS Operation successful * \return UCS_RET_ERR_NOT_AVAILABLE System Diagnosis not running */ Ucs_Return_t SysDiag_Abort(CSysDiag *self) { Ucs_Return_t ret_val = UCS_RET_SUCCESS; if (self->startup_locked == true) /* check if System Diagnosis was started */ { Tm_ClearTimer(&self->base->tm, &self->timer); Fsm_SetEvent(&self->fsm, SD_E_ABORT); Srv_SetEvent(&self->sd_srv, SD_EVENT_SERVICE); TR_INFO((self->base->ucs_user_ptr, "[SD]", "SysDiag_Abort", 0U)); } else { ret_val = UCS_RET_ERR_NOT_AVAILABLE; } return ret_val; } /*! Initialize the System Diagnosis * * \param self Reference to System Diagnosis object */ static void Sd_SysDiagInit(void* self) { CSysDiag *self_ = (CSysDiag *)self; self_->hello_retry = SD_NUM_HELLO; self_->segment_nr = 0U; self_->num_ports = 0U; self_->curr_branch = 0U; self_->source.node_address = 0xFFFFU; self_->source.available = false; self_->last_result = SD_INIT; self_->target.node_address = 0x0001U; /* address of own INIC */ self_->target.available = false; self_->admin_node_address = SD_DIAG_ADDR_BASE; } /*! FSM action function: sets the INIC into System Diagnosis Mode * * \param *self Reference to System Diagnosis object */ static void Sd_SysDiagStart(void *self) { Ucs_Return_t ret_val; CSysDiag *self_ = (CSysDiag *)self; ret_val = Inic_NwSysDiagnosis(self_->inic, &self_->sys_diag_start); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStart", 0U)); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_COMMAND, 0U); MISC_UNUSED(ret_val); } /*! Callback function for the Inic_NwSysDiagnosis() command * * \param *self Reference to System Diagnosis object * \param *result_ptr Result of the Inic_NwSysDiagnosis() command */ static void Sd_SysDiagStartResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_SD_RES_OK", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStartResultCb SD_E_ERROR", 0U)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! FSM action function: Timeout occured * * \param *self Reference to System Diagnosis object */ static void Sd_SysDiagTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Sd_SysDiagStop(self_); } /*! FSM action function: Timeout occured * * \param *self Reference to System Diagnosis object */ static void Sd_EnablePortTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Sd_SysDiagStop(self_); } /*! FSM action function: Timeout occured * * \param *self Reference to System Diagnosis object */ static void Sd_DisablePortTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Sd_SysDiagStop(self_); } /*! Helper function. Stops the System Diagnosis * * \param *self Reference to System Diagnosis object */ static void Sd_SysDiagStop(void *self) { Ucs_Return_t ret_val; CSysDiag *self_ = (CSysDiag *)self; ret_val = Inic_NwSysDiagEnd(self_->inic, &self_->sys_diag_stop); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStop", 0U)); if (ret_val == UCS_RET_SUCCESS) { Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_COMMAND, 0U); } else { MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Fsm_SetEvent(&self_->fsm, SD_E_ERROR); Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } } /*! \brief Callback function for the Inic_NwSysDiagEnd() command * * \param *self Reference to System Diagnosis object * \param *result_ptr Result of the Inic_NwSysDiagEnd() command */ static void Sd_SysDiagStopResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", UCS_RES_SUCCESS == result_ptr_->result.code); if (result_ptr_->result.code == UCS_RES_SUCCESS) { Fsm_SetEvent(&self_->fsm, SD_E_SD_RES_OK); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_SD_RES_OK", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_SysDiagStopResultCb SD_E_ERROR", 0U)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! FSM action function: Send Hello.Get command * * \param *self Reference to System Diagnosis object */ static void Sd_SendHello(void *self) { Ucs_Return_t ret_val; CSysDiag *self_ = (CSysDiag *)self; ret_val = Exc_Hello_Get(self_->exc, UCS_ADDR_BROADCAST_BLOCKING, SD_SIGNATURE_VERSION, &self_->sys_hello); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_HELLO, 0U); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); MISC_UNUSED(ret_val); } /*! Callback function for the Enc.Hello.Status message * * \param *self Reference to System Diagnosis object * \param *result_ptr Result of the Exc_Hello_Get() command */ static void Sd_HelloStatusCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { /* read signature and store it for the Welcome command */ self_->target.signature = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).signature; self_->target.version = (*(Exc_HelloStatus_t *)(result_ptr_->data_info)).version; if (self_->segment_nr != 0U) { self_->target.node_address = self_->segment_nr + 0x0400U; } Fsm_SetEvent(&self_->fsm, SD_E_HELLO_OK); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_SD_RES_OK", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloStatusCb SD_E_ERROR", 0U)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! \brief Timer callback used for supervising INIC command timeouts. * \param self Reference to System Diagnosis object */ static void Sd_TimerCb(void *self) { CSysDiag *self_ = (CSysDiag *)self; Fsm_SetEvent(&self_->fsm, SD_E_TIMEOUT); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_TimerCb SD_E_TIMEOUT", 0U)); Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! FSM action function: retry hello command or start CableLinkDiagnosis * * \param *self Reference to System Diagnosis object */ static void Sd_HelloTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; if (self_->hello_retry > 0U) { --self_->hello_retry; Fsm_SetEvent(&self_->fsm, SD_E_HELLO_RETRY); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_RETRY", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_HELLO_ALL_DONE); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_HelloTimeout SD_E_HELLO_ALL_DONE", 0U)); } /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ } /*! FSM action function: Send Welcome message * * \param *self Reference to System Diagnosis object */ static void Sd_SendWelcome(void *self) { Ucs_Return_t ret_val; CSysDiag *self_ = (CSysDiag *)self; self_->admin_node_address = SD_DIAG_ADDR_BASE + self_->segment_nr; ret_val = Exc_Welcome_Sr(self_->exc, self_->target.node_address, self_->admin_node_address, SD_SIGNATURE_VERSION, self_->target.signature, &self_->sys_welcome); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_COMMAND, 0U); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); MISC_UNUSED(ret_val); } /*! \brief Function is called on reception of the Welcome.Result messsage * \param self Reference to System Diagnosis object * \param result_ptr Pointer to the result of the Welcome message */ static void Sd_WelcomeResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { /* read signature and store it for the Welcome command */ self_->target.result = (*(Exc_WelcomeResult_t *)(result_ptr_->data_info)).res; if (self_->target.result == SD_WELCOME_SUCCESS) { self_->target.available = true; if (self_->segment_nr == 0U) { self_->num_ports = self_->target.signature.num_ports; } else { self_->last_result = SD_SEGMENT; } /* do not report result for own node */ if (self_->segment_nr != 0U) { MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_TARGET_FOUND; self_->report.segment.branch = self_->curr_branch; self_->report.segment.num = self_->segment_nr; self_->report.segment.source = self_->source.signature; self_->report.segment.target = self_->target.signature; /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ Ssub_Notify(&self_->sysdiag, &self_->report, false); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb ReportSegment", 0U)); } Fsm_SetEvent(&self_->fsm, SD_E_WELCOME); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb SD_E_WELCOME", 0U)); } else { MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.segment.branch = self_->curr_branch; self_->report.segment.num = self_->segment_nr; self_->report.segment.source = self_->source.signature; self_->report.segment.target = self_->target.signature; /*self_->report.cable_link_info = 0U;*/ /* element is not written deliberately */ self_->report.err_info = UCS_SD_ERR_WELCOME_NO_SUCCESS; Ssub_Notify(&self_->sysdiag, &self_->report, false); Fsm_SetEvent(&self_->fsm, SD_E_NO_SUCCESS); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb reported NoSuccess", 0U)); } } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_WelcomeResultCb Error SD_E_ERROR 0x%x", 1U, result_ptr_->result.code)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! \brief FSM action function: Calculate the next port tobe examined * \param self Reference to System Diagnosis object */ static void Sd_CalcPort(void *self) { CSysDiag *self_ = (CSysDiag *)self; switch (self_->last_result) { case SD_INIT: self_->curr_branch = 0U; /* Master device has at least one port */ self_->source = self_->target; self_->master = self_->target; MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); self_->last_result = SD_SEGMENT; Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); break; case SD_SEGMENT: if (self_->target.signature.num_ports > 1U) { self_->source = self_->target; MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); Fsm_SetEvent(&self_->fsm, SD_E_PORT_FOUND); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_PORT_FOUND", 0U)); } else /* switch to next branch if possible*/ { if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ { Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); } else { self_->segment_nr = 1U; /* reset segment number */ self_->curr_branch++; /* switch to next port */ self_->source = self_->master; MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); } } break; case SD_CABLE_LINK: if (self_->num_ports == (self_->curr_branch + 1U)) /* last branch */ { Fsm_SetEvent(&self_->fsm, SD_E_ALL_DONE); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_ALL_DONE", 0U)); } else { self_->segment_nr = 1U; /* reset segment number */ self_->curr_branch++; /* switch to next port */ self_->source = self_->master; MISC_MEM_SET(&(self_->target), 0, sizeof(self_->target)); Fsm_SetEvent(&self_->fsm, SD_E_BRANCH_FOUND); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CalcPort SD_E_BRANCH_FOUND", 0U)); } break; default: break; } /*Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE);*/ } /*! \brief FSM action function: Enable port * * \param *self Reference to System Diagnosis object */ static void Sd_EnablePort(void *self) { CSysDiag *self_ = (CSysDiag *)self; uint16_t target_address; uint8_t port_number; Ucs_Return_t ret_val; if (self_->segment_nr == 0U) { port_number = self_->curr_branch; target_address = 0x0001U; } else { port_number = 1U; target_address = self_->source.node_address; } ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, true, &self_->sys_enable_port); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_COMMAND, 0U); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); MISC_UNUSED(ret_val); } /*! Function is called on reception of the EnablePort.Result messsage * * \param *self Reference to System Diagnosis object * \param *result_ptr */ static void Sd_EnablePortResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { self_->segment_nr++; Fsm_SetEvent(&self_->fsm, SD_E_PORT_ENABLED); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_PORT_ENABLED", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_EnablePortResultCb SD_E_ERROR", 0U)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! \brief FSM action function: * * \param *self Reference to System Diagnosis object */ static void Sd_DisablePort(void *self) { CSysDiag *self_ = (CSysDiag *)self; uint16_t target_address; uint8_t port_number; Ucs_Return_t ret_val; target_address = self_->admin_node_address; port_number = self_->curr_branch; ret_val = Exc_EnablePort_Sr(self_->exc, target_address, port_number, false, &self_->sys_disable_port); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_COMMAND, 0U); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); MISC_UNUSED(ret_val); } static void Sd_DisablePortResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { Fsm_SetEvent(&self_->fsm, SD_E_PORT_DISABLED); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_PORT_DISABLED", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_DisablePortResultCb SD_E_ERROR", 0U)); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! \brief FSM action function: Start CableLinkDiagnosis * * \param *self Reference to System Diagnosis object */ static void Sd_CableLinkDiagnosis(void *self) { CSysDiag *self_ = (CSysDiag *)self; uint16_t target_address; uint8_t port_number; Ucs_Return_t ret_val; if (self_->segment_nr != 0U) /* do not start CableLinkDiagnosis when connecting to local INIC */ { target_address = self_->source.node_address; if (self_->segment_nr == 1U) { port_number = self_->curr_branch; } else { port_number = 1U; /* OS81119: always port 1 */ } self_->last_result = SD_CABLE_LINK; ret_val = Exc_CableLinkDiagnosis_Start(self_->exc, target_address, port_number, &self_->sys_cable_link_diagnosis); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosis", 0U)); Tm_SetTimer(&self_->base->tm, &self_->timer, &Sd_TimerCb, self_, SD_TIMEOUT_CABLE_DIAGNOSIS, 0U); TR_ASSERT(self_->base->ucs_user_ptr, "[SD]", ret_val == UCS_RET_SUCCESS); MISC_UNUSED(ret_val); } else /* stop SystemDiagnosis when connecting to local INIC failed */ { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } } static void Sd_CableLinkDiagnosisResultCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr; Tm_ClearTimer(&self_->base->tm, &self_->timer); if (result_ptr_->result.code == UCS_RES_SUCCESS) { MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_CABLE_LINK_RES; self_->report.segment.branch = self_->curr_branch; self_->report.segment.num = self_->segment_nr; self_->report.segment.source = self_->source.signature; /*self_->report.segment.target = self_->target.signature;*/ /* structure is not written deliberately */ self_->report.cable_link_info = (*(Exc_CableLinkDiagResult_t *)(result_ptr_->data_info)).result; /*self_->report.err_info = 0U;*/ /* element is not written deliberately */ Ssub_Notify(&self_->sysdiag, &self_->report, false); Fsm_SetEvent(&self_->fsm, SD_E_CABLE_LINK_RES); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_CABLE_LINK_RES", 0U)); } else { Fsm_SetEvent(&self_->fsm, SD_E_ERROR); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_CableLinkDiagnosisResultCb SD_E_ERROR %02X %02X %02X", 3U, result_ptr_->result.info_ptr[0], result_ptr_->result.info_ptr[1], result_ptr_->result.info_ptr[2])); } Srv_SetEvent(&self_->sd_srv, SD_EVENT_SERVICE); } /*! \brief FSM action function: React on Timeout of CableLinkDiagnosis * * \param *self Reference to System Diagnosis object */ static void Sd_CableLinkDiagnosisTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); Sd_SysDiagStop(self_); } /*! \brief FSM action function: React on Timeout of Welcome * * \param *self Reference to System Diagnosis object */ static void Sd_WelcomeTimeout(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); TR_FAILED_ASSERT(self_->base->ucs_user_ptr, "[SD]"); Sd_SysDiagStop(self_); } /*! \brief FSM action function: All branches and segments explored, finish System Diagnosis * * \param *self Reference to System Diagnosis object */ static void Sd_AllDone(void *self) { CSysDiag *self_ = (CSysDiag *)self; TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_AllDone", 0U)); Sd_SysDiagStop(self_); } /*! \brief FSM action function: INIC system Diagnosis mode ended * * \param *self Reference to System Diagnosis object */ static void Sd_Finish(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_FINISHED; Ssub_Notify(&self_->sysdiag, &self_->report, true); self_->startup_locked = false; TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Finish", 0U)); } /*! \brief FSM action function: An unexpected error occurred. * * \param *self Reference to System Diagnosis object */ static void Sd_Error(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_UNSPECIFIED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Sd_SysDiagStop(self_); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Error", 0U)); } /*! \brief FSM action function: Welcome reports NoSuccess. * * \param *self Reference to System Diagnosis object */ static void Sd_ErrorWelcome(void *self) { CSysDiag *self_ = (CSysDiag *)self; Sd_SysDiagStop(self_); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_ErrorWelcome", 0U)); } /*! \brief FSM action function: stopping system diagnosis mode failed * * \param *self Reference to System Diagnosis object */ static void Sd_StopDiagFailed(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_STOP_SYSDIAG_FAILED; Ssub_Notify(&self_->sysdiag, &self_->report, false); /* always finish the System Diagnosis with event UCS_SD_FINISHED */ MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_FINISHED; Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ self_->startup_locked = false; TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_StopDiagFailed", 0U)); } /*! \brief FSM action function: Application requested to abort the System Diagnosis. * * \param *self Reference to System Diagnosis object */ static void Sd_Abort(void *self) { CSysDiag *self_ = (CSysDiag *)self; MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ABORTED; Ssub_Notify(&self_->sysdiag, &self_->report, false); Sd_SysDiagStop(self_); TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_Abort", 0U)); } /*! Function is called on severe internal errors * * \param *self Reference to System Diagnosis object * \param *result_ptr Reference to data */ static void Sd_OnTerminateEventCb(void *self, void *result_ptr) { CSysDiag *self_ = (CSysDiag *)self; MISC_UNUSED(result_ptr); if (self_->fsm.current_state != SD_S_IDLE) { Tm_ClearTimer(&self_->base->tm, &self_->timer); MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_ERROR; self_->report.err_info = UCS_SD_ERR_TERMINATED; Ssub_Notify(&self_->sysdiag, &self_->report, false); /* always finish the System Diagnosis with event UCS_SD_FINISHED */ MISC_MEM_SET(&self_->report, 0, sizeof(self_->report)); self_->report.code = UCS_SD_FINISHED; Ssub_Notify(&self_->sysdiag, &self_->report, true); /* remove the observer function */ TR_INFO((self_->base->ucs_user_ptr, "[SD]", "Sd_OnTerminateEventCb", 0U)); /* reset FSM */ self_->startup_locked = false; Sd_SysDiagInit(self_); self_->fsm.current_state = SD_S_IDLE; } } /*! * @} * \endcond */ /*------------------------------------------------------------------------------------------------*/ /* End of file */ /*------------------------------------------------------------------------------------------------*/