Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 8a93b752

History | View | Annotate | Download (46.453 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

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

    
38
/******************************************************************************/
39
/* LOCAL DEFINITIONS                                                          */
40
/******************************************************************************/
41

    
42
/**
43
 * @brief   Event mask to identify I/O events.
44
 */
45
#define IOEVENT_MASK                            EVENT_MASK(0)
46

    
47
/**
48
 * @brief   Event mask to identify OS events.
49
 */
50
#define OSEVENT_MASK                            EVENT_MASK(1)
51

    
52
/**
53
 * @brief   Event mask to idetify CAN events.
54
 */
55
#define CANEVENT_MASK                           EVENT_MASK(2)
56

    
57
/**
58
 * @brief   Event mask to idetify timeout events.
59
 */
60
#define TIMEOUTEVENT_MASK                       EVENT_MASK(3)
61

    
62
/**
63
 * @brief   Event mask to idetify signal delay events.
64
 */
65
#define DELAYEVENT_MASK                         EVENT_MASK(4)
66

    
67
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
68

    
69
/**
70
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
71
 */
72
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
73

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

    
79
/**
80
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
81
 */
82
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
83

    
84
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
85

    
86
/**
87
 * @brief   Default shutdown mode if SSSP is unavailable.
88
 */
89
#define AOS_SHUTDOWN_DEFAULT                    AOS_SHUTDOWN_DEEPSLEEP
90

    
91
#endif /* AMIROOS_CFG_SSSP_ENABLE */
92

    
93
/**
94
 * @brief   CAN message identifier for calender synchronization message.
95
 */
96
#define CALENDERSYNC_CANMSGID                   0x004
97

    
98
/******************************************************************************/
99
/* EXPORTED VARIABLES                                                         */
100
/******************************************************************************/
101

    
102
/******************************************************************************/
103
/* LOCAL TYPES                                                                */
104
/******************************************************************************/
105

    
106
/******************************************************************************/
107
/* LOCAL VARIABLES                                                            */
108
/******************************************************************************/
109

    
110
/**
111
 * @brief   Listener object for I/O events.
112
 */
113
static event_listener_t _eventListenerIO;
114

    
115
/**
116
 * @brief   Listener object for OS events.
117
 */
118
static event_listener_t _eventListenerOS;
119

    
120
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
121
/**
122
 * @brief   I/O channel for the programmer interface.
123
 */
124
static AosIOChannel _stdiochannel;
125

    
126
#if (AMIROOS_CFG_SHELL_ENABLE == true) || (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
127
/**
128
 * @brief   I/O shell channel for the programmer interface.
129
 */
130
static AosShellChannel _stdshellchannel;
131
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) || (AMIROOS_CFG_TESTS_ENABLE == true)*/
132
#endif /* defined(MODULE_HAL_PROGIF) */
133

    
134
/*
135
 * hook to add further static variables
136
 */
137
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
138
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
139
#endif
140

    
141
/******************************************************************************/
142
/* LOCAL FUNCTIONS                                                            */
143
/******************************************************************************/
144

    
145
/**
146
 * @brief   Prints an error message about an unexpected event.
147
 *
148
 * @param[in] mask    The event mask.
149
 * @param[in] flags   The event flags.
150
 */
151
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
152
{
153
#if (AMIROOS_CFG_DBG == true)
154
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
155
#else
156
  (void)(mask);
157
  (void)(flags);
158
#endif
159
  return;
160
}
161

    
162
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
163
/**
164
 * @brief   Callback function to be used during SSSP stack initialization sequence.
165
 *
166
 * @param[in] par   A pointer to an @p event_source_t to be fired.
167
 */
168
static void _ssspTimerCallback(void* par)
169
{
170
  aosDbgCheck(par != NULL);
171

    
172
  chSysLockFromISR();
173
  chEvtBroadcastI((event_source_t*)par);
174
  chSysUnlockFromISR();
175

    
176
  return;
177
}
178
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
179

    
180
/**
181
 * @brief   Helper function to serialize data.
182
 *
183
 * @param[out]  dst   Pointer to the output buffer.
184
 * @param[in]   src   Data to be serialized.
185
 * @param[in]   n     Number of bytes to serialize.
186
 */
