Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 1678f270

History | View | Annotate | Download (44.8 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
/**
20
 * @file    aos_main.cpp
21
 * @brief   Main function.
22
 * @details Main function with SSSP and initialization,
23
 *          extendable via hooks.
24
 *
25
 * @addtogroup aos_system
26
 * @{
27
 */
28

    
29
#include <amiroos.h>
30
#include <module.h>
31

    
32
/*
33
 * hook to add further includes
34
 */
35
#if defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER)
36
#include AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER
37
#endif
38

    
39
/**
40
 * @brief   Event mask to identify I/O events.
41
 */
42
#define IOEVENT_MASK                            EVENT_MASK(0)
43

    
44
/**
45
 * @brief   Event mask to identify OS events.
46
 */
47
#define OSEVENT_MASK                            EVENT_MASK(1)
48

    
49
/**
50
 * @brief   Event mask to idetify CAN events.
51
 */
52
#define CANEVENT_MASK                           EVENT_MASK(2)
53

    
54
/**
55
 * @brief   Event mask to idetify timeout events.
56
 */
57
#define TIMEOUTEVENT_MASK                       EVENT_MASK(3)
58

    
59
/**
60
 * @brief   Event mask to idetify signal delay events.
61
 */
62
#define DELAYEVENT_MASK                         EVENT_MASK(4)
63

    
64
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
65

    
66
/**
67
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
68
 */
69
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
70

    
71
/**
72
 * @brief   CAN message identifier for transmitting module IDs during the SSSP stack initialization sequence.
73
 */
74
#define SSSP_STACKINIT_CANMSGID_MODULEID        0x002
75

    
76
/**
77
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
78
 */
79
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
80

    
81
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
82

    
83
/**
84
 * @brief   Default shutdown mode if SSSP is unavailable.
85
 */
86
#define AOS_SHUTDOWN_DEFAULT                    AOS_SHUTDOWN_DEEPSLEEP
87

    
88
#endif /* AMIROOS_CFG_SSSP_ENABLE */
89

    
90
/**
91
 * @brief   CAN message identifier for calender synchronization message.
92
 */
93
#define CALENDERSYNC_CANMSGID                   0x004
94

    
95
/**
96
 * @brief   Listener object for I/O events.
97
 */
98
static event_listener_t _eventListenerIO;
99

    
100
/**
101
 * @brief   Listener object for OS events.
102
 */
103
static event_listener_t _eventListenerOS;
104

    
105
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
106
/**
107
 * @brief   I/O channel for the programmer interface.
108
 */
109
static AosIOChannel _stdiochannel;
110

    
111
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
112
/**
113
 * @brief   I/O shell channel for the programmer interface.
114
 */
115
static AosShellChannel _stdshellchannel;
116
#endif /* AMIROOS_CFG_SHELL_ENABLE == true */
117
#endif /* defined(MODULE_HAL_PROGIF) */
118

    
119
/*
120
 * hook to add further static variables
121
 */
122
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
123
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
124
#endif
125

    
126
/**
127
 * @brief   Prints an error message about an unexpected event.
128
 *
129
 * @param[in] mask    The event mask.
130
 * @param[in] flags   The event flags.
131
 */
132
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
133
{
134
#if (AMIROOS_CFG_DBG == true)
135
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
136
#else
137
  (void)(mask);
138
  (void)(flags);
139
#endif
140
  return;
141
}
142

    
143
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
144
/**
145
 * @brief   Callback function to be used during SSSP stack initialization sequence.
146
 *
147
 * @param[in] par   A pointer to an @p event_source_t to be fired.
148
 */
149
static void _ssspTimerCallback(void* par)
150
{
151
  aosDbgCheck(par != NULL);
152

    
153
  chSysLockFromISR();
154
  chEvtBroadcastI((event_source_t*)par);
155
  chSysUnlockFromISR();
156

    
157
  return;
158
}
159
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
160

    
161
/**
162
 * @brief   Helper function to serialize data.
163
 *
164
 * @param[out]  dst   Pointer to the output buffer.
165
 * @param[in]   src   Data to be serialized.
166
 * @param[in]   n     Number of bytes to serialize.
167
 */
168
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
169
{
170
  aosDbgCheck(dst != NULL);
171
  aosDbgCheck(n > 0 && n <= 8);
172

    
173
  for (uint8_t byte = 0; byte < n; ++byte) {
174
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
175
  }
176

    
177
  return;
178
}
179

    
180
/**
181
 * @brief   Helper function to deserialize data.
182
 *
183
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
184
 * @param[in] n     Number of bytes to deserialize.
185
 *
186
 * @return    The deserialized 32 bit data.
187
 */
188
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
189
{
190
  aosDbgCheck(src != NULL);
191
  aosDbgCheck(n > 0 && n <= 8);
192

    
193
  uint64_t result = 0;
194
  for (uint8_t byte = 0; byte < n; ++byte) {
195
    result |= ((uint64_t)src[byte]) << (byte * 8);
196
  }
197

    
198
  return result;
199
}
200

    
201
/**
202
 * @brief   Converter function to encode a TM value to a single unsigned 64 bit integer.
203
 *
204
 * @details Contents of the TM struct are mapped as follows:
205
 *            bits  |63     62|61      53|52    50|49         26|25     22|21     17|16     12|11      6|5       0|
206
 *            #bits |       2 |        9 |      3 |          24 |       4 |       5 |       5 |       6 |       6 |
207
 *            value |   isdst |     yday |   wday |        year |     mon |    mday |    hour |     min |     sec |
208
 *            range | special | [0, 365] | [0, 6] | [1900, ...] | [0, 11] | [1, 31] | [0, 23] | [0, 59] | [0, 61] |
209
 *          The Daylight Saving Time Flag (isdsst) is encoded as follows:
210
 *            DST not in effect         -> 0
211
 *            DST in effect             -> 1
212
 *            no information available  -> 2
213
 *
214
 * @param[in] src   Pointer to the TM struct to encode.
215
 *
216
 * @return  An unsigned 64 bit integer, which holds the encoded time value.
217
 */
218
inline uint64_t _TM2U64(struct tm* src)
219
{
220
  aosDbgCheck(src != NULL);
221

    
222
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
223
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
224
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
225
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
226
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
227
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
228
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
229
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
230
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
231
}
232

    
233
/**
234
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
235
 *
236
 * @details For information on the encoding, please refer to @p _TM2U64 function.
237
 *
238
 * @param[out] dst  The TM struct to fill with the decoded values.
239
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
240
 */
241
inline void _U642TM(struct tm* dst, const uint64_t src)
242
{
243
  aosDbgCheck(dst != NULL);
244

    
245
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
246
  dst->tm_min  = (src >> 6)  & 0x0000003F;
247
  dst->tm_hour = (src >> 12) & 0x0000001F;
248
  dst->tm_mday = (src >> 17) & 0x0000001F;
249
  dst->tm_mon  = (src >> 22) & 0x0000000F;
250
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
251
  dst->tm_wday = (src >> 50) & 0x00000007;
252
  dst->tm_yday = (src >> 53) & 0x000001FF;
253
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
254

    
255
  return;
256
}
257

    
258
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
259
/**
260
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
261
 *
262
 * @return Shutdown value.
263
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
264
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
265
 */
266
aos_shutdown_t _ssspModuleStackInitialization(void)
267
{
268
  // local types
269
  /**
270
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
271
   */
272
  typedef enum {
273
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
274
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
275
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
276
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
277
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
278
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
279
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
280
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
281
  } sssp_modulestackinitstage_t;
282

    
283
  typedef struct {
284
    bool loop     : 1;
285
    bool wfe      : 1;
286
    bool wfe_next : 1;
287
  } flags_t;
288

    
289
  // local variables
290
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
291
  sssp_modulestackinitstage_t stage = STAGE_3_1;
292
  eventmask_t eventmask = 0;
293
  eventflags_t ioflags = 0;
294
  event_source_t eventSourceTimeout;
295
  event_source_t eventSourceDelay;
296
  event_listener_t eventListenerTimeout;
297
  event_listener_t eventListenerDelay;
298
  event_listener_t eventListenerCan;
299
  virtual_timer_t timerTimeout;
300
  virtual_timer_t timerDelay;
301
  CANTxFrame canTxFrame;
302
  CANRxFrame canRxFrame;
303
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
304
  aos_ssspmoduleid_t lastid = 0;
305
#endif
306
  flags_t flags;
307
  aos_timestamp_t uptime;
308

    
309
  // initialize local varibles
310
  chEvtObjectInit(&eventSourceTimeout);
311
  chEvtObjectInit(&eventSourceDelay);
312
  chVTObjectInit(&timerTimeout);
313
  chVTObjectInit(&timerDelay);
314
  canTxFrame.RTR = CAN_RTR_DATA;
315
  canTxFrame.IDE = CAN_IDE_STD;
316
  flags.loop = true;
317
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
318
  flags.wfe_next = true;
319

    
320
  // initialize system variables
321
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
322
  aos.sssp.moduleId = 0;
323

    
324
  // listen to events (timout, delay, CAN receive)
325
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
326
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
327
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
328

    
329
  /*
330
   * FSM in a loop.
331
   *
332
   * This is a fully event-based FSM for the module stack initialization
333
   * sequence, defined by SSSP as startup stage 3. There are five different
334
   * events that can occur at this point:
335
   *  I/O events: The input level of an input pin has changed. Such events must
336
   *              be handled differently depending on the current state. Most
337
   *              of the time, however, such events can be ignored.
338
   *  OS events:  Such events are only available after this stage completed and
339
   *              thus should never occur. However, there is an optional hook
340
   *              to handle such events, nevertheless.
341
   *  CAN events: At least one CAN message was received. Note that this event
342
   *              will only fire again if all input buffers have been cleared.
343
   *  timeouts:   If some module does not support the sequence of there is any
344
   *              issue, such a case is detected via timeouts and must be
345
   *              handled accordingly (see abort state). In some cases, it is
346
   *              possible that a timeout event occurres 'simultaneously' with
347
   *              some other event. This can be caused by several timing issues
348
   *              and is a valid situation. As a result, any other events
349
   *              should be handled before the timeout event. If the other
350
   *              events are expected and valid, this implementation requires
351
   *              the timeout event flag to be cleared explicitely. Otherwise
352
   *              it is evaluated at the end of each iteration of the loop.
353
   *  delays:     Depending on the current state, delays are required by SSSP
354
   *              for timing of the sequential activation of signals.
355
   */
356
  aosDbgPrintf("SSSP stack initialization sequence:\n");
357
  while (flags.loop) {
358
#if (AMIROOS_CFG_DBG == true)
359
    switch (stage) {
360
      case STAGE_3_1:
361
        aosDbgPrintf(">>> 3-1\n");
362
        break;
363
      case STAGE_3_2:
364
        aosDbgPrintf(">>> 3-2\n");
365
        break;
366
      case STAGE_3_3_WAITFORFIRSTID:
367
        aosDbgPrintf(">>> 3-3 (1st ID)\n");
368
        break;
369
      case STAGE_3_3_WAITFORIDORSIG:
370
        aosDbgPrintf(">>> 3-3 (ID/sig)\n");
371
        break;
372
      case STAGE_3_3_WAITFORID:
373
        aosDbgPrintf(">>> 3-3 (ID)\n");
374
        break;
375
      case STAGE_3_4_FINISH:
376
        aosDbgPrintf(">>> 3-4 (finish)\n");
377
        break;
378
      case STAGE_3_4_ABORT_ACTIVE:
379
        aosDbgPrintf(">>> 3-4 (active abort)\n");
380
        break;
381
      case STAGE_3_4_ABORT:
382
        aosDbgPrintf(">>> 3-4 (abort)\n");
383
        break;
384
    }
385
#endif
386

    
387
    // reset wfe flag for the next iteration
388
    flags.wfe_next = true;
389

    
390
    // waiting for events (may be skipped)
391
    if (flags.wfe) {
392
      // wait for any event to occur
393
      aosDbgPrintf("WFE...");
394
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT));
395
      aosDbgPrintf("\t0x%08X", eventmask);
396
    } else {
397
      aosDbgPrintf("WFE skipped");
398
      eventmask = 0;
399
    }
400
    aosSysGetUptime(&uptime);
401
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
402

    
403
    /*
404
     * execute some general tasks and high priority events
405
     */
406
    // no event occurred at all
407
    if ((flags.wfe) && (eventmask == 0)) {
408
      aosDbgPrintf("ERR: no evt\n");
409
      // enforce timeout event
410
      chEvtBroadcast(&eventSourceTimeout);
411
      continue;
412
    }
413
    // if an IO event occurred
414
    if (eventmask & _eventListenerIO.events) {
415
      ioflags = chEvtGetAndClearFlags(&_eventListenerIO);
416
      aosDbgPrintf("INFO: IO evt (0x%08X)\n", ioflags);
417
      // a power-down event occurred
418
      if (ioflags & MODULE_SSSP_EVENTFLAGS_PD) {
419
        aosDbgPrintf("PD evt\n");
420
        // deactivate S and UP
421
        aosDbgPrintf("disabling S\n");
422
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
423
#if (AMIROOS_CFG_SSSP_STACK_END != true)
424
        aosDbgPrintf("disabling UP\n");
425
        apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
426
#endif
427
        // set shutdown flag and exit the loop
428
        shutdown = AOS_SHUTDOWN_PASSIVE;
429
        break;
430
      }
431
      // the S signal was deactivated
432
      if (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC) {
433
        apalControlGpioState_t sstate;
434
        apalControlGpioGet(&moduleSsspGpioSync, &sstate);
435
        if (sstate == APAL_GPIO_ON) {
436
          aosDbgPrintf("S evt (enabled)\n");
437
        } else {
438
          aosDbgPrintf("S evt (disabled)\n");
439
          // either finish or abort
440
          if ((stage == STAGE_3_3_WAITFORID) && (aos.sssp.moduleId != 0)) {
441
            stage = STAGE_3_4_FINISH;
442
          } else if (stage != STAGE_3_4_ABORT) {
443
            stage = STAGE_3_4_ABORT_ACTIVE;
444
          }
445
        }
446
      }
447
    }
448
    // an OS event occurred
449
    if (eventmask & _eventListenerOS.events) {
450
      aosDbgPrintf("WARN: OS evt\n");
451
      // get the flags
452
      eventflags_t oseventflags = chEvtGetAndClearFlags(&_eventListenerOS);
453
      // there should be no OS events at this point
454
#ifdef MODULE_SSSP_STARTUP_3_OSEVENT_HOOK
455
      MODULE_SSSP_STARTUP_3_OSEVENT_HOOK(eventmask, eventflags);
456
#else
457
      _unexpectedEventError(eventmask, oseventflags);
458
#endif
459
    }
460
    // if a CAN event occurred
461
    if ((eventmask & eventListenerCan.events)) {
462
      aosDbgPrintf("CAN evt\n");
463
      // fetch message
464
      if (flags.wfe) {
465
        canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE);
466
        aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
467
      }
468
      // identify and handle abort messgaes
469
      if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
470
        stage = STAGE_3_4_ABORT;
471
      }
