Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 47e89ebf

History | View | Annotate | Download (51.762 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 /* defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER) */
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) && (HAL_USE_CAN == TRUE)) || defined(__DOXYGEN__)
68
#define SSSP_STAGE3_ENABLE                      true
69
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) && (HAL_USE_CAN == TRUE) */
70
#define SSSP_STAGE3_ENABLE                      false
71
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (HAL_USE_CAN == TRUE) */
72

    
73
#if (SSSP_STAGE3_ENABLE == true) || defined(__DOXYGEN__)
74

    
75
/**
76
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
77
 */
78
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
79

    
80
/**
81
 * @brief   CAN message identifier for transmitting module IDs during the SSSP stack initialization sequence.
82
 */
83
#define SSSP_STACKINIT_CANMSGID_MODULEID        0x002
84

    
85
/**
86
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
87
 */
88
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
89

    
90
#endif /* (SSSP_STAGE3_ENABLE == true) */
91

    
92
#if (AMIROOS_CFG_SSSP_ENABLE != true) || defined(__DOXYGEN__)
93
/**
94
 * @brief   Default shutdown mode if SSSP is unavailable.
95
 */
96
#define AOS_SHUTDOWN_DEFAULT                    AOS_SHUTDOWN_DEEPSLEEP
97
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
98

    
99
#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
100
/**
101
 * @brief   CAN message identifier for calender synchronization message.
102
 */
103
#define CALENDERSYNC_CANMSGID                   0x004
104
#endif /* (HAL_USE_CAN == TRUE) */
105

    
106
/******************************************************************************/
107
/* EXPORTED VARIABLES                                                         */
108
/******************************************************************************/
109

    
110
/******************************************************************************/
111
/* LOCAL TYPES                                                                */
112
/******************************************************************************/
113

    
114
/******************************************************************************/
115
/* LOCAL VARIABLES                                                            */
116
/******************************************************************************/
117

    
118
/**
119
 * @brief   Listener object for I/O events.
120
 */
121
static event_listener_t _eventListenerIO;
122

    
123
/**
124
 * @brief   Listener object for OS events.
125
 */
126
static event_listener_t _eventListenerOS;
127

    
128
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
129
/**
130
 * @brief   I/O channel for the programmer interface.
131
 */
132
static AosIOChannel _stdiochannel;
133

    
134
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
135

    
136
/**
137
 * @brief   I/O shell channel for the programmer interface.
138
 */
139
static AosShellChannel _stdshellchannel;
140

    
141
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
142
#endif /* defined(MODULE_HAL_PROGIF) */
143

    
144
/*
145
 * hook to add further static variables
146
 */
147
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
148
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
149
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES) */
150

    
151
/******************************************************************************/
152
/* LOCAL FUNCTIONS                                                            */
153
/******************************************************************************/
154

    
155
/**
156
 * @brief   Prints an error message about an unexpected event.
157
 *
158
 * @param[in] mask    The event mask.
159
 * @param[in] flags   The event flags.
160
 */
161
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
162
{
163
#if (AMIROOS_CFG_DBG == true)
164
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
165
#else /* (AMIROOS_CFG_DBG == true) */
166
  (void)(mask);
167
  (void)(flags);
168
#endif /* (AMIROOS_CFG_DBG == true) */
169
  return;
170
}
171

    
172
#if (SSSP_STAGE3_ENABLE == true) || defined(__DOXYGEN__)
173
/**
174
 * @brief   Callback function to be used during SSSP stack initialization sequence.
175
 *
176
 * @param[in] par   A pointer to an @p event_source_t to be fired.
177
 */
178
static void _ssspTimerCallback(void* par)
179
{
180
  aosDbgCheck(par != NULL);
181

    
182
  chSysLockFromISR();
183
  chEvtBroadcastI((event_source_t*)par);
184
  chSysUnlockFromISR();
185

    
186
  return;
187
}
188
#endif /* (SSSP_STAGE3_ENABLE == true) */
189

    
190
/**
191
 * @brief   Helper function to serialize data.
192
 *
193
 * @param[out]  dst   Pointer to the output buffer.
194
 * @param[in]   src   Data to be serialized.
195
 * @param[in]   n     Number of bytes to serialize.
196
 */