187
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
188
{
189
  aosDbgCheck(dst != NULL);
190
  aosDbgCheck(n > 0 && n <= 8);
191

    
192
  for (uint8_t byte = 0; byte < n; ++byte) {
193
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
194
  }
195

    
196
  return;
197
}
198

    
199
/**
200
 * @brief   Helper function to deserialize data.
201
 *
202
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
203
 * @param[in] n     Number of bytes to deserialize.
204
 *
205
 * @return    The deserialized 32 bit data.
206
 */
207
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
208
{
209
  aosDbgCheck(src != NULL);
210
  aosDbgCheck(n > 0 && n <= 8);
211

    
212
  uint64_t result = 0;
213
  for (uint8_t byte = 0; byte < n; ++byte) {
214
    result |= ((uint64_t)src[byte]) << (byte * 8);
215
  }
216

    
217
  return result;
218
}
219

    
220
/**
221
 * @brief   Converter function to encode a TM value to a single unsigned 64 bit integer.
222
 *
223
 * @details Contents of the TM struct are mapped as follows:
224
 *            bits  |63     62|61      53|52    50|49         26|25     22|21     17|16     12|11      6|5       0|
225
 *            #bits |       2 |        9 |      3 |          24 |       4 |       5 |       5 |       6 |       6 |
226
 *            value |   isdst |     yday |   wday |        year |     mon |    mday |    hour |     min |     sec |
227
 *            range | special | [0, 365] | [0, 6] | [1900, ...] | [0, 11] | [1, 31] | [0, 23] | [0, 59] | [0, 61] |
228
 *          The Daylight Saving Time Flag (isdsst) is encoded as follows:
229
 *            DST not in effect         -> 0
230
 *            DST in effect             -> 1
231
 *            no information available  -> 2
232
 *
233
 * @param[in] src   Pointer to the TM struct to encode.
234
 *
235
 * @return  An unsigned 64 bit integer, which holds the encoded time value.
236
 */
237
inline uint64_t _TM2U64(struct tm* src)
238
{
239
  aosDbgCheck(src != NULL);
240

    
241
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
242
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
243
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
244
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
245
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
246
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
247
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
248
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
249
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
250
}
251

    
252
/**
253
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
254
 *
255
 * @details For information on the encoding, please refer to @p _TM2U64 function.
256
 *
257
 * @param[out] dst  The TM struct to fill with the decoded values.
258
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
259
 */
260
inline void _U642TM(struct tm* dst, const uint64_t src)
261
{
262
  aosDbgCheck(dst != NULL);
263

    
264
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
265
  dst->tm_min  = (src >> 6)  & 0x0000003F;
266
  dst->tm_hour = (src >> 12) & 0x0000001F;
267
  dst->tm_mday = (src >> 17) & 0x0000001F;
268
  dst->tm_mon  = (src >> 22) & 0x0000000F;
269
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
270
  dst->tm_wday = (src >> 50) & 0x00000007;
271
  dst->tm_yday = (src >> 53) & 0x000001FF;
272
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
273

    
274
  return;
275
}
276

    
277
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
278
/**
279
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
280
 *
281
 * @return Shutdown value.
282
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
283
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
284
 */