472
      // warn if a unexpected message was received
473
      else if ((canRxFrame.SID != SSSP_STACKINIT_CANMSGID_INIT) &&
474
               (canRxFrame.SID != SSSP_STACKINIT_CANMSGID_MODULEID)) {
475
        aosDbgPrintf("WARN: unknown msg\n");
476
      }
477
      // any further pending messages are fetched at the end of the loop
478
    }
479
    // if a timeout event occurred
480
    if (eventmask & eventListenerTimeout.events) {
481
      aosDbgPrintf("timeout evt\n");
482
      // is handled at the end of the loop (or must be cleared by FSM)
483
    }
484
    // if a delay event occurred
485
    if (eventmask & eventListenerDelay.events) {
486
      aosDbgPrintf("delay evt\n");
487
      // is handled by FSM
488
    }
489

    
490
    /*
491
     * this is the actual FSM
492
     */
493
    switch (stage) {
494
      case STAGE_3_1:
495
      {
496
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
497

    
498
        // there was no event at all (skipped wfe)
499
        if (eventmask == 0 && flags.wfe == false) {
500
#if (AMIROOS_CFG_SSSP_MASTER == true)
501
          // initialize the stage by transmitting an according CAN message
502
          aosDbgPrintf("CAN -> init\n");
503
          canTxFrame.DLC = 0;
504
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
505
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
506
            chEvtBroadcast(&eventSourceTimeout);
507
            break;
508
          }
509
          // activate S
510
          aosDbgPrintf("enabling S\n");
511
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
512
#if (AMIROOS_CFG_SSSP_STACK_START == true)
513
          // proceed immediately
514
          stage = STAGE_3_2;
515
          flags.wfe_next = false;
516
#else
517
          // set the timeout timer
518
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
519
          // proceed
520
          stage = STAGE_3_3_WAITFORFIRSTID;
521
#endif
522
#else
523
          // set the timeout timer
524
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
525
#endif
526
        }
527

    
528
#if (AMIROOS_CFG_SSSP_MASTER != true)
529
        // a CAN message was received
530
        else if (eventmask & eventListenerCan.events) {
531
          // if an initiation message was received
532
          if (canRxFrame.DLC == 0 &&
533
              canRxFrame.RTR == CAN_RTR_DATA &&
534
              canRxFrame.IDE == CAN_IDE_STD &&
535
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
536
            aosDbgPrintf("init msg\n");
537
            // reset the timeout timer and clear pending flags
538
            chVTReset(&timerTimeout);
539
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
540
            eventmask &= ~(eventListenerTimeout.events);
541
            // activate S
542
            aosDbgPrintf("enabling S\n");
543
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
544
#if (AMIROOS_CFG_SSSP_STACK_START == true)
545
            // proceed
546
            stage = STAGE_3_2;
547
            flags.wfe_next = false;
548
#else
549
            // set the timeout timer
550
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
551
            // proceed
552
            stage = STAGE_3_3_WAITFORFIRSTID;
553
#endif
554
          }
555
        }
556
#endif
557

    
558
        break;
559
      } /* end of STAGE_3_1 */
