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 Programming Service.
26 * \cond UCS_INTERNAL_DOC
27 * \addtogroup G_PROG_MODE
32 /*------------------------------------------------------------------------------------------------*/
34 /*------------------------------------------------------------------------------------------------*/
35 #include "ucs_inic_pb.h"
40 /*------------------------------------------------------------------------------------------------*/
41 /* Internal constants */
42 /*------------------------------------------------------------------------------------------------*/
43 #define PRG_NUM_STATES 6U /*!< \brief Number of state machine states */
44 #define PRG_NUM_EVENTS 13U /*!< \brief Number of state machine events */
46 #define PRG_TIMEOUT_COMMAND 100U /*!< \brief supervise EXC commands */
48 #define PRG_SIGNATURE_VERSION 1U /*!< \brief signature version used for Node Discovery */
50 #define PRG_ADMIN_BASE_ADDR 0x0F00U /*!< \brief bas admin address */
54 #define PRG_HW_RESET_REQ 0x200110U /* HW reset required */
55 #define PRG_SESSION_ACTIVE 0x200111U /* Session already active */
56 #define PRG_CFG_STRING_ERROR 0x200220U /* A configuration string erase error has occurred. */
57 #define PRG_MEM_ERASE_ERROR 0x200221U /* An error memory erase error has occurred.*/
58 #define PRG_CFG_WRITE_ERROR 0x200225U /* Configuration memory write error. */
59 #define PRG_CFG_FULL_ERROR 0x200226U /* Configuration memory is full. */
60 #define PRG_HDL_MATCH_ERROR 0x200330U /* The SessionHandle does not match the current memory session. */
61 #define PRG_MEMID_ERROR 0x200331U /* The memory session does not support the requested MemID. */
62 #define PRG_ADDR_EVEN_ERROR 0x200332U /* The Address is not even when writing the configuration memory. */
63 #define PRG_LEN_EVEN_ERROR 0x200333U /* The UnitLen is not even when writing the configuration memory. */
65 /*------------------------------------------------------------------------------------------------*/
66 /* Service parameters */
67 /*------------------------------------------------------------------------------------------------*/
68 /*! Priority of the Programming service used by scheduler */
69 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." */
70 /*! Main event for the Programming service */
71 static const Srv_Event_t PRG_EVENT_SERVICE = 1U;
74 /*------------------------------------------------------------------------------------------------*/
75 /* Internal enumerators */
76 /*------------------------------------------------------------------------------------------------*/
77 /*! \brief Possible events of the system diagnosis state machine */
78 typedef enum Prg_Events_
80 PRG_E_NIL = 0U, /*!< \brief NIL Event */
81 PRG_E_START = 1U, /*!< \brief API start command was called. */
82 PRG_E_STOP = 2U, /*!< \brief Stop request occurred. */
83 PRG_E_WELCOME_SUCCESS = 3U, /*!< \brief Welcome command was successful. */
84 PRG_E_WELCOME_NOSUCCESS = 4U, /*!< \brief Welcome command was not successful. */
85 PRG_E_MEM_WRITE_CMD = 5U, /*!< \brief MemorySessionOpen command was succcessful */
86 PRG_E_MEM_WRITE_FINISH = 6U, /*!< \brief MemoryWrite command was succcessful */
87 PRG_E_MEM_CLOSE_SUCCESS = 7U, /*!< \brief MemorySessionClose command was succcessful */
88 PRG_E_NET_OFF = 8U, /*!< \brief NetOff occurred. */
89 PRG_E_TIMEOUT = 9U, /*!< \brief Timeout occurred. */
90 PRG_E_ERROR = 10U, /*!< \brief An error occurred which requires no command to be sent to the INIC. */
91 PRG_E_ERROR_INIT = 11U, /*!< \brief Error requires Init.Start to be sent. */
92 PRG_E_ERROR_CLOSE_INIT = 12U /*!< \brief Error requires MemorySessionClose.SR and Init.Start to be sent. */
96 /*! \brief States of the node discovery state machine */
97 typedef enum Prg_State_
99 PRG_S_IDLE = 0U, /*!< \brief Idle state. */
100 PRG_S_WAIT_WELCOME = 1U, /*!< \brief Programming started. */
101 PRG_S_WAIT_MEM_OPEN = 2U, /*!< \brief Wait for MemorySessionOpen result. */
102 PRG_S_WAIT_MEM_WRITE = 3U, /*!< \brief Wait for MemoryWrite result. */
103 PRG_S_WAIT_MEM_CLOSE = 4U, /*!< \brief Wait for MemorySessionClose result. */
104 PRG_S_WAIT_MEM_ERR_CLOSE = 5U /*!< \brief Wait for MemorySessionClose result in error case. */
108 /*------------------------------------------------------------------------------------------------*/
109 /* Internal prototypes */
110 /*------------------------------------------------------------------------------------------------*/
111 static void Prg_Service(void *self);
113 static void Prg_WelcomeResultCb(void *self, void *result_ptr);
114 static void Prg_MemOpenResultCb(void *self, void *result_ptr);
115 static void Prg_MemWriteResultCb(void *self, void *result_ptr);
116 static void Prg_MemCloseResultCb(void *self, void *result_ptr);
118 static void Prg_OnTerminateEventCb(void *self, void *result_ptr);
119 static void Prg_NetworkStatusCb(void *self, void *result_ptr);
121 static void Prg_A_Start(void *self);
122 static void Prg_A_MemOpen(void *self);
123 static void Prg_A_MemWrite(void *self);
124 static void Prg_A_MemClose(void *self);
125 static void Prg_A_InitDevice(void *self);
126 static void Prg_A_NetOff(void *self);
127 static void Prg_A_Timeout(void *self);
128 static void Prg_A_Error(void *self);
129 static void Prg_A_Error_Init(void *self);
130 static void Prg_A_Error_Close_Init(void *self);
133 static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val);
134 static uint32_t Prg_CalcError(uint8_t val[]);
136 static void Prg_TimerCb(void *self);
138 /*------------------------------------------------------------------------------------------------*/
139 /* State transition table (used by finite state machine) */
140 /*------------------------------------------------------------------------------------------------*/
141 /*! \brief State transition table */
142 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." */
144 { /* State PRG_S_IDLE */
145 /* PRG_E_NIL */ {NULL, PRG_S_IDLE },
146 /* PRG_E_START */ {Prg_A_Start, PRG_S_WAIT_WELCOME },
147 /* PRG_E_STOP */ {NULL, PRG_S_IDLE },
148 /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_IDLE },
149 /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_IDLE },
150 /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_IDLE },
151 /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_IDLE },
152 /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_IDLE },
153 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
154 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
155 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
156 /* PRG_E_ERROR_INIT */ {NULL, PRG_S_IDLE },
157 /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_IDLE },
159 { /* State PRG_S_WAIT_WELCOME */
160 /* PRG_E_NIL */ {NULL, PRG_S_WAIT_WELCOME },
161 /* PRG_E_START */ {NULL, PRG_S_WAIT_WELCOME },
162 /* PRG_E_STOP */ {NULL, PRG_S_WAIT_WELCOME },
163 /* PRG_E_WELCOME_SUCCESS */ {Prg_A_MemOpen, PRG_S_WAIT_MEM_OPEN },
164 /* PRG_E_WELCOME_NOSUCCESS */ {Prg_A_Error, PRG_S_IDLE },
165 /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_WELCOME },
166 /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_WELCOME },
167 /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_WELCOME },
168 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
169 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
170 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
171 /* PRG_E_ERROR_INIT */ {NULL, PRG_S_WAIT_WELCOME },
172 /* PRG_E_ERROR_CLOSE_INIT */ {NULL, PRG_S_WAIT_WELCOME }
174 { /* State PRG_S_WAIT_MEM_OPEN */
175 /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_OPEN },
176 /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_OPEN },
177 /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_OPEN },
178 /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN },
179 /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN },
180 /* PRG_E_MEM_WRITE_CMD */ {Prg_A_MemWrite, PRG_S_WAIT_MEM_WRITE },
181 /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE },
182 /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_OPEN },
183 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
184 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
185 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
186 /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE },
187 /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE }
189 { /* State PRG_S_WAIT_MEM_WRITE */
190 /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_WRITE },
191 /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_WRITE },
192 /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_WRITE },
193 /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE },
194 /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE },
195 /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_WRITE },
196 /* PRG_E_MEM_WRITE_FINISH */ {Prg_A_MemClose, PRG_S_WAIT_MEM_CLOSE },
197 /* PRG_E_MEM_CLOSE_SUCCESS */ {NULL, PRG_S_WAIT_MEM_WRITE },
198 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
199 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
200 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
201 /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE },
202 /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error_Close_Init, PRG_S_WAIT_MEM_ERR_CLOSE }
204 { /* State PRG_S_WAIT_MEM_CLOSE */
205 /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_CLOSE },
206 /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_CLOSE },
207 /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_CLOSE },
208 /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE },
209 /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_CLOSE },
210 /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_CLOSE },
211 /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_CLOSE },
212 /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_InitDevice, PRG_S_IDLE },
213 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
214 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
215 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
216 /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE },
217 /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE },
219 { /* State PRG_S_WAIT_MEM_ERR_CLOSE */
220 /* PRG_E_NIL */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
221 /* PRG_E_START */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
222 /* PRG_E_STOP */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
223 /* PRG_E_WELCOME_SUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
224 /* PRG_E_WELCOME_NOSUCCESS */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
225 /* PRG_E_MEM_WRITE_CMD */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
226 /* PRG_E_MEM_WRITE_FINISH */ {NULL, PRG_S_WAIT_MEM_ERR_CLOSE },
227 /* PRG_E_MEM_CLOSE_SUCCESS */ {Prg_A_Error_Init, PRG_S_IDLE },
228 /* PRG_E_NET_OFF */ {Prg_A_NetOff, PRG_S_IDLE },
229 /* PRG_E_TIMEOUT */ {Prg_A_Timeout, PRG_S_IDLE },
230 /* PRG_E_ERROR */ {Prg_A_Error, PRG_S_IDLE },
231 /* PRG_E_ERROR_INIT */ {Prg_A_Error_Init, PRG_S_IDLE },
232 /* PRG_E_ERROR_CLOSE_INIT */ {Prg_A_Error, PRG_S_IDLE },
238 /*! \brief Constructor of class CProgramming.
239 * \param self Reference to CProgramming instance
240 * \param inic Reference to CInic instance
241 * \param base Reference to CBase instance
242 * \param exc Reference to CExc instance
244 /* \param init_ptr Report callback function*/
245 void Prg_Ctor(CProgramming *self, CInic *inic, CBase *base, CExc *exc)
247 MISC_MEM_SET((void *)self, 0, sizeof(*self));
253 Fsm_Ctor(&self->fsm, self, &(prg_trans_tab[0][0]), PRG_NUM_EVENTS, PRG_E_NIL);
255 Sobs_Ctor(&self->prg_welcome, self, &Prg_WelcomeResultCb);
256 Sobs_Ctor(&self->prg_memopen, self, &Prg_MemOpenResultCb);
257 Sobs_Ctor(&self->prg_memwrite, self, &Prg_MemWriteResultCb);
258 Sobs_Ctor(&self->prg_memclose, self, &Prg_MemCloseResultCb);
260 /* register termination events */
261 Mobs_Ctor(&self->prg_terminate, self, EH_M_TERMINATION_EVENTS, &Prg_OnTerminateEventCb);
262 Eh_AddObsrvInternalEvent(&self->base->eh, &self->prg_terminate);
264 /* Register NetOn and MPR events */
265 Obs_Ctor(&self->prg_nwstatus, self, &Prg_NetworkStatusCb);
266 Inic_AddObsrvNwStatus(self->inic, &self->prg_nwstatus);
269 /* Initialize Programming service */
270 Srv_Ctor(&self->service, PRG_SRV_PRIO, self, &Prg_Service);
271 /* Add Programming service to scheduler */
272 (void)Scd_AddService(&self->base->scd, &self->service);
277 /*! \brief Service function of the Node Discovery service.
278 * \param self Reference to Programming service object
280 static void Prg_Service(void *self)
282 CProgramming *self_ = (CProgramming *)self;
283 Srv_Event_t event_mask;
284 Srv_GetEvent(&self_->service, &event_mask);
285 if(PRG_EVENT_SERVICE == (event_mask & PRG_EVENT_SERVICE)) /* Is event pending? */
288 Srv_ClearEvent(&self_->service, PRG_EVENT_SERVICE);
289 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM __ %d %d", 2U, self_->fsm.current_state, self_->fsm.event_occured));
290 result = Fsm_Service(&self_->fsm);
291 TR_ASSERT(self_->base->ucs_user_ptr, "[PRG]", (result != FSM_STATE_ERROR));
292 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "FSM -> %d", 1U, self_->fsm.current_state));
299 /**************************************************************************************************/
301 /**************************************************************************************************/
304 * \param *self Reference to Programming service object
306 /*! \brief Program a node
308 * \param *self Reference to Programming service object
309 * \param node_id Node position address of the node to be programmed
310 * \param *signature Signature of the node to be programmed
311 * \param session_type Defines the memory access type.
312 * \param command_list Refers to array of programming tasks.
313 * \param report_fptr Report callback function
315 void Prg_Start(CProgramming *self,
317 Ucs_Signature_t *signature,
318 Ucs_Prg_SessionType_t session_type,
319 Ucs_Prg_Command_t* command_list,
320 Ucs_Prg_ReportCb_t report_fptr)
324 self->node_id = node_id;
325 self->signature = *signature;
326 self->session_type = session_type;
327 self->command_list = command_list;
328 self->report_fptr = report_fptr;
329 self->current_function = UCS_PRG_FKT_DUMMY;
331 if (self->neton == true)
333 Fsm_SetEvent(&self->fsm, PRG_E_START);
334 Srv_SetEvent(&self->service, PRG_EVENT_SERVICE);
336 TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start", 0U));
340 if (self->report_fptr != NULL)
342 self->report_fptr(UCS_PRG_RES_NET_OFF,
343 self->current_function,
346 self->base->ucs_user_ptr);
348 TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start failed: NET_OFF", 0U));
354 /**************************************************************************************************/
356 /**************************************************************************************************/
357 /*! Action on Start command
359 * \param *self Reference to Node Discovery object
361 static void Prg_A_Start(void *self)
363 CProgramming *self_ = (CProgramming *)self;
364 Ucs_Return_t ret_val;
366 if (self_->node_id == 0x0400U)
368 self_->target_address = UCS_ADDR_LOCAL_INIC;
372 self_->target_address = self_->node_id;
375 self_->admin_node_address = PRG_ADMIN_BASE_ADDR + ((self_->node_id) & 0x00FFU);
376 self_->current_function = UCS_PRG_FKT_WELCOME;
378 ret_val = Exc_Welcome_Sr(self_->exc,
379 self_->target_address,
380 self_->admin_node_address,
381 PRG_SIGNATURE_VERSION,
383 &self_->prg_welcome);
384 Prg_Check_RetVal(self_, ret_val);
387 static void Prg_A_MemOpen(void *self)
389 CProgramming *self_ = (CProgramming *)self;
390 Ucs_Return_t ret_val;
392 self_->current_function = UCS_PRG_FKT_MEM_OPEN;
394 ret_val = Exc_MemSessionOpen_Sr(self_->exc,
395 self_->admin_node_address,
397 &self_->prg_memopen);
398 Prg_Check_RetVal(self_, ret_val);
401 static void Prg_A_MemWrite(void *self)
403 CProgramming *self_ = (CProgramming *)self;
404 Ucs_Return_t ret_val;
406 self_->current_function = UCS_PRG_FKT_MEM_WRITE;
408 ret_val = Exc_MemoryWrite_Sr(self_->exc,
409 self_->admin_node_address,
410 self_->session_handle,
411 self_->command_list[self_->command_index].mem_id,
412 self_->command_list[self_->command_index].address,
413 self_->command_list[self_->command_index].unit_length,
414 self_->command_list[self_->command_index].data,
415 &self_->prg_memwrite);
416 Prg_Check_RetVal(self_, ret_val);
419 static void Prg_A_MemClose(void *self)
421 CProgramming *self_ = (CProgramming *)self;
422 Ucs_Return_t ret_val;
424 self_->current_function = UCS_PRG_FKT_MEM_CLOSE;
425 ret_val = Exc_MemSessionClose_Sr(self_->exc,
426 self_->admin_node_address,
427 self_->session_handle,
428 &self_->prg_memclose);
429 Prg_Check_RetVal(self_, ret_val);
432 static void Prg_A_InitDevice(void *self)
434 CProgramming *self_ = (CProgramming *)self;
435 Ucs_Return_t ret_val;
437 self_->current_function = UCS_PRG_FKT_INIT;
438 ret_val = Exc_DeviceInit_Start(self_->exc,
439 self_->admin_node_address,
441 Prg_Check_RetVal(self_, ret_val);
443 if (ret_val == UCS_RET_SUCCESS)
445 if (self_->report_fptr != NULL)
447 self_->report_fptr(UCS_PRG_RES_SUCCESS,
451 self_->base->ucs_user_ptr);
456 static void Prg_A_NetOff(void *self)
458 CProgramming *self_ = (CProgramming *)self;
460 if (self_->report_fptr != NULL)
462 self_->report_fptr(UCS_PRG_RES_NET_OFF,
463 self_->current_function,
466 self_->base->ucs_user_ptr);
470 static void Prg_A_Timeout(void *self)
472 CProgramming *self_ = (CProgramming *)self;
474 if (self_->report_fptr != NULL)
476 self_->report_fptr(UCS_PRG_RES_TIMEOUT,
477 self_->current_function,
480 self_->base->ucs_user_ptr);
484 static void Prg_A_Error(void *self)
486 CProgramming *self_ = (CProgramming *)self;
487 uint8_t *data_ptr = NULL;
489 if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
490 && (self_->error.ret_len != 0U))
492 data_ptr = &(self_->error.parm[0]);
495 if (self_->report_fptr != NULL)
497 self_->report_fptr(self_->error.code,
498 self_->error.function,
499 self_->error.ret_len,
501 self_->base->ucs_user_ptr);
506 static void Prg_A_Error_Init(void *self)
508 CProgramming *self_ = (CProgramming *)self;
509 uint8_t *data_ptr = NULL;
510 Ucs_Return_t ret_val;
512 ret_val = Exc_DeviceInit_Start(self_->exc,
513 self_->admin_node_address,
515 Prg_Check_RetVal(self_, ret_val);
517 if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
518 && (self_->error.ret_len != 0U))
520 data_ptr = &(self_->error.parm[0]);
523 if (self_->report_fptr != NULL)
525 self_->report_fptr(self_->error.code,
526 self_->error.function,
527 self_->error.ret_len,
529 self_->base->ucs_user_ptr);
533 static void Prg_A_Error_Close_Init(void *self)
535 CProgramming *self_ = (CProgramming *)self;
536 uint8_t *data_ptr = NULL;
537 Ucs_Return_t ret_val;
539 ret_val = Exc_DeviceInit_Start(self_->exc,
540 self_->admin_node_address,
542 Prg_Check_RetVal(self_, ret_val);
545 if ( (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
546 && (self_->error.ret_len != 0U))
548 data_ptr = &(self_->error.parm[0]);
551 if (self_->report_fptr != NULL)
553 self_->report_fptr(self_->error.code,
554 self_->error.function,
555 self_->error.ret_len,
557 self_->base->ucs_user_ptr);
562 /**************************************************************************************************/
563 /* Callback functions */
564 /**************************************************************************************************/
566 /*! \brief Function is called on reception of the Welcome.Result messsage
567 * \param self Reference to Programming service object
568 * \param result_ptr Pointer to the result of the Welcome message
570 static void Prg_WelcomeResultCb(void *self, void *result_ptr)
572 CProgramming *self_ = (CProgramming *)self;
573 Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
575 Tm_ClearTimer(&self_->base->tm, &self_->timer);
577 if (result_ptr_->result.code == UCS_RES_SUCCESS)
579 Exc_WelcomeResult_t welcome_result;
580 /* read signature and store it */
581 welcome_result = *(Exc_WelcomeResult_t *)(result_ptr_->data_info);
582 if (welcome_result.res == EXC_WELCOME_SUCCESS)
584 Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_SUCCESS);
585 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_SUCCESS", 0U));
589 /* store error paramters */
590 self_->error.code = UCS_PRG_RES_FKT_ASYNCH;
591 self_->error.function = UCS_PRG_FKT_WELCOME_NOSUCCESS;
592 self_->error.ret_len = 0U;
594 Fsm_SetEvent(&self_->fsm, PRG_E_WELCOME_NOSUCCESS);
595 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb PRG_E_WELCOME_NOSUCCESS", 0U));
601 /* store error paramters */
602 self_->error.code = UCS_PRG_RES_FKT_ASYNCH;
603 self_->error.function = UCS_PRG_FKT_WELCOME;
604 self_->error.ret_len = result_ptr_->result.info_size;
605 for (i=0U; i< result_ptr_->result.info_size; ++i)
607 self_->error.parm[i] = result_ptr_->result.info_ptr[i];
610 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
612 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (code) 0x%x", 1U, result_ptr_->result.code));
613 for (i=0U; i< result_ptr_->result.info_size; ++i)
615 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i]));
619 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
624 /*! \brief Function is called on reception of the MemorySessionOpen.Result messsage
625 * \param self Reference to Programming service object
626 * \param result_ptr Pointer to the result of the Welcome message
628 static void Prg_MemOpenResultCb(void *self, void *result_ptr)
630 CProgramming *self_ = (CProgramming *)self;
631 Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
633 Tm_ClearTimer(&self_->base->tm, &self_->timer);
635 if (result_ptr_->result.code == UCS_RES_SUCCESS)
637 self_->session_handle = *(uint16_t *)(result_ptr_->data_info);
638 self_->command_index = 0U;
640 if ( (self_->command_list[self_->command_index].data_length == 0U)
641 || (self_->command_list[self_->command_index].data == NULL))
643 Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH);
644 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb No Tasks", 0U));
648 Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD);
649 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb successful", 0U));
657 /* store error paramters */
658 self_->error.code = UCS_PRG_RES_FKT_ASYNCH;
659 self_->error.function = UCS_PRG_FKT_MEM_OPEN;
660 self_->error.ret_len = result_ptr_->result.info_size;
661 for (i=0U; i< result_ptr_->result.info_size; ++i)
663 self_->error.parm[i] = result_ptr_->result.info_ptr[i];
666 fs_error = Prg_CalcError(&(self_->error.parm[0]));
670 case PRG_HW_RESET_REQ:
671 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
674 case PRG_SESSION_ACTIVE:
675 self_->session_handle = (uint16_t)(((uint16_t)(self_->error.parm[3])) << 8U) + self_->error.parm[4]; /* get correct session handle */
676 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
680 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
684 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb Error 0x%x", 1U, result_ptr_->result.code));
687 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
691 /*! \brief Function is called on reception of the MemoryWrite.Result messsage
692 * \param self Reference to Programming service object
693 * \param result_ptr Pointer to the result of the Welcome message
695 static void Prg_MemWriteResultCb(void *self, void *result_ptr)
697 CProgramming *self_ = (CProgramming *)self;
698 Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
700 Tm_ClearTimer(&self_->base->tm, &self_->timer);
702 if (result_ptr_->result.code == UCS_RES_SUCCESS)
704 self_->command_index++;
705 if ( (self_->command_list[self_->command_index].data_length == 0U)
706 || (self_->command_list[self_->command_index].data == NULL))
708 Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH);
709 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb PRG_E_MEM_WRITE_FINISH", 0U));
713 Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD);
714 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb successful", 0U));
722 /* store error paramters */
723 self_->error.code = UCS_PRG_RES_FKT_ASYNCH;
724 self_->error.function = UCS_PRG_FKT_MEM_WRITE;
725 self_->error.ret_len = result_ptr_->result.info_size;
726 for (i=0U; i< result_ptr_->result.info_size; ++i)
728 self_->error.parm[i] = result_ptr_->result.info_ptr[i];
731 fs_error = Prg_CalcError(&(self_->error.parm[0]));
735 case PRG_CFG_WRITE_ERROR:
736 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
739 case PRG_CFG_FULL_ERROR:
740 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
743 case PRG_HDL_MATCH_ERROR:
744 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
747 case PRG_MEMID_ERROR:
748 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
751 case PRG_ADDR_EVEN_ERROR:
752 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
755 case PRG_LEN_EVEN_ERROR:
756 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
760 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
763 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb Error 0x%x", 1U, result_ptr_->result.code));
766 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
770 /*! \brief Function is called on reception of the MemorySessionClose.Result messsage
771 * \param self Reference to Programming service object
772 * \param result_ptr Pointer to the result of the Welcome message
774 static void Prg_MemCloseResultCb(void *self, void *result_ptr)
776 CProgramming *self_ = (CProgramming *)self;
777 Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
779 Tm_ClearTimer(&self_->base->tm, &self_->timer);
781 if (result_ptr_->result.code == UCS_RES_SUCCESS)
783 uint8_t session_result = *(uint8_t *)(result_ptr_->data_info);
785 if (session_result == 0U)
787 Fsm_SetEvent(&self_->fsm, PRG_E_MEM_CLOSE_SUCCESS);
788 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb PRG_E_MEM_CLOSE_SUCCESS", 0U));
792 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
793 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb ErrResult PRG_E_ERROR_INIT", 0U));
801 /* store error paramters */
802 self_->error.code = UCS_PRG_RES_FKT_ASYNCH;
803 self_->error.function = UCS_PRG_FKT_MEM_CLOSE;
804 self_->error.ret_len = result_ptr_->result.info_size;
805 for (i=0U; i< result_ptr_->result.info_size; ++i)
807 self_->error.parm[i] = result_ptr_->result.info_ptr[i];
810 fs_error = Prg_CalcError(&(self_->error.parm[0]));
812 if (fs_error == PRG_HDL_MATCH_ERROR)
814 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
818 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
821 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb Error 0x%x", 1U, result_ptr_->result.code));
824 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
830 /*! Function is called on severe internal errors
832 * \param *self Reference to Programming object
833 * \param *result_ptr Reference to data
835 static void Prg_OnTerminateEventCb(void *self, void *result_ptr)
837 CProgramming *self_ = (CProgramming *)self;
839 MISC_UNUSED(result_ptr);
841 if (self_->fsm.current_state != PRG_S_IDLE)
843 Tm_ClearTimer(&self_->base->tm, &self_->timer);
844 if (self_->report_fptr != NULL)
846 self_->report_fptr(UCS_PRG_RES_ERROR,
847 self_->current_function,
850 self_->base->ucs_user_ptr);
854 self_->fsm.current_state = PRG_S_IDLE;
859 /*! \brief Callback function for the INIC.NetworkStatus status and error messages
861 * \param *self Reference to Node Discovery object
862 * \param *result_ptr Pointer to the result of the INIC.NetworkStatus message
864 static void Prg_NetworkStatusCb(void *self, void *result_ptr)
866 CProgramming *self_ = (CProgramming *)self;
867 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
869 if (result_ptr_->result.code == UCS_RES_SUCCESS)
871 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_NetworkStatusCb 0x%x", 1U, result_ptr_->result.code));
872 /* check for NetOn/NetOff events */
873 if ( (self_->neton == true)
874 && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_NOT_AVAILABLE) )
876 self_->neton = false;
877 Fsm_SetEvent(&self_->fsm, PRG_E_NET_OFF);
879 else if ( (self_->neton == false)
880 && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) )
886 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
891 /*! \brief Timer callback used for supervising INIC command timeouts.
892 * \param self Reference to System Diagnosis object
894 static void Prg_TimerCb(void *self)
896 CProgramming *self_ = (CProgramming *)self;
898 Fsm_SetEvent(&self_->fsm, PRG_E_TIMEOUT);
899 TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_TimerCb PRG_E_TIMEOUT", 0U));
901 Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
906 /**************************************************************************************************/
907 /* Helper functions */
908 /**************************************************************************************************/
910 static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t ret_val)
912 if (ret_val == UCS_RET_SUCCESS)
914 Tm_SetTimer(&self->base->tm,
923 TR_ASSERT(self->base->ucs_user_ptr, "[PRG]", ret_val == UCS_RET_SUCCESS);
925 /* store error paramter */
926 self->error.code = UCS_PRG_RES_FKT_SYNCH;
927 self->error.function = self->current_function;
928 self->error.ret_len = (uint8_t)ret_val;
930 Fsm_SetEvent(&self->fsm, PRG_E_ERROR);
931 Srv_SetEvent(&self->service, PRG_EVENT_SERVICE);
936 static uint32_t Prg_CalcError(uint8_t val[])
940 temp = val[0] + (((uint32_t)val[1]) << 8U) + (((uint32_t)val[2]) << 16U);
954 /*------------------------------------------------------------------------------------------------*/
956 /*------------------------------------------------------------------------------------------------*/