285
aos_shutdown_t _ssspModuleStackInitialization(void)
286
{
287
  // local types
288
  /**
289
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
290
   */
291
  typedef enum {
292
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
293
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
294
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
295
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
296
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
297
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
298
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
299
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
300
  } sssp_modulestackinitstage_t;
301

    
302
  typedef struct {
303
    bool loop     : 1;
304
    bool wfe      : 1;
305
    bool wfe_next : 1;
306
  } flags_t;
307

    
308
  // local variables
309
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
310
  sssp_modulestackinitstage_t stage = STAGE_3_1;
311
  eventmask_t eventmask = 0;
312
  eventflags_t ioflags = 0;
313
  event_source_t eventSourceTimeout;
314
  event_source_t eventSourceDelay;
315
  event_listener_t eventListenerTimeout;
316
  event_listener_t eventListenerDelay;
317
  event_listener_t eventListenerCan;
318
  virtual_timer_t timerTimeout;
319
  virtual_timer_t timerDelay;
320
  CANTxFrame canTxFrame;
321
  CANRxFrame canRxFrame;
322
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
323
  aos_ssspmoduleid_t lastid = 0;
324
#endif
325
  flags_t flags;
326
  aos_timestamp_t uptime;
327

    
328
  // initialize local varibles
329
  chEvtObjectInit(&eventSourceTimeout);
330
  chEvtObjectInit(&eventSourceDelay);
331
  chVTObjectInit(&timerTimeout);
332
  chVTObjectInit(&timerDelay);
333
  canTxFrame.RTR = CAN_RTR_DATA;
334
  canTxFrame.IDE = CAN_IDE_STD;
335
  flags.loop = true;
336
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
337
  flags.wfe_next = true;
338

    
339
  // initialize system variables
340
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
341
  aos.sssp.moduleId = 0;
342

    
343
  // listen to events (timout, delay, CAN receive)
344
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
345
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
346
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
347

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

    
406
    // reset wfe flag for the next iteration
407
    flags.wfe_next = true;
408

    
409
    // waiting for events (may be skipped)
410
    if (flags.wfe) {
411
      // wait for any event to occur
412
      aosDbgPrintf("WFE...");
413
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT));
414
      aosDbgPrintf("\t0x%08X", eventmask);
415
    } else {
416
      aosDbgPrintf("WFE skipped");
417
      eventmask = 0;
418
    }
419
    aosSysGetUptime(&uptime);
420
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
421

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

    
509
    /*
510
     * this is the actual FSM
511
     */
512
    switch (stage) {
513
      case STAGE_3_1:
514
      {
515
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
516

    
517
        // there was no event at all (skipped wfe)
518
        if (eventmask == 0 && flags.wfe == false) {
519
#if (AMIROOS_CFG_SSSP_MASTER == true)
520
          // initialize the stage by transmitting an according CAN message
521
          aosDbgPrintf("CAN -> init\n");
522
          canTxFrame.DLC = 0;
523
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
524
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
525
            chEvtBroadcast(&eventSourceTimeout);
526
            break;
527
          }
528
          // activate S
529
          aosDbgPrintf("enabling S\n");
530
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
531
#if (AMIROOS_CFG_SSSP_STACK_START == true)
532
          // proceed immediately
533
          stage = STAGE_3_2;
534
          flags.wfe_next = false;
535
#else
536
          // set the timeout timer
537
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
538
          // proceed
539
          stage = STAGE_3_3_WAITFORFIRSTID;
540
#endif
541
#else
542
          // set the timeout timer
543
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
544
#endif
545
        }
546

    
547
#if (AMIROOS_CFG_SSSP_MASTER != true)
548
        // a CAN message was received
549
        else if (eventmask & eventListenerCan.events) {
550
          // if an initiation message was received
551
          if (canRxFrame.DLC == 0 &&
552
              canRxFrame.RTR == CAN_RTR_DATA &&
553
              canRxFrame.IDE == CAN_IDE_STD &&
554
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
555
            aosDbgPrintf("init msg\n");
556
            // reset the timeout timer and clear pending flags
557
            chVTReset(&timerTimeout);
558
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
559
            eventmask &= ~(eventListenerTimeout.events);
560
            // activate S
561
            aosDbgPrintf("enabling S\n");
562
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
563
#if (AMIROOS_CFG_SSSP_STACK_START == true)
564
            // proceed
565
            stage = STAGE_3_2;
566
            flags.wfe_next = false;
567
#else
568
            // set the timeout timer
569
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
570
            // proceed
571
            stage = STAGE_3_3_WAITFORFIRSTID;
572
#endif
573
          }
574
        }
575
#endif
576

    
577
        break;
578
      } /* end of STAGE_3_1 */