197
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
198
{
199
  aosDbgCheck(dst != NULL);
200
  aosDbgCheck(n > 0 && n <= 8);
201

    
202
  for (uint8_t byte = 0; byte < n; ++byte) {
203
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
204
  }
205

    
206
  return;
207
}
208

    
209
/**
210
 * @brief   Helper function to deserialize data.
211
 *
212
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
213
 * @param[in] n     Number of bytes to deserialize.
214
 *
215
 * @return    The deserialized 32 bit data.
216
 */
217
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
218
{
219
  aosDbgCheck(src != NULL);
220
  aosDbgCheck(n > 0 && n <= 8);
221

    
222
  uint64_t result = 0;
223
  for (uint8_t byte = 0; byte < n; ++byte) {
224
    result |= ((uint64_t)src[byte]) << (byte * 8);
225
  }
226

    
227
  return result;
228
}
229

    
230
#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
231

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

    
253
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
254
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
255
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
256
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
257
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
258
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
259
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
260
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
261
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
262
}
263

    
264
/**
265
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
266
 *
267
 * @details For information on the encoding, please refer to @p _TM2U64 function.
268
 *
269
 * @param[out] dst  The TM struct to fill with the decoded values.
270
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
271
 */
272
inline void _U642TM(struct tm* dst, const uint64_t src)
273
{
274
  aosDbgCheck(dst != NULL);
275

    
276
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
277
  dst->tm_min  = (src >> 6)  & 0x0000003F;
278
  dst->tm_hour = (src >> 12) & 0x0000001F;
279
  dst->tm_mday = (src >> 17) & 0x0000001F;
280
  dst->tm_mon  = (src >> 22) & 0x0000000F;
281
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
282
  dst->tm_wday = (src >> 50) & 0x00000007;
283
  dst->tm_yday = (src >> 53) & 0x000001FF;
284
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
285

    
286
  return;
287
}
288

    
289
#endif /* (HAL_USE_RTC == TRUE) */
290

    
291
#if (SSSP_STAGE3_ENABLE) || defined(__DOXYGEN__)
292
/**
293
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
294
 *
295
 * @return Shutdown value.
296
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
297
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
298
 */
299
aos_shutdown_t _ssspModuleStackInitialization(void)
300
{
301
  // local types
302
  /**
303
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
304
   */
305
  typedef enum {
306
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
307
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
308
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
309
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
310
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
311
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
312
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
313
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
314
  } sssp_modulestackinitstage_t;
315

    
316
  typedef struct {
317
    bool loop     : 1;
318
    bool wfe      : 1;
319
    bool wfe_next : 1;
320
  } flags_t;
321

    
322
  // local variables
323
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
324
  sssp_modulestackinitstage_t stage = STAGE_3_1;
325
  eventmask_t eventmask = 0;
326
  eventflags_t ioflags = 0;
327
  event_source_t eventSourceTimeout;
328
  event_source_t eventSourceDelay;
329
  event_listener_t eventListenerTimeout;
330
  event_listener_t eventListenerDelay;
331
  event_listener_t eventListenerCan;
332
  virtual_timer_t timerTimeout;
333
  virtual_timer_t timerDelay;
334
  CANTxFrame canTxFrame;
335
  CANRxFrame canRxFrame;
336
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
337
  aos_ssspmoduleid_t lastid = 0;
338
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true) */
339
  flags_t flags;
340
  aos_timestamp_t uptime;
341

    
342
  // initialize local varibles
343
  chEvtObjectInit(&eventSourceTimeout);
344
  chEvtObjectInit(&eventSourceDelay);
345
  chVTObjectInit(&timerTimeout);
346
  chVTObjectInit(&timerDelay);
347
  canTxFrame.RTR = CAN_RTR_DATA;
348
  canTxFrame.IDE = CAN_IDE_STD;
349
  flags.loop = true;
350
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
351
  flags.wfe_next = true;
352

    
353
  // initialize system variables
354
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
355
  aos.sssp.moduleId = 0;
356

    
357
  // listen to events (timout, delay, CAN receive)
358
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
359
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
360
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
361

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

    
420
    // reset wfe flag for the next iteration
421
    flags.wfe_next = true;
422

    
423
    // waiting for events (may be skipped)
424
    if (flags.wfe) {
425
      // wait for any event to occur
426
      aosDbgPrintf("WFE...");
427
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT));
428
      aosDbgPrintf("\t0x%08X", eventmask);
