Revision c218345a core/src/aos_sssp.c

View differences:

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