579

    
580
      case STAGE_3_2:
581
      {
582
#if (AMIROOS_CFG_SSSP_STACK_START == true)
583
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
584

    
585
        // if this stage was just entered
586
        if (flags.wfe == false) {
587
          // set the module ID
588
          aos.sssp.moduleId = 1;
589
          // broadcast module ID
590
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
591
          canTxFrame.DLC = 4;
592
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
593
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
594
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
595
            chEvtBroadcast(&eventSourceTimeout);
596
            break;
597
          }
598
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
599
          lastid = aos.sssp.moduleId;
600
#endif
601
#if (AMIROOS_CFG_SSSP_STACK_END == true)
602
          // sequence is already over
603
          // deactivate S
604
          aosDbgPrintf("disabling S\n");
605
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
606
          // proceed
607
          stage = STAGE_3_3_WAITFORID;
608
#else
609
          // set the delay timer so the UP signal is activated later
610
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
611
#endif
612
        }
613

    
614
        // if a delay event occurred
615
        if (eventmask & eventListenerDelay.events) {
616
          // activate UP
617
          aosDbgPrintf("enabling UP\n");
618
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
619
          // deactivate S
620
          aosDbgPrintf("disabling S\n");
621
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
622
          // explicitely clear timeout event flag
623
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
624
          eventmask &= ~(eventListenerTimeout.events);
625
          // proceed
626
          stage = STAGE_3_3_WAITFORID;
627
        }
628
#endif
629

    
630
        break;
631
      } /* end of STAGE_3_2 */
632

    
633
      case STAGE_3_3_WAITFORFIRSTID:
634
      {
635
#if (AMIROOS_CFG_SSSP_STACK_START != true)
636
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
637

    
638
        // a CAN message was received
639
        if (eventmask & eventListenerCan.events) {
640
          // if an ID message was received
641
          if (canRxFrame.DLC == 4 &&
642
              canRxFrame.RTR == CAN_RTR_DATA &&
643
              canRxFrame.IDE == CAN_IDE_STD &&
644
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
645
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
646
            // validate received ID
647
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
648
              // store received ID
649
              lastid = _deserialize(canRxFrame.data8, 4);
650
              // restart timeout timer
651
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
652
              // proceed
653
              stage = STAGE_3_3_WAITFORIDORSIG;
654
            } else {
655
              aosDbgPrintf("ERR: invalid ID\n");
656
              // abort
657
              stage = STAGE_3_4_ABORT_ACTIVE;
658
              flags.wfe_next = false;
659
            }
660
            // explicitely clear timeout event flag
661
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
662
            eventmask &= ~(eventListenerTimeout.events);
663
          }
664
        }
665
#endif
666
        break;
667
      } /* end of STAGE_3_3_WAITFORFIRSTID */
668

    
669
      case STAGE_3_3_WAITFORIDORSIG:
670
      {
671
#if (AMIROOS_CFG_SSSP_STACK_START != true)
672
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
673

    
674
        // a CAN message was received
675
        if (eventmask & eventListenerCan.events) {
676
          // if an ID message was received
677
          if (canRxFrame.DLC == 4 &&
678
              canRxFrame.RTR == CAN_RTR_DATA &&
679
              canRxFrame.IDE == CAN_IDE_STD &&
680
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
681
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
682
            // validate received ID
683
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
684
              // store received ID
685
              lastid = _deserialize(canRxFrame.data8, 4);
686
              // restart timeout timer
687
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
688
            } else {
689
              aosDbgPrintf("ERR: invalid ID\n");
690
              // abort
691
              stage = STAGE_3_4_ABORT_ACTIVE;
692
              flags.wfe_next = false;
693
            }
694
            // explicitely clear timeout event flag
695
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
696
            eventmask &= ~(eventListenerTimeout.events);
697
          }
698
        }
699

    
700
        // if an IO event was received (DN signal)
701
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
702
          aosDbgPrintf("DN evt\n");
703
          // reset timeout timer
704
          chVTReset(&timerTimeout);