429
    } else {
430
      aosDbgPrintf("WFE skipped");
431
      eventmask = 0;
432
    }
433
    aosSysGetUptime(&uptime);
434
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
435

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

    
523
    /*
524
     * this is the actual FSM
525
     */
526
    switch (stage) {
527
      case STAGE_3_1:
528
      {
529
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
530

    
531
        // there was no event at all (skipped wfe)
532
        if (eventmask == 0 && flags.wfe == false) {
533
#if (AMIROOS_CFG_SSSP_MASTER == true)
534
          // initialize the stage by transmitting an according CAN message
535
          aosDbgPrintf("CAN -> init\n");
536
          canTxFrame.DLC = 0;
537
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
538
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
539
            chEvtBroadcast(&eventSourceTimeout);
540
            break;
541
          }
542
          // activate S
543
          aosDbgPrintf("enabling S\n");
544
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
545
#if (AMIROOS_CFG_SSSP_STACK_START == true)
546
          // proceed immediately
547
          stage = STAGE_3_2;
548
          flags.wfe_next = false;
549
#else /* (AMIROOS_CFG_SSSP_STACK_START == true) */
550
          // set the timeout timer
551
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
552
          // proceed
553
          stage = STAGE_3_3_WAITFORFIRSTID;
554
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */
555
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
556
          // set the timeout timer
557
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
558
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
559
        }
560

    
561
#if (AMIROOS_CFG_SSSP_MASTER != true)
562
        // a CAN message was received
563
        else if (eventmask & eventListenerCan.events) {
564
          // if an initiation message was received
565
          if (canRxFrame.DLC == 0 &&
566
              canRxFrame.RTR == CAN_RTR_DATA &&
567
              canRxFrame.IDE == CAN_IDE_STD &&
568
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
569
            aosDbgPrintf("init msg\n");
570
            // reset the timeout timer and clear pending flags
571
            chVTReset(&timerTimeout);
572
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
573
            eventmask &= ~(eventListenerTimeout.events);
574
            // activate S
575
            aosDbgPrintf("enabling S\n");
576
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
577
#if (AMIROOS_CFG_SSSP_STACK_START == true)
578
            // proceed
579
            stage = STAGE_3_2;
580
            flags.wfe_next = false;
581
#else /* (AMIROOS_CFG_SSSP_STACK_START == true) */
582
            // set the timeout timer
583
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
584
            // proceed
585
            stage = STAGE_3_3_WAITFORFIRSTID;
586
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */
587
          }
588
        }
589
#endif /* (AMIROOS_CFG_SSSP_MASTER != true) */
590

    
591
        break;
592
      } /* end of STAGE_3_1 */
593

    
594
      case STAGE_3_2:
595
      {
596
#if (AMIROOS_CFG_SSSP_STACK_START == true)
597
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
598

    
599
        // if this stage was just entered
600
        if (flags.wfe == false) {
601
          // set the module ID
602
          aos.sssp.moduleId = 1;
603
          // broadcast module ID
604
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
605
          canTxFrame.DLC = 4;
606
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
607
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
608
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
609
            chEvtBroadcast(&eventSourceTimeout);
610
            break;
611
          }
612
#if (AMIROOS_CFG_DBG == true)
613
          lastid = aos.sssp.moduleId;
614
#endif /* (AMIROOS_CFG_DBG == true) */
615
#if (AMIROOS_CFG_SSSP_STACK_END == true)
616
          // sequence is already over
617
          // deactivate S
618
          aosDbgPrintf("disabling S\n");
619
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
620
          // proceed
621
          stage = STAGE_3_3_WAITFORID;
622
#else /* (AMIROOS_CFG_SSSP_STACK_END == true) */
623
          // set the delay timer so the UP signal is activated later
624
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
625
#endif /* (AMIROOS_CFG_SSSP_STACK_END == true) */
626
        }
627

    
628
        // if a delay event occurred
629
        if (eventmask & eventListenerDelay.events) {
630
          // activate UP
631
          aosDbgPrintf("enabling UP\n");
632
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
633
          // deactivate S
634
          aosDbgPrintf("disabling S\n");
635
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
636
          // explicitely clear timeout event flag
637
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
638
          eventmask &= ~(eventListenerTimeout.events);
639
          // proceed
640
          stage = STAGE_3_3_WAITFORID;
641
        }
642
#endif /* (AMIROOS_CFG_SSSP_STACK_START == true) */
643

    
644
        break;
