Initial Commit
[apps/agl-service-unicens.git] / ucs2-lib / src / ucs_prog.c
1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491                                                                            */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG.                              */
4 /*                                                                                                */
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.                                                            */
9 /*                                                                                                */
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.                                                   */
14 /*                                                                                                */
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/>.                          */
17 /*                                                                                                */
18 /* You may also obtain this software under a propriety license from Microchip.                    */
19 /* Please contact Microchip for further information.                                              */
20 /*------------------------------------------------------------------------------------------------*/
21
22 /*!
23  * \file
24  * \brief Implementation of the Programming Service.
25  *
26  * \cond UCS_INTERNAL_DOC
27  * \addtogroup G_PROG_MODE
28  * @{
29
30  */
31
32 /*------------------------------------------------------------------------------------------------*/
33 /* Includes                                                                                       */
34 /*------------------------------------------------------------------------------------------------*/
35 #include "ucs_inic_pb.h"
36 #include "ucs_prog.h"
37 #include "ucs_misc.h"
38
39
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 */
45
46 #define PRG_TIMEOUT_COMMAND      100U    /*!< \brief supervise EXC commands */
47
48 #define PRG_SIGNATURE_VERSION      1U    /*!< \brief signature version used for Node Discovery */
49
50 #define PRG_ADMIN_BASE_ADDR   0x0F00U    /*!< \brief bas admin address */
51
52
53 /* Error values */
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. */
64
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;
72
73
74 /*------------------------------------------------------------------------------------------------*/
75 /* Internal enumerators                                                                           */
76 /*------------------------------------------------------------------------------------------------*/
77 /*! \brief Possible events of the system diagnosis state machine */
78 typedef enum Prg_Events_
79 {
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. */
93 } Prg_Events_t;
94
95
96 /*! \brief States of the node discovery state machine */
97 typedef enum Prg_State_
98 {
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. */
105 } Prg_State_t;
106
107
108 /*------------------------------------------------------------------------------------------------*/
109 /* Internal prototypes                                                                            */
110 /*------------------------------------------------------------------------------------------------*/
111 static void Prg_Service(void *self);
112
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);
117
118 static void Prg_OnTerminateEventCb(void *self, void *result_ptr);
119 static void Prg_NetworkStatusCb(void *self, void *result_ptr);
120
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);
131
132
133 static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t  ret_val);
134 static uint32_t Prg_CalcError(uint8_t val[]);
135
136 static void Prg_TimerCb(void *self);
137
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." */
143 {
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               },
158     },
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       }
173     },
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 }
188     },
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 }
203     },
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               },
218     },
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               },
233     }
234
235 };
236
237
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
243  */
244  /*  \param init_ptr    Report callback function*/
245 void Prg_Ctor(CProgramming *self, CInic *inic, CBase *base, CExc *exc)
246 {
247     MISC_MEM_SET((void *)self, 0, sizeof(*self));
248
249     self->inic       = inic;
250     self->exc        = exc;
251     self->base       = base;
252
253     Fsm_Ctor(&self->fsm, self, &(prg_trans_tab[0][0]), PRG_NUM_EVENTS, PRG_E_NIL);
254
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);
259
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);
263
264     /* Register NetOn and MPR events */
265     Obs_Ctor(&self->prg_nwstatus, self, &Prg_NetworkStatusCb);
266     Inic_AddObsrvNwStatus(self->inic,  &self->prg_nwstatus);
267     self->neton = false;
268
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);
273
274 }
275
276
277 /*! \brief Service function of the Node Discovery service.
278  *  \param self    Reference to Programming service object
279  */
280 static void Prg_Service(void *self)
281 {
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? */
286     {
287         Fsm_State_t result;
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));
293         MISC_UNUSED(result);
294     }
295 }
296
297
298
299 /**************************************************************************************************/
300 /* API functions                                                                                  */
301 /**************************************************************************************************/
302 /*!
303  *
304  * \param *self Reference to Programming service object
305  */
306 /*! \brief Program a node
307  *
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
314  */
315 void Prg_Start(CProgramming *self,
316                uint16_t node_id,
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)
321 {
322
323
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;
330
331     if (self->neton == true)
332     {
333         Fsm_SetEvent(&self->fsm, PRG_E_START);
334         Srv_SetEvent(&self->service, PRG_EVENT_SERVICE);
335
336         TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start", 0U));
337     }
338     else
339     {
340         if (self->report_fptr != NULL)
341         {
342             self->report_fptr(UCS_PRG_RES_NET_OFF,
343                               self->current_function,
344                               0U,
345                               NULL,
346                               self->base->ucs_user_ptr);
347         }
348         TR_INFO((self->base->ucs_user_ptr, "[PRG]", "Prg_Start failed: NET_OFF", 0U));
349     }
350 }
351
352
353
354 /**************************************************************************************************/
355 /*  FSM Actions                                                                                   */
356 /**************************************************************************************************/
357 /*!  Action on Start command
358  *
359  * \param *self Reference to Node Discovery object
360  */
361 static void Prg_A_Start(void *self)
362 {
363     CProgramming *self_ = (CProgramming *)self;
364     Ucs_Return_t  ret_val;
365
366     if (self_->node_id == 0x0400U)
367     {
368         self_->target_address = UCS_ADDR_LOCAL_INIC;
369     }
370     else
371     {
372         self_->target_address = self_->node_id;
373     }
374
375     self_->admin_node_address = PRG_ADMIN_BASE_ADDR + ((self_->node_id) & 0x00FFU);
376     self_->current_function = UCS_PRG_FKT_WELCOME;
377
378     ret_val = Exc_Welcome_Sr(self_->exc,
379                              self_->target_address,
380                              self_->admin_node_address,
381                              PRG_SIGNATURE_VERSION,
382                              self_->signature,
383                              &self_->prg_welcome);
384     Prg_Check_RetVal(self_, ret_val);
385 }
386
387 static void Prg_A_MemOpen(void *self)
388 {
389     CProgramming *self_ = (CProgramming *)self;
390     Ucs_Return_t  ret_val;
391
392     self_->current_function = UCS_PRG_FKT_MEM_OPEN;
393
394     ret_val = Exc_MemSessionOpen_Sr(self_->exc,
395                                     self_->admin_node_address,
396                                     self_->session_type,
397                                     &self_->prg_memopen);
398     Prg_Check_RetVal(self_, ret_val);
399 }
400
401 static void Prg_A_MemWrite(void *self)
402 {
403     CProgramming *self_ = (CProgramming *)self;
404     Ucs_Return_t  ret_val;
405
406     self_->current_function = UCS_PRG_FKT_MEM_WRITE;
407
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);
417 }
418
419 static void Prg_A_MemClose(void *self)
420 {
421     CProgramming *self_ = (CProgramming *)self;
422     Ucs_Return_t  ret_val;
423
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);
430 }
431
432 static void Prg_A_InitDevice(void *self)
433 {
434     CProgramming *self_ = (CProgramming *)self;
435     Ucs_Return_t  ret_val;
436
437     self_->current_function = UCS_PRG_FKT_INIT;
438     ret_val = Exc_DeviceInit_Start(self_->exc,
439                                    self_->admin_node_address,
440                                    NULL);
441     Prg_Check_RetVal(self_, ret_val);
442
443     if (ret_val == UCS_RET_SUCCESS)
444     {
445         if (self_->report_fptr != NULL)
446         {
447             self_->report_fptr(UCS_PRG_RES_SUCCESS,
448                                UCS_PRG_FKT_DUMMY,
449                                0U,
450                                NULL,
451                                self_->base->ucs_user_ptr);
452         }
453     }
454 }
455
456 static void Prg_A_NetOff(void *self)
457 {
458     CProgramming *self_ = (CProgramming *)self;
459
460     if (self_->report_fptr != NULL)
461     {
462         self_->report_fptr(UCS_PRG_RES_NET_OFF,
463                            self_->current_function,
464                            0U,
465                            NULL,
466                            self_->base->ucs_user_ptr);
467     }
468 }
469
470 static void Prg_A_Timeout(void *self)
471 {
472     CProgramming *self_ = (CProgramming *)self;
473
474     if (self_->report_fptr != NULL)
475     {
476         self_->report_fptr(UCS_PRG_RES_TIMEOUT,
477                            self_->current_function,
478                            0U,
479                            NULL,
480                            self_->base->ucs_user_ptr);
481     }
482 }
483
484 static void Prg_A_Error(void *self)
485 {
486     CProgramming *self_ = (CProgramming *)self;
487     uint8_t *data_ptr   = NULL;
488
489     if (   (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
490         && (self_->error.ret_len != 0U))
491     {
492         data_ptr = &(self_->error.parm[0]);
493     }
494
495     if (self_->report_fptr != NULL)
496     {
497         self_->report_fptr(self_->error.code,
498                            self_->error.function,
499                            self_->error.ret_len,
500                            data_ptr,
501                            self_->base->ucs_user_ptr);
502     }
503 }
504
505
506 static void Prg_A_Error_Init(void *self)
507 {
508     CProgramming *self_ = (CProgramming *)self;
509     uint8_t *data_ptr   = NULL;
510     Ucs_Return_t  ret_val;
511
512     ret_val = Exc_DeviceInit_Start(self_->exc,
513                                      self_->admin_node_address,
514                                      NULL);
515     Prg_Check_RetVal(self_, ret_val);
516
517     if (   (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
518         && (self_->error.ret_len != 0U))
519     {
520         data_ptr = &(self_->error.parm[0]);
521     }
522
523     if (self_->report_fptr != NULL)
524     {
525         self_->report_fptr(self_->error.code,
526                            self_->error.function,
527                            self_->error.ret_len,
528                            data_ptr,
529                            self_->base->ucs_user_ptr);
530     }
531 }
532
533 static void Prg_A_Error_Close_Init(void *self)
534 {
535     CProgramming *self_ = (CProgramming *)self;
536     uint8_t *data_ptr   = NULL;
537     Ucs_Return_t  ret_val;
538
539     ret_val = Exc_DeviceInit_Start(self_->exc,
540                                      self_->admin_node_address,
541                                      NULL);
542     Prg_Check_RetVal(self_, ret_val);
543
544
545     if (   (self_->error.code == UCS_PRG_RES_FKT_ASYNCH)
546         && (self_->error.ret_len != 0U))
547     {
548         data_ptr = &(self_->error.parm[0]);
549     }
550
551     if (self_->report_fptr != NULL)
552     {
553         self_->report_fptr(self_->error.code,
554                            self_->error.function,
555                            self_->error.ret_len,
556                            data_ptr,
557                            self_->base->ucs_user_ptr);
558     }
559 }
560
561
562 /**************************************************************************************************/
563 /*  Callback functions                                                                            */
564 /**************************************************************************************************/
565
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
569  */
570 static void Prg_WelcomeResultCb(void *self, void *result_ptr)
571 {
572     CProgramming *self_          = (CProgramming *)self;
573     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
574
575     Tm_ClearTimer(&self_->base->tm, &self_->timer);
576
577     if (result_ptr_->result.code == UCS_RES_SUCCESS)
578     {
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)
583         {
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));
586         }
587         else
588         {
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;
593
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)); 
596         }
597     }
598     else
599     {
600         uint8_t i;
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)
606         {
607             self_->error.parm[i] = result_ptr_->result.info_ptr[i];
608         }
609
610         Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
611
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)
614         {
615             TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_WelcomeResultCb Error (info) 0x%x", 1U, result_ptr_->result.info_ptr[i]));
616         }
617     }
618
619     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
620 }
621
622
623
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
627  */
628 static void Prg_MemOpenResultCb(void *self, void *result_ptr)
629 {
630     CProgramming *self_          = (CProgramming *)self;
631     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
632
633     Tm_ClearTimer(&self_->base->tm, &self_->timer);
634
635     if (result_ptr_->result.code == UCS_RES_SUCCESS)
636     {
637         self_->session_handle = *(uint16_t *)(result_ptr_->data_info);
638         self_->command_index = 0U;
639
640         if (   (self_->command_list[self_->command_index].data_length == 0U)
641             || (self_->command_list[self_->command_index].data        == NULL))
642         {
643             Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_FINISH);
644             TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb No Tasks", 0U));
645         }
646         else
647         {
648             Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD);
649             TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb successful", 0U));
650         }
651     }
652     else
653     {
654         uint8_t i;
655         uint32_t fs_error;
656
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)
662         {
663             self_->error.parm[i] = result_ptr_->result.info_ptr[i];
664         }
665
666         fs_error = Prg_CalcError(&(self_->error.parm[0]));
667
668         switch (fs_error)
669         {
670             case PRG_HW_RESET_REQ:
671                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
672                 break;
673
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);
677                 break;
678
679             default:
680                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
681                 break;
682         }
683
684         TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemOpenResultCb Error  0x%x", 1U, result_ptr_->result.code));
685     }
686
687     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
688 }
689
690
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
694  */
695 static void Prg_MemWriteResultCb(void *self, void *result_ptr)
696 {
697     CProgramming *self_        = (CProgramming *)self;
698     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
699
700     Tm_ClearTimer(&self_->base->tm, &self_->timer);
701
702     if (result_ptr_->result.code == UCS_RES_SUCCESS)
703     {
704         self_->command_index++;
705         if (   (self_->command_list[self_->command_index].data_length == 0U)
706             || (self_->command_list[self_->command_index].data        == NULL))
707         {
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));
710         }
711         else
712         {
713             Fsm_SetEvent(&self_->fsm, PRG_E_MEM_WRITE_CMD);
714             TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb successful", 0U));
715         }
716     }
717     else
718     {
719         uint8_t i;
720         uint32_t fs_error;
721
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)
727         {
728             self_->error.parm[i] = result_ptr_->result.info_ptr[i];
729         }
730
731         fs_error = Prg_CalcError(&(self_->error.parm[0]));
732
733         switch (fs_error)
734         {
735             case PRG_CFG_WRITE_ERROR:
736                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
737                 break;
738
739             case PRG_CFG_FULL_ERROR:
740                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
741                 break;
742
743             case PRG_HDL_MATCH_ERROR:
744                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
745                 break;
746
747             case PRG_MEMID_ERROR:
748                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
749                 break;
750
751             case PRG_ADDR_EVEN_ERROR:
752                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
753                 break;
754
755             case PRG_LEN_EVEN_ERROR:
756                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_CLOSE_INIT);
757                 break;
758
759             default:
760                 Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
761                 break;
762         }
763         TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemWriteResultCb Error  0x%x", 1U, result_ptr_->result.code));
764     }
765
766     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
767 }
768
769
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
773  */
774 static void Prg_MemCloseResultCb(void *self, void *result_ptr)
775 {
776     CProgramming *self_          = (CProgramming *)self;
777     Exc_StdResult_t *result_ptr_ = (Exc_StdResult_t *)result_ptr;
778
779     Tm_ClearTimer(&self_->base->tm, &self_->timer);
780
781     if (result_ptr_->result.code == UCS_RES_SUCCESS)
782     {
783         uint8_t session_result = *(uint8_t *)(result_ptr_->data_info);
784
785         if (session_result == 0U)
786         {
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));
789         }
790         else
791         {
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));
794         }
795     }
796     else
797     {
798         uint8_t i;
799         uint32_t fs_error;
800
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)
806         {
807             self_->error.parm[i] = result_ptr_->result.info_ptr[i];
808         }
809
810         fs_error = Prg_CalcError(&(self_->error.parm[0]));
811
812         if (fs_error == PRG_HDL_MATCH_ERROR)
813         {
814             Fsm_SetEvent(&self_->fsm, PRG_E_ERROR_INIT);
815         }
816         else
817         {
818             Fsm_SetEvent(&self_->fsm, PRG_E_ERROR);
819         }
820
821         TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_MemCloseResultCb Error  0x%x", 1U, result_ptr_->result.code));
822     }
823
824     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
825 }
826
827
828
829
830 /*!  Function is called on severe internal errors
831  *
832  * \param *self         Reference to Programming object
833  * \param *result_ptr   Reference to data
834  */
835 static void Prg_OnTerminateEventCb(void *self, void *result_ptr)
836 {
837     CProgramming *self_ = (CProgramming *)self;
838
839     MISC_UNUSED(result_ptr);
840
841     if (self_->fsm.current_state != PRG_S_IDLE)
842     {
843         Tm_ClearTimer(&self_->base->tm, &self_->timer);
844         if (self_->report_fptr != NULL)
845         {
846             self_->report_fptr(UCS_PRG_RES_ERROR, 
847                                self_->current_function, 
848                                0U, 
849                                NULL, 
850                                self_->base->ucs_user_ptr);
851         }
852
853         /* reset FSM */
854         self_->fsm.current_state = PRG_S_IDLE;
855     }
856 }
857
858
859 /*! \brief Callback function for the INIC.NetworkStatus status and error messages
860  *
861  * \param *self         Reference to Node Discovery object
862  * \param *result_ptr   Pointer to the result of the INIC.NetworkStatus message
863  */
864 static void Prg_NetworkStatusCb(void *self, void *result_ptr)
865 {
866     CProgramming *self_ = (CProgramming *)self;
867     Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
868
869     if (result_ptr_->result.code == UCS_RES_SUCCESS)
870     {
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) )
875         {
876             self_->neton = false;
877             Fsm_SetEvent(&self_->fsm, PRG_E_NET_OFF);
878         }
879         else if (    (self_->neton == false)
880                 && ((((Inic_NetworkStatus_t *)(result_ptr_->data_info))->availability) == UCS_NW_AVAILABLE) )
881         {
882             self_->neton = true;
883         }
884     }
885
886     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
887 }
888
889
890
891 /*! \brief Timer callback used for supervising INIC command timeouts.
892  *  \param self    Reference to System Diagnosis object
893  */
894 static void Prg_TimerCb(void *self)
895 {
896     CProgramming *self_ = (CProgramming *)self;
897
898     Fsm_SetEvent(&self_->fsm, PRG_E_TIMEOUT);
899     TR_INFO((self_->base->ucs_user_ptr, "[PRG]", "Prg_TimerCb PRG_E_TIMEOUT", 0U));
900
901     Srv_SetEvent(&self_->service, PRG_EVENT_SERVICE);
902 }
903
904
905
906 /**************************************************************************************************/
907 /*  Helper functions                                                                              */
908 /**************************************************************************************************/
909
910 static void Prg_Check_RetVal(CProgramming *self, Ucs_Return_t  ret_val)
911 {
912     if (ret_val == UCS_RET_SUCCESS)
913     {
914         Tm_SetTimer(&self->base->tm,
915                     &self->timer,
916                     &Prg_TimerCb,
917                     self,
918                     PRG_TIMEOUT_COMMAND,
919                     0U);
920     }
921     else
922     {
923         TR_ASSERT(self->base->ucs_user_ptr, "[PRG]", ret_val == UCS_RET_SUCCESS);
924
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;
929
930         Fsm_SetEvent(&self->fsm, PRG_E_ERROR);
931         Srv_SetEvent(&self->service, PRG_EVENT_SERVICE);
932     }
933 }
934
935
936 static uint32_t Prg_CalcError(uint8_t val[])
937 {
938     uint32_t temp;
939
940     temp = val[0] + (((uint32_t)val[1]) << 8U) + (((uint32_t)val[2]) << 16U);
941
942     return temp;
943 }
944
945
946
947
948
949 /*!
950  * @}
951  * \endcond
952  */
953
954 /*------------------------------------------------------------------------------------------------*/
955 /* End of file                                                                                    */
956 /*------------------------------------------------------------------------------------------------*/
957