705
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
706
          eventmask &= ~(eventListenerTimeout.events);
707
          // increment and broadcast ID
708
          aos.sssp.moduleId = lastid + 1;
709
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
710
          canTxFrame.DLC = 4;
711
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
712
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
713
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
714
            chEvtBroadcast(&eventSourceTimeout);
715
            break;
716
          }
717
          // set delay timer
718
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
719
        }
720

    
721
        // if a delay event occurred
722
        if (eventmask & eventListenerDelay.events) {
723
#if (AMIROOS_CFG_SSSP_STACK_END != true)
724
          // activate UP
725
          aosDbgPrintf("enabling UP\n");
726
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
727
#endif
728
          // deactivate S
729
          aosDbgPrintf("disabling S\n");
730
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
731
          // reset the timeout timer
732
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
733
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
734
          eventmask &= ~(eventListenerTimeout.events);
735
          // proceed
736
          stage = STAGE_3_3_WAITFORID;
737
        }
738
#endif
739

    
740
        break;
741
      } /* end of STAGE_3_3_WAITFORIDORSIG */
742

    
743
      case STAGE_3_3_WAITFORID:
744
      {
745
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
746

    
747
#if (AMIROOS_CFG_SSSP_STACK_END != true)
748
        // a CAN message was received
749
        if (eventmask & eventListenerCan.events) {
750
          // if an ID message was received
751
          if (canRxFrame.DLC == 4 &&
752
              canRxFrame.RTR == CAN_RTR_DATA &&
753
              canRxFrame.IDE == CAN_IDE_STD &&
754
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
755
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
756
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
757
            lastid = _deserialize(canRxFrame.data8, 4);
758
            aosDbgPrintf("ID (%u)\n", lastid);
759
#endif
760
            // restart timeout timer
761
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
762
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
763
            eventmask &= ~(eventListenerTimeout.events);
764
          }
765
        }
766
#endif
767

    
768
        break;
769
      } /* end of STAGE_3_3_WAITFORID */
770

    
771
      case STAGE_3_4_FINISH:
772
      {
773
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
774

    
775
        // if an IO event was received (S signal)
776
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
777
          // reset the timeout timer
778
          chVTReset(&timerTimeout);
779
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
780
          eventmask &= ~(eventListenerTimeout.events);
781
          //set the delay timer
782
          chVTSet(&timerDelay, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
783
        }
784

    
785
        // if a CAN event was received
786
        if (eventmask & eventListenerCan.events) {
787
          // if an abort message was received
788
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
789
            aosDbgPrintf("abort msg\n");
790
            // reset the delay timer
791
            chVTReset(&timerDelay);
792
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
793
            eventmask &= ~(eventListenerDelay.events);
794
            // proceed
795
            stage = STAGE_3_4_ABORT;
796
          }
797
        }
798

    
799
        // if a delay timer event occurred
800
        if (eventmask & eventListenerDelay.events) {
801
          aosDbgPrintf("sequence sucessful\n");
802
          // sequence finished sucessfully
803
          flags.loop = false;
804
        }
805

    
806
        break;
807
      } /* end of STAGE_3_4_FINISH */
808

    
809
      case STAGE_3_4_ABORT_ACTIVE:
810
      {
811
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
812

    
813
        // emit abort message
814
        canTxFrame.DLC = 0;
815
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
816
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
817
        aosDbgPrintf("CAN -> abort\n");
818
        // clear timeout flag
819
        eventmask &= ~(eventListenerTimeout.events);
820
        // proceed immediately
821
        stage = STAGE_3_4_ABORT;
822
        flags.wfe_next = false;
823
        break;
824
      } /* end of STAGE_3_4_ABORT_ACTIVE */
825

    
826
      case STAGE_3_4_ABORT:
827
      {
828
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
829

    
830
        // deactivate S
831
        aosDbgPrintf("disabling SYNC\n");
832
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
833
        // invalidate module ID
834
        aos.sssp.moduleId = 0;
835

    
836
        // if an IO event was received (S signal)
837
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
838
          aosDbgPrintf("sequence aborted\n");
839
          // exit the sequence
840
          flags.loop = false;
841
        }