645
      } /* end of STAGE_3_2 */
646

    
647
      case STAGE_3_3_WAITFORFIRSTID:
648
      {
649
#if (AMIROOS_CFG_SSSP_STACK_START != true)
650
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
651

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

    
683
      case STAGE_3_3_WAITFORIDORSIG:
684
      {
685
#if (AMIROOS_CFG_SSSP_STACK_START != true)
686
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
687

    
688
        // a CAN message was received
689
        if (eventmask & eventListenerCan.events) {
690
          // if an ID message was received
691
          if (canRxFrame.DLC == 4 &&
692
              canRxFrame.RTR == CAN_RTR_DATA &&
693
              canRxFrame.IDE == CAN_IDE_STD &&
694
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
695
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
696
            // validate received ID
697
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
698
              // store received ID
699
              lastid = _deserialize(canRxFrame.data8, 4);
700
              // restart timeout timer
701
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
702
            } else {
703
              aosDbgPrintf("ERR: invalid ID\n");
704
              // abort
705
              stage = STAGE_3_4_ABORT_ACTIVE;
706
              flags.wfe_next = false;
707
            }
708
            // explicitely clear timeout event flag
709
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
710
            eventmask &= ~(eventListenerTimeout.events);
711
          }
712
        }
713

    
714
        // if an IO event was received (DN signal)
715
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
716
          aosDbgPrintf("DN evt\n");
717
          // reset timeout timer
718
          chVTReset(&timerTimeout);
719
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
720
          eventmask &= ~(eventListenerTimeout.events);
721
          // increment and broadcast ID
722
          aos.sssp.moduleId = lastid + 1;
723
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
724
          canTxFrame.DLC = 4;
725
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
726
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
727
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
728
            chEvtBroadcast(&eventSourceTimeout);
729
            break;
730
          }
731
          // set delay timer
732
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
733
        }
734

    
735
        // if a delay event occurred
736
        if (eventmask & eventListenerDelay.events) {
737
#if (AMIROOS_CFG_SSSP_STACK_END != true)
738
          // activate UP
739
          aosDbgPrintf("enabling UP\n");
740
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
741
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
742
          // deactivate S
743
          aosDbgPrintf("disabling S\n");
744
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
745
          // reset the timeout timer
746
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
747
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
748
          eventmask &= ~(eventListenerTimeout.events);
749
          // proceed
750
          stage = STAGE_3_3_WAITFORID;
751
        }
752
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
753

    
754
        break;
755
      } /* end of STAGE_3_3_WAITFORIDORSIG */
756

    
757
      case STAGE_3_3_WAITFORID:
758
      {
759
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
760

    
761
#if (AMIROOS_CFG_SSSP_STACK_END != true)
762
        // a CAN message was received
763
        if (eventmask & eventListenerCan.events) {
764
          // if an ID message was received
765
          if (canRxFrame.DLC == 4 &&
766
              canRxFrame.RTR == CAN_RTR_DATA &&
767
              canRxFrame.IDE == CAN_IDE_STD &&
768
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
769
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
770
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
771
            lastid = _deserialize(canRxFrame.data8, 4);
772
            aosDbgPrintf("ID (%u)\n", lastid);
773
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true) */
774
            // restart timeout timer
775
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
776
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
777
            eventmask &= ~(eventListenerTimeout.events);
778
          }
779
        }
780
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
781

    
782
        break;
783
      } /* end of STAGE_3_3_WAITFORID */
784

    
785
      case STAGE_3_4_FINISH:
786
      {
787
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
788

    
789
        // if an IO event was received (S signal)
790
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
791
          // reset the timeout timer
792
          chVTReset(&timerTimeout);
793
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
794
          eventmask &= ~(eventListenerTimeout.events);
795
          //set the delay timer
796
          chVTSet(&timerDelay, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
797
        }
798

    
799
        // if a CAN event was received
800
        if (eventmask & eventListenerCan.events) {
801
          // if an abort message was received
802
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
803
            aosDbgPrintf("abort msg\n");
804
            // reset the delay timer
805
            chVTReset(&timerDelay);
806
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
807
            eventmask &= ~(eventListenerDelay.events);
808
            // proceed
809
            stage = STAGE_3_4_ABORT;
810
          }
811
        }
812

    
813
        // if a delay timer event occurred