560

    
561
      case STAGE_3_2:
562
      {
563
#if (AMIROOS_CFG_SSSP_STACK_START == true)
564
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
565

    
566
        // if this stage was just entered
567
        if (flags.wfe == false) {
568
          // set the module ID
569
          aos.sssp.moduleId = 1;
570
          // broadcast module ID
571
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
572
          canTxFrame.DLC = 4;
573
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
574
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
575
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
576
            chEvtBroadcast(&eventSourceTimeout);
577
            break;
578
          }
579
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
580
          lastid = aos.sssp.moduleId;
581
#endif
582
#if (AMIROOS_CFG_SSSP_STACK_END == true)
583
          // sequence is already over
584
          // deactivate S
585
          aosDbgPrintf("disabling S\n");
586
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
587
          // proceed
588
          stage = STAGE_3_3_WAITFORID;
589
#else
590
          // set the delay timer so the UP signal is activated later
591
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
592
#endif
593
        }
594

    
595
        // if a delay event occurred
596
        if (eventmask & eventListenerDelay.events) {
597
          // activate UP
598
          aosDbgPrintf("enabling UP\n");
599
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
600
          // deactivate S
601
          aosDbgPrintf("disabling S\n");
602
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
603
          // explicitely clear timeout event flag
604
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
605
          eventmask &= ~(eventListenerTimeout.events);
606
          // proceed
607
          stage = STAGE_3_3_WAITFORID;
608
        }