842

    
843
        break;
844
      } /* end of STAGE_3_4_ABORT */
845
    } /* end of switch(stage) */
846

    
847
    // fetch pending CAN message (if any)
848
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
849
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
850
      flags.wfe_next = false;
851
    }
852

    
853
    // handle unhandled timeout events
854
    if (eventmask & eventListenerTimeout.events) {
855
      aosDbgPrintf("ERR: timeout evt\n");
856
      // abort
857
      flags.wfe_next = false;
858
      stage = STAGE_3_4_ABORT_ACTIVE;
859
    }
860

    
861
    // apply wfe value for next iteration
862
    flags.wfe = flags.wfe_next;
863
  } /* end of FSM loop */
864

    
865
  // unregister all events (timeout, delay, CAN receive)
866
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
867
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
868
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
869
  // clear any pending events (timeout, delay, CAN receive)
870
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
871

    
872
  // reset all control signals
873
#if (AMIROOS_CFG_SSSP_STACK_END != true)
874
  aosDbgPrintf("disabling UP\n");
875
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
876
#endif
877
  aosDbgPrintf("disabling S\n");
878
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
879
  aosSysGetUptime(&uptime);
880
  aosDbgPrintf("done\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
881

    
882
  return shutdown;
883
}
884
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
885

    
886
/**
887
 * @brief   Application entry point.
888
 */
889
int main(void)
890
{
891
  // local variables
892
  eventmask_t eventmask = 0;
893
  eventflags_t eventflags = 0;
894
  eventflags_t ioeventflagsmask = AMIROOS_CFG_MAIN_LOOP_IOEVENT_MASK;
895
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
896
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
897
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
898
#endif
899

    
900
  /*
901
   * ##########################################################################
902
   * # system initialization                                                  #
903
   * ##########################################################################
904
   */
905

    
906
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
907
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
908
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
909
#else
910
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
911
#endif
912
#endif
913

    
914
  /* hardware, kernel, and operating system initialization */
915
  // ChibiOS/HAL and custom hal additions (if any)
916
  halInit();
917
#ifdef MODULE_INIT_HAL_EXTRA
918
  MODULE_INIT_HAL_EXTRA();
919
#endif
920

    
921
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
922
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
923
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
924
#else
925
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
926
#endif
927
#endif
928

    
929
  // ChibiOS/RT kernel and custom kernel additions (if any)
930
  chSysInit();
931
#ifdef MODULE_INIT_KERNEL_EXTRA
932
  MODULE_INIT_KERNEL_EXTRA();
933
#endif
934

    
935
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
936
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
937
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
938
#else
939
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
940
#endif
941
#endif
942

    
943
  // AMiRo-OS and custom OS additions (if any)
944
#if (AMIROOS_CFG_SHELL_ENABLE == true) || (AMIROOS_CFG_TESTS_ENABLE == true)
945
  aosSysInit(moduleShellPrompt);
946
#else
947
  aosSysInit();
948
#endif
949
#ifdef MODULE_INIT_OS_EXTRA
950
  MODULE_INIT_OS_EXTRA();
951
#endif
952

    
953
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
954
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
955
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
956
#else
957
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
958
#endif
959
#endif
960

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

    
976
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
977
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
978
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
979
#else
980
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
981
#endif
982
#endif
983

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

    
1006
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
1007
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
1008
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
1009
#else
1010
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
1011
#endif
1012
#endif
1013

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

    
1031
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
1032
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
1033
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
1034
#else
1035
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
1036
#endif
1037
#endif
1038

    
1039
#if (AMIROOS_CFG_TESTS_ENABLE == true)
1040
#if defined(MODULE_INIT_TESTS)
1041
  MODULE_INIT_TESTS();
1042
#else
1043
  #warning "MODULE_INIT_TESTS() not defined"
1044
#endif
1045
#endif
1046

    
1047
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7)
1048
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS)
1049
  AMIROOS_CFG_MAIN_INIT_HOOK_7(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS);