814
        if (eventmask & eventListenerDelay.events) {
815
          aosDbgPrintf("sequence sucessful\n");
816
          // sequence finished sucessfully
817
          flags.loop = false;
818
        }
819

    
820
        break;
821
      } /* end of STAGE_3_4_FINISH */
822

    
823
      case STAGE_3_4_ABORT_ACTIVE:
824
      {
825
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
826

    
827
        // emit abort message
828
        canTxFrame.DLC = 0;
829
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
830
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
831
        aosDbgPrintf("CAN -> abort\n");
832
        // clear timeout flag
833
        eventmask &= ~(eventListenerTimeout.events);
834
        // proceed immediately
835
        stage = STAGE_3_4_ABORT;
836
        flags.wfe_next = false;
837
        break;
838
      } /* end of STAGE_3_4_ABORT_ACTIVE */
839

    
840
      case STAGE_3_4_ABORT:
841
      {
842
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
843

    
844
        // deactivate S
845
        aosDbgPrintf("disabling SYNC\n");
846
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
847
        // invalidate module ID
848
        aos.sssp.moduleId = 0;
849

    
850
        // if an IO event was received (S signal)
851
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
852
          aosDbgPrintf("sequence aborted\n");
853
          // exit the sequence
854
          flags.loop = false;
855
        }
856

    
857
        break;
858
      } /* end of STAGE_3_4_ABORT */
859
    } /* end of switch(stage) */
860

    
861
    // fetch pending CAN message (if any)
862
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
863
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
864
      flags.wfe_next = false;
865
    }
866

    
867
    // handle unhandled timeout events
868
    if (eventmask & eventListenerTimeout.events) {
869
      aosDbgPrintf("ERR: timeout evt\n");
870
      // abort
871
      flags.wfe_next = false;
872
      stage = STAGE_3_4_ABORT_ACTIVE;
873
    }
874

    
875
    // apply wfe value for next iteration
876
    flags.wfe = flags.wfe_next;
877
  } /* end of FSM loop */
878

    
879
  // unregister all events (timeout, delay, CAN receive)
880
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
881
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
882
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
883
  // clear any pending events (timeout, delay, CAN receive)
884
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
885

    
886
  // reset all control signals
887
#if (AMIROOS_CFG_SSSP_STACK_END != true)
888
  aosDbgPrintf("disabling UP\n");
889
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
890
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
891
  aosDbgPrintf("disabling S\n");
892
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
893
  aosSysGetUptime(&uptime);
894
  aosDbgPrintf("done\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
895

    
896
  return shutdown;
897
}
898
#endif /* (SSSP_STAGE3_ENABLE == true) */
899

    
900
/**
901
 * @brief   Application entry point.
902
 */
903
int main(void)
904
{
905
  // local variables
906
  eventmask_t eventmask = 0;
907
  eventflags_t eventflags = 0;
908
  eventflags_t ioeventflagsmask = AMIROOS_CFG_MAIN_LOOP_IOEVENT_MASK;
909
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
910
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
911
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
912
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES) */
913

    
914
  /*
915
   * ##########################################################################
916
   * # system initialization                                                  #
917
   * ##########################################################################
918
   */
919

    
920
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
921
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
922
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
923
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS) */
924
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
925
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS) */
926
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_0) */
927

    
928
  /* hardware, kernel, and operating system initialization */
929
  // ChibiOS/HAL and custom hal additions (if any)
930
  halInit();
931
#if defined(MODULE_INIT_HAL_EXTRA)
932
  MODULE_INIT_HAL_EXTRA();
933
#endif /* defined(MODULE_INIT_HAL_EXTRA) */
934

    
935
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
936
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
937
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
938
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS) */
939
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
940
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS) */
941
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1) */
942

    
943
  // ChibiOS/RT kernel and custom kernel additions (if any)
944
  chSysInit();
945
#if defined(MODULE_INIT_KERNEL_EXTRA)
946
  MODULE_INIT_KERNEL_EXTRA();
947
#endif /* defined(MODULE_INIT_KERNEL_EXTRA) */
948

    
949
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
950
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
951
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
952
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS) */
953
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
954
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS) */
955
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2) */
956

    
957
  // AMiRo-OS, additional interrupts and custom OS additions (if any)
958
#if (AMIROOS_CFG_SHELL_ENABLE == true)
959
  aosSysInit(moduleShellPrompt);
