diff options
Diffstat (limited to 'ucs2-lib/src/ucs_prog.c')
-rw-r--r-- | ucs2-lib/src/ucs_prog.c | 957 |
1 files changed, 957 insertions, 0 deletions
diff --git a/ucs2-lib/src/ucs_prog.c b/ucs2-lib/src/ucs_prog.c new file mode 100644 index 0000000..e64d519 --- /dev/null +++ b/ucs2-lib/src/ucs_prog.c @@ -0,0 +1,957 @@ +/*------------------------------------------------------------------------------------------------*/ +/* UNICENS V2.1.0-3491 */ +/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */ +/* */ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* */ +/* You may also obtain this software under a propriety license from Microchip. */ +/* Please contact Microchip for further information. */ +/*------------------------------------------------------------------------------------------------*/ + +/*! + * \file + * \brief Implementation of the Programming Service. + * + * \cond UCS_INTERNAL_DOC + * \addtogroup G_PROG_MODE + * @{ + + */ + +/*------------------------------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------------------------------*/ +#include "ucs_inic_pb.h" +#include "ucs_prog.h" +#include "ucs_misc.h" + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal constants */ +/*------------------------------------------------------------------------------------------------*/ +#define PRG_NUM_STATES 6U /*!< \brief Number of state machine states */ +#define PRG_NUM_EVENTS 13U /*!< \brief Number of state machine events */ + +#define PRG_TIMEOUT_COMMAND 100U /*!< \brief supervise EXC commands */ + +#define PRG_SIGNATURE_VERSION 1U /*!< \brief signature version used for Node Discovery */ + +#define PRG_ADMIN_BASE_ADDR 0x0F00U /*!< \brief bas admin address */ + + +/* Error values */ +#define PRG_HW_RESET_REQ 0x200110U /* HW reset required */ +#define PRG_SESSION_ACTIVE 0x200111U /* Session already active */ +#define PRG_CFG_STRING_ERROR 0x200220U /* A configuration string erase error has occurred. */ +#define PRG_MEM_ERASE_ERROR 0x200221U /* An error memory erase error has occurred.*/ +#define PRG_CFG_WRITE_ERROR 0x200225U /* Configuration memory write error. */ +#define PRG_CFG_FULL_ERROR 0x200226U /* Configuration memory is full. */ +#define PRG_HDL_MATCH_ERROR 0x200330U /* The SessionHandle does not match the current memory session. */ +#define PRG_MEMID_ERROR 0x200331U /* The memory session does not support the requested MemID. */ +#define PRG_ADDR_EVEN_ERROR 0x200332U /* The Address is not even when writing the configuration memory. */ +#define PRG_LEN_EVEN_ERROR 0x200333U /* The UnitLen is not even when writing the configuration memory. */ + +/*------------------------------------------------------------------------------------------------*/ +/* Service parameters */ +/*------------------------------------------------------------------------------------------------*/ +/*! Priority of the Programming service used by scheduler */ +static const uint8_t PRG_SRV_PRIO = 248U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ +/*! Main event for the Programming service */ +static const Srv_Event_t PRG_EVENT_SERVICE = 1U; + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal enumerators */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief Possible events of the system diagnosis state machine */ +typedef enum Prg_Events_ +{ + PRG_E_NIL = 0U, /*!< \brief NIL Event */ + PRG_E_START = 1U, /*!< \brief API start command was called. */ + PRG_E_STOP = 2U, /*!< \brief Stop request occurred. */ + PRG_E_WELCOME_SUCCESS = 3U, /*!< \brief Welcome command was successful. */ + PRG_E_WELCOME_NOSUCCESS = 4U, /*!< \brief Welcome command was not successful. */ + PRG_E_MEM_WRITE_CMD = 5U, /*!< \brief MemorySessionOpen command was succcessful */ + PRG_E_MEM_WRITE_FINISH = 6U, /*!< \brief MemoryWrite command was succcessful */ + PRG_E_MEM_CLOSE_SUCCESS = 7U, /*!< \brief MemorySessionClose command was succcessful */ + PRG_E_NET_OFF = 8U, /*!< \brief NetOff occurred. */ + PRG_E_TIMEOUT = 9U, /*!< \brief Timeout occurred. */ + PRG_E_ERROR = 10U, /*!< \brief An error occurred which requires no command to be sent to the INIC. */ + PRG_E_ERROR_INIT = 11U, /*!< \brief Error requires Init.Start to be sent. */ + PRG_E_ERROR_CLOSE_INIT = 12U /*!< \brief Error requires MemorySessionClose.SR and Init.Start to be sent. */ +} Prg_Events_t; + + +/*! \brief States of the node discovery state machine */ +typedef enum Prg_State_ +{ + PRG_S_IDLE = 0U, /*!< \brief Idle state. */ + PRG_S_WAIT_WELCOME = 1U, /*!< \brief Programming started. */ + PRG_S_WAIT_MEM_OPEN = 2U, /*!< \brief Wait for MemorySessionOpen result. */ + PRG_S_WAIT_MEM_WRITE = 3U, /*!< \brief Wait for MemoryWrite result. */ + PRG_S_WAIT_MEM_CLOSE = 4U, /*!< \brief Wait for MemorySessionClose result. */ + PRG_S_WAIT_MEM_ERR_CLOSE = 5U /*!< \brief Wait for MemorySessionClose result in error case. */ +} Prg_State_t; + + +/*------------------------------------------------------------------------------------------------*/ +/* Internal prototypes */ +/*------------------------------------------------------------------------------------------------*/ +static void Prg_Service(void *self); + +static void Prg_WelcomeResultCb(void *self, void *result_ptr); +static void Prg_MemOpenResultCb(void *self, void *result_ptr); +static void Prg_MemWriteResultCb(void *self, void *result_ptr); +static void Prg_MemCloseResultCb(void *self, void *result_ptr); + +static void Prg_OnTerminateEventCb(void *self, void *result_ptr); +static void Prg_NetworkStatusCb(void *self, void *result_ptr); + +static void Prg_A_Start(void *self); +static void Prg_A_MemOpen(void *self); +static void Prg_A_MemWrite(void *self); +static void Prg_A_MemClose(void *self); +static void Prg_A_InitDevice(void *self); +static void Prg_A_NetOff(void *self); +static void Prg_A_Timeout(void *self); +static void Prg_A_Error(void *self); +static void Prg_A_Error_Init(void *self); +static void Prg_A_Error_Close_Init(void *self); + + +static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val); +static uint32_t Prg_CalcError(uint8_t val[]); + +static void Prg_TimerCb(void *self); + +/*------------------------------------------------------------------------------------------------*/ +/* State transition table (used by finite state machine) */ +/*------------------------------------------------------------------------------------------------*/ +/*! \brief State transition table */ +static const Fsm_StateElem_t prg_trans_tab[PRG_NUM_STATES][PRG_NUM_EVENTS] = /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */ +{ + { /* State PRG_S_IDLE */ + /* PRG_E_NIL */ {NULL, PRG_S_IDLE }, + /* PRG_E_START */ {Prg_A_Start, PRG_S_WAIT_WELCOME }, + /* PRG_E_STOP */ {NULL, PRG_S_IDLE }, + /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_IDLE }, + /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_IDLE }, + /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_IDLE }, + /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_IDLE }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_IDLE }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {NULL, PRG_S_IDLE }, + /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_IDLE }, + }, + { /* State PRG_S_WAIT_WELCOME */ + /* PRG_E_NIL */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_START */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_STOP */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_WELCOME_SUCCESS */ {Prg_A_MemOpen, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_WELCOME_NOSUCCESS */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {NULL, PRG_S_WAIT_WELCOME }, + /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_WAIT_WELCOME } + }, + { /* State PRG_S_WAIT_MEM_OPEN */ + /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_MEM_WRITE_CMD */ {Prg_A_MemWrite, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, + /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE } + }, + { /* State PRG_S_WAIT_MEM_WRITE */ + /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, + /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE } + }, + { /* State PRG_S_WAIT_MEM_CLOSE */ + /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_CLOSE }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_InitDevice, PRG_S_IDLE }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, + /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE }, + }, + { /* State PRG_S_WAIT_MEM_ERR_CLOSE */ + /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE }, + /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_Error_Init, PRG_S_IDLE }, + /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE }, + /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE }, + /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE }, + /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE }, + /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE }, + } + +}; + + +/*! \brief Constructor of class CProgramming. + * \param self Reference to CProgramming instance + * \param inic Reference to CInic instance + * \param base Reference to CBase instance + * \param exc Reference to CExc instance + */ + /* \param init_ptr Report callback function*/ +void Prg_Ctor(CProgramming *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, &(prg_trans_tab[0][0]), PRG_NUM_EVENTS, PRG_E_NIL); + + Sobs_Ctor(&self->prg_welcome, self, &Prg_WelcomeResultCb); + Sobs_Ctor(&self->prg_memopen, self, &Prg_MemOpenResultCb); + Sobs_Ctor(&self->prg_memwrite, self, &Prg_MemWriteResultCb); + Sobs_Ctor(&self->prg_memclose, self, &Prg_MemCloseResultCb); + + /* register termination events */ + Mobs_Ctor(&self->prg_terminate, self, EH_M_TERMINATION_EVENTS, &Prg_OnTerminateEventCb); + Eh_AddObsrvInternalEvent(&self->base->eh, &self->prg_terminate); + + /* Register NetOn and MPR events */ + Obs_Ctor(&self->prg_nwstatus, self, &Prg_NetworkStatusCb); + Inic_AddObsrvNwStatus(self->inic, &self->prg_nwstatus); + self->neton = false; + + /* Initialize Programming service */ + Srv_Ctor(&self->service, PRG_SRV_PRIO, self, &Prg_Service); + /* Add Programming service to scheduler */ + (void)Scd_AddService(&self->base->scd, &self->service); + +} + + +/*! \brief Service function of the Node Discovery service. + * \param self Reference to Programming service object + */ +static void Prg_Service(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Srv_Event_t event_mask; + Srv_GetEvent(&self_->service, &event_mask); + if(PRG_EVENT_SERVICE == (event_mask & PRG_EVENT_SERVICE)) /* Is event pending? */ + { + Fsm_State_t result; + Srv_ClearEvent(&self_->service, PRG_EVENT_SERVICE); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured)); + result = Fsm_Service(&self_->fsm); + TR_ASSERT(self_->base->ucs_user_ptr, "[PRG]", (result != FSM_STATE_ERROR)); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM -> %d", 1U, self_->fsm.current_state)); + MISC_UNUSED(result); + } +} + + + +/**************************************************************************************************/ +/* API functions */ +/**************************************************************************************************/ +/*! + * + * \param *self Reference to Programming service object + */ +/*! \brief Program a node + * + * \param *self Reference to Programming service object + * \param node_id Node position address of the node to be programmed + * \param *signature Signature of the node to be programmed + * \param session_type Defines the memory access type. + * \param command_list Refers to array of programming tasks. + * \param report_fptr Report callback function + */ +void Prg_Start(CProgramming *self, + uint16_t node_id, + Ucs_Signature_t *signature, + Ucs_Prg_SessionType_t session_type, + Ucs_Prg_Command_t* command_list, + Ucs_Prg_ReportCb_t report_fptr) +{ + + + self->node_id = node_id; + self->signature = *signature; + self->session_type = session_type; + self->command_list = command_list; + self->report_fptr = report_fptr; + self->current_function = UCS_PRG_FKT_DUMMY; + + if (self->neton == true) + { + Fsm_SetEvent(&self->fsm, PRG_E_START); + Srv_SetEvent(&self->service, PRG_EVENT_SERVICE); + + TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start", 0U)); + } + else + { + if (self->report_fptr != NULL) + { + self->report_fptr(UCS_PRG_RES_NET_OFF, + self->current_function, + 0U, + NULL, + self->base->ucs_user_ptr); + } + TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start failed: NET_OFF", 0U)); + } +} + + + +/**************************************************************************************************/ +/* FSM Actions */ +/**************************************************************************************************/ +/*! Action on Start command + * + * \param *self Reference to Node Discovery object + */ +static void Prg_A_Start(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Ucs_Return_t ret_val; + + if (self_->node_id == 0x0400U) + { + self_->target_address = UCS_ADDR_LOCAL_INIC; + } + else + { + self_->target_address = self_->node_id; + } + + self_->admin_node_address = PRG_ADMIN_BASE_ADDR + ((self_->node_id) & 0x00FFU); + self_->current_function = UCS_PRG_FKT_WELCOME; + + ret_val = Exc_Welcome_Sr(self_->exc, + self_->target_address, + self_->admin_node_address, + PRG_SIGNATURE_VERSION, + self_->signature, + &self_->prg_welcome); + Prg_Check_RetVal(self_, ret_val); +} + +static void Prg_A_MemOpen(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Ucs_Return_t ret_val; + + self_->current_function = UCS_PRG_FKT_MEM_OPEN; + + ret_val = Exc_MemSessionOpen_Sr(self_->exc, + self_->admin_node_address, + self_->session_type, + &self_->prg_memopen); + Prg_Check_RetVal(self_, ret_val); +} + +static void Prg_A_MemWrite(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Ucs_Return_t ret_val; + + self_->current_function = UCS_PRG_FKT_MEM_WRITE; + + ret_val = Exc_MemoryWrite_Sr(self_->exc, + self_->admin_node_address, + self_->session_handle, + self_->command_list[self_->command_index].mem_id, + self_->command_list[self_->command_index].address, + self_->command_list[self_->command_index].unit_length, + self_->command_list[self_->command_index].data, + &self_->prg_memwrite); + Prg_Check_RetVal(self_, ret_val); +} + +static void Prg_A_MemClose(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Ucs_Return_t ret_val; + + self_->current_function = UCS_PRG_FKT_MEM_CLOSE; + ret_val = Exc_MemSessionClose_Sr(self_->exc, + self_->admin_node_address, + self_->session_handle, + &self_->prg_memclose); + Prg_Check_RetVal(self_, ret_val); +} + +static void Prg_A_InitDevice(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + Ucs_Return_t ret_val; + + self_->current_function = UCS_PRG_FKT_INIT; + ret_val = Exc_DeviceInit_Start(self_->exc, + self_->admin_node_address, + NULL); + Prg_Check_RetVal(self_, ret_val); + + if (ret_val == UCS_RET_SUCCESS) + { + if (self_->report_fptr != NULL) + { + self_->report_fptr(UCS_PRG_RES_SUCCESS, + UCS_PRG_FKT_DUMMY, + 0U, + NULL, + self_->base->ucs_user_ptr); + } + } +} + +static void Prg_A_NetOff(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + + if (self_->report_fptr != NULL) + { + self_->report_fptr(UCS_PRG_RES_NET_OFF, + self_->current_function, + 0U, + NULL, + self_->base->ucs_user_ptr); + } +} + +static void Prg_A_Timeout(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + + if (self_->report_fptr != NULL) + { + self_->report_fptr(UCS_PRG_RES_TIMEOUT, + self_->current_function, + 0U, + NULL, + self_->base->ucs_user_ptr); + } +} + +static void Prg_A_Error(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + uint8_t *data_ptr = NULL; + + if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) + && (self_->error.ret_len != 0U)) + { + data_ptr = &(self_->error.parm[0]); + } + + if (self_->report_fptr != NULL) + { + self_->report_fptr(self_->error.code, + self_->error.function, + self_->error.ret_len, + data_ptr, + self_->base->ucs_user_ptr); + } +} + + +static void Prg_A_Error_Init(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + uint8_t *data_ptr = NULL; + Ucs_Return_t ret_val; + + ret_val = Exc_DeviceInit_Start(self_->exc, + self_->admin_node_address, + NULL); + Prg_Check_RetVal(self_, ret_val); + + if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) + && (self_->error.ret_len != 0U)) + { + data_ptr = &(self_->error.parm[0]); + } + + if (self_->report_fptr != NULL) + { + self_->report_fptr(self_->error.code, + self_->error.function, + self_->error.ret_len, + data_ptr, + self_->base->ucs_user_ptr); + } +} + +static void Prg_A_Error_Close_Init(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + uint8_t *data_ptr = NULL; + Ucs_Return_t ret_val; + + ret_val = Exc_DeviceInit_Start(self_->exc, + self_->admin_node_address, + NULL); + Prg_Check_RetVal(self_, ret_val); + + + if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH) + && (self_->error.ret_len != 0U)) + { + data_ptr = &(self_->error.parm[0]); + } + + if (self_->report_fptr != NULL) + { + self_->report_fptr(self_->error.code, + self_->error.function, + self_->error.ret_len, + data_ptr, + self_->base->ucs_user_ptr); + } +} + + +/**************************************************************************************************/ +/* Callback functions */ +/**************************************************************************************************/ + +/*! \brief Function is called on reception of the Welcome.Result messsage + * \param self Reference to Programming service object + * \param result_ptr Pointer to the result of the Welcome message + */ +static void Prg_WelcomeResultCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)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) + { + Exc_WelcomeResult_t welcome_result; + /* read signature and store it */ + welcome_result = *(Exc_WelcomeResult_t *)(result_ptr_->data_info); + if (welcome_result.res == EXC_WELCOME_SUCCESS) + { + Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_SUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_SUCCESS", 0U)); + } + else + { + /* store error paramters */ + self_->error.code = UCS_PRG_RES_FKT_ASYNCH; + self_->error.function = UCS_PRG_FKT_WELCOME_NOSUCCESS; + self_->error.ret_len = 0U; + + Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_NOSUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_NOSUCCESS", 0U)); + } + } + else + { + uint8_t i; + /* store error paramters */ + self_->error.code = UCS_PRG_RES_FKT_ASYNCH; + self_->error.function = UCS_PRG_FKT_WELCOME; + self_->error.ret_len = result_ptr_->result.info_size; + for (i=0U; i< result_ptr_->result.info_size; ++i) + { + self_->error.parm[i] = result_ptr_->result.info_ptr[i]; + } + + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); + + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (code) 0x%x", 1U, result_ptr_->result.code)); + for (i=0U; i< result_ptr_->result.info_size; ++i) + { + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i])); + } + } + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + + +/*! \brief Function is called on reception of the MemorySessionOpen.Result messsage + * \param self Reference to Programming service object + * \param result_ptr Pointer to the result of the Welcome message + */ +static void Prg_MemOpenResultCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)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_->session_handle = *(uint16_t *)(result_ptr_->data_info); + self_->command_index = 0U; + + if ( (self_->command_list[self_->command_index].data_length == 0U) + || (self_->command_list[self_->command_index].data == NULL)) + { + Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb No Tasks", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb successful", 0U)); + } + } + else + { + uint8_t i; + uint32_t fs_error; + + /* store error paramters */ + self_->error.code = UCS_PRG_RES_FKT_ASYNCH; + self_->error.function = UCS_PRG_FKT_MEM_OPEN; + self_->error.ret_len = result_ptr_->result.info_size; + for (i=0U; i< result_ptr_->result.info_size; ++i) + { + self_->error.parm[i] = result_ptr_->result.info_ptr[i]; + } + + fs_error = Prg_CalcError(&(self_->error.parm[0])); + + switch (fs_error) + { + case PRG_HW_RESET_REQ: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); + break; + + case PRG_SESSION_ACTIVE: + self_->session_handle = (uint16_t)(((uint16_t)(self_->error.parm[3])) << 8U) + self_->error.parm[4]; /* get correct session handle */ + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + default: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); + break; + } + + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb Error 0x%x", 1U, result_ptr_->result.code)); + } + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + +/*! \brief Function is called on reception of the MemoryWrite.Result messsage + * \param self Reference to Programming service object + * \param result_ptr Pointer to the result of the Welcome message + */ +static void Prg_MemWriteResultCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)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_->command_index++; + if ( (self_->command_list[self_->command_index].data_length == 0U) + || (self_->command_list[self_->command_index].data == NULL)) + { + Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb PRG_E_MEM_WRITE_FINISH", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb successful", 0U)); + } + } + else + { + uint8_t i; + uint32_t fs_error; + + /* store error paramters */ + self_->error.code = UCS_PRG_RES_FKT_ASYNCH; + self_->error.function = UCS_PRG_FKT_MEM_WRITE; + self_->error.ret_len = result_ptr_->result.info_size; + for (i=0U; i< result_ptr_->result.info_size; ++i) + { + self_->error.parm[i] = result_ptr_->result.info_ptr[i]; + } + + fs_error = Prg_CalcError(&(self_->error.parm[0])); + + switch (fs_error) + { + case PRG_CFG_WRITE_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + case PRG_CFG_FULL_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + case PRG_HDL_MATCH_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); + break; + + case PRG_MEMID_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + case PRG_ADDR_EVEN_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + case PRG_LEN_EVEN_ERROR: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT); + break; + + default: + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); + break; + } + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb Error 0x%x", 1U, result_ptr_->result.code)); + } + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + +/*! \brief Function is called on reception of the MemorySessionClose.Result messsage + * \param self Reference to Programming service object + * \param result_ptr Pointer to the result of the Welcome message + */ +static void Prg_MemCloseResultCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)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) + { + uint8_t session_result = *(uint8_t *)(result_ptr_->data_info); + + if (session_result == 0U) + { + Fsm_SetEvent(&self_->fsm, PRG_E_MEM_CLOSE_SUCCESS); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb PRG_E_MEM_CLOSE_SUCCESS", 0U)); + } + else + { + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb ErrResult PRG_E_ERROR_INIT", 0U)); + } + } + else + { + uint8_t i; + uint32_t fs_error; + + /* store error paramters */ + self_->error.code = UCS_PRG_RES_FKT_ASYNCH; + self_->error.function = UCS_PRG_FKT_MEM_CLOSE; + self_->error.ret_len = result_ptr_->result.info_size; + for (i=0U; i< result_ptr_->result.info_size; ++i) + { + self_->error.parm[i] = result_ptr_->result.info_ptr[i]; + } + + fs_error = Prg_CalcError(&(self_->error.parm[0])); + + if (fs_error == PRG_HDL_MATCH_ERROR) + { + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT); + } + else + { + Fsm_SetEvent(&self_->fsm, PRG_E_ERROR); + } + + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb Error 0x%x", 1U, result_ptr_->result.code)); + } + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + + + +/*! Function is called on severe internal errors + * + * \param *self Reference to Programming object + * \param *result_ptr Reference to data + */ +static void Prg_OnTerminateEventCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)self; + + MISC_UNUSED(result_ptr); + + if (self_->fsm.current_state != PRG_S_IDLE) + { + Tm_ClearTimer(&self_->base->tm, &self_->timer); + if (self_->report_fptr != NULL) + { + self_->report_fptr(UCS_PRG_RES_ERROR, + self_->current_function, + 0U, + NULL, + self_->base->ucs_user_ptr); + } + + /* reset FSM */ + self_->fsm.current_state = PRG_S_IDLE; + } +} + + +/*! \brief Callback function for the INIC.NetworkStatus status and error messages + * + * \param *self Reference to Node Discovery object + * \param *result_ptr Pointer to the result of the INIC.NetworkStatus message + */ +static void Prg_NetworkStatusCb(void *self, void *result_ptr) +{ + CProgramming *self_ = (CProgramming *)self; + Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr; + + if (result_ptr_->result.code == UCS_RES_SUCCESS) + { + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_NetworkStatusCb 0x%x", 1U, result_ptr_->result.code)); + /* check for NetOn/NetOff events */ + if ( (self_->neton == true) + && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) ) + { + self_->neton = false; + Fsm_SetEvent(&self_->fsm, PRG_E_NET_OFF); + } + else if ( (self_->neton == false) + && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) ) + { + self_->neton = true; + } + } + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + + +/*! \brief Timer callback used for supervising INIC command timeouts. + * \param self Reference to System Diagnosis object + */ +static void Prg_TimerCb(void *self) +{ + CProgramming *self_ = (CProgramming *)self; + + Fsm_SetEvent(&self_->fsm, PRG_E_TIMEOUT); + TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_TimerCb PRG_E_TIMEOUT", 0U)); + + Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE); +} + + + +/**************************************************************************************************/ +/* Helper functions */ +/**************************************************************************************************/ + +static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val) +{ + if (ret_val == UCS_RET_SUCCESS) + { + Tm_SetTimer(&self->base->tm, + &self->timer, + &Prg_TimerCb, + self, + PRG_TIMEOUT_COMMAND, + 0U); + } + else + { + TR_ASSERT(self->base->ucs_user_ptr, "[PRG]", ret_val == UCS_RET_SUCCESS); + + /* store error paramter */ + self->error.code = UCS_PRG_RES_FKT_SYNCH; + self->error.function = self->current_function; + self->error.ret_len = (uint8_t)ret_val; + + Fsm_SetEvent(&self->fsm, PRG_E_ERROR); + Srv_SetEvent(&self->service, PRG_EVENT_SERVICE); + } +} + + +static uint32_t Prg_CalcError(uint8_t val[]) +{ + uint32_t temp; + + temp = val[0] + (((uint32_t)val[1]) << 8U) + (((uint32_t)val[2]) << 16U); + + return temp; +} + + + + + +/*! + * @} + * \endcond + */ + +/*------------------------------------------------------------------------------------------------*/ +/* End of file */ +/*------------------------------------------------------------------------------------------------*/ + |