609
#endif
610

    
611
        break;
612
      } /* end of STAGE_3_2 */
613

    
614
      case STAGE_3_3_WAITFORFIRSTID:
615
      {
616
#if (AMIROOS_CFG_SSSP_STACK_START != true)
617
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
618

    
619
        // a CAN message was received
620
        if (eventmask & eventListenerCan.events) {
621
          // if an ID message was received
622
          if (canRxFrame.DLC == 4 &&
623
              canRxFrame.RTR == CAN_RTR_DATA &&
624
              canRxFrame.IDE == CAN_IDE_STD &&
625
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
626
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
627
            // validate received ID
628
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
629
              // store received ID
630
              lastid = _deserialize(canRxFrame.data8, 4);
631
              // restart timeout timer
632
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
633
              // proceed
634
              stage = STAGE_3_3_WAITFORIDORSIG;
635
            } else {
636
              aosDbgPrintf("ERR: invalid ID\n");
637
              // abort
638
              stage = STAGE_3_4_ABORT_ACTIVE;
639
              flags.wfe_next = false;
640
            }
641
            // explicitely clear timeout event flag
642
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
643
            eventmask &= ~(eventListenerTimeout.events);
644
          }
645
        }
646
#endif
647
        break;
648
      } /* end of STAGE_3_3_WAITFORFIRSTID */