960
#else /* (AMIROOS_CFG_SHELL_ENABLE == true) */
961
  aosSysInit(NULL);
962
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
963
#if defined(MODULE_INIT_INTERRUPTS)
964
  MODULE_INIT_INTERRUPTS();
965
#endif
966
#if defined(MODULE_INIT_OS_EXTRA)
967
  MODULE_INIT_OS_EXTRA();
968
#endif /* defined(MODULE_INIT_OS_EXTRA) */
969

    
970
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
971
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
972
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
973
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS) */
974
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
975
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS) */
976
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3) */
977

    
978
  /* event associations */
979
#if (AMIROOS_CFG_SSSP_ENABLE == true)
980
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC;
981
#if (AMIROOS_CFG_SSSP_STACK_START != true)
982
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_DN;
983
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
984
#if (AMIROOS_CFG_SSSP_STACK_END != true)
985
  ioeventflagsmask |= MODULE_SSSP_EVENTFLAGS_UP;
986
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
987
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
988
  if (ioeventflagsmask != 0) {
989
    chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, ioeventflagsmask);
990
  }
991
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
992

    
993
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
994
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
995
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
996
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS) */
997
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
998
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS) */
999
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4) */
1000

    
1001
  /* periphery communication interfaces initialization */
1002
  // module specific initialization (if any)
1003
#if defined(MODULE_INIT_PERIPHERY_IF)
1004
  MODULE_INIT_PERIPHERY_IF();
1005
#endif /* defined(MODULE_INIT_PERIPHERY_IF) */
1006
#if ((SSSP_STAGE3_ENABLE == true) && (HAL_USE_CAN == TRUE))
1007
  // CAN
1008
  if (MODULE_HAL_CAN.state == CAN_STOP) {
1009
    canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
1010
  }
1011
#endif /* (SSSP_STAGE3_ENABLE == true) && (HAL_USE_CAN == TRUE) */
1012
  // user interface (if any)
1013
#if defined(MODULE_HAL_PROGIF)
1014
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
1015
  aosIOChannelOutputEnable(&_stdiochannel);
1016
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
1017
#if (AMIROOS_CFG_SHELL_ENABLE == true)
1018
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
1019
  aosShellChannelInputEnable(&_stdshellchannel);
1020
  aosShellChannelOutputEnable(&_stdshellchannel);
1021
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
1022
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
1023
#endif /* defined(MODULE_HAL_PROGIF) */
1024

    
1025
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
1026
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
1027
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
1028
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS) */
1029
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
1030
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS) */
1031
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5) */
1032

    
1033
  /* module is ready -> print welcome prompt */
1034
  aosprintf("\n");
1035
  aosprintf("######################################################################\n");
1036
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
1037
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
1038
  aosprintf("# Copyright (C) 2016..2019  Thomas Schöpping et al.                  #\n");
1039
  aosprintf("#                                                                    #\n");
1040
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
1041
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
1042
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
1043
  aosprintf("# The development of this software was supported by the Excellence   #\n");
1044
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
1045
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
1046
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
1047
  aosprintf("######################################################################\n");
1048
  aosprintf("\n");
1049

    
1050
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
1051
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
1052
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
1053
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS) */
1054
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
1055
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS) */
1056
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_6) */
1057

    
1058
#if (AMIROOS_CFG_TESTS_ENABLE == true)
1059
#if defined(MODULE_INIT_TESTS)
1060
  MODULE_INIT_TESTS();
1061
#else /* defined(MODULE_INIT_TESTS) */
1062
  #warning "AMIROOS_CFG_TESTS_ENABLE set to true, but MODULE_INIT_TESTS() not defined"
1063
#endif /* defined(MODULE_INIT_TESTS) */
1064
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */
1065

    
1066
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7)
1067
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS)
1068
  AMIROOS_CFG_MAIN_INIT_HOOK_7(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS);
1069
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS) */
1070
  AMIROOS_CFG_MAIN_INIT_HOOK_7();
1071
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS) */
1072
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_7) */
1073

    
1074
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1075
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
1076
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
1077
    /*
1078
     * This code is executed if the received event was not about the SYS_SYNC control signal.
1079
     * The returned event could be caused by any listener (not only the argument).
1080
     */
1081
    // IO event
