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 CManager class
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
36 #include "ucs_scheduler.h"
37 #include "ucs_trace.h"
39 /*------------------------------------------------------------------------------------------------*/
40 /* Internal constants */
41 /*------------------------------------------------------------------------------------------------*/
42 /*! \brief Priority of the Application Message Service */
43 static const uint8_t MGR_SRV_PRIO = 245U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */
44 /*! \brief Event which triggers the service */
45 static const Srv_Event_t MGR_SRV_EV_SERVICE = 1U;
47 /*! \brief Network status mask */
48 static const uint32_t MGR_NWSTATUS_MASK = 0x0FU; /* parasoft-suppress MISRA2004-8_7 "configuration property" */
49 /*! \brief The time in milliseconds the INIC will go to AutoForcedNA after sync lost. */
50 static const uint16_t MGR_AUTOFORCED_NA_TIME = 5000U; /* parasoft-suppress MISRA2004-8_7 "configuration property" */
53 /*------------------------------------------------------------------------------------------------*/
54 /* Internal prototypes */
55 /*------------------------------------------------------------------------------------------------*/
56 static void Mgr_OnInitComplete(void *self, void *error_code_ptr);
57 static void Mgr_OnNwStatus(void *self, void *data_ptr);
58 static void Mgr_OnJobQResult(void *self, void *result_ptr);
59 static void Mgr_Startup(void *self);
60 static void Mgr_OnNwStartupResult(void *self, void *result_ptr);
61 static void Mgr_LeaveForcedNA(void *self);
62 static void Mgr_OnLeaveForcedNAResult(void *self, void *result_ptr);
64 static void Mgr_Shutdown(void *self);
65 static void Mgr_OnNwShutdownResult(void *self, void *result_ptr);
68 /*------------------------------------------------------------------------------------------------*/
70 /*------------------------------------------------------------------------------------------------*/
71 /*! \brief Constructor of Manager class
72 * \param self The instance
73 * \param base_ptr Reference to base component
74 * \param inic_ptr Reference to INIC component
75 * \param net_ptr Reference to net component
76 * \param nd_ptr Reference to NodeDiscovery component
77 * \param packet_bw Desired packet bandwidth
79 void Mgr_Ctor(CManager *self, CBase *base_ptr, CInic *inic_ptr, CNetworkManagement *net_ptr, CNodeDiscovery *nd_ptr, uint16_t packet_bw)
81 MISC_MEM_SET(self, 0, sizeof(*self));
84 self->base_ptr = base_ptr;
85 self->inic_ptr = inic_ptr;
86 self->net_ptr = net_ptr;
87 self->nd_ptr = nd_ptr;
88 self->packet_bw = packet_bw;
90 Jbs_Ctor(&self->job_service, base_ptr);
91 Job_Ctor(&self->job_leave_forced_na, &Mgr_LeaveForcedNA, self);
92 Job_Ctor(&self->job_startup, &Mgr_Startup, self);
94 Job_Ctor(&self->job_shutdown, &Mgr_Shutdown, self);
97 self->list_startup[0] = &self->job_startup;
98 self->list_startup[1] = NULL;
99 self->list_force_startup[0] = &self->job_leave_forced_na;
100 self->list_force_startup[1] = &self->job_startup;
101 self->list_force_startup[2] = NULL;
103 self->list_shutdown[0] = &self->job_shutdown;
104 self->list_shutdown[1] = NULL;
107 Jbq_Ctor(&self->job_q_startup, &self->job_service, 1U, self->list_startup);
108 Jbq_Ctor(&self->job_q_force_startup, &self->job_service, 2U, self->list_force_startup);
110 Jbq_Ctor(&self->job_q_shutdown, &self->job_service, 4U, self->list_shutdown);
113 Sobs_Ctor(&self->startup_obs, self, &Mgr_OnNwStartupResult);
114 Sobs_Ctor(&self->force_na_obs, self, &Mgr_OnLeaveForcedNAResult);
116 Sobs_Ctor(&self->shutdown_obs, self, &Mgr_OnNwShutdownResult);
118 Sobs_Ctor(&self->job_q_obs, self, &Mgr_OnJobQResult);
120 Mobs_Ctor(&self->event_observer, self, EH_E_INIT_SUCCEEDED, &Mgr_OnInitComplete);
121 Eh_AddObsrvInternalEvent(&self->base_ptr->eh, &self->event_observer);
122 Mobs_Ctor(&self->nwstatus_mobs, self, MGR_NWSTATUS_MASK, &Mgr_OnNwStatus);
125 /*------------------------------------------------------------------------------------------------*/
126 /* Callback Methods */
127 /*------------------------------------------------------------------------------------------------*/
128 /*! \brief Callback function which is invoked if the initialization is complete
129 * \param self The instance
130 * \param error_code_ptr Reference to the error code
132 static void Mgr_OnInitComplete(void *self, void *error_code_ptr)
134 CManager *self_ = (CManager*)self;
135 MISC_UNUSED(error_code_ptr);
137 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Received init complete event", 0U));
138 Net_AddObserverNetworkStatus(self_->net_ptr, &self_->nwstatus_mobs); /* register observer */
139 (void)Nd_Start(self_->nd_ptr);
142 /*! \brief NetworkStatus callback function
143 * \details The function is only active if \c listening flag is \c true.
144 * This avoids to re-register und un-register the observer for several times.
145 * \param self The instance
146 * \param data_ptr Reference to \ref Net_NetworkStatusParam_t
148 static void Mgr_OnNwStatus(void *self, void *data_ptr)
150 CManager *self_ = (CManager*)self;
151 Net_NetworkStatusParam_t *param_ptr = (Net_NetworkStatusParam_t *)data_ptr;
153 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus()", 0U));
155 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): mask=0x%04X, events=0x%04X", 2U, param_ptr->change_mask ,param_ptr->events));
156 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): avail=0x%X, avail_i=0x%X, bw=0x%X", 3U, param_ptr->availability, param_ptr->avail_info, param_ptr->packet_bw));
157 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): addr=0x%03X, pos=0x%X, mpr=0x%X", 3U, param_ptr->node_address, param_ptr->node_position, param_ptr->max_position));
159 if ((param_ptr->change_mask & ((uint16_t)UCS_NW_M_AVAIL | (uint16_t)UCS_NW_M_PACKET_BW)) != 0U)
161 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStatus(): trigger event", 0U));
163 if (self_->current_q_ptr != NULL)
165 Jbq_Stop(self_->current_q_ptr);
168 if (param_ptr->avail_info == UCS_NW_AVAIL_INFO_FORCED_NA)
170 self_->current_q_ptr = &self_->job_q_force_startup; /* stop forcing NA, then startup */
171 Jbq_Start(&self_->job_q_force_startup, &self_->job_q_obs);
173 else if (param_ptr->availability == UCS_NW_NOT_AVAILABLE)
175 self_->current_q_ptr = &self_->job_q_startup; /* just startup */
176 Jbq_Start(&self_->job_q_startup, &self_->job_q_obs);
179 else if ((param_ptr->node_position != 0U) || (param_ptr->packet_bw != self_->packet_bw))
181 self_->current_q_ptr = &self_->job_q_shutdown; /* just shutdown - startup is triggered automatically */
182 Jbq_Start(&self_->job_q_shutdown, &self_->job_q_obs);
185 if (self_->initial != false)
187 self_->initial = false;
188 if (self_->current_q_ptr == NULL) /* trigger InitAll() if no job is required for the */
189 { /* initial network status notification */
190 Nd_InitAll(self_->nd_ptr);
196 /*! \brief Callback function that is triggered after finished a job.
197 * \details Failed jobs will be restarted here.
198 * \param self The instance
199 * \param result_ptr Reference to the job result \ref Job_Result_t.
201 static void Mgr_OnJobQResult(void *self, void *result_ptr)
203 CManager *self_ = (CManager*)self;
204 Job_Result_t *res = (Job_Result_t *)result_ptr;
205 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnJobQResult(): result=%d", 1U, *res));
207 if ((*res != JOB_R_SUCCESS) && (self_->current_q_ptr != NULL))
209 Jbq_Start(self_->current_q_ptr, &self_->job_q_obs);
213 self_->current_q_ptr = NULL;
218 /*------------------------------------------------------------------------------------------------*/
219 /* Job: LeaveForcedNA */
220 /*------------------------------------------------------------------------------------------------*/
221 /*! \brief Action that sets the INIC from "Forced-NotAvailable" to "NotAvailable"
222 * \param self The instance
224 static void Mgr_LeaveForcedNA(void *self)
226 CManager *self_ = (CManager*)self;
229 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_LeaveForcedNA()", 0U));
230 ret = Inic_NwForceNotAvailable(self_->inic_ptr, false /*no longer force NA*/, &self_->force_na_obs);
232 if (ret != UCS_RET_SUCCESS)
234 TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_LeaveForcedNA(), function returns 0x%02X", 1U, ret));
235 Job_SetResult(&self_->job_leave_forced_na, JOB_R_FAILED);
239 /*! \brief Callback function which announces the result of Inic_NwForceNotAvailable()
240 * \param self The instance
241 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
243 static void Mgr_OnLeaveForcedNAResult(void *self, void *result_ptr)
245 CManager *self_ = (CManager*)self;
246 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
248 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnLeaveForcedNAResult(): code=0x%02X", 1U, result_ptr_->result.code));
250 if (result_ptr_->result.code == UCS_RES_SUCCESS)
252 Job_SetResult(&self_->job_leave_forced_na, JOB_R_SUCCESS);
256 Job_SetResult(&self_->job_leave_forced_na, JOB_R_FAILED);
260 /*------------------------------------------------------------------------------------------------*/
262 /*------------------------------------------------------------------------------------------------*/
263 /*! \brief Action that starts the network with the given parameters
264 * \param self The instance
266 static void Mgr_Startup(void *self)
268 CManager *self_ = (CManager*)self;
271 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Startup()", 0U));
272 ret = Inic_NwStartup(self_->inic_ptr, MGR_AUTOFORCED_NA_TIME, self_->packet_bw, &self_->startup_obs); /* Startup without ForcedNA */
274 if (ret != UCS_RET_SUCCESS)
276 TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Startup(), startup returns 0x%02X", 1U, ret));
277 Job_SetResult(&self_->job_startup, JOB_R_FAILED);
281 /*! \brief Callback function which announces the result of Net_NetworkStartup()
282 * \param self The instance
283 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
285 static void Mgr_OnNwStartupResult(void *self, void *result_ptr)
287 CManager *self_ = (CManager*)self;
288 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
290 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwStartupResult(): code=0x%02X", 1U, result_ptr_->result.code));
292 if (result_ptr_->result.code == UCS_RES_SUCCESS)
294 Job_SetResult(&self_->job_startup, JOB_R_SUCCESS);
298 Job_SetResult(&self_->job_startup, JOB_R_FAILED);
302 /*------------------------------------------------------------------------------------------------*/
304 /*------------------------------------------------------------------------------------------------*/
306 /*! \brief Action that performs a network shutdown.
307 * \param self The instance
309 static void Mgr_Shutdown(void *self)
311 CManager *self_ = (CManager*)self;
314 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Shutdown()", 0U));
315 ret = Inic_NwShutdown(self_->inic_ptr, &self_->shutdown_obs);
317 if (ret != UCS_RET_SUCCESS)
319 TR_ERROR((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_Shutdown(), shutdown returns 0x%02X", 1U, ret));
320 Job_SetResult(&self_->job_shutdown, JOB_R_FAILED);
324 /*! \brief Callback function which announces the result of Net_NetworkShutdown()
325 * \param self The instance
326 * \param result_ptr Reference to result. Must be casted into Inic_StdResult_t.
328 static void Mgr_OnNwShutdownResult(void *self, void *result_ptr)
330 CManager *self_ = (CManager*)self;
331 Inic_StdResult_t *result_ptr_ = (Inic_StdResult_t *)result_ptr;
333 TR_INFO((self_->base_ptr->ucs_user_ptr, "[MGR]", "Mgr_OnNwShutdownResult(): code=0x%02X", 1U, result_ptr_->result.code));
335 if (result_ptr_->result.code == UCS_RES_SUCCESS)
337 Job_SetResult(&self_->job_shutdown, JOB_R_SUCCESS);
341 Job_SetResult(&self_->job_shutdown, JOB_R_FAILED);
351 /*------------------------------------------------------------------------------------------------*/
353 /*------------------------------------------------------------------------------------------------*/