649

    
650
      case STAGE_3_3_WAITFORIDORSIG:
651
      {
652
#if (AMIROOS_CFG_SSSP_STACK_START != true)
653
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
654

    
655
        // a CAN message was received
656
        if (eventmask & eventListenerCan.events) {
657
          // if an ID message was received
658
          if (canRxFrame.DLC == 4 &&
659
              canRxFrame.RTR == CAN_RTR_DATA &&
660
              canRxFrame.IDE == CAN_IDE_STD &&
661
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
662
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
663
            // validate received ID
664
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
665
              // store received ID
666
              lastid = _deserialize(canRxFrame.data8, 4);
667
              // restart timeout timer
668
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
669
            } else {
670
              aosDbgPrintf("ERR: invalid ID\n");
671
              // abort
672
              stage = STAGE_3_4_ABORT_ACTIVE;
673
              flags.wfe_next = false;
674
            }
675
            // explicitely clear timeout event flag
676
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
677
            eventmask &= ~(eventListenerTimeout.events);
678
          }
679
        }
680

    
681
        // if an IO event was received (DN signal)
682
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
683
          aosDbgPrintf("DN evt\n");
684
          // reset timeout timer
685
          chVTReset(&timerTimeout);
686
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
687
          eventmask &= ~(eventListenerTimeout.events);
688
          // increment and broadcast ID
689
          aos.sssp.moduleId = lastid + 1;
690
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
691
          canTxFrame.DLC = 4;
692
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
693
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
694
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
695
            chEvtBroadcast(&eventSourceTimeout);
696
            break;
697
          }
698
          // set delay timer
699
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
700
        }
701

    
702
        // if a delay event occurred
703
        if (eventmask & eventListenerDelay.events) {
704
#if (AMIROOS_CFG_SSSP_STACK_END != true)
705
          // activate UP
706
          aosDbgPrintf("enabling UP\n");
707
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
708
#endif
709
          // deactivate S
710
          aosDbgPrintf("disabling S\n");
711
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
712
          // reset the timeout timer
713
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
714
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
715
          eventmask &= ~(eventListenerTimeout.events);
716
          // proceed
717
          stage = STAGE_3_3_WAITFORID;
718
        }
719
#endif
720

    
721
        break;
722
      } /* end of STAGE_3_3_WAITFORIDORSIG */
723

    
724
      case STAGE_3_3_WAITFORID:
725
      {
726
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
727

    
728
#if (AMIROOS_CFG_SSSP_STACK_END != true)
729
        // a CAN message was received
730
        if (eventmask & eventListenerCan.events) {
731
          // if an ID message was received
732
          if (canRxFrame.DLC == 4 &&
733
              canRxFrame.RTR == CAN_RTR_DATA &&
734
              canRxFrame.IDE == CAN_IDE_STD &&
735
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
736
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
737
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
738
            lastid = _deserialize(canRxFrame.data8, 4);
739
            aosDbgPrintf("ID (%u)\n", lastid);
740
#endif
741
            // restart timeout timer
742
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
743
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
744
            eventmask &= ~(eventListenerTimeout.events);
745
          }
746
        }
747
#endif
748

    
749
        break;
750
      } /* end of STAGE_3_3_WAITFORID */
751

    
752
      case STAGE_3_4_FINISH:
753
      {
754
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
755

    
756
        // if an IO event was received (S signal)
757
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
758
          // reset the timeout timer
759
          chVTReset(&timerTimeout);
760
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
761
          eventmask &= ~(eventListenerTimeout.events);
762
          //set the delay timer
763
          chVTSet(&timerDelay, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
764
        }
765

    
766
        // if a CAN event was received
767
        if (eventmask & eventListenerCan.events) {
768
          // if an abort message was received
769
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
770
            aosDbgPrintf("abort msg\n");
771
            // reset the delay timer
772
            chVTReset(&timerDelay);
773
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
774
            eventmask &= ~(eventListenerDelay.events);
775
            // proceed
776
            stage = STAGE_3_4_ABORT;
777
          }
778
        }