1082
    if (eventmask & _eventListenerIO.events) {
1083
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1084
      // PD event
1085
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1086
        shutdown = AOS_SHUTDOWN_PASSIVE;
1087
      } else {
1088
#if defined(MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK)
1089
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1090
#else /* defined(MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK) */
1091
        // ignore any other IO events
1092
#endif /* defined(MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK) */
1093
      }
1094
    }
1095
    // OS event
1096
    else if (eventmask & _eventListenerOS.events) {
1097
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1098
      _unexpectedEventError(eventmask, eventflags);
1099
    }
1100
    // unknown event
1101
    else {
1102
      _unexpectedEventError(eventmask, 0);
1103
    }
1104
  }
1105

    
1106
#if (HAL_USE_CAN == TRUE)
1107

    
1108
  /*
1109
   * There must be no delays at this point, thus no hook is allowed.
1110
   */
1111

    
1112
  /* SSSP startup stage 3 (module stack initialization) */
1113
  if (shutdown == AOS_SHUTDOWN_NONE) {
1114
    shutdown = _ssspModuleStackInitialization();
1115
  }
1116

    
1117
  /*
1118
   * There must be no delays at this point, thus no hook is allowed.
1119
   */
1120

    
1121
#if (HAL_USE_RTC == TRUE)
1122
  /* synchronize calendars */
1123
  if (shutdown == AOS_SHUTDOWN_NONE) {
1124
#if (AMIROOS_CFG_SSSP_MASTER == true)
1125
    CANTxFrame frame;
1126
    struct tm t;
1127
    uint64_t encoded;
1128

    
1129
    frame.DLC = 8;
1130
    frame.RTR = CAN_RTR_DATA;
1131
    frame.IDE = CAN_IDE_STD;
1132
    frame.SID = CALENDERSYNC_CANMSGID;
1133

    
1134
    aosDbgPrintf("transmitting current date/time...\t");
1135
    // get current date & time
1136
    aosSysGetDateTime(&t);
1137
    // encode
1138
    encoded = _TM2U64(&t);
1139
    // serialize
1140
    _serialize(frame.data8, encoded, 8);
1141
    // transmit
1142
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1143

    
1144
    aosDbgPrintf("done\n");
1145
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
1146
    CANRxFrame frame;
1147
    uint64_t encoded;
1148
    struct tm t;
1149

    
1150
    aosDbgPrintf("receiving current date/time...\t");
1151
    // receive message
1152
#if (AMIROOS_CFG_DBG == true)
1153
    // increase timeout in debug mode due to additional delays introduced by the many prinf() calls
1154
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(10 * AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1155
#else /* (AMIROOS_CFG_DBG == true) */
1156
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1157
#endif /* (AMIROOS_CFG_DBG == true) */
1158
      // validate message
1159
      if (frame.DLC == 8 &&
1160
          frame.RTR == CAN_RTR_DATA &&
1161
          frame.IDE == CAN_IDE_STD &&
1162
          frame.SID == CALENDERSYNC_CANMSGID) {
1163
        // deserialize
1164
        encoded = _deserialize(frame.data8, 8);
1165
        // decode
1166
        _U642TM(&t, encoded);
1167
        // set current date & time
1168
        aosSysSetDateTime(&t);
1169
        aosDbgPrintf("success\n");
1170
      } else {
1171
        aosDbgPrintf("fail (invalid message)\n");
1172
      }
1173
    } else {
1174
      aosDbgPrintf("fail (timeout)\n");
1175
    }
1176
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
1177
    aosDbgPrintf("\n");
1178
  }
1179
#endif /* (HAL_USE_RTC == TRUE) */
1180
#endif /* (HAL_USE_CAN == TRUE) */
1181
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1182

    
1183
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1184
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1185
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1186
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS) */
1187
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1188
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS) */
1189
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_8) */
1190

    
1191
  /* completely start AMiRo-OS */
1192
  if (shutdown == AOS_SHUTDOWN_NONE) {
1193
    aosSysStart();
1194
  }
1195

    
1196
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1197
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1198
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1199
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS) */
1200
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1201
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS) */
1202
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_9) */
1203

    
1204
  /*
1205
   * ##########################################################################
1206
   * # infinite loop                                                          #
1207
   * ##########################################################################
1208
   */
1209

    
1210
  // sleep until a shutdown event is received