1050
#else
1051
  AMIROOS_CFG_MAIN_INIT_HOOK_7();
1052
#endif
1053
#endif
1054

    
1055
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1056
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
1057
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
1058
    /*
1059
     * This code is executed if the received event was not about the SYS_SYNC control signal.
1060
     * The returned event could be caused by any listener (not only the argument).
1061
     */
1062
    // IO event
1063
    if (eventmask & _eventListenerIO.events) {
1064
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1065
      // PD event
1066
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1067
        shutdown = AOS_SHUTDOWN_PASSIVE;
1068
      } else {
1069
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
1070
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1071
#else
1072
        // ignore any other IO events
1073
#endif
1074
      }
1075
    }
1076
    // OS event
1077
    else if (eventmask & _eventListenerOS.events) {
1078
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1079
      _unexpectedEventError(eventmask, eventflags);
1080
    }
1081
    // unknown event
1082
    else {
1083
      _unexpectedEventError(eventmask, 0);
1084
    }
1085
  }
1086

    
1087
  /*
1088
   * There must be no delays at this point, thus no hook is allowed.
1089
   */
1090

    
1091
  /* SSSP startup stage 3 (module stack initialization) */
1092
  if (shutdown == AOS_SHUTDOWN_NONE) {
1093
    shutdown = _ssspModuleStackInitialization();
1094
  }
1095
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1096

    
1097
  /*
1098
   * There must be no delays at this point, thus no hook is allowed.
1099
   */
1100

    
1101
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1102
  /* synchronize calendars */
1103
  if (shutdown == AOS_SHUTDOWN_NONE) {
1104
#if (AMIROOS_CFG_SSSP_MASTER == true)
1105
    CANTxFrame frame;
1106
    struct tm t;
1107
    uint64_t encoded;
1108

    
1109
    frame.DLC = 8;
1110
    frame.RTR = CAN_RTR_DATA;
1111
    frame.IDE = CAN_IDE_STD;
1112
    frame.SID = CALENDERSYNC_CANMSGID;
1113

    
1114
    aosDbgPrintf("transmitting current date/time...\t");
1115
    // get current date & time
1116
    aosSysGetDateTime(&t);
1117
    // encode
1118
    encoded = _TM2U64(&t);
1119
    // serialize
1120
    _serialize(frame.data8, encoded, 8);
1121
    // transmit
1122
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1123

    
1124
    aosDbgPrintf("done\n");
1125
#else /* AMIROOS_CFG_SSSP_MASTER == false */
1126
    CANRxFrame frame;
1127
    uint64_t encoded;
1128
    struct tm t;
1129

    
1130
    aosDbgPrintf("receiving current date/time...\t");
1131
    // receive message
1132
#if (AMIROOS_CFG_DBG == true)
1133
    // increase timeout in debug mode due to additional delays introduced by the many prinf() calls
1134
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(10 * AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1135
#else
1136
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1137
#endif
1138
      // validate message
1139
      if (frame.DLC == 8 &&
1140
          frame.RTR == CAN_RTR_DATA &&
1141
          frame.IDE == CAN_IDE_STD &&
1142
          frame.SID == CALENDERSYNC_CANMSGID) {
1143
        // deserialize
1144
        encoded = _deserialize(frame.data8, 8);
1145
        // decode
1146
        _U642TM(&t, encoded);
1147
        // set current date & time
1148
        aosSysSetDateTime(&t);
1149
        aosDbgPrintf("success\n");
1150
      } else {
1151
        aosDbgPrintf("fail (invalid message)\n");
1152
      }
1153
    } else {
1154
      aosDbgPrintf("fail (timeout)\n");
1155
    }
1156
#endif /* AMIROOS_CFG_SSSP_MASTER == false */
1157
    aosDbgPrintf("\n");
1158
  }
1159
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1160

    
1161
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1162
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1163
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1164
#else
1165
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1166
#endif
1167
#endif
1168

    
1169
  /* completely start AMiRo-OS */
