Revision c218345a core/src/aos_sssp.c
core/src/aos_sssp.c | ||
---|---|---|
32 | 32 |
/* LOCAL DEFINITIONS */ |
33 | 33 |
/******************************************************************************/ |
34 | 34 |
|
35 |
#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__) |
|
36 |
|
|
37 |
/** |
|
38 |
* @brief Weighting factor for smoothing the @p _syncskew value. |
|
39 |
*/ |
|
40 |
#define SYNCSKEW_SMOOTHFACTOR (0.1f / AOS_SYSTEM_TIME_RESOLUTION) |
|
41 |
|
|
42 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
|
43 |
|
|
35 | 44 |
/******************************************************************************/ |
36 | 45 |
/* EXPORTED VARIABLES */ |
37 | 46 |
/******************************************************************************/ |
... | ... | |
45 | 54 |
/******************************************************************************/ |
46 | 55 |
|
47 | 56 |
/** |
57 |
* @brief Pointer to the system uptime. |
|
58 |
*/ |
|
59 |
static aos_timestamp_t* _uptime; |
|
60 |
|
|
61 |
#if (AMIROOS_CFG_SSSP_MASTER == true) || defined(__DOXYGEN__) |
|
62 |
|
|
63 |
/** |
|
64 |
* @brief Timer to drive the S signal for system wide time synchronization during operation phase. |
|
65 |
*/ |
|
66 |
static virtual_timer_t _synctimer; |
|
67 |
|
|
68 |
/** |
|
69 |
* @brief Last uptime of system wide time synchronization. |
|
70 |
*/ |
|
71 |
static aos_timestamp_t _synctime; |
|
72 |
|
|
73 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
74 |
|
|
75 |
#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__) |
|
76 |
|
|
77 |
/** |
|
78 |
* @brief Offset between local clock and system wide synchronization signal. |
|
79 |
*/ |
|
80 |
static float _syncskew; |
|
81 |
|
|
82 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
|
83 |
|
|
84 |
/** |
|
48 | 85 |
* @brief A timer event based delays. |
49 | 86 |
*/ |
50 | 87 |
static virtual_timer_t _delayTimer; |
... | ... | |
63 | 100 |
/* LOCAL FUNCTIONS */ |
64 | 101 |
/******************************************************************************/ |
65 | 102 |
|
103 |
#if (AMIROOS_CFG_SSSP_MASTER != true) || defined(__DOXYGEN__) |
|
104 |
|
|
105 |
/** |
|
106 |
* @brief Callback function for the Sync signal interrupt. |
|
107 |
* |
|
108 |
* @param[in] args Pointer to the GPIO line identifier. |
|
109 |
*/ |
|
110 |
static void _gpioCallbackSSignal(void *args) |
|
111 |
{ |
|
112 |
aosDbgCheck((args != NULL) && (*((ioline_t*)args) != PAL_NOLINE) && (PAL_PAD(*((ioline_t*)args)) < sizeof(eventflags_t) * 8)); |
|
113 |
|
|
114 |
apalControlGpioState_t s; |
|
115 |
aos_timestamp_t t; |
|
116 |
|
|
117 |
chSysLockFromISR(); |
|
118 |
|
|
119 |
// if the system is in operation phase |
|
120 |
if (aos.sssp.stage == AOS_SSSP_STAGE_OPERATION) { |
|
121 |
// read signal S |
|
122 |
apalControlGpioGet(&moduleSsspGpioS, &s); |
|
123 |
// if S was toggled from on to off |
|
124 |
if (s == APAL_GPIO_OFF) { |
|
125 |
// get current uptime |
|
126 |
aosSysGetUptimeX(&t); |
|
127 |
// align the uptime with the synchronization period |
|
128 |
t %= AMIROOS_CFG_SSSP_SYSSYNCPERIOD; |
|
129 |
if (t < AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2) { |
|
130 |
*_uptime -= t; |
|
131 |
#if (AMIROOS_CFG_PROFILE == true) |
|
132 |
_syncskew = ((1.0f - SYNCSKEW_SMOOTHFACTOR) * _syncskew) + (SYNCSKEW_SMOOTHFACTOR * t); |
|
133 |
#endif /* (AMIROOS_CFG_PROFILE == true) */ |
|
134 |
} else { |
|
135 |
t = AMIROOS_CFG_SSSP_SYSSYNCPERIOD - t; |
|
136 |
*_uptime += t; |
|
137 |
#if (AMIROOS_CFG_PROFILE == true) |
|
138 |
_syncskew = ((1.0f - SYNCSKEW_SMOOTHFACTOR) * _syncskew) - (SYNCSKEW_SMOOTHFACTOR * t); |
|
139 |
#endif /* (AMIROOS_CFG_PROFILE == true) */ |
|
140 |
} |
|
141 |
} |
|
142 |
} |
|
143 |
|
|
144 |
// broadcast event |
|
145 |
chEvtBroadcastFlagsI(&aos.events.gpio, AOS_GPIOEVENT_FLAG(PAL_PAD(*((ioline_t*)args)))); |
|
146 |
chSysUnlockFromISR(); |
|
147 |
|
|
148 |
return; |
|
149 |
} |
|
150 |
|
|
151 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) */ |
|
152 |
|
|
153 |
#if (AMIROOS_CFG_SSSP_MASTER == true) || defined (__DOXYGEN__) |
|
154 |
|
|
155 |
/** |
|
156 |
* @brief Periodic system synchronization callback function. |
|
157 |
* @details Toggles the SYS_SYNC signal and reconfigures the system synchronization timer. |
|
158 |
* |
|
159 |
* @param[in] par Unused parameters. |
|
160 |
*/ |
|
161 |
static void _syncTimerCallback(void* par) |
|
162 |
{ |
|
163 |
(void)par; |
|
164 |
|
|
165 |
apalControlGpioState_t state; |
|
166 |
aos_timestamp_t uptime; |
|
167 |
|
|
168 |
chSysLockFromISR(); |
|
169 |
// toggle and read signal S |
|
170 |
apalGpioToggle(moduleSsspGpioS.gpio); |
|
171 |
apalControlGpioGet(&moduleSsspGpioS, &state); |
|
172 |
// if S was toggled from off to on |
|
173 |
if (state == APAL_GPIO_ON) { |
|
174 |
// reconfigure the timer precisely, because the logically falling edge (next interrupt) snychronizes the system time |
|
175 |
_synctime += AMIROOS_CFG_SSSP_SYSSYNCPERIOD; |
|
176 |
aosSysGetUptimeX(&uptime); |
|
177 |
chVTSetI(&_synctimer, chTimeUS2I(_synctime - uptime), _syncTimerCallback, NULL); |
|
178 |
} |
|
179 |
// if S was toggled from on to off |
|
180 |
else /* if (state == APAL_GPIO_OFF) */ { |
|
181 |
// reconfigure the timer (lazy) |
|
182 |
chVTSetI(&_synctimer, chTimeUS2I(AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2), _syncTimerCallback, NULL); |
|
183 |
} |
|
184 |
chSysUnlockFromISR(); |
|
185 |
|
|
186 |
return; |
|
187 |
} |
|
188 |
|
|
189 |
/** |
|
190 |
* @brief Start the timer that toggles S for synchronization of the system. |
|
191 |
* @note Must be called from a locked context. |
|
192 |
*/ |
|
193 |
static inline void _syncTimerStartS(void) |
|
194 |
{ |
|
195 |
chDbgCheckClassS(); |
|
196 |
|
|
197 |
// start synchronization timer |
|
198 |
// The first iteration of the timer is set to the next 'center' of a 'slice'. |
|
199 |
aos_timestamp_t t; |
|
200 |
aosSysGetUptimeX(&t); |
|
201 |
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); |
|
203 |
|
|
204 |
return; |
|
205 |
} |
|
206 |
|
|
207 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
208 |
|
|
66 | 209 |
/** |
67 | 210 |
* @brief General callback function to be used for any local timers. |
68 | 211 |
* |
... | ... | |
153 | 296 |
/** |
154 | 297 |
* @brief Initialize all SSSP related data. |
155 | 298 |
*/ |
156 |
void aosSsspInit(void)
|
|
299 |
void aosSsspInit(aos_timestamp_t* system_uptime)
|
|
157 | 300 |
{ |
301 |
aosDbgCheck(system_uptime != NULL); |
|
302 |
|
|
158 | 303 |
// local variables |
159 | 304 |
apalControlGpioState_t state; |
160 | 305 |
|
... | ... | |
171 | 316 |
aosDbgAssert(state == APAL_GPIO_ON); |
172 | 317 |
apalControlGpioGet(&moduleSsspGpioPD, &state); |
173 | 318 |
aosDbgAssert(state == APAL_GPIO_OFF); |
319 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
|
174 | 320 |
#if (AMIROOS_CFG_SSSP_STACK_END != true) |
175 | 321 |
apalControlGpioGet(&moduleSsspGpioUP, &state); |
176 | 322 |
aosDbgAssert(state == APAL_GPIO_OFF); |
... | ... | |
179 | 325 |
apalControlGpioGet(&moduleSsspGpioDN, &state); |
180 | 326 |
aosDbgAssert(state == APAL_GPIO_OFF); |
181 | 327 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */ |
328 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
182 | 329 |
|
183 | 330 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
184 | 331 |
// module ID is initialized as 'invalid' |
... | ... | |
186 | 333 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
187 | 334 |
|
188 | 335 |
// initialize static variables |
336 |
_uptime = system_uptime; |
|
337 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
338 |
chVTObjectInit(&_synctimer); |
|
339 |
_synctime = 0; |
|
340 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
341 |
#if (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) |
|
342 |
_syncskew = 0.0f; |
|
343 |
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */ |
|
189 | 344 |
chVTObjectInit(&_delayTimer); |
190 | 345 |
chEvtObjectInit(&_eventSourceDelay); |
191 | 346 |
|
347 |
// signal interrupt setup |
|
348 |
palSetLineCallback(moduleSsspGpioPD.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioPD.gpio->line); |
|
349 |
palEnableLineEvent(moduleSsspGpioPD.gpio->line, APAL2CH_EDGE(moduleSsspGpioPD.meta.edge)); |
|
350 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
351 |
palSetLineCallback(moduleSsspGpioS.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioS.gpio->line); |
|
352 |
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
353 |
palSetLineCallback(moduleSsspGpioS.gpio->line, _gpioCallbackSSignal, &moduleSsspGpioS.gpio->line); |
|
354 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
355 |
palEnableLineEvent(moduleSsspGpioS.gpio->line, APAL2CH_EDGE(moduleSsspGpioS.meta.edge)); |
|
356 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
|
357 |
#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)); |
|
360 |
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */ |
|
361 |
#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)); |
|
364 |
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */ |
|
365 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
|
366 |
|
|
192 | 367 |
return; |
193 | 368 |
} |
194 | 369 |
|
195 | 370 |
/** |
196 | 371 |
* @brief Proceed to the next SSSP stage. |
372 |
* @note Calling this function when in operation phase is invalid. |
|
373 |
* The function aosSsspShutdownInit() must be used instead. |
|
197 | 374 |
* |
198 | 375 |
* @param[in] listener An optional listener, in case the system has to wait for a specific event. |
199 | 376 |
* @param[in] flags The relevant flags to wait for (mandatory if a listener is given). |
... | ... | |
331 | 508 |
|
332 | 509 |
/* |
333 | 510 |
* Wait for the S signal to become inactive. |
511 |
* When proceeding to operation phase, the master starts toggling S for synchronization |
|
334 | 512 |
*/ |
335 | 513 |
case AOS_SSSP_STAGE_STARTUP_2_2: |
336 | 514 |
{ |
... | ... | |
344 | 522 |
#if (AMIROOS_CFG_SSSP_MSI == true) |
345 | 523 |
nextstage = AOS_SSSP_STAGE_STARTUP_3; |
346 | 524 |
#else /* (AMIROOS_CFG_SSSP_MSI == true) */ |
525 |
chSysLock(); |
|
526 |
// start the internal uptime aggregation |
|
527 |
aosSysStartUptimeS(); |
|
528 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
529 |
// start toggling S for system synchronization |
|
530 |
_syncTimerStartS(); |
|
531 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
532 |
chSysUnlock(); |
|
347 | 533 |
nextstage = AOS_SSSP_STAGE_OPERATION; |
348 | 534 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
349 | 535 |
} |
... | ... | |
357 | 543 |
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
358 | 544 |
|
359 | 545 |
/* |
546 |
* Invalid operation. |
|
547 |
* Shutdon must be initiatid via the aosSsspShutdownInit() function. |
|
548 |
*/ |
|
549 |
case AOS_SSSP_STAGE_OPERATION: |
|
550 |
{ |
|
551 |
aosDbgAssertMsg(false, "in order to exit operation phase, aosSsspShutdownInit() function must be used"); |
|
552 |
break; |
|
553 |
} |
|
554 |
|
|
555 |
/* |
|
360 | 556 |
* Delay execution by one perion AOS_SSSP_DELAY, deactivate the SYNC signal and proceed. |
361 | 557 |
* NOTE: Actually only the module that initiated the shutdown has to delay execution here. |
362 | 558 |
* For the sake of simlicity though, each module delays execution. |
... | ... | |
446 | 642 |
return status; |
447 | 643 |
} |
448 | 644 |
|
449 |
void aosSsspShutdownInit(void) |
|
645 |
/** |
|
646 |
* @brief Leave the operation pahse and initiate or acknowledge shutdown. |
|
647 |
* |
|
648 |
* @param[in] active Flag, indicating whether the shutdon shall be activeliy initiated (true) or a passive request was received (false). |
|
649 |
*/ |
|
650 |
void aosSsspShutdownInit(bool active) |
|
450 | 651 |
{ |
451 |
// activate S signal
|
|
452 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
|
652 |
aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_OPERATION);
|
|
653 |
|
|
453 | 654 |
// proceed to shutdown phase |
655 |
aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_1; |
|
656 |
|
|
657 |
// activate PD if this was an active shutdown initiation |
|
658 |
if (active) { |
|
659 |
apalControlGpioSet(&moduleSsspGpioPD, APAL_GPIO_ON); |
|
660 |
} |
|
661 |
|
|
662 |
#if (AMIROOS_CFG_SSSP_MASTER == true) |
|
663 |
// stop toggling S |
|
664 |
chVTReset(&_synctimer); |
|
665 |
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
|
666 |
|
|
667 |
// activate S |
|
668 |
apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
|
669 |
|
|
670 |
// proceed in the shutdown phase |
|
454 | 671 |
aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_2; |
455 | 672 |
|
456 | 673 |
return; |
... | ... | |
547 | 764 |
|
548 | 765 |
#endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */ |
549 | 766 |
|
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 |
|
|
550 | 781 |
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */ |
551 | 782 |
|
552 | 783 |
/** @} */ |
Also available in: Unified diff