1211
  while (shutdown == AOS_SHUTDOWN_NONE) {
1212
    // wait for an event
1213
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1214
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1215
#else /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0) */
1216
    eventmask = chEvtWaitOne(ALL_EVENTS);
1217
#endif /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0) */
1218

    
1219
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1220
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1221
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1222
#else /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS) */
1223
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1224
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS) */
1225
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0) */
1226

    
1227
    switch (eventmask) {
1228
      // if this was an I/O event
1229
      case IOEVENT_MASK:
1230
        // evaluate flags
1231
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1232
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1233
        // PD event
1234
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1235
          shutdown = AOS_SHUTDOWN_PASSIVE;
1236
        }
1237
        // all other events
1238
#if defined(MODULE_MAIN_LOOP_IO_EVENT)
1239
        else {
1240
          MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1241
        }
1242
#endif /* defined(MODULE_MAIN_LOOP_IO_EVENT) */
1243
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1244
#if defined(MODULE_MAIN_LOOP_IO_EVENT)
1245
        MODULE_MAIN_LOOP_IO_EVENT(eventflags);
1246
#endif /* defined(MODULE_MAIN_LOOP_IO_EVENT) */
1247
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1248
        break;
1249

    
1250
      // if this was an OS event
1251
      case OSEVENT_MASK:
1252
        // evaluate flags
1253
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1254
        switch (eventflags) {
1255
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1256
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1257
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1258
            break;
1259
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1260
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1261
            break;
1262
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1263
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1264
            break;
1265
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1266
            shutdown = AOS_SHUTDOWN_RESTART;
1267
            break;
1268
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1269
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN:
1270
            shutdown = AOS_SHUTDOWN_DEFAULT;
1271
            break;
1272
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1273
          default:
1274
            _unexpectedEventError(eventmask, eventflags);
1275
            break;
1276
        }
1277
        break;
1278

    
1279
      // if this was any other event (should be impossible to occur)
1280
      default:
1281
        eventflags = 0;
1282
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0)
1283
        _unexpectedEventError(eventmask, eventflags);
1284
#endif /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0) */
1285
        break;
1286
    }
1287

    
1288
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1289
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1290
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1291
#else /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS) */
1292
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1293
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS) */
1294
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1) */
1295
  }
1296

    
1297
  /*
1298
   * ##########################################################################
1299
   * # system shutdown                                                        #
1300
   * ##########################################################################
1301
   */
1302

    
1303
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1304
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1305
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1306
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS) */
1307
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1308
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS) */
1309
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0) */
1310

    
1311
  // initialize/acknowledge shutdown
1312
  aosSysShutdownInit(shutdown);
1313

    
1314
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1315
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1316
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1317
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS) */
1318
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1319
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS) */
1320
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1) */
1321

    
1322
  // stop system threads
1323
  aosSysStop();
1324

    
1325
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1326
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1327
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1328
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS) */
1329
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1330
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS) */
1331
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2) */
1332

    
1333
  // deinitialize system
1334
  aosSysDeinit();
1335

    
1336
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1337
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1338
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1339
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS) */
1340
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1341
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS) */
1342
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3) */
1343

    
1344
  /* stop all periphery communication interfaces */
1345
#if defined(MODULE_SHUTDOWN_PERIPHERY_IF)
1346
  MODULE_SHUTDOWN_PERIPHERY_IF();
1347
#endif /* defined(MODULE_SHUTDOWN_PERIPHERY_IF) */
1348
#if (HAL_USE_CAN == TRUE)
1349
  if (MODULE_HAL_CAN.state != CAN_STOP) {
1350
    canStop(&MODULE_HAL_CAN);
1351
  }
1352
#endif /* (HAL_USE_CAN == TRUE) */
1353

    
1354
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1355
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1356
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1357
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS) */
1358
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1359
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS) */
1360
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4) */
1361

    
1362
  // finally hand over to bootloader
1363
  aosSysShutdownFinal(shutdown);
1364

    
1365
  /*
1366
   * ##########################################################################
1367
   * # after shutdown/restart                                                 #
1368
   * ##########################################################################
1369
   *
1370
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1371
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1372
   *       which subsystems should NOT be shut down.
1373
   */
1374

    
1375
  // return an error, since this code should not be executed
1376
  return -1;
1377
}
1378

    
1379
/******************************************************************************/
1380
/* EXPORTED FUNCTIONS                                                         */
1381
/******************************************************************************/
1382

    
1383
/** @} */