779

    
780
        // if a delay timer event occurred
781
        if (eventmask & eventListenerDelay.events) {
782
          aosDbgPrintf("sequence sucessful\n");
783
          // sequence finished sucessfully
784
          flags.loop = false;
785
        }
786

    
787
        break;
788
      } /* end of STAGE_3_4_FINISH */
789

    
790
      case STAGE_3_4_ABORT_ACTIVE:
791
      {
792
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
793

    
794
        // emit abort message
795
        canTxFrame.DLC = 0;
796
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
797
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
798
        aosDbgPrintf("CAN -> abort\n");
799
        // clear timeout flag
800
        eventmask &= ~(eventListenerTimeout.events);
801
        // proceed immediately
802
        stage = STAGE_3_4_ABORT;
803
        flags.wfe_next = false;
804
        break;
805
      } /* end of STAGE_3_4_ABORT_ACTIVE */
806

    
807
      case STAGE_3_4_ABORT:
808
      {
809
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
810

    
811
        // deactivate S
812
        aosDbgPrintf("disabling SYNC\n");
813
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
814
        // invalidate module ID
815
        aos.sssp.moduleId = 0;
816

    
817
        // if an IO event was received (S signal)
818
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
819
          aosDbgPrintf("sequence aborted\n");
820
          // exit the sequence
821
          flags.loop = false;
822
        }
823

    
824
        break;
825
      } /* end of STAGE_3_4_ABORT */
826
    } /* end of switch(stage) */
827

    
828
    // fetch pending CAN message (if any)
829
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
830
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
831
      flags.wfe_next = false;
832
    }
833

    
834
    // handle unhandled timeout events
835
    if (eventmask & eventListenerTimeout.events) {
836
      aosDbgPrintf("ERR: timeout evt\n");
837
      // abort
838
      flags.wfe_next = false;
839
      stage = STAGE_3_4_ABORT_ACTIVE;
840
    }
841

    
842
    // apply wfe value for next iteration
843
    flags.wfe = flags.wfe_next;
844
  } /* end of FSM loop */
845

    
846
  // unregister all events (timeout, delay, CAN receive)
847
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
848
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
849
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
850
  // clear any pending events (timeout, delay, CAN receive)
851
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
852

    
853
  // reset all control signals
854
#if (AMIROOS_CFG_SSSP_STACK_END != true)
855
  aosDbgPrintf("disabling UP\n");
856
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
857
#endif
858
  aosDbgPrintf("disabling S\n");
859
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
860
  aosSysGetUptime(&uptime);
861
  aosDbgPrintf("done\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
862

    
863
  return shutdown;
864
}
865
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
866

    
867
/**
868
 * @brief   Application entry point.
869
 */
870
int main(void)
871
{
872
  // local variables
873
  eventmask_t eventmask = 0;
874
  eventflags_t eventflags = 0;
875
  eventflags_t ioeventflagsmask = AMIROOS_CFG_MAIN_LOOP_IOEVENT_MASK;
876
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
877
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
878
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
879
#endif
880

    
881
  /*
882
   * ##########################################################################
883
   * # system initialization                                                  #
884
   * ##########################################################################
885
   */
886

    
887
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
888
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
889
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
890
#else
891
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
892
#endif
893
#endif
894

    
895
  /* hardware, kernel, and operating system initialization */
896
  // ChibiOS/HAL and custom hal additions (if any)
897
  halInit();
898
#ifdef MODULE_INIT_HAL_EXTRA
899
  MODULE_INIT_HAL_EXTRA();
900
#endif
901

    
902
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
903
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
904
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
905
#else
906
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
907
#endif
908
#endif
909

    
910
  // ChibiOS/RT kernel and custom kernel additions (if any)
911
  chSysInit();
912
#ifdef MODULE_INIT_KERNEL_EXTRA
913
  MODULE_INIT_KERNEL_EXTRA();
914
#endif
915

    
916
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
917
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
918
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
919
#else
920
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
921
#endif
922
#endif
923

    
924
  // AMiRo-OS and custom OS additions (if any)
925
#if (AMIROOS_CFG_SHELL_ENABLE == true)
926
  aosSysInit(moduleShellPrompt);
927
#else
928
  aosSysInit();
929
#endif
930
#ifdef MODULE_INIT_OS_EXTRA
931
  MODULE_INIT_OS_EXTRA();
932
#endif
933

    
934
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
935
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
936
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
937
#else
938
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
939
#endif
940
#endif
941

    
942
#if (AMIROOS_CFG_TESTS_ENABLE == true)
943
#if defined(MODULE_INIT_TESTS)
944
  MODULE_INIT_TESTS();
945
#else
946
  #warning "MODULE_INIT_TESTS() not defined"
947
#endif
948
#endif
949

    
950
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
951
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
952
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
953
#else
954
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
955
#endif
956
#endif
957

    
958
  /* event associations */
959
#if (AMIROOS_CFG_SSSP_ENABLE == true)
960
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC;
961
#if (AMIROOS_CFG_SSSP_STACK_START != true)
962
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_DN;
963
#endif
964
#if (AMIROOS_CFG_SSSP_STACK_END != true)
965
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_UP;
966
#endif
967
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
968
  if (ioeventflagsmask != 0) {
969
    chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, ioeventflagsmask);
970
  }
