commit c218345a0ad12a54f704b665ed16c7eef1d7b227
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Thu Oct 31 16:26:02 2019 +0100

    SSSP system synchronization is now handled in aos_sssp.h/.c

diff --git a/core/inc/aos_sssp.h b/core/inc/aos_sssp.h
index 5a729da..be5dc22 100644
--- a/core/inc/aos_sssp.h
+++ b/core/inc/aos_sssp.h
@@ -101,7 +101,7 @@ typedef enum {
   AOS_SSSP_STAGE_STARTUP_3_2  = 0x1320, /**< Identifier of SSSP startup phase stage 3-2.  */
   AOS_SSSP_STAGE_STARTUP_3_3  = 0x1330, /**< Identifier of SSSP startup phase stage 3-3.  */
   AOS_SSSP_STAGE_STARTUP_3_4  = 0x1340, /**< Identifier of SSSP startup phase stage 3-4.  */
-  AOS_SSSP_STAGE_OPERATION    = 0x2000, /**< Identifier of SSSP operation pahse.          */
+  AOS_SSSP_STAGE_OPERATION    = 0x2000, /**< Identifier of SSSP operation phase.          */
   AOS_SSSP_STAGE_SHUTDOWN     = 0x3000, /**< Identifier of SSSP shutdown phase.           */
   AOS_SSSP_STAGE_SHUTDOWN_1   = 0x3100, /**< Identifier of SSSP shutdown phase stage 1.   */
   AOS_SSSP_STAGE_SHUTDOWN_1_1 = 0x3110, /**< Identifier of SSSP shutdown phase stage 1-1. */
@@ -159,13 +159,16 @@ typedef struct {
 #if defined(__cplusplus)
 extern "C" {
 #endif /* defined(__cplusplus) */
-  void aosSsspInit(void);
+  void aosSsspInit(aos_timestamp_t* system_uptime);
   aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, eventmask_t mask, eventmask_t* received);
-  void aosSsspShutdownInit(void);
+  void aosSsspShutdownInit(bool active);
 #if (AMIROOS_CFG_SSSP_SHUTDOWN == true) || defined(__DOXYGEN__)
   void aosSsspShutdownBroadcastIdentifier(unsigned int identifier);
   eventmask_t aosSsspShutdownWaitForIdentifierPulse(event_listener_t* gpiolistener, eventflags_t sflags, eventmask_t timermask, unsigned int* identifier);
 #endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */
+#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
+  float aosSsspGetSyncSkew(void);
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
 #if defined(__cplusplus)
 }
 #endif /* defined(__cplusplus) */
diff --git a/core/inc/aos_system.h b/core/inc/aos_system.h
index c92e781..c71eeb4 100644
--- a/core/inc/aos_system.h
+++ b/core/inc/aos_system.h
@@ -171,9 +171,7 @@ extern "C" {
 #endif /* defined(__cplusplus) */
   void aosSysInit(const char* shellPrompt);
   void aosSysStart(void);
-#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined (__DOXYGEN__)
-  void aosSysStartUptime(void);
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
+  void aosSysStartUptimeS(void);
   void aosSysGetUptimeX(aos_timestamp_t* ut);
 #if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
   void aosSysGetDateTime(struct tm* dt);
diff --git a/core/src/aos_main.cpp b/core/src/aos_main.cpp
index 5132c9b..9d74144 100644
--- a/core/src/aos_main.cpp
+++ b/core/src/aos_main.cpp
@@ -274,12 +274,14 @@ int main(void)
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
   {
     eventflags_t flagsmask = AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK | MODULE_SSSP_EVENTFLAG_PD | MODULE_SSSP_EVENTFLAG_S;
+#if (AMIROOS_CFG_SSSP_MSI == true)
 #if (AMIROOS_CFG_SSSP_STACK_START != true)
     flagsmask |= MODULE_SSSP_EVENTFLAG_DN;
 #endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
 #if (AMIROOS_CFG_SSSP_STACK_END != true)
     flagsmask |= MODULE_SSSP_EVENTFLAG_UP;
 #endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
+#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
     chEvtRegisterMaskWithFlags(&aos.events.gpio, &_eventListenerGPIO, EVENTMASK_GPIO, flagsmask);
   }
 #else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
@@ -600,17 +602,19 @@ int main(void)
 #endif /* (AMIROOS_CFG_SSSP_MSI == true) */
   }
 
-  // start the internal system uptime counter
-  aosSysStartUptime();
-
   /*
-   * There must be no delays at this point, thus no hook allowed.
+   * There must be no delay at this point, thus no hook allowed.
    */
 
 #if (AMIROOS_CFG_SSSP_MSI == true)
 
-  //TODO
+  //TODO: MSI
 
+#if (HAL_USE_RTC == TRUE)
+
+  //TODO: Calendar synchronization
+
+#endif /* (HAL_USE_RTC == TRUE) */
 #endif /* (AMIROOS_CFG_SSSP_MSI == true) */
 
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
@@ -634,6 +638,21 @@ int main(void)
    * ##########################################################################
    */
 
+#if (AMIROOS_CFG_SSSP_ENABLE == true)
+  /* ignore all SSSP signal events, except for PD and configured events */
+  eventflags = MODULE_SSSP_EVENTFLAG_S;
+#if (AMIROOS_CFG_SSSP_MSI == true)
+#if (AMIROOS_CFG_SSSP_STACK_START != true)
+  eventflags |= MODULE_SSSP_EVENTFLAG_DN;
+#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
+#if (AMIROOS_CFG_SSSP_STACK_END != true)
+  eventflags |= MODULE_SSSP_EVENTFLAG_UP;
+#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
+#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
+  eventflags &= ~((eventflags_t)AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK);
+  _eventListenerGPIO.wflags &= ~eventflags;
+#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
+
   // sleep until a shutdown event is received
   while (shutdown == AOS_SHUTDOWN_NONE) {
     // wait for an event
@@ -659,7 +678,7 @@ int main(void)
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
         // PD event
         if (eventflags & MODULE_SSSP_EVENTFLAG_PD) {
-          aosSsspShutdownInit();
+          aosSsspShutdownInit(false);
           shutdown = AOS_SHUTDOWN_PASSIVE;
         }
         // all other events
@@ -716,6 +735,18 @@ int main(void)
         break;
     }
 
+#if (AMIROOS_CFG_SSSP_ENABLE == true)
+
+    /*
+     * Re-anable the S signal GPIO event.
+     * Note that events for the optional signals UP and DN are not enabled as they are not utilized during SSSP shutdown phase.
+     */
+    chSysLock();
+    _eventListenerGPIO.wflags |= MODULE_SSSP_EVENTFLAG_S;
+    chSysUnlock();
+
+#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
+
 #if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2)
 #if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS)
     AMIROOS_CFG_MAIN_LOOP_HOOK_2(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS);
diff --git a/core/src/aos_sssp.c b/core/src/aos_sssp.c
index c058862..8f82143 100644
--- a/core/src/aos_sssp.c
+++ b/core/src/aos_sssp.c
@@ -32,6 +32,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* LOCAL DEFINITIONS                                                          */
 /******************************************************************************/
 
+#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Weighting factor for smoothing the @p _syncskew value.
+ */
+#define SYNCSKEW_SMOOTHFACTOR                   (0.1f / AOS_SYSTEM_TIME_RESOLUTION)
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
+
 /******************************************************************************/
 /* EXPORTED VARIABLES                                                         */
 /******************************************************************************/
@@ -45,6 +54,34 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /******************************************************************************/
 
 /**
+ * @brief   Pointer to the system uptime.
+ */
+static aos_timestamp_t* _uptime;
+
+#if (AMIROOS_CFG_SSSP_MASTER == true) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Timer to drive the S signal for system wide time synchronization during operation phase.
+ */
+static virtual_timer_t _synctimer;
+
+/**
+ * @brief   Last uptime of system wide time synchronization.
+ */
+static aos_timestamp_t _synctime;
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+
+#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Offset between local clock and system wide synchronization signal.
+ */
+static float _syncskew;
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
+
+/**
  * @brief   A timer event based delays.
  */
 static virtual_timer_t _delayTimer;
@@ -63,6 +100,112 @@ static event_listener_t _eventListenerDelay;
 /* LOCAL FUNCTIONS                                                            */
 /******************************************************************************/
 
+#if (AMIROOS_CFG_SSSP_MASTER != true) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Callback function for the Sync signal interrupt.
+ *
+ * @param[in] args   Pointer to the GPIO line identifier.
+ */
+static void _gpioCallbackSSignal(void *args)
+{
+  aosDbgCheck((args != NULL) && (*((ioline_t*)args) != PAL_NOLINE) && (PAL_PAD(*((ioline_t*)args)) < sizeof(eventflags_t) * 8));
+
+  apalControlGpioState_t s;
+  aos_timestamp_t t;
+
+  chSysLockFromISR();
+
+  // if the system is in operation phase
+  if (aos.sssp.stage == AOS_SSSP_STAGE_OPERATION) {
+    // read signal S
+    apalControlGpioGet(&moduleSsspGpioS, &s);
+    // if S was toggled from on to off
+    if (s == APAL_GPIO_OFF) {
+      // get current uptime
+      aosSysGetUptimeX(&t);
+      // align the uptime with the synchronization period
+      t %= AMIROOS_CFG_SSSP_SYSSYNCPERIOD;
+      if (t < AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2) {
+        *_uptime -= t;
+#if (AMIROOS_CFG_PROFILE == true)
+        _syncskew = ((1.0f - SYNCSKEW_SMOOTHFACTOR) * _syncskew) + (SYNCSKEW_SMOOTHFACTOR * t);
+#endif /* (AMIROOS_CFG_PROFILE == true) */
+      } else {
+        t = AMIROOS_CFG_SSSP_SYSSYNCPERIOD - t;
+        *_uptime += t;
+#if (AMIROOS_CFG_PROFILE == true)
+        _syncskew = ((1.0f - SYNCSKEW_SMOOTHFACTOR) * _syncskew) - (SYNCSKEW_SMOOTHFACTOR * t);
+#endif /* (AMIROOS_CFG_PROFILE == true) */
+      }
+    }
+  }
+
+  // broadcast event
+  chEvtBroadcastFlagsI(&aos.events.gpio, AOS_GPIOEVENT_FLAG(PAL_PAD(*((ioline_t*)args))));
+  chSysUnlockFromISR();
+
+  return;
+}
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) */
+
+#if (AMIROOS_CFG_SSSP_MASTER == true) || defined (__DOXYGEN__)
+
+/**
+ * @brief   Periodic system synchronization callback function.
+ * @details Toggles the SYS_SYNC signal and reconfigures the system synchronization timer.
+ *
+ * @param[in] par   Unused parameters.
+ */
+static void _syncTimerCallback(void* par)
+{
+  (void)par;
+
+  apalControlGpioState_t state;
+  aos_timestamp_t uptime;
+
+  chSysLockFromISR();
+  // toggle and read signal S
+  apalGpioToggle(moduleSsspGpioS.gpio);
+  apalControlGpioGet(&moduleSsspGpioS, &state);
+  // if S was toggled from off to on
+  if (state == APAL_GPIO_ON) {
+    // reconfigure the timer precisely, because the logically falling edge (next interrupt) snychronizes the system time
+    _synctime += AMIROOS_CFG_SSSP_SYSSYNCPERIOD;
+    aosSysGetUptimeX(&uptime);
+    chVTSetI(&_synctimer, chTimeUS2I(_synctime - uptime), _syncTimerCallback, NULL);
+  }
+  // if S was toggled from on to off
+  else /* if (state == APAL_GPIO_OFF) */ {
+    // reconfigure the timer (lazy)
+    chVTSetI(&_synctimer, chTimeUS2I(AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2), _syncTimerCallback, NULL);
+  }
+  chSysUnlockFromISR();
+
+  return;
+}
+
+/**
+ * @brief   Start the timer that toggles S for synchronization of the system.
+ * @note    Must be called from a locked context.
+ */
+static inline void _syncTimerStartS(void)
+{
+  chDbgCheckClassS();
+
+  // start synchronization timer
+  // The first iteration of the timer is set to the next 'center' of a 'slice'.
+  aos_timestamp_t t;
+  aosSysGetUptimeX(&t);
+  t = AMIROOS_CFG_SSSP_SYSSYNCPERIOD - (t % AMIROOS_CFG_SSSP_SYSSYNCPERIOD);
+  chVTSetI(&_synctimer, chTimeUS2I((t > (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) ? (t - (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) : (t + (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2))), _syncTimerCallback, NULL);
+
+  return;
+}
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+
 /**
  * @brief   General callback function to be used for any local timers.
  *
@@ -153,8 +296,10 @@ static inline aos_status_t _delay(uint32_t dt, eventmask_t mask, bool arm_timer,
 /**
  * @brief   Initialize all SSSP related data.
  */
-void aosSsspInit(void)
+void aosSsspInit(aos_timestamp_t* system_uptime)
 {
+  aosDbgCheck(system_uptime != NULL);
+
   // local variables
   apalControlGpioState_t state;
 
@@ -171,6 +316,7 @@ void aosSsspInit(void)
   aosDbgAssert(state == APAL_GPIO_ON);
   apalControlGpioGet(&moduleSsspGpioPD, &state);
   aosDbgAssert(state == APAL_GPIO_OFF);
+#if (AMIROOS_CFG_SSSP_MSI == true)
 #if (AMIROOS_CFG_SSSP_STACK_END != true)
   apalControlGpioGet(&moduleSsspGpioUP, &state);
   aosDbgAssert(state == APAL_GPIO_OFF);
@@ -179,6 +325,7 @@ void aosSsspInit(void)
   apalControlGpioGet(&moduleSsspGpioDN, &state);
   aosDbgAssert(state == APAL_GPIO_OFF);
 #endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
+#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
 
 #if (AMIROOS_CFG_SSSP_MSI == true)
   // module ID is initialized as 'invalid'
@@ -186,14 +333,44 @@ void aosSsspInit(void)
 #endif /* (AMIROOS_CFG_SSSP_MSI == true) */
 
   // initialize static variables
+  _uptime = system_uptime;
+#if (AMIROOS_CFG_SSSP_MASTER == true)
+  chVTObjectInit(&_synctimer);
+  _synctime = 0;
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+#if (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)
+  _syncskew = 0.0f;
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
   chVTObjectInit(&_delayTimer);
   chEvtObjectInit(&_eventSourceDelay);
 
+  // signal interrupt setup
+  palSetLineCallback(moduleSsspGpioPD.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioPD.gpio->line);
+  palEnableLineEvent(moduleSsspGpioPD.gpio->line, APAL2CH_EDGE(moduleSsspGpioPD.meta.edge));
+#if (AMIROOS_CFG_SSSP_MASTER == true)
+  palSetLineCallback(moduleSsspGpioS.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioS.gpio->line);
+#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
+  palSetLineCallback(moduleSsspGpioS.gpio->line, _gpioCallbackSSignal, &moduleSsspGpioS.gpio->line);
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+  palEnableLineEvent(moduleSsspGpioS.gpio->line, APAL2CH_EDGE(moduleSsspGpioS.meta.edge));
+#if (AMIROOS_CFG_SSSP_MSI == true)
+#if (AMIROOS_CFG_SSSP_STACK_START != true)
+  palSetLineCallback(moduleSsspGpioDN.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioDN.gpio->line);
+  palEnableLineEvent(moduleSsspGpioDN.gpio->line, APAL2CH_EDGE(moduleSsspGpioDN.meta.edge));
+#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
+#if (AMIROOS_CFG_SSSP_STACK_END != true)
+  palSetLineCallback(moduleSsspGpioUP.gpio->line, aosSysGetStdGpioCallback(), &moduleSsspGpioUP.gpio->line);
+  palEnableLineEvent(moduleSsspGpioUP.gpio->line, APAL2CH_EDGE(moduleSsspGpioUP.meta.edge));
+#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
+#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
+
   return;
 }
 
 /**
  * @brief   Proceed to the next SSSP stage.
+ * @note    Calling this function when in operation phase is invalid.
+ *          The function aosSsspShutdownInit() must be used instead.
  *
  * @param[in]   listener  An optional listener, in case the system has to wait for a specific event.
  * @param[in]   flags     The relevant flags to wait for (mandatory if a listener is given).
@@ -331,6 +508,7 @@ aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, even
 
     /*
      * Wait for the S signal to become inactive.
+     * When proceeding to operation phase, the master starts toggling S for synchronization
      */
     case AOS_SSSP_STAGE_STARTUP_2_2:
     {
@@ -344,6 +522,14 @@ aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, even
 #if (AMIROOS_CFG_SSSP_MSI == true)
         nextstage = AOS_SSSP_STAGE_STARTUP_3;
 #else /* (AMIROOS_CFG_SSSP_MSI == true) */
+        chSysLock();
+        // start the internal uptime aggregation
+        aosSysStartUptimeS();
+#if (AMIROOS_CFG_SSSP_MASTER == true)
+        // start toggling S for system synchronization
+        _syncTimerStartS();
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+        chSysUnlock();
         nextstage = AOS_SSSP_STAGE_OPERATION;
 #endif /* (AMIROOS_CFG_SSSP_MSI == true) */
       }
@@ -357,6 +543,16 @@ aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, even
 #endif /* (AMIROOS_CFG_SSSP_MSI == true) */
 
     /*
+     * Invalid operation.
+     * Shutdon must be initiatid via the aosSsspShutdownInit() function.
+     */
+    case AOS_SSSP_STAGE_OPERATION:
+    {
+      aosDbgAssertMsg(false, "in order to exit operation phase, aosSsspShutdownInit() function must be used");
+      break;
+    }
+
+    /*
      * Delay execution by one perion AOS_SSSP_DELAY, deactivate the SYNC signal and proceed.
      * NOTE: Actually only the module that initiated the shutdown has to delay execution here.
      *       For the sake of simlicity though, each module delays execution.
@@ -446,11 +642,32 @@ aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, even
   return status;
 }
 
-void aosSsspShutdownInit(void)
+/**
+ * @brief   Leave the operation pahse and initiate or acknowledge shutdown.
+ *
+ * @param[in] active  Flag, indicating whether the shutdon shall be activeliy initiated (true) or a passive request was received (false).
+ */
+void aosSsspShutdownInit(bool active)
 {
-  // activate S signal
-  apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
+  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_OPERATION);
+
   // proceed to shutdown phase
+  aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_1;
+
+  // activate PD if this was an active shutdown initiation
+  if (active) {
+    apalControlGpioSet(&moduleSsspGpioPD, APAL_GPIO_ON);
+  }
+
+#if (AMIROOS_CFG_SSSP_MASTER == true)
+  // stop toggling S
+  chVTReset(&_synctimer);
+#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
+
+  // activate S
+  apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
+
+  // proceed in the shutdown phase
   aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_2;
 
   return;
@@ -547,6 +764,20 @@ eventmask_t aosSsspShutdownWaitForIdentifierPulse(event_listener_t* gpiolistener
 
 #endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */
 
+#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
+
+/**
+ * @brief   Retreive the offset between local clock and system synchronization signal.
+ *
+ * @return
+ */
+float aosSsspGetSyncSkew(void)
+{
+  return _syncskew;
+}
+
+#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
+
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
 
 /** @} */
diff --git a/core/src/aos_system.c b/core/src/aos_system.c
index 6578a9f..89b59e1 100644
--- a/core/src/aos_system.c
+++ b/core/src/aos_system.c
@@ -55,15 +55,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #define SYSTEM_INFO_NAMEWIDTH         14
 
-#if ((AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
-
-/**
- * @brief   Weighting factor for the low-pass filter used for calculating the @p _syssyncskew value.
- */
-#define SYSTEM_SYSSYNCSKEW_LPFACTOR   (0.1f / AOS_SYSTEM_TIME_RESOLUTION)
-
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
-
 /******************************************************************************/
 /* EXPORTED VARIABLES                                                         */
 /******************************************************************************/
@@ -108,31 +99,6 @@ static aos_timestamp_t _uptime;
  */
 static systime_t _synctime;
 
-#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
-#if (AMIROOS_CFG_SSSP_MASTER == true) || defined(__DOXYGEN__)
-
-/**
- * @brief   Timer to drive the SYS_SYNC signal for system wide time synchronization according to SSSP.
- */
-static virtual_timer_t _syssynctimer;
-
-/**
- * @brief   Last uptime of system wide time synchronization.
- */
-static aos_timestamp_t _syssynctime;
-
-#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
-
-#if ((AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)) || defined(__DOXYGEN__)
-
-/**
- * @brief   Offset between local clock and system wide synchronization signal.
- */
-static float _syssyncskew;
-
-#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
-
 #if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
 
 /**
@@ -536,7 +502,7 @@ static int _shellcmd_infocb(BaseSequentialStream* stream, int argc, char* argv[]
   chprintf(stream, "%10u milliseconds\n", (uint16_t)(uptime % MICROSECONDS_PER_SECOND / MICROSECONDS_PER_MILLISECOND));
   chprintf(stream, "%10u microseconds\n", (uint16_t)(uptime % MICROSECONDS_PER_MILLISECOND / MICROSECONDS_PER_MICROSECOND));
 #if (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)
-  chprintf(stream, "SSSP synchronization offset: %.3fus per %uus\n", (double)_syssyncskew, AMIROOS_CFG_SSSP_SYSSYNCPERIOD);
+  chprintf(stream, "SSSP synchronization offset: %.3fus per %uus\n", (double)aosSsspGetSyncSkew(), AMIROOS_CFG_SSSP_SYSSYNCPERIOD);
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
   _printSystemInfoSeparator(stream, '=', SYSTEM_INFO_WIDTH);
 
@@ -694,54 +660,6 @@ static void _gpioCallback(void* args)
 }
 #pragma GCC diagnostic pop
 
-#if ((AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true)) || defined(__DOXYGEN__)
-
-/**
- * @brief   Callback function for the Sync signal interrupt.
- *
- * @param[in] args   Pointer to the GPIO line identifier.
- */
-static void _signalSyncCallback(void *args)
-{
-  aosDbgCheck((args != NULL) && (*((ioline_t*)args) != PAL_NOLINE) && (PAL_PAD(*((ioline_t*)args)) < sizeof(eventflags_t) * 8));
-
-  apalControlGpioState_t state;
-  aos_timestamp_t uptime;
-
-  chSysLockFromISR();
-
-  // if the system is in operation phase
-  if (aos.sssp.stage == AOS_SSSP_STAGE_OPERATION) {
-    // read signal S
-    apalControlGpioGet(&moduleSsspGpioS, &state);
-    // if S was toggled from on to off
-    if (state == APAL_GPIO_OFF) {
-      // get current uptime
-      aosSysGetUptimeX(&uptime);
-      // align the uptime with the synchronization period
-      if (uptime % AMIROOS_CFG_SSSP_SYSSYNCPERIOD < AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2) {
-        _uptime -= uptime % AMIROOS_CFG_SSSP_SYSSYNCPERIOD;
-#if (AMIROOS_CFG_PROFILE == true)
-        _syssyncskew = ((1.0f - SYSTEM_SYSSYNCSKEW_LPFACTOR) * _syssyncskew) + (SYSTEM_SYSSYNCSKEW_LPFACTOR * (uptime % AMIROOS_CFG_SSSP_SYSSYNCPERIOD));
-#endif /* (AMIROOS_CFG_PROFILE == true) */
-      } else {
-        _uptime += AMIROOS_CFG_SSSP_SYSSYNCPERIOD - (uptime % AMIROOS_CFG_SSSP_SYSSYNCPERIOD);
-#if (AMIROOS_CFG_PROFILE == true)
-        _syssyncskew = ((1.0f - SYSTEM_SYSSYNCSKEW_LPFACTOR) * _syssyncskew) - (SYSTEM_SYSSYNCSKEW_LPFACTOR * (AMIROOS_CFG_SSSP_SYSSYNCPERIOD - (uptime % AMIROOS_CFG_SSSP_SYSSYNCPERIOD)));
-#endif /* (AMIROOS_CFG_PROFILE == true) */
-      }
-    }
-  }
-
-  // broadcast event
-  chEvtBroadcastFlagsI(&aos.events.gpio, AOS_GPIOEVENT_FLAG(PAL_PAD(*((ioline_t*)args))));
-  chSysUnlockFromISR();
-
-  return;
-}
-
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER != true) */
-
 /**
  * @brief   Callback function for the uptime accumulation timer.
  *
@@ -764,44 +682,6 @@ static void _uptimeCallback(void* par)
   return;
 }
 
-#if ((AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER == true)) || defined (__DOXYGEN__)
-
-/**
- * @brief   Periodic system synchronization callback function.
- * @details Toggles the SYS_SYNC signal and reconfigures the system synchronization timer.
- *
- * @param[in] par   Unused parameters.
- */
-static void _sysSyncTimerCallback(void* par)
-{
-  (void)par;
-
-  apalControlGpioState_t state;
-  aos_timestamp_t uptime;
-
-  chSysLockFromISR();
-  // toggle and read signal S
-  apalGpioToggle(moduleSsspGpioS.gpio);
-  apalControlGpioGet(&moduleSsspGpioS, &state);
-  // if S was toggled from off to on
-  if (state == APAL_GPIO_ON) {
-    // reconfigure the timer precisely, because the logically falling edge (next interrupt) snychronizes the system time
-    _syssynctime += AMIROOS_CFG_SSSP_SYSSYNCPERIOD;
-    aosSysGetUptimeX(&uptime);
-    chVTSetI(&_syssynctimer, chTimeUS2I(_syssynctime - uptime), _sysSyncTimerCallback, NULL);
-  }
-  // if S was toggled from on to off
-  else /* if (state == APAL_GPIO_OFF) */ {
-    // reconfigure the timer (lazy)
-    chVTSetI(&_syssynctimer, chTimeUS2I(AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2), _sysSyncTimerCallback, NULL);
-  }
-  chSysUnlockFromISR();
-
-  return;
-}
-
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER == true) */
-
 /**
  * @brief   Retreive the number of active threads.
  *
@@ -835,27 +715,19 @@ void aosSysInit(const char* shellPrompt)
   chThdSetPriority(AOS_THD_CTRLPRIO);
 
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
-  aosSsspInit();
+  aosSsspInit(&_uptime);
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
 
   /* set local variables */
   chVTObjectInit(&_systimer);
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
+  // uptime counter is started when SSSP proceeds to operation phase
   _synctime = 0;
   _uptime = 0;
-#if (AMIROOS_CFG_SSSP_MASTER == true)
-  chVTObjectInit(&_syssynctimer);
-  _syssynctime = 0;
-#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
-#if (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true)
-  _syssyncskew = 0.0f;
-#endif /* (AMIROOS_CFG_SSSP_MASTER != true) && (AMIROOS_CFG_PROFILE == true) */
 #else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
   // start the uptime counter
   chSysLock();
-  _synctime = chVTGetSystemTimeX();
-  _uptime = 0;
-  chVTSetI(&_systimer, SYSTIMER_PERIOD, &_uptimeCallback, NULL);
+  aosSysStartUptimeS();
   chSysUnlock();
 #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
 
@@ -864,32 +736,6 @@ void aosSysInit(const char* shellPrompt)
   chEvtObjectInit(&aos.events.gpio);
   chEvtObjectInit(&aos.events.os);
 
-#if (AMIROOS_CFG_SSSP_ENABLE == true)
-
-  /* SSSP signal interrupt setup */
-  // PD signal
-  palSetLineCallback(moduleSsspGpioPD.gpio->line, _gpioCallback, &moduleSsspGpioPD.gpio->line);
-  palEnableLineEvent(moduleSsspGpioPD.gpio->line, APAL2CH_EDGE(moduleSsspGpioPD.meta.edge));
-  // S signal
-#if (AMIROOS_CFG_SSSP_MASTER == true)
-  palSetLineCallback(moduleSsspGpioS.gpio->line, _gpioCallback, &moduleSsspGpioS.gpio->line);
-#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
-  palSetLineCallback(moduleSsspGpioS.gpio->line, _signalSyncCallback, &moduleSsspGpioS.gpio->line);
-#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
-  palEnableLineEvent(moduleSsspGpioS.gpio->line, APAL2CH_EDGE(moduleSsspGpioS.meta.edge));
-#if (AMIROOS_CFG_SSSP_STACK_START != true)
-  // DN signal
-  palSetLineCallback(moduleSsspGpioDN.gpio->line, _gpioCallback, &moduleSsspGpioDN.gpio->line);
-  palEnableLineEvent(moduleSsspGpioDN.gpio->line, APAL2CH_EDGE(moduleSsspGpioDN.meta.edge));
-#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
-#if (AMIROOS_CFG_SSSP_STACK_END != true)
-  // UP signal
-  palSetLineCallback(moduleSsspGpioUP.gpio->line, _gpioCallback, &moduleSsspGpioUP.gpio->line);
-  palEnableLineEvent(moduleSsspGpioUP.gpio->line, APAL2CH_EDGE(moduleSsspGpioUP.meta.edge));
-#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
-
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
-
 #if (AMIROOS_CFG_SHELL_ENABLE == true)
 
   /* init shell */
@@ -908,6 +754,11 @@ void aosSysInit(const char* shellPrompt)
   aosShellAddCommand(&aos.shell, &_shellcmd_kerneltest);
 #endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */
 
+#else /* (AMIROOS_CFG_SHELL_ENABLE == true) */
+
+  // suppress unused variable warnings
+  (void)shellPrompt;
+
 #endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
 
   return;
@@ -918,19 +769,6 @@ void aosSysInit(const char* shellPrompt)
  */
 void aosSysStart(void)
 {
-#if (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_MASTER == true)
-  {
-    chSysLock();
-    // start the system synchronization counter
-    // The first iteration of the timer is set to the next 'center' of a 'slice'.
-    aos_timestamp_t t;
-    aosSysGetUptimeX(&t);
-    t = AMIROOS_CFG_SSSP_SYSSYNCPERIOD - (t % AMIROOS_CFG_SSSP_SYSSYNCPERIOD);
-    chVTSetI(&_syssynctimer, chTimeUS2I((t > (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) ? (t - (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2)) : (t + (AMIROOS_CFG_SSSP_SYSSYNCPERIOD / 2))), _sysSyncTimerCallback, NULL);
-    chSysUnlock();
-  }
-#endif /* (AMIROOS_CFG_SSSP_MASTER == true) && (AMIROOS_CFG_SSSP_ENABLE == true) */
-
   // print system information;
   _printSystemInfo((BaseSequentialStream*)&aos.iostream);
   aosprintf("\n");
@@ -947,27 +785,22 @@ void aosSysStart(void)
   return;
 }
 
-#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
-
 /**
  * @brief   Start the system uptime measurement.
+ * @note    Must be called from a locked context.
  */
-void aosSysStartUptime(void)
+void aosSysStartUptimeS(void)
 {
-  chSysLock();
+  chDbgCheckClassS();
 
-  // start the uptime counter
+  // start the uptime aggregation counter
   _synctime = chVTGetSystemTimeX();
   _uptime = 0;
   chVTSetI(&_systimer, SYSTIMER_PERIOD, &_uptimeCallback, NULL);
 
-  chSysUnlock();
-
   return;
 }
 
-#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
-
 /**
  * @brief   Retrieves the system uptime.
  *
@@ -1031,17 +864,9 @@ void aosSysShutdownInit(aos_shutdown_t shutdown)
 
 #if (AMIROOS_CFG_SSSP_ENABLE == true)
 
-#if (AMIROOS_CFG_SSSP_MASTER == true)
-  // deactivate the system synchronization timer
-  chVTReset(&_syssynctimer);
-  // activate SSSP S signal in case the synchronization timer had it deactivated.
-  apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON);
-#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
-
   // activate the PD signal only if this module initiated the shutdown
   if (shutdown != AOS_SHUTDOWN_PASSIVE) {
-    apalControlGpioSet(&moduleSsspGpioPD, APAL_GPIO_ON);
-    aosSsspShutdownInit();
+    aosSsspShutdownInit(true);
   }
 
   switch (shutdown) {
