Revision c53ef0b1 core/src/aos_sssp.c
core/src/aos_sssp.c | ||
---|---|---|
83 | 83 |
|
84 | 84 |
/** |
85 | 85 |
* @brief A timer event based delays. |
86 |
* @details This timer must not be an AMiRo-OS timer, since delays occurr before system is initialized. |
|
86 | 87 |
*/ |
87 | 88 |
static virtual_timer_t _delayTimer; |
88 | 89 |
|
89 | 90 |
/** |
90 | 91 |
* @brief Event source for the delay timer. |
91 | 92 |
*/ |
92 |
static event_source_t _eventSourceDelay;
|
|
93 |
static event_source_t _delayEventSource;
|
|
93 | 94 |
|
94 | 95 |
/** |
95 | 96 |
* @brief Event listener for the delay event. |
96 | 97 |
*/ |
97 |
static event_listener_t _eventListenerDelay;
|
|
98 |
static event_listener_t _delayEventListener;
|
|
98 | 99 |
|
99 | 100 |
/******************************************************************************/ |
100 | 101 |
/* LOCAL FUNCTIONS */ |
... | ... | |
103 | 104 |
#if (AMIROOS_CFG_SSSP_MASTER != true) || defined(__DOXYGEN__) |
104 | 105 |
|
105 | 106 |
/** |
106 |
* @brief Callback function for the Sync signal interrupt.
|
|
107 |
* @brief Callback function for the S signal interrupt. |
|
107 | 108 |
* |
108 | 109 |
* @param[in] args Pointer to the GPIO line identifier. |
109 | 110 |
*/ |
... | ... | |
119 | 120 |
// if the system is in operation phase |
120 | 121 |
if (aos.sssp.stage == AOS_SSSP_STAGE_OPERATION) { |
121 | 122 |
// read signal S |
122 |
apalControlGpioGet(&moduleSsspGpioS, &s);
|
|
123 |
apalControlGpioGet(moduleSsspSignalS(), &s);
|
|
123 | 124 |
// if S was toggled from on to off |
124 | 125 |
if (s == APAL_GPIO_OFF) { |
125 | 126 |
// get current uptime |
... | ... | |
154 | 155 |
|
155 | 156 |
/** |
156 | 157 |
* @brief Periodic system synchronization callback function. |
157 |
* @details Toggles the SYS_SYNC signal and reconfigures the system synchronization timer.
|
|
158 |
* @details Toggles the S signal and reconfigures the system synchronization timer. |
|
158 | 159 |
* |
159 | 160 |
* @param[in] par Unused parameters. |
160 | 161 |
*/ |
... | ... | |
162 | 163 |
{ |
163 | 164 |
(void)par; |
164 | 165 |
|
166 |
// local variables |
|
165 | 167 |
apalControlGpioState_t state; |
166 | 168 |
aos_timestamp_t uptime; |
167 | 169 |
|
168 | 170 |
chSysLockFromISR(); |
169 | 171 |
// toggle and read signal S |
170 |
apalGpioToggle(moduleSsspGpioS.gpio);
|
|
171 |
apalControlGpioGet(&moduleSsspGpioS, &state);
|
|
172 |
apalGpioToggle(moduleSsspSignalS()->gpio);
|
|
173 |
apalControlGpioGet(moduleSsspSignalS(), &state);
|
|
172 | 174 |
// if S was toggled from off to on |
173 | 175 |
if (state == APAL_GPIO_ON) { |
174 | 176 |
// reconfigure the timer precisely, because the logically falling edge (next interrupt) snychronizes the system time |
175 | 177 |
_synctime += AMIROOS_CFG_SSSP_SYSSYNCPERIOD; |
176 | 178 |
aosSysGetUptimeX(&uptime); |
177 |
chVTSetI(&_synctimer, chTimeUS2I(_synctime - uptime), _syncTimerCallback, NULL);
|
|
179 |
chVTSetI(&_synctimer, chTimeUS2I((time_usecs_t)(_synctime - uptime)), _syncTimerCallback, NULL);
|
|
178 | 180 |
} |
179 | 181 |
// if S was toggled from on to off |
180 | 182 |
else /* if (state == APAL_GPIO_OFF) */ { |
... | ... | |
199 | 201 |
aos_timestamp_t t; |
200 | 202 |
aosSysGetUptimeX(&t); |
201 | 203 |
t = AMIROOS_CFG_SSSP_SYSSYNCPERIOD - (t % AMIROOS_CFG_SSSP_SYSSYNCPERIOD); |
202 |
chVTSetI(&_synctimer, chTimeUS2I((t > (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) ? (t - (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) : (t + (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2))), _syncTimerCallback, NULL);
|
|
204 |
chVTSetI(&_synctimer, chTimeUS2I((time_usecs_t)((t > (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) ? (t - (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) : (t + (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)))), _syncTimerCallback, NULL);
|
|
203 | 205 |
|
204 | 206 |
return; |
205 | 207 |
} |
... | ... | |
226 | 228 |
* @brief Waits for the S signal to switch to the desired state. |
227 | 229 |
* |
228 | 230 |
* @param[in] listener Pointer to the GPIO event listener to be used. |
229 |
* @param[in] flags Event flags to listen to by the event listener (indicating a S signal event). |
|
230 | 231 |
* @param[in] signalstate Desired state of the S signal ti be waited for. |
231 | 232 |
* @param[out] received Output variable to store the received event mask to. |
232 | 233 |
* |
233 | 234 |
* @return Status, indicating whether the expected event was received. |
234 | 235 |
*/ |
235 |
static inline aos_status_t _waitForS(event_listener_t* listener, eventflags_t flags, apalControlGpioState_t signalstate, eventmask_t* received)
|
|
236 |
static inline aos_status_t _waitForS(event_listener_t* listener, apalControlGpioState_t signalstate, eventmask_t* received) |
|
236 | 237 |
{ |
237 | 238 |
aosDbgCheck(listener != NULL); |
238 |
aosDbgCheck(flags != 0); |
|
239 | 239 |
aosDbgCheck(received != NULL); |
240 | 240 |
|
241 |
// local variables |
|
242 |
aos_status_t status = AOS_FAILURE; |
|
243 |
|
|
241 | 244 |
// wait for the next event (do not apply any filters in order not to miss any events) |
242 | 245 |
*received = chEvtWaitOne(ALL_EVENTS); |
243 | 246 |
// if the correct event was triggered |
244 |
if (*received == listener->events) {
|
|
247 |
if (*received & listener->events) {
|
|
245 | 248 |
apalControlGpioState_t s; |
246 |
apalControlGpioGet(&moduleSsspGpioS, &s); |
|
249 |
apalControlGpioGet(moduleSsspSignalS(), &s); |
|
250 |
chSysLock(); |
|
247 | 251 |
// only check for the expected event |
248 |
if (flags & listener->flags && s == signalstate) {
|
|
252 |
if ((listener->flags & moduleSsspEventflagS()) && (s == signalstate)) {
|
|
249 | 253 |
// unset the expected flags but keep any other ones |
250 |
listener->flags &= ~flags;
|
|
251 |
return AOS_SUCCESS;
|
|
254 |
listener->flags &= ~moduleSsspEventflagS();
|
|
255 |
status = AOS_SUCCESS;
|
|
252 | 256 |
} |
257 |
// if no further flags are set |
|
258 |
if (listener->flags == 0) { |
|
259 |
// clear event |
|
260 |
*received &= ~(listener->events); |
|
261 |
} |
|
262 |
chSysUnlock(); |
|
253 | 263 |
} |
254 | 264 |
|
255 |
return AOS_FAILURE;
|
|
265 |
return status;
|
|
256 | 266 |
} |
257 | 267 |
|
258 | 268 |
/** |
... | ... | |
260 | 270 |
* |
261 | 271 |
* @param[in] dt Delay time in microseconds to be set to the timer. |
262 | 272 |
* @param[in] mask Event mask to be used for the delay timer. |
263 |
* @param[in] arm_timer Flag to indicate whether the timer has to be armed yet (i.e. on first call of this function). |
|
264 | 273 |
* @param[out] received Output variable to store the received event mask to. |
265 | 274 |
* |
266 | 275 |
* @return Status, indicating whether the expected event (delay timer) was received. |
267 | 276 |
*/ |
268 |
static inline aos_status_t _delay(uint32_t dt, eventmask_t mask, bool arm_timer, eventmask_t* received)
|
|
277 |
static inline aos_status_t _delay(uint32_t dt, eventmask_t mask, eventmask_t* received) |
|
269 | 278 |
{ |
270 | 279 |
aosDbgCheck(dt != TIME_IMMEDIATE); |
271 | 280 |
aosDbgCheck(mask != 0); |
272 | 281 |
aosDbgCheck(received != NULL); |
273 | 282 |
|
274 | 283 |
// arm the delay timer once |
275 |
if (arm_timer) {
|
|
276 |
chEvtRegisterMask(&_eventSourceDelay, &_eventListenerDelay, mask);
|
|
277 |
chVTSet(&_delayTimer, chTimeUS2I(dt), _timerCallback, &_eventSourceDelay);
|
|
284 |
if (!chVTIsArmed(&_delayTimer)) {
|
|
285 |
chEvtRegisterMask(&_delayEventSource, &_delayEventListener, mask);
|
|
286 |
chVTSet(&_delayTimer, chTimeUS2I(dt), _timerCallback, &_delayEventSource);
|
|
278 | 287 |
} |
279 | 288 |
|
280 | 289 |
// wait for any event to occur (do not apply any filters in order not to miss any events) |
281 | 290 |
*received = chEvtWaitOne(ALL_EVENTS); |
282 | 291 |
|
283 | 292 |
// if the timer event was received, cleanup |
284 |
if (*received & _eventListenerDelay.events) { |
|
285 |
chEvtUnregister(&_eventSourceDelay, &_eventListenerDelay); |
|
293 |
if (*received & _delayEventListener.events) { |
|
294 |
chEvtUnregister(&_delayEventSource, &_delayEventListener); |
|
295 |
*received &= ~(_delayEventListener.events); |
|
286 | 296 |
return AOS_SUCCESS; |
287 | 297 |
} |
288 | 298 |
|
289 | 299 |
return AOS_FAILURE; |
290 | 300 |
} |
291 | 301 |
|
302 |
#if (AMIROOS_CFG_SSSP_MSI == true) || defined(__DOXYGEN__) |
|
303 |
|
|
304 |
/** |
|
305 |
* @brief Serialize a BCB message. |
|
306 |
* @details The individual primitives are serialized in big-endian fashion. |
|
307 |
* |
|
308 |
* @param[out] buffer Buffer to write the serialized message to. |
|
309 |
* @param[in] message The message to be serialized. |
|
310 |
*/ |
|
311 |
aos_status_t _serializeBcbMessage(uint8_t* buffer, aos_ssspbcbmessage_t message) |
|
312 |
{ |
|
313 |
aosDbgCheck(buffer != NULL); |
|
314 |
|
|
315 |
// encode the message depending on its type |
|
316 |
switch (message.type) { |
|
317 |
case AOS_SSSP_BCBMESSAGE_MSIINIT: |
|
318 |
case AOS_SSSP_BCBMESSAGE_MSIABORT: |
|
319 |
{ |
|
320 |
buffer[0] = message.type; |
|
321 |
return AOS_SUCCESS; |
|
322 |
} |
|
323 |
case AOS_SSSP_BCBMESSAGE_MSIID: |
|
324 |
{ |
|
325 |
buffer[0] = message.type; |
|
326 |
for (size_t byte = 0; byte < sizeof(aos_ssspmoduleid_t); ++byte) { |
|
327 |
buffer[byte+1] = (message.payload.id >> (8 * (sizeof(aos_ssspmoduleid_t) - (byte+1)))) & 0xFF; |
|
328 |
} |
|
329 |
return AOS_SUCCESS; |
|
330 |
} |
|
331 |
default: |
|
332 |
{ |
|
333 |
return AOS_FAILURE; |
|
334 |
} |
|
335 |
} |
|
336 |
} |
|
337 |
|
|
338 |
/** |
|
339 |
* @brief Deserialize a BCB message. |
|
340 |
* @details The individual primitives must be serialized in big-endian fashion. |
|
341 |
* |
|
342 |
* @param[out] message Message object to be filled. |
|
343 |
* @param[in] buffer Buffer holding the serialized message. |
|
344 |
*/ |
|
345 |
aos_status_t _deserializeBcbMessage(aos_ssspbcbmessage_t* message, uint8_t* buffer) |
|
346 |
{ |
|
347 |
aosDbgCheck(message != NULL); |
|
348 |
aosDbgCheck(buffer != NULL); |
|
349 |
|
|
350 |
// only decode the first byte, which contains the message type |
|
351 |
message->type = buffer[0]; |
|
352 |
|
|
353 |
// decode the message depedning on its type |
|
354 |
switch (message->type) { |
|
355 |
case AOS_SSSP_BCBMESSAGE_MSIINIT: |
|
356 |
case AOS_SSSP_BCBMESSAGE_MSIABORT: |
|
357 |
{ |
|
358 |
return AOS_SUCCESS; |
|
359 |
} |
|
360 |
case AOS_SSSP_BCBMESSAGE_MSIID: |
|
361 |
{ |
|
362 |
message->payload.id = 0; |
|
363 |
for (size_t byte = 0; byte < sizeof(aos_ssspmoduleid_t); ++byte) { |
|
364 |
message->payload.id |= (aos_ssspmoduleid_t)(buffer[byte+1] << (8 * (sizeof(aos_ssspmoduleid_t) - (byte+1)))); |
|
365 |
} |
|
366 |
return AOS_SUCCESS; |
|
367 |
} |
|
368 |
default: |
|
369 |
{ |
|
370 |
message->type = AOS_SSSP_BCBMESSAGE_INVALID; |
|
371 |
return AOS_FAILURE; |
|
372 |
} |
|
373 |
} |
|
374 |
} |
|
375 |
|
|
376 |
/** |
|
377 |
* @brief Common outro of the module stack initialization (MSI). |
|
378 |
* @details This function must be called on failure, success and if MSI is skipped. |
|
379 |
* |
|
380 |
* @param[in] msidata Pointer to the temporary data structure used during MSI. |
|
381 |
*/ |
|
382 |
void _msiOutro(aos_ssspmsidata_t* msidata) |
|
383 |
{ |
|
384 |
aosDbgCheck(msidata != NULL); |
|
385 |
|
|
386 |
// local variables |
|
387 |
eventmask_t mask = 0; |
|
388 |
|
|
389 |
// start the internal uptime aggregation |
|
390 |
chSysLock(); |
|
391 |
aosSysStartUptimeS(); |
|
392 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
393 |
// start toggling S for system synchronization |
|
394 |
_syncTimerStartS(); |
|
395 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
396 |
chSysUnlock(); |
|
397 |
|
|
398 |
// reset delay timer |
|
399 |
chVTIsArmed(&_delayTimer); |
|
400 |
// unregister delay events |
|
401 |
mask |= _delayEventListener.events; |
|
402 |
chEvtUnregister(&_delayEventSource, &_delayEventListener); |
|
403 |
|
|
404 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
|
405 |
// deactivate UP signal |
|
406 |
apalControlGpioSet(moduleSsspSignalUP(), APAL_GPIO_OFF); |
|
407 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */ |
|
408 |
|
|
409 |
// reset timeout timer |
|
410 |
chVTReset(&msidata->timeout.timer); |
|
411 |
// unregister timeout events |
|
412 |
mask |= msidata->timeout.eventlistener.events; |
|
413 |
chEvtUnregister(&msidata->timeout.eventsource, &msidata->timeout.eventlistener); |
|
414 |
|
|
415 |
// discard any pending timing events |
|
416 |
chEvtWaitAnyTimeout(mask, TIME_IMMEDIATE); |
|
417 |
|
|
418 |
// proceed to operation phase |
|
419 |
aos.sssp.stage = AOS_SSSP_STAGE_OPERATION; |
|
420 |
|
|
421 |
return; |
|
422 |
} |
|
423 |
|
|
424 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
425 |
|
|
292 | 426 |
/******************************************************************************/ |
293 | 427 |
/* EXPORTED FUNCTIONS */ |
294 | 428 |
/******************************************************************************/ |
... | ... | |
300 | 434 |
{ |
301 | 435 |
aosDbgCheck(system_uptime != NULL); |
302 | 436 |
|
303 |
// local variables |
|
304 |
apalControlGpioState_t state; |
|
305 |
|
|
306 | 437 |
#if (AMIROOS_CFG_SSSP_STARTUP == true) |
307 | 438 |
// AMiRo-OS has to perform the basic initialization |
308 | 439 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_1_1; |
... | ... | |
311 | 442 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_2_1; |
312 | 443 |
#endif /* (AMIROOS_CFG_SSSP_STARTUP == true) */ |
313 | 444 |
|
445 |
// module ID is initialized as 'invalid' |
|
446 |
aos.sssp.moduleId = AOS_SSSP_MODULEID_INVALID; |
|
447 |
|
|
448 |
#if (AMIROOS_CFG_DBG == true) |
|
314 | 449 |
// check all SSSP signals for correct state |
315 |
apalControlGpioGet(&moduleSsspGpioS, &state); |
|
316 |
aosDbgAssert(state == APAL_GPIO_ON); |
|
317 |
apalControlGpioGet(&moduleSsspGpioPD, &state); |
|
318 |
aosDbgAssert(state == APAL_GPIO_OFF); |
|
450 |
{ |
|
451 |
apalControlGpioState_t state; |
|
452 |
apalControlGpioGet(moduleSsspSignalS(), &state); |
|
453 |
aosDbgAssert(state == APAL_GPIO_ON); |
|
454 |
apalControlGpioGet(moduleSsspSignalPD(), &state); |
|
455 |
aosDbgAssert(state == APAL_GPIO_OFF); |
|
319 | 456 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
320 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
|
321 |
apalControlGpioGet(&moduleSsspGpioUP, &state); |
|
322 |
aosDbgAssert(state == APAL_GPIO_OFF); |
|
323 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */ |
|
324 | 457 |
#if (AMIROOS_CFG_SSSP_STACK_START != true) |
325 |
apalControlGpioGet(&moduleSsspGpioDN, &state);
|
|
326 |
aosDbgAssert(state == APAL_GPIO_OFF); |
|
458 |
apalControlGpioGet(moduleSsspSignalDN(), &state);
|
|
459 |
aosDbgAssert(state == APAL_GPIO_OFF);
|
|
327 | 460 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */ |
461 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
|
462 |
apalControlGpioGet(moduleSsspSignalUP(), &state); |
|
463 |
aosDbgAssert(state == APAL_GPIO_OFF); |
|
464 |
#endif /* (AMIROOS_CFG_SSSP_END_START != true) */ |
|
328 | 465 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
329 |
|
|
330 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
|
331 |
// module ID is initialized as 'invalid' |
|
332 |
aos.sssp.moduleId = AOS_SSSP_MODULEID_INVALID; |
|
333 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
466 |
} |
|
467 |
#endif /* (AMIROOS_CFG_DBG == true) */ |
|
334 | 468 |
|
335 | 469 |
// initialize static variables |
336 | 470 |
_uptime = system_uptime; |
... | ... | |
342 | 476 |
_syncskew = 0.0f; |
343 | 477 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
344 | 478 |
chVTObjectInit(&_delayTimer); |
345 |
chEvtObjectInit(&_eventSourceDelay);
|
|
479 |
chEvtObjectInit(&_delayEventSource);
|
|
346 | 480 |
|
347 | 481 |
// signal interrupt setup |
348 |
palSetLineCallback(moduleSsspGpioPD.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioPD.gpio->line);
|
|
349 |
palEnableLineEvent(moduleSsspGpioPD.gpio->line, APAL2CH_EDGE(moduleSsspGpioPD.meta.edge));
|
|
482 |
palSetLineCallback(moduleSsspSignalPD()->gpio->line, aosSysGetStdGpioCallback(), &moduleSsspSignalPD()->gpio->line);
|
|
483 |
palEnableLineEvent(moduleSsspSignalPD()->gpio->line, APAL2CH_EDGE(moduleSsspSignalPD()->meta.edge));
|
|
350 | 484 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
351 |
palSetLineCallback(moduleSsspGpioS.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioS.gpio->line);
|
|
485 |
palSetLineCallback(moduleSsspSignalS()->gpio->line, aosSysGetStdGpioCallback(), &moduleSsspSignalS()->gpio->line);
|
|
352 | 486 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
353 |
palSetLineCallback(moduleSsspGpioS.gpio->line, _gpioCallbackSSignal, &moduleSsspGpioS.gpio->line);
|
|
487 |
palSetLineCallback(moduleSsspSignalS()->gpio->line, _gpioCallbackSSignal, &moduleSsspSignalS()->gpio->line);
|
|
354 | 488 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
355 |
palEnableLineEvent(moduleSsspGpioS.gpio->line, APAL2CH_EDGE(moduleSsspGpioS.meta.edge));
|
|
489 |
palEnableLineEvent(moduleSsspSignalS()->gpio->line, APAL2CH_EDGE(moduleSsspSignalS()->meta.edge));
|
|
356 | 490 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
357 | 491 |
#if (AMIROOS_CFG_SSSP_STACK_START != true) |
358 |
palSetLineCallback(moduleSsspGpioDN.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioDN.gpio->line);
|
|
359 |
palEnableLineEvent(moduleSsspGpioDN.gpio->line, APAL2CH_EDGE(moduleSsspGpioDN.meta.edge));
|
|
492 |
palSetLineCallback(moduleSsspSignalDN()->gpio->line, aosSysGetStdGpioCallback(), &moduleSsspSignalDN()->gpio->line);
|
|
493 |
palEnableLineEvent(moduleSsspSignalDN()->gpio->line, APAL2CH_EDGE(moduleSsspSignalDN()->meta.edge));
|
|
360 | 494 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */ |
361 | 495 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
362 |
palSetLineCallback(moduleSsspGpioUP.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioUP.gpio->line);
|
|
363 |
palEnableLineEvent(moduleSsspGpioUP.gpio->line, APAL2CH_EDGE(moduleSsspGpioUP.meta.edge));
|
|
496 |
palSetLineCallback(moduleSsspSignalUP()->gpio->line, aosSysGetStdGpioCallback(), &moduleSsspSignalUP()->gpio->line);
|
|
497 |
palEnableLineEvent(moduleSsspSignalUP()->gpio->line, APAL2CH_EDGE(moduleSsspSignalUP()->meta.edge));
|
|
364 | 498 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */ |
365 | 499 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
366 | 500 |
|
... | ... | |
373 | 507 |
* The function aosSsspShutdownInit() must be used instead. |
374 | 508 |
* |
375 | 509 |
* @param[in] listener An optional listener, in case the system has to wait for a specific event. |
376 |
* @param[in] flags The relevant flags to wait for (mandatory if a listener is given). |
|
377 | 510 |
* @param[in] mask If the stage transition involves a timer event (handled internally by this function), |
378 | 511 |
* the given input value of this parameter defines the mask to be used for that event. |
379 | 512 |
* In case a listener was specified, the according mask is retrieved from the listener but this parameter is still used as input for sanity checks. |
... | ... | |
381 | 514 |
* |
382 | 515 |
* @return Status, indicating whether proceeding in the protocol was successful. |
383 | 516 |
*/ |
384 |
aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, eventmask_t mask, eventmask_t* received)
|
|
517 |
aos_status_t aosSsspProceed(event_listener_t* listener, eventmask_t mask, eventmask_t* received) |
|
385 | 518 |
{ |
386 | 519 |
// local variables |
387 | 520 |
#pragma GCC diagnostic push |
... | ... | |
402 | 535 |
{ |
403 | 536 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
404 | 537 |
aosDbgCheck(listener == NULL); |
405 |
aosDbgCheck(flags == 0); |
|
406 | 538 |
aosDbgCheck(mask != 0); |
407 | 539 |
aosDbgCheck(received != NULL); |
408 | 540 |
|
409 | 541 |
// delay execution and deactivate the S signal on success |
410 |
if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_1_1), received) == AOS_SUCCESS) {
|
|
411 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
542 |
if (_delay(AOS_SSSP_DELAY, mask, received) == AOS_SUCCESS) { |
|
543 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
412 | 544 |
nextstage = AOS_SSSP_STAGE_STARTUP_1_2; |
413 | 545 |
} |
414 | 546 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
415 | 547 |
aosDbgCheck(listener == NULL); |
416 |
aosDbgCheck(flags == 0); |
|
417 | 548 |
aosDbgCheck(mask == 0); |
418 | 549 |
aosDbgCheck(received == NULL); |
419 | 550 |
|
420 | 551 |
// deactivate S signal and proceed |
421 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
552 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
422 | 553 |
nextstage = AOS_SSSP_STAGE_STARTUP_1_2; |
423 | 554 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
424 | 555 |
break; |
... | ... | |
430 | 561 |
case AOS_SSSP_STAGE_STARTUP_1_2: |
431 | 562 |
{ |
432 | 563 |
aosDbgCheck(listener != NULL); |
433 |
aosDbgCheck(flags != 0); |
|
434 | 564 |
aosDbgCheck(mask == listener->events); |
435 | 565 |
aosDbgCheck(received != NULL); |
436 | 566 |
|
437 | 567 |
// wait for the S signal to become inactive and proceed on success |
438 |
if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
|
568 |
if (_waitForS(listener, APAL_GPIO_OFF, received) == AOS_SUCCESS) { |
|
439 | 569 |
nextstage = AOS_SSSP_STAGE_STARTUP_1_3; |
440 | 570 |
} |
441 | 571 |
break; |
... | ... | |
449 | 579 |
{ |
450 | 580 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
451 | 581 |
aosDbgCheck(listener == NULL); |
452 |
aosDbgCheck(flags == 0); |
|
453 | 582 |
aosDbgCheck(mask != 0); |
454 | 583 |
aosDbgCheck(received != NULL); |
455 | 584 |
|
456 | 585 |
// delay execution and deactivate the S signal on success |
457 |
if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_1_3), received) == AOS_SUCCESS) {
|
|
458 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
|
|
586 |
if (_delay(AOS_SSSP_DELAY, mask, received) == AOS_SUCCESS) { |
|
587 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON);
|
|
459 | 588 |
nextstage = AOS_SSSP_STAGE_STARTUP_2_1; |
460 | 589 |
} |
461 | 590 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
462 | 591 |
aosDbgCheck(listener != NULL); |
463 |
aosDbgCheck(flags != 0); |
|
464 | 592 |
aosDbgCheck(mask == listener->events); |
465 | 593 |
aosDbgCheck(received != NULL); |
466 | 594 |
|
467 | 595 |
// wait for the S signal to become active and activate it as well and proceed on success |
468 |
if (_waitForS(listener, flags, APAL_GPIO_ON, received) == AOS_SUCCESS) {
|
|
469 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
|
|
596 |
if (_waitForS(listener, APAL_GPIO_ON, received) == AOS_SUCCESS) { |
|
597 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON);
|
|
470 | 598 |
nextstage = AOS_SSSP_STAGE_STARTUP_2_1; |
471 | 599 |
} |
472 | 600 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
... | ... | |
483 | 611 |
{ |
484 | 612 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
485 | 613 |
aosDbgCheck(listener == NULL); |
486 |
aosDbgCheck(flags == 0); |
|
487 | 614 |
aosDbgCheck(mask != 0); |
488 | 615 |
aosDbgCheck(received != NULL); |
489 | 616 |
|
490 | 617 |
// delay execution and deactivate the S signal on success |
491 |
if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_2_1), received) == AOS_SUCCESS) {
|
|
492 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
618 |
if (_delay(AOS_SSSP_DELAY, mask, received) == AOS_SUCCESS) { |
|
619 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
493 | 620 |
nextstage = AOS_SSSP_STAGE_STARTUP_2_2; |
621 |
} else { |
|
622 |
aosprintf("."); |
|
494 | 623 |
} |
495 | 624 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
496 | 625 |
aosDbgCheck(listener == NULL); |
497 |
aosDbgCheck(flags == 0); |
|
498 | 626 |
aosDbgCheck(mask == 0); |
499 | 627 |
aosDbgCheck(received == NULL); |
500 | 628 |
|
501 | 629 |
// deactivate S signal and proceed |
502 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
630 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
503 | 631 |
nextstage = AOS_SSSP_STAGE_STARTUP_2_2; |
504 | 632 |
mask = 0; |
505 | 633 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
... | ... | |
513 | 641 |
case AOS_SSSP_STAGE_STARTUP_2_2: |
514 | 642 |
{ |
515 | 643 |
aosDbgCheck(listener != NULL); |
516 |
aosDbgCheck(flags != 0); |
|
517 | 644 |
aosDbgCheck(mask == listener->events); |
518 | 645 |
aosDbgCheck(received != NULL); |
519 | 646 |
|
520 | 647 |
// wait for the S signal to become inactive and proceed on success |
521 |
if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
|
648 |
if (_waitForS(listener, APAL_GPIO_OFF, received) == AOS_SUCCESS) { |
|
522 | 649 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
523 | 650 |
nextstage = AOS_SSSP_STAGE_STARTUP_3; |
524 | 651 |
#else /* (AMIROOS_CFG_SSSP_MSI == true) */ |
525 |
chSysLock(); |
|
526 | 652 |
// start the internal uptime aggregation |
653 |
chSysLock(); |
|
527 | 654 |
aosSysStartUptimeS(); |
528 | 655 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
529 | 656 |
// start toggling S for system synchronization |
... | ... | |
536 | 663 |
break; |
537 | 664 |
} |
538 | 665 |
|
539 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
|
540 |
|
|
541 |
//TODO |
|
542 |
|
|
543 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
666 |
/* |
|
667 |
* PLEASE NOTE: |
|
668 |
* Stage transitions during MSI are not hanlded by thins function but are executed in aosSsspMsi(). |
|
669 |
*/ |
|
544 | 670 |
|
545 | 671 |
/* |
546 | 672 |
* Invalid operation. |
... | ... | |
560 | 686 |
case AOS_SSSP_STAGE_SHUTDOWN_1_2: |
561 | 687 |
{ |
562 | 688 |
aosDbgCheck(listener == NULL); |
563 |
aosDbgCheck(flags == 0); |
|
564 | 689 |
aosDbgCheck(mask == 0); |
565 | 690 |
aosDbgCheck(received == NULL); |
566 | 691 |
|
567 | 692 |
// delay execution |
568 | 693 |
aosThdUSleep(AOS_SSSP_DELAY); |
569 | 694 |
// deactivate S signal |
570 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
695 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
571 | 696 |
nextstage = AOS_SSSP_STAGE_SHUTDOWN_1_3; |
572 | 697 |
break; |
573 | 698 |
} |
... | ... | |
580 | 705 |
case AOS_SSSP_STAGE_SHUTDOWN_1_3: |
581 | 706 |
{ |
582 | 707 |
aosDbgCheck(listener != NULL); |
583 |
aosDbgCheck(flags != 0); |
|
584 | 708 |
aosDbgCheck(mask == listener->events); |
585 | 709 |
aosDbgCheck(received != NULL); |
586 | 710 |
|
587 | 711 |
// wait for the S signal to become inactive and proceed on success |
588 |
if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
|
712 |
if (_waitForS(listener, APAL_GPIO_OFF, received) == AOS_SUCCESS) { |
|
589 | 713 |
nextstage = AOS_SSSP_STAGE_SHUTDOWN_2_1; |
590 | 714 |
} |
591 | 715 |
break; |
... | ... | |
598 | 722 |
case AOS_SSSP_STAGE_SHUTDOWN_2_1: |
599 | 723 |
{ |
600 | 724 |
aosDbgCheck(listener == NULL); |
601 |
aosDbgCheck(flags == 0); |
|
602 | 725 |
aosDbgCheck(mask == 0); |
603 | 726 |
aosDbgCheck(received != NULL); |
604 | 727 |
|
605 | 728 |
// evaluate PD signal |
606 | 729 |
apalControlGpioState_t pd; |
607 |
apalControlGpioGet(&moduleSsspGpioPD, &pd);
|
|
730 |
apalControlGpioGet(moduleSsspSignalPD(), &pd);
|
|
608 | 731 |
*received = (pd == APAL_GPIO_ON) ? (eventmask_t)~0 : 0; |
609 | 732 |
nextstage = AOS_SSSP_STAGE_SHUTDOWN_2_2; |
610 | 733 |
break; |
... | ... | |
616 | 739 |
case AOS_SSSP_STAGE_SHUTDOWN_2_2: |
617 | 740 |
{ |
618 | 741 |
aosDbgCheck(listener == NULL); |
619 |
aosDbgCheck(flags == 0); |
|
620 | 742 |
aosDbgCheck(mask == 0); |
621 | 743 |
aosDbgCheck(received == NULL); |
622 | 744 |
|
... | ... | |
642 | 764 |
return status; |
643 | 765 |
} |
644 | 766 |
|
767 |
#if (AMIROOS_CFG_SSSP_MSI == true) || defined(__DOXYGEN__) |
|
768 |
|
|
769 |
/** |
|
770 |
* @brief Initialize MSI data structure. |
|
771 |
* |
|
772 |
* @param[out] msidata Pointer to the MSI data structure to be initialized. |
|
773 |
* @param[in] delayMask Event maks used for delay events. |
|
774 |
* @param[in] timeoutMask Event mask used for timeout events. |
|
775 |
* @param[in] gpioListener Event listener for GPIO events. |
|
776 |
*/ |
|
777 |
void aosSsspMsiInit(aos_ssspmsidata_t* msidata, eventmask_t delayMask, eventmask_t timeoutMask, event_listener_t* gpioListener) |
|
778 |
{ |
|
779 |
aosDbgCheck(msidata != NULL); |
|
780 |
aosDbgCheck(gpioListener != NULL); |
|
781 |
|
|
782 |
// register delay events |
|
783 |
chEvtRegisterMask(&_delayEventSource, &_delayEventListener, delayMask); |
|
784 |
|
|
785 |
// initialize timeout related data |
|
786 |
chVTObjectInit(&msidata->timeout.timer); |
|
787 |
chEvtObjectInit(&msidata->timeout.eventsource); |
|
788 |
chEvtRegisterMask(&msidata->timeout.eventsource, &msidata->timeout.eventlistener, timeoutMask); |
|
789 |
|
|
790 |
// set GPIO event information |
|
791 |
msidata->signals.eventlistener = gpioListener; |
|
792 |
|
|
793 |
// initialize BCB related data |
|
794 |
msidata->bcb.lastid = AOS_SSSP_MODULEID_INVALID; |
|
795 |
|
|
796 |
return; |
|
797 |
} |
|
798 |
|
|
799 |
/** |
|
800 |
* @brief Execute module stack initialization (MSI). |
|
801 |
* |
|
802 |
* @param[in] msidata Data required for MSI. |
|
803 |
* @param[out] received Output variable to store the received event mask to. |
|
804 |
*/ |
|
805 |
void aosSsspMsi(aos_ssspmsidata_t* msidata, eventmask_t* received) |
|
806 |
{ |
|
807 |
aosDbgCheck(msidata != NULL); |
|
808 |
aosDbgCheck(received != NULL); |
|
809 |
|
|
810 |
/* |
|
811 |
* execute anything that does not depend on BCB messages or events |
|
812 |
*/ |
|
813 |
switch (aos.sssp.stage) { |
|
814 |
case AOS_SSSP_STAGE_STARTUP_3: |
|
815 |
case AOS_SSSP_STAGE_STARTUP_3_1: |
|
816 |
{ |
|
817 |
aosDbgPrintf(">>> MSI init\n"); |
|
818 |
// setup timeout timer |
|
819 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
820 |
// proceed |
|
821 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
822 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_1_BROADCASTINIT; |
|
823 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
824 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_1_WAITFORINIT; |
|
825 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
826 |
break; |
|
827 |
} |
|
828 |
|
|
829 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
830 |
case AOS_SSSP_STAGE_STARTUP_3_1_BROADCASTINIT: |
|
831 |
{ |
|
832 |
aosDbgPrintf("%u\tsend INIT\t", chVTGetSystemTime()); |
|
833 |
// send init command |
|
834 |
msidata->bcb.message.type = AOS_SSSP_BCBMESSAGE_MSIINIT; |
|
835 |
_serializeBcbMessage(msidata->bcb.buffer, msidata->bcb.message); |
|
836 |
if (moduleSsspBcbTransmit(msidata->bcb.buffer, sizeof(aos_ssspbcbmessage_t)) == AOS_SSSP_BCB_SUCCESS) { |
|
837 |
aosDbgPrintf("ok\tS+\t"); |
|
838 |
// activate S |
|
839 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON); |
|
840 |
// restart timeout timer |
|
841 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
842 |
// proceed |
|
843 |
#if (AMIROOS_CFG_SSSP_STACK_START == true) |
|
844 |
aosDbgPrintf("->start\n"); |
|
845 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_2; |
|
846 |
#else /* (AMIROOS_CFG_SSSP_STACK_START == true) */ |
|
847 |
aosDbgPrintf("->count\n"); |
|
848 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT; |
|
849 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */ |
|
850 |
} else { |
|
851 |
aosDbgPrintf("fail\t->retry\n"); |
|
852 |
// retry in next iteration |
|
853 |
} |
|
854 |
break; |
|
855 |
} |
|
856 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
857 |
|
|
858 |
#if (AMIROOS_CFG_SSSP_STACK_START == true) |
|
859 |
case AOS_SSSP_STAGE_STARTUP_3_2: |
|
860 |
{ |
|
861 |
aosDbgPrintf("%u\tstart\t", chVTGetSystemTime()); |
|
862 |
// set the own module ID |
|
863 |
aos.sssp.moduleId = 1; |
|
864 |
// broadcast the new ID |
|
865 |
msidata->bcb.message.type = AOS_SSSP_BCBMESSAGE_MSIID; |
|
866 |
msidata->bcb.message.payload.id = aos.sssp.moduleId; |
|
867 |
aosDbgPrintf("bc ID (%u)\t", msidata->bcb.message.payload.id); |
|
868 |
_serializeBcbMessage(msidata->bcb.buffer, msidata->bcb.message); |
|
869 |
if (moduleSsspBcbTransmit(msidata->bcb.buffer, sizeof(aos_ssspbcbmessage_t)) == AOS_SSSP_BCB_SUCCESS) { |
|
870 |
aosDbgPrintf("ok\t->count\n"); |
|
871 |
// restart timeout timer |
|
872 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
873 |
// set delay timer so UP will be activated and S deactivated later |
|
874 |
chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_DELAY), _timerCallback, &_delayEventSource); |
|
875 |
// store the transmitted ID |
|
876 |
msidata->bcb.lastid = msidata->bcb.message.payload.id; |
|
877 |
// proceed |
|
878 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT; |
|
879 |
} else { |
|
880 |
aosDbgPrintf("fail\t->retry\n"); |
|
881 |
// retry next iteration |
|
882 |
} |
|
883 |
break; |
|
884 |
} |
|
885 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */ |
|
886 |
|
|
887 |
case AOS_SSSP_STAGE_STARTUP_3_3_BROADCASTID: |
|
888 |
{ |
|
889 |
// broadcast ID |
|
890 |
msidata->bcb.message.type = AOS_SSSP_BCBMESSAGE_MSIID; |
|
891 |
msidata->bcb.message.payload.id = aos.sssp.moduleId; |
|
892 |
aosDbgPrintf("%u\tbc ID (%u)\t", chVTGetSystemTime(), msidata->bcb.message.payload.id); |
|
893 |
_serializeBcbMessage(msidata->bcb.buffer, msidata->bcb.message); |
|
894 |
if (moduleSsspBcbTransmit(msidata->bcb.buffer, sizeof(aos_ssspbcbmessage_t)) == AOS_SSSP_BCB_SUCCESS) { |
|
895 |
aosDbgPrintf("ok->count\n"); |
|
896 |
// restart timeout timer |
|
897 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
898 |
// set delay timer so UP will be activated and S deactivated later |
|
899 |
chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_DELAY), _timerCallback, &_delayEventSource); |
|
900 |
// store the transmitted ID |
|
901 |
msidata->bcb.lastid = msidata->bcb.message.payload.id; |
|
902 |
// return to receiving |
|
903 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT; |
|
904 |
} else { |
|
905 |
aosDbgPrintf("fail\t->retry\n"); |
|
906 |
// retry next iteration |
|
907 |
} |
|
908 |
break; |
|
909 |
} |
|
910 |
|
|
911 |
case AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT: |
|
912 |
{ |
|
913 |
aosDbgPrintf("%u\tabort\t", chVTGetSystemTime()); |
|
914 |
// reset timeout timer |
|
915 |
chVTReset(&msidata->timeout.timer); |
|
916 |
// transmit abort message |
|
917 |
msidata->bcb.message.type = AOS_SSSP_BCBMESSAGE_MSIABORT; |
|
918 |
_serializeBcbMessage(msidata->bcb.buffer, msidata->bcb.message); |
|
919 |
if (moduleSsspBcbTransmit(msidata->bcb.buffer, sizeof(aos_ssspbcbmessage_t)) == AOS_SSSP_BCB_SUCCESS) { |
|
920 |
aosDbgPrintf("ok\tS-\t->sync\n"); |
|
921 |
// deactivate S |
|
922 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF); |
|
923 |
// proceed |
|
924 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_SYNC; |
|
925 |
} else { |
|
926 |
aosDbgPrintf("fail\t->retry\n"); |
|
927 |
// retry next iteration |
|
928 |
} |
|
929 |
break; |
|
930 |
} |
|
931 |
|
|
932 |
default: |
|
933 |
{ |
|
934 |
// all other stages depend on events or BCB messages and are thus handled below |
|
935 |
break; |
|
936 |
} |
|
937 |
} |
|
938 |
|
|
939 |
/* |
|
940 |
* handle BCB messages |
|
941 |
*/ |
|
942 |
msidata->bcb.status = moduleSsspBcbReceive(msidata->bcb.buffer, sizeof(aos_ssspbcbmessage_t)); |
|
943 |
switch (msidata->bcb.status) { |
|
944 |
|
|
945 |
/* VALID BCB MESSAGE |
|
946 |
* A message was received via BCB that seems to be plausible. |
|
947 |
* The first BCB message initiates the sequence once. |
|
948 |
* During MSI an arbitrary number of IDs will be received. |
|
949 |
* Abort messages can be received at any time. |
|
950 |
*/ |
|
951 |
case AOS_SSSP_BCB_SUCCESS: |
|
952 |
{ |
|
953 |
aosDbgPrintf("%u\tBCB\t", chVTGetSystemTime()); |
|
954 |
// deserialize message and handle types differently |
|
955 |
_deserializeBcbMessage(&msidata->bcb.message, msidata->bcb.buffer); |
|
956 |
switch (msidata->bcb.message.type) { |
|
957 |
// initialization message |
|
958 |
case AOS_SSSP_BCBMESSAGE_MSIINIT: |
|
959 |
{ |
|
960 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
961 |
aosDbgPrintf("INIT\t->abort\n"); |
|
962 |
// initiate abortion |
|
963 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
964 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
965 |
aosDbgPrintf("INIT\t"); |
|
966 |
// check for correct SSSP stage |
|
967 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_1_WAITFORINIT) { |
|
968 |
aosDbgPrintf("S+\t"); |
|
969 |
// activate S |
|
970 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON); |
|
971 |
// restart timeout timer |
|
972 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
973 |
// proceed |
|
974 |
#if (AMIROOS_CFG_SSSP_STACK_START == true) |
|
975 |
aosDbgPrintf("->start\n"); |
|
976 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_2; |
|
977 |
#else /* (AMIROOS_CFG_SSSP_STACK_START == true) */ |
|
978 |
aosDbgPrintf("->count\n"); |
|
979 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT; |
|
980 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */ |
|
981 |
} else { |
|
982 |
aosDbgPrintf("->abort\n"); |
|
983 |
// initiate abortion |
|
984 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
985 |
} |
|
986 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
987 |
break; |
|
988 |
} |
|
989 |
// ID message |
|
990 |
case AOS_SSSP_BCBMESSAGE_MSIID: |
|
991 |
{ |
|
992 |
aosDbgPrintf("ID (%u)\t", msidata->bcb.message.payload.id); |
|
993 |
// check for correct stage and whether ID was increased |
|
994 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT && |
|
995 |
msidata->bcb.message.payload.id > msidata->bcb.lastid) { |
|
996 |
aosDbgPrintf("ok\n"); |
|
997 |
// restart timeout timer |
|
998 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
999 |
// store ID |
|
1000 |
msidata->bcb.lastid = msidata->bcb.message.payload.id; |
|
1001 |
} else { |
|
1002 |
aosDbgPrintf("fail\t->abort\n"); |
|
1003 |
// initiate abortion |
|
1004 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1005 |
} |
|
1006 |
break; |
|
1007 |
} |
|
1008 |
// abort message |
|
1009 |
case AOS_SSSP_BCBMESSAGE_MSIABORT: |
|
1010 |
{ |
|
1011 |
aosDbgPrintf("ABORT\tS-\t->sync\n"); |
|
1012 |
// reset timeout timer |
|
1013 |
chVTReset(&msidata->timeout.timer); |
|
1014 |
// deactivate S |
|
1015 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF); |
|
1016 |
// proceed to abort synchronization |
|
1017 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_SYNC; |
|
1018 |
break; |
|
1019 |
} |
|
1020 |
// invalid message |
|
1021 |
default: |
|
1022 |
{ |
|
1023 |
aosDbgPrintf("invalid\t->abort\n"); |
|
1024 |
// initiate abortion |
|
1025 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1026 |
break; |
|
1027 |
} |
|
1028 |
} |
|
1029 |
return; |
|
1030 |
} |
|
1031 |
|
|
1032 |
/* INVALID BCB MESSAGE |
|
1033 |
* An obviously invalid message was received via BCB. |
|
1034 |
*/ |
|
1035 |
case AOS_SSSP_BCB_INVALIDMSG: |
|
1036 |
{ |
|
1037 |
// error but ignore |
|
1038 |
aosDbgPrintf("WARNING: unknown message received via BCB\n"); |
|
1039 |
break; |
|
1040 |
} |
|
1041 |
|
|
1042 |
/* NO BCB MESSAGE |
|
1043 |
* No message was received via BCB at all. |
|
1044 |
*/ |
|
1045 |
case AOS_SSSP_BCB_ERROR: |
|
1046 |
{ |
|
1047 |
// do nothing and proceed |
|
1048 |
break; |
|
1049 |
} |
|
1050 |
} |
|
1051 |
|
|
1052 |
/* |
|
1053 |
* handle events |
|
1054 |
*/ |
|
1055 |
*received = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE); |
|
1056 |
/* TIMEOUT EVENT |
|
1057 |
* Timeouts can occur at any time during MSI after they have been initialized. |
|
1058 |
* As soon as the module has made it to the 3.4 completion stage, there will be no more timeouts, though. |
|
1059 |
*/ |
|
1060 |
if (*received & msidata->timeout.eventlistener.events) { |
|
1061 |
aosDbgPrintf("%u\ttimeout\t", chVTGetSystemTime()); |
|
1062 |
// special cases |
|
1063 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_1_WAITFORINIT || |
|
1064 |
aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_4_COMPLETION) { |
|
1065 |
// master did not initiate the sequence |
|
1066 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_1_WAITFORINIT) { |
|
1067 |
aosDbgPrintf("no init\t->operation\n"); |
|
1068 |
// invalidate module ID |
|
1069 |
aos.sssp.moduleId = AOS_SSSP_MODULEID_INVALID; |
|
1070 |
aosDbgPrintf("<<< MSI skipped\n"); |
|
1071 |
} |
|
1072 |
// no abort messages received after completion |
|
1073 |
else /* if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_4_COMPLETION) */ { |
|
1074 |
aosDbgPrintf("success\t->operation\n"); |
|
1075 |
aosDbgPrintf("<<< MSI completed\n"); |
|
1076 |
} |
|
1077 |
// cleanup and proceed to operation phase |
|
1078 |
_msiOutro(msidata); |
|
1079 |
} |
|
1080 |
// general timeout |
|
1081 |
else { |
|
1082 |
aosDbgPrintf("->abort\n"); |
|
1083 |
// initiate active abort |
|
1084 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1085 |
} |
|
1086 |
// clear event |
|
1087 |
chEvtGetAndClearFlags(&msidata->timeout.eventlistener); |
|
1088 |
*received &= ~(msidata->timeout.eventlistener.events); |
|
1089 |
} |
|
1090 |
/* DELAY EVENT |
|
1091 |
* Delays are only used to toggle the UP signal. |
|
1092 |
*/ |
|
1093 |
else if (*received & _delayEventListener.events) { |
|
1094 |
aosDbgPrintf("%u\tdelay\t", chVTGetSystemTime()); |
|
1095 |
#if (AMIROOS_CFG_SSSP_STACK_END == true) |
|
1096 |
apalControlGpioState_t s; |
|
1097 |
aosDbgPrintf("S-\t"); |
|
1098 |
// deactivate S |
|
1099 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF); |
|
1100 |
// verify deactivation |
|
1101 |
apalControlGpioGet(moduleSsspSignalS(), &s); |
|
1102 |
if (s == APAL_GPIO_OFF) { |
|
1103 |
aosDbgPrintf("ok\t->done\n"); |
|
1104 |
// set the timeout timer so no abort messages are missed |
|
1105 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
1106 |
// proceed to the completion stage |
|
1107 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_COMPLETION; |
|
1108 |
} else { |
|
1109 |
aosDbgPrintf("fail\t->abort\n"); |
|
1110 |
// initiate active abort |
|
1111 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1112 |
} |
|
1113 |
#else /* (AMIROOS_CFG_SSSP_STACK_END == true) */ |
|
1114 |
apalControlGpioState_t s; |
|
1115 |
// read the current state of the UP signal |
|
1116 |
apalControlGpioGet(moduleSsspSignalUP(), &s); |
|
1117 |
if (s == APAL_GPIO_OFF) { |
|
1118 |
aosDbgPrintf("UP+ & S-\n"); |
|
1119 |
// activate UP in order to trigger the next module |
|
1120 |
apalControlGpioSet(moduleSsspSignalUP(), APAL_GPIO_ON); |
|
1121 |
// deactivate S |
|
1122 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF); |
|
1123 |
// set the delay timer so the UP signal will get deactivated again later |
|
1124 |
chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_DELAY), _timerCallback, &_delayEventSource); |
|
1125 |
} else { |
|
1126 |
aosDbgPrintf("UP-\n"); |
|
1127 |
// deactvate UP |
|
1128 |
apalControlGpioSet(moduleSsspSignalUP(), APAL_GPIO_OFF); |
|
1129 |
} |
|
1130 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END == true) */ |
|
1131 |
// clear event |
|
1132 |
chEvtGetAndClearFlags(&_delayEventListener); |
|
1133 |
*received &= ~(_delayEventListener.events); |
|
1134 |
} |
|
1135 |
/* GPIO EVENT |
|
1136 |
* GPIO events can occurr at any time, but only DN and S events are expected. |
|
1137 |
* DN may be activated only once per module to trigger the counting process and is deactivated briefly after activation. |
|
1138 |
* S must only deactivate when MSI is comleted by the last module in the stack. |
|
1139 |
*/ |
|
1140 |
else if (*received & msidata->signals.eventlistener->events) { |
|
1141 |
aosDbgPrintf("%u\tGPIO\t", chVTGetSystemTime()); |
|
1142 |
apalControlGpioState_t s; |
|
1143 |
// fetch event flags |
|
1144 |
eventflags_t flags = chEvtGetAndClearFlags(msidata->signals.eventlistener); |
|
1145 |
#if (AMIROOS_CFG_SSSP_STACK_START != true) |
|
1146 |
// if the DN signal was triggered |
|
1147 |
if (flags & moduleSsspEventflagDN()) { |
|
1148 |
// read the signal state |
|
1149 |
apalControlGpioGet(moduleSsspSignalDN(), &s); |
|
1150 |
// rising edge |
|
1151 |
if (s == APAL_GPIO_ON) { |
|
1152 |
aosDbgPrintf("+DN\t"); |
|
1153 |
// Correct SSSP stage and no ID assigned yet? |
|
1154 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT && |
|
1155 |
aos.sssp.moduleId == AOS_SSSP_MODULEID_INVALID) { |
|
1156 |
// set the own module ID |
|
1157 |
aos.sssp.moduleId = msidata->bcb.lastid + 1; |
|
1158 |
aosDbgPrintf("set ID (%u)\t->bc ID\n", aos.sssp.moduleId); |
|
1159 |
// proceed to broadcasting |
|
1160 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_3_BROADCASTID; |
|
1161 |
} |
|
1162 |
// incorrect SSSP stage or ID already assigned (triggered for a second time) |
|
1163 |
else { |
|
1164 |
aosDbgPrintf("->abort\n"); |
|
1165 |
// initiate active abort |
|
1166 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1167 |
} |
|
1168 |
} |
|
1169 |
// falling egde |
|
1170 |
else { |
|
1171 |
aosDbgPrintf("-DN\n"); |
|
1172 |
// ignored |
|
1173 |
} |
|
1174 |
// clear DN flags |
|
1175 |
flags &= ~moduleSsspEventflagDN(); |
|
1176 |
} |
|
1177 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */ |
|
1178 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
|
1179 |
// if the UP signal was triggered |
|
1180 |
if (flags & moduleSsspEventflagUP()) { |
|
1181 |
/* |
|
1182 |
* The UP signal is acting as output only. |
|
1183 |
* Any events resulting from toggling the signal are thus ignored. |
|
1184 |
*/ |
|
1185 |
aosDbgPrintf("?UP\n"); |
|
1186 |
// clear UP flags |
|
1187 |
flags &= ~moduleSsspEventflagUP(); |
|
1188 |
} |
|
1189 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */ |
|
1190 |
// if the S signal was triggered |
|
1191 |
if (flags & moduleSsspEventflagS()) { |
|
1192 |
// read the signal state |
|
1193 |
apalControlGpioGet(moduleSsspSignalS(), &s); |
|
1194 |
// rising edge |
|
1195 |
if (s == APAL_GPIO_ON) { |
|
1196 |
aosDbgPrintf("+S\n"); |
|
1197 |
// ignored |
|
1198 |
} |
|
1199 |
// falling edge |
|
1200 |
else { |
|
1201 |
aosDbgPrintf("-S\t"); |
|
1202 |
// special case |
|
1203 |
if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_SYNC) { |
|
1204 |
aosDbgPrintf("->operation\n"); |
|
1205 |
// invalidate module ID |
|
1206 |
aos.sssp.moduleId = AOS_SSSP_MODULEID_INVALID; |
|
1207 |
// proceed |
|
1208 |
aosDbgPrintf("<<< MSI aborted\n"); |
|
1209 |
_msiOutro(msidata); |
|
1210 |
} |
|
1211 |
#if (AMIROOS_CFG_SSSP_STACK_END == true) |
|
1212 |
// Correct SSSP stage? |
|
1213 |
else if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_4_COMPLETION) { |
|
1214 |
aosDbgPrintf("ok\n"); |
|
1215 |
// ignored |
|
1216 |
} else { |
|
1217 |
aosDbgPrintf("->abort\n"); |
|
1218 |
// initialize abortion |
|
1219 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1220 |
} |
|
1221 |
#else /* (AMIROOS_CFG_SSSP_STACK_END == true) */ |
|
1222 |
// Correct SSSP stage and ID assigned? |
|
1223 |
else if (aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3_3_WAIT4EVENT && |
|
1224 |
aos.sssp.moduleId != AOS_SSSP_MODULEID_INVALID) { |
|
1225 |
aosDbgPrintf("->done\n"); |
|
1226 |
// set the timeout timer so no abort messages are missed |
|
1227 |
chVTSet(&msidata->timeout.timer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &msidata->timeout.eventsource); |
|
1228 |
// proceed to the completion stage |
|
1229 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_COMPLETION; |
|
1230 |
} else { |
|
1231 |
aosDbgPrintf("->abort\n"); |
|
1232 |
// initiate abortion |
|
1233 |
aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_3_4_ABORTION_INIT; |
|
1234 |
} |
|
1235 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END == true) */ |
|
1236 |
} |
|
1237 |
// clear S flags |
|
1238 |
flags &= ~moduleSsspEventflagS(); |
|
1239 |
} |
|
1240 |
// any further flags set? |
|
1241 |
if (flags) { |
|
1242 |
aosDbgPrintf("0x%08X\n", flags); |
|
1243 |
// reassign remaining flags and do not clear event mask |
|
1244 |
msidata->signals.eventlistener->flags |= flags; |
|
1245 |
} else { |
|
1246 |
// clear event |
|
1247 |
*received &= ~(msidata->signals.eventlistener->events); |
|
1248 |
} |
|
1249 |
} |
|
1250 |
/* OTHER EVENT |
|
1251 |
* Any other events may occur as well but are not handled by this function |
|
1252 |
*/ |
|
1253 |
else if (*received != 0){ |
|
1254 |
aosDbgPrintf("%u\tOTHER\t0x%08X\n", chVTGetSystemTime(), *received); |
|
1255 |
// do not clear the event mask |
|
1256 |
} |
|
1257 |
|
|
1258 |
return; |
|
1259 |
} |
|
1260 |
|
|
1261 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
1262 |
|
|
1263 |
#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__) |
|
1264 |
|
|
1265 |
/** |
|
1266 |
* @brief Retreive the offset between local clock and system synchronization signal. |
|
1267 |
* |
|
1268 |
* @return |
|
1269 |
*/ |
|
1270 |
inline float aosSsspGetSyncSkew(void) |
|
1271 |
{ |
|
1272 |
return _syncskew; |
|
1273 |
} |
|
1274 |
|
|
1275 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
|
1276 |
|
|
645 | 1277 |
/** |
646 | 1278 |
* @brief Leave the operation pahse and initiate or acknowledge shutdown. |
647 | 1279 |
* |
... | ... | |
656 | 1288 |
|
657 | 1289 |
// activate PD if this was an active shutdown initiation |
658 | 1290 |
if (active) { |
659 |
apalControlGpioSet(&moduleSsspGpioPD, APAL_GPIO_ON);
|
|
1291 |
apalControlGpioSet(moduleSsspSignalPD(), APAL_GPIO_ON);
|
|
660 | 1292 |
} |
661 | 1293 |
|
662 | 1294 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
... | ... | |
665 | 1297 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
666 | 1298 |
|
667 | 1299 |
// activate S |
668 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
|
|
1300 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON);
|
|
669 | 1301 |
|
670 | 1302 |
// proceed in the shutdown phase |
671 | 1303 |
aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_2; |
... | ... | |
690 | 1322 |
aosThdUSleep(AOS_SSSP_DELAY); |
691 | 1323 |
|
692 | 1324 |
// activate S for one AOS_SSSP_DELAY. |
693 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
|
|
1325 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_ON);
|
|
694 | 1326 |
aosThdUSleep(AOS_SSSP_DELAY); |
695 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF);
|
|
1327 |
apalControlGpioSet(moduleSsspSignalS(), APAL_GPIO_OFF);
|
|
696 | 1328 |
} |
697 | 1329 |
} |
698 | 1330 |
|
... | ... | |
728 | 1360 |
|
729 | 1361 |
// arm the timer once |
730 | 1362 |
if (!chVTIsArmed(&_delayTimer)) { |
731 |
chEvtRegisterMask(&_eventSourceDelay, &_eventListenerDelay, timermask);
|
|
732 |
chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_eventSourceDelay);
|
|
1363 |
chEvtRegisterMask(&_delayEventSource, &_delayEventListener, timermask);
|
|
1364 |
chVtSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_delayEventSource);
|
|
733 | 1365 |
} |
734 | 1366 |
|
735 | 1367 |
// wait for any event to occur (do not apply any filters in order not to miss any events) |
... | ... | |
739 | 1371 |
if (mask & gpiolistener->events) { |
740 | 1372 |
// retreive flags without clearing them |
741 | 1373 |
flags = gpiolistener->flags; |
742 |
apalControlGpioGet(&moduleSsspGpioS, &sstate);
|
|
1374 |
apalControlGpioGet(moduleSsspSignalS(), &sstate);
|
|
743 | 1375 |
if (flags == sflags) { |
744 |
apalControlGpioGet(&moduleSsspGpioS, &sstate);
|
|
1376 |
apalControlGpioGet(moduleSsspSignalS(), &sstate);
|
|
745 | 1377 |
// if this was the end of a pulse |
746 | 1378 |
if (sstate == APAL_GPIO_OFF) { |
747 | 1379 |
// restart the timer |
748 |
chVTReset(&_delayTimer); |
|
749 |
chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_eventSourceDelay); |
|
1380 |
chVtSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_delayEventSource); |
|
750 | 1381 |
// increment the identifier |
751 | 1382 |
++(*identifier); |
752 | 1383 |
} |
753 | 1384 |
} |
754 | 1385 |
} |
755 | 1386 |
// timer event |
756 |
else if (mask & _eventListenerDelay.events) {
|
|
1387 |
else if (mask & _delayEventListener.events) {
|
|
757 | 1388 |
// unregister event |
758 |
chEvtUnregister(&_eventSourceDelay, &_eventListenerDelay);
|
|
1389 |
chEvtUnregister(&_delayEventSource, &_delayEventListener);
|
|
759 | 1390 |
} |
760 | 1391 |
// any further events must be handled externally |
761 | 1392 |
|
... | ... | |
764 | 1395 |
|
765 | 1396 |
#endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */ |
766 | 1397 |
|
767 |
#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__) |
|
768 |
|
|
769 |
/** |
|
770 |
* @brief Retreive the offset between local clock and system synchronization signal. |
|
771 |
* |
|
772 |
* @return |
|
773 |
*/ |
|
774 |
float aosSsspGetSyncSkew(void) |
|
775 |
{ |
|
776 |
return _syncskew; |
|
777 |
} |
|
778 |
|
|
779 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
|
780 |
|
|
781 | 1398 |
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */ |
782 | 1399 |
|
783 | 1400 |
/** @} */ |
Also available in: Unified diff