971
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
972

    
973
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
974
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
975
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
976
#else
977
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
978
#endif
979
#endif
980

    
981
  /* periphery communication initialization */
982
  // CAN (mandatory)
983
  canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
984
  // module specific initialization (if any)
985
#ifdef MODULE_INIT_PERIPHERY_COMM
986
  MODULE_INIT_PERIPHERY_COMM();
987
#endif
988
  // user interface (if any)
989
#ifdef MODULE_HAL_PROGIF
990
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
991
  aosIOChannelOutputEnable(&_stdiochannel);
992
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
993
#if (AMIROOS_CFG_SHELL_ENABLE == true)
994
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
995
  aosShellChannelInputEnable(&_stdshellchannel);
996
  aosShellChannelOutputEnable(&_stdshellchannel);
997
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
998
#endif
999
#endif
1000

    
1001
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
1002
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
1003
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
1004
#else
1005
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
1006
#endif
1007
#endif
1008

    
1009
  /* module is ready -> print welcome prompt */
1010
  aosprintf("\n");
1011
  aosprintf("######################################################################\n");
1012
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
1013
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
1014
  aosprintf("# Copyright (C) 2016..2019  Thomas Schöpping et al.                  #\n");
1015
  aosprintf("#                                                                    #\n");
1016
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
1017
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
1018
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
1019
  aosprintf("# The development of this software was supported by the Excellence   #\n");
1020
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
1021
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
1022
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
1023
  aosprintf("######################################################################\n");
1024
  aosprintf("\n");
1025

    
1026
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7)
1027
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS)
1028
  AMIROOS_CFG_MAIN_INIT_HOOK_7(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS);
1029
#else
1030
  AMIROOS_CFG_MAIN_INIT_HOOK_7();
1031
#endif
1032
#endif
1033

    
1034
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1035
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
1036
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
1037
    /*
1038
     * This code is executed if the received event was not about the SYS_SYNC control signal.
1039
     * The returned event could be caused by any listener (not only the argument).
1040
     */
1041
    // IO event
1042
    if (eventmask & _eventListenerIO.events) {
1043
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1044
      // PD event
1045
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1046
        shutdown = AOS_SHUTDOWN_PASSIVE;
1047
      } else {
1048
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
1049
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1050
#else
1051
        // ignore any other IO events
1052
#endif
1053
      }
1054
    }
1055
    // OS event
1056
    else if (eventmask & _eventListenerOS.events) {
1057
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1058
      _unexpectedEventError(eventmask, eventflags);
1059
    }
1060
    // unknown event
1061
    else {
1062
      _unexpectedEventError(eventmask, 0);
1063
    }
1064
  }
1065

    
1066
  /*
1067
   * There must be no delays at this point, thus no hook is allowed.
1068
   */
1069

    
1070
  /* SSSP startup stage 3 (module stack initialization) */
1071
  if (shutdown == AOS_SHUTDOWN_NONE) {
1072
    shutdown = _ssspModuleStackInitialization();
1073
  }
1074
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1075

    
1076
  /*
1077
   * There must be no delays at this point, thus no hook is allowed.
1078
   */
1079

    
1080
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1081
  /* synchronize calendars */
1082
  if (shutdown == AOS_SHUTDOWN_NONE) {
1083
#if (AMIROOS_CFG_SSSP_MASTER == true)
1084
    CANTxFrame frame;
1085
    struct tm t;
1086
    uint64_t encoded;
1087

    
1088
    frame.DLC = 8;
1089
    frame.RTR = CAN_RTR_DATA;
1090
    frame.IDE = CAN_IDE_STD;
1091
    frame.SID = CALENDERSYNC_CANMSGID;
1092

    
1093
    aosDbgPrintf("transmitting current date/time...\t");
1094
    // get current date & time
1095
    aosSysGetDateTime(&t);
1096
    // encode
1097
    encoded = _TM2U64(&t);
1098
    // serialize
1099
    _serialize(frame.data8, encoded, 8);
1100
    // transmit
1101
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1102

    
1103
    aosDbgPrintf("done\n");
1104
#else /* AMIROOS_CFG_SSSP_MASTER == false */
1105
    CANRxFrame frame;
1106
    uint64_t encoded;
1107
    struct tm t;
1108

    
1109
    aosDbgPrintf("receiving current date/time...\t");
1110
    // receive message
1111
#if (AMIROOS_CFG_DBG == true)
1112
    // increase timeout in debug mode due to additional delays introduced by the many prinf() calls
1113
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(10 * AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1114
#else
1115
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1116
#endif
1117
      // validate message
1118
      if (frame.DLC == 8 &&
1119
          frame.RTR == CAN_RTR_DATA &&
1120
          frame.IDE == CAN_IDE_STD &&
1121
          frame.SID == CALENDERSYNC_CANMSGID) {
1122
        // deserialize
1123
        encoded = _deserialize(frame.data8, 8);
1124
        // decode
1125
        _U642TM(&t, encoded);
1126
        // set current date & time
1127
        aosSysSetDateTime(&t);
1128
        aosDbgPrintf("success\n");
1129
      } else {
1130
        aosDbgPrintf("fail (invalid message)\n");
1131
      }
1132
    } else {
1133
      aosDbgPrintf("fail (timeout)\n");
1134
    }
1135
#endif /* AMIROOS_CFG_SSSP_MASTER == false */
1136
    aosDbgPrintf("\n");
1137
  }