1170
  if (shutdown == AOS_SHUTDOWN_NONE) {
1171
    aosSysStart();
1172
  }
1173

    
1174
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1175
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1176
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1177
#else
1178
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1179
#endif
1180
#endif
1181

    
1182
  /*
1183
   * ##########################################################################
1184
   * # infinite loop                                                          #
1185
   * ##########################################################################
1186
   */
1187

    
1188
  // sleep until a shutdown event is received
1189
  while (shutdown == AOS_SHUTDOWN_NONE) {
1190
    // wait for an event
1191
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1192
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1193
#else
1194
    eventmask = chEvtWaitOne(ALL_EVENTS);
1195
#endif
1196

    
1197
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1198
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1199
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1200
#else
1201
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1202
#endif
1203
#endif
1204

    
1205
    switch (eventmask) {
1206
      // if this was an I/O event
1207
      case IOEVENT_MASK:
1208
        // evaluate flags
1209
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1210
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1211
        // PD event
1212
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1213
          shutdown = AOS_SHUTDOWN_PASSIVE;
1214
        }
1215
        // all other events
1216
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1217
        else {
1218
          MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1219
        }
1220
#endif
1221
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1222
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1223
        MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1224
#endif
1225
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1226
        break;
1227

    
1228
      // if this was an OS event
1229
      case OSEVENT_MASK:
1230
        // evaluate flags
1231
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1232
        switch (eventflags) {
1233
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1234
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1235
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1236
            break;
1237
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1238
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1239
            break;
1240
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1241
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1242
            break;
1243
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1244
            shutdown = AOS_SHUTDOWN_RESTART;
1245
            break;
1246
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1247
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN:
1248
            shutdown = AOS_SHUTDOWN_DEFAULT;
1249
            break;
1250
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1251
          default:
1252
            _unexpectedEventError(eventmask, eventflags);
1253
            break;
1254
        }
1255
        break;
1256

    
1257
      // if this was any other event (should be impossible to occur)
1258
      default:
1259
        eventflags = 0;
1260
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0)
1261
        _unexpectedEventError(eventmask, eventflags);
1262
#endif
1263
        break;
1264
    }
1265

    
1266
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1267
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1268
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1269
#else
1270
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1271
#endif
1272
#endif
1273
  }
1274

    
1275
  /*
1276
   * ##########################################################################
1277
   * # system shutdown                                                        #
1278
   * ##########################################################################
1279
   */
1280

    
1281
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1282
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1283
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1284
#else
1285
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1286
#endif
1287
#endif
1288

    
1289
  // initialize/acknowledge shutdown
1290
  aosSysShutdownInit(shutdown);
1291

    
1292
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1293
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1294
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1295
#else
1296
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1297
#endif
1298
#endif
1299

    
1300
  // stop system threads
1301
  aosSysStop();
1302

    
1303
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1304
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1305
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1306
#else
1307
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1308
#endif
1309
#endif
1310

    
1311
  // deinitialize system
1312
  aosSysDeinit();
1313

    
1314
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1315
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1316
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1317
#else
1318
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1319
#endif
1320
#endif
1321

    
1322
  /* stop all periphery communication */
1323
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1324
  // CAN (mandatory)
1325
  canStop(&MODULE_HAL_CAN);
1326
#endif
1327
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1328
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1329
#endif
1330

    
1331
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1332
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1333
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1334
#else
1335
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1336
#endif
1337
#endif
1338

    
1339
  // finally hand over to bootloader
1340
  aosSysShutdownFinal(shutdown);
1341

    
1342
  /*
1343
   * ##########################################################################
1344
   * # after shutdown/restart                                                 #
1345
   * ##########################################################################
1346
   *
1347
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1348
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1349
   *       which subsystems should NOT be shut down.
1350
   */
1351

    
1352
  // return an error, since this code should not be executed
1353
  return -1;
1354
}
1355

    
1356
/******************************************************************************/
1357
/* EXPORTED FUNCTIONS                                                         */
1358
/******************************************************************************/
1359

    
1360
/** @} */