1138
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1139

    
1140
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1141
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1142
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1143
#else
1144
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1145
#endif
1146
#endif
1147

    
1148
  /* completely start AMiRo-OS */
1149
  if (shutdown == AOS_SHUTDOWN_NONE) {
1150
    aosSysStart();
1151
  }
1152

    
1153
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1154
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1155
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1156
#else
1157
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1158
#endif
1159
#endif
1160

    
1161
  /*
1162
   * ##########################################################################
1163
   * # infinite loop                                                          #
1164
   * ##########################################################################
1165
   */
1166

    
1167
  // sleep until a shutdown event is received
1168
  while (shutdown == AOS_SHUTDOWN_NONE) {
1169
    // wait for an event
1170
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1171
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1172
#else
1173
    eventmask = chEvtWaitOne(ALL_EVENTS);
1174
#endif
1175

    
1176
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1177
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1178
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1179
#else
1180
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1181
#endif
1182
#endif
1183

    
1184
    switch (eventmask) {
1185
      // if this was an I/O event
1186
      case IOEVENT_MASK:
1187
        // evaluate flags
1188
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1189
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1190
        // PD event
1191
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1192
          shutdown = AOS_SHUTDOWN_PASSIVE;
1193
        }
1194
        // all other events
1195
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1196
        else {
1197
          MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1198
        }
1199
#endif
1200
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1201
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1202
        MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1203
#endif
1204
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1205
        break;
1206

    
1207
      // if this was an OS event
1208
      case OSEVENT_MASK:
1209
        // evaluate flags
1210
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1211
        switch (eventflags) {
1212
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1213
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1214
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1215
            break;
1216
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1217
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1218
            break;
1219
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1220
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1221
            break;
1222
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1223
            shutdown = AOS_SHUTDOWN_RESTART;
1224
            break;
1225
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1226
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN:
1227
            shutdown = AOS_SHUTDOWN_DEFAULT;
1228
            break;
1229
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1230
          default:
1231
            _unexpectedEventError(eventmask, eventflags);
1232
            break;
1233
        }
1234
        break;
1235

    
1236
      // if this was any other event (should be impossible to occur)
1237
      default:
1238
        eventflags = 0;
1239
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0)
1240
        _unexpectedEventError(eventmask, eventflags);
1241
#endif
1242
        break;
1243
    }
1244

    
1245
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1246
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1247
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1248
#else
1249
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1250
#endif
1251
#endif
1252
  }
1253

    
1254
  /*
1255
   * ##########################################################################
1256
   * # system shutdown                                                        #
1257
   * ##########################################################################
1258
   */
1259

    
1260
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1261
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1262
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1263
#else
1264
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1265
#endif
1266
#endif
1267

    
1268
  // initialize/acknowledge shutdown
1269
  aosSysShutdownInit(shutdown);
1270

    
1271
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1272
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1273
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1274
#else
1275
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1276
#endif
1277
#endif
1278

    
1279
  // stop system threads
1280
  aosSysStop();
1281

    
1282
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1283
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1284
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1285
#else
1286
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1287
#endif
1288
#endif
1289

    
1290
  // deinitialize system
1291
  aosSysDeinit();
1292

    
1293
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1294
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1295
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1296
#else
1297
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1298
#endif
1299
#endif
1300

    
1301
  /* stop all periphery communication */
1302
  // CAN (mandatory)
1303
  canStop(&MODULE_HAL_CAN);
1304
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1305
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1306
#endif
1307

    
1308
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1309
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1310
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1311
#else
1312
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1313
#endif
1314
#endif
1315

    
1316
  // finally hand over to bootloader
1317
  aosSysShutdownFinal(shutdown);
1318

    
1319
  /*
1320
   * ##########################################################################
1321
   * # after shutdown/restart                                                 #
1322
   * ##########################################################################
1323
   *
1324
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1325
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1326
   *       which subsystems should NOT be shut down.
1327
   */
1328

    
1329
  // return an error, since this code should not be executed
1330
  return -1;
1331
}
1332

    
1333
/** @} */