Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_main.cpp @ 933df08e

History | View | Annotate | Download (37.1 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2018  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
#include <amiroos.h>
20
#include <module.h>
21

    
22
/*
23
 * hook to add further includes
24
 */
25
#if defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER)
26
#include AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER
27
#endif
28

    
29
/**
30
 * @brief   Event mask to identify I/O events.
31
 */
32
#define IOEVENT_MASK                            EVENT_MASK(0)
33

    
34
/**
35
 * @brief   Event mask to identify OS events.
36
 */
37
#define OSEVENT_MASK                            EVENT_MASK(1)
38

    
39
/**
40
 * @brief   Event mask to idetify CAN events.
41
 */
42
#define CANEVENT_MASK                           EVENT_MASK(2)
43

    
44
/**
45
 * @brief   Event mask to idetify timeout events.
46
 */
47
#define TIMEOUTEVENT_MASK                       EVENT_MASK(3)
48

    
49
/**
50
 * @brief   Event mask to idetify signal delay events.
51
 */
52
#define DELAYEVENT_MASK                         EVENT_MASK(4)
53

    
54
/**
55
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
56
 */
57
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
58

    
59
/**
60
 * @brief   CAN message identifier for transmitting module IDs during the SSSP stack initialization sequence.
61
 */
62
#define SSSP_STACKINIT_CANMSGID_MODULEID        0x002
63

    
64
/**
65
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
66
 */
67
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
68

    
69
/**
70
 * @brief   Listener object for I/O events.
71
 */
72
static event_listener_t _eventListenerIO;
73

    
74
/**
75
 * @brief   Listener object for OS events.
76
 */
77
static event_listener_t _eventListenerOS;
78

    
79
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
80
/**
81
 * @brief   I/O channel for the programmer interface.
82
 */
83
static AosIOChannel _stdiochannel;
84

    
85
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
86
/**
87
 * @brief   I/O shell channel for the programmer interface.
88
 */
89
static AosShellChannel _stdshellchannel;
90
#endif
91
#endif
92

    
93
/*
94
 * hook to add further static variables
95
 */
96
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
97
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
98
#endif
99

    
100
/**
101
 * @brief   Prints an error message about an unexpected event.
102
 *
103
 * @param[in] mask    The event mask.
104
 * @param[in] flags   The event flags.
105
 */
106
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
107
{
108
#if (AMIROOS_CFG_DBG == true)
109
  aosprintf("unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
110
#else
111
  (void)(mask);
112
  (void)(flags);
113
#endif
114
}
115

    
116
/**
117
 * @brief   Callback function to be used during SSSP stack initialization sequence.
118
 *
119
 * @param[in] par   A pointer to an @p event_source_t to be fired.
120
 */
121
static void _ssspTimerCallback(void* par)
122
{
123
  aosDbgCheck(par != NULL);
124

    
125
  chSysLockFromISR();
126
  chEvtBroadcastI((event_source_t*)par);
127
  chSysUnlockFromISR();
128

    
129
  return;
130
}
131

    
132
/**
133
 * @brief   Helper function to serialize 32 bit data.
134
 *
135
 * @param[out]  dst   Pointer to the output buffer.
136
 * @param[in]   src   32 bit data to be serielized.
137
 */
138
inline void _canSerialize32(uint8_t* dst, const uint32_t src)
139
{
140
  aosDbgCheck(dst != NULL);
141

    
142
  for (uint8_t byte = 0; byte < 4; ++byte) {
143
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
144
  }
145

    
146
  return;
147
}
148

    
149
/**
150
 * @brief   Helper function to deserialize 32 bit data.
151
 *
152
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
153
 *
154
 * @return    The deserialized 32 bit data.
155
 */
156
inline uint32_t _canDeserialize32(uint8_t* src)
157
{
158
  aosDbgCheck(src != NULL);
159

    
160
  return ((uint32_t)src[0]) | (((uint32_t)src[1]) << 8) | (((uint32_t)src[2]) << 16) | (((uint32_t)src[3]) << 24);
161
}
162

    
163
/**
164
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
165
 *
166
 * @return Shutdown value.
167
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
168
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
169
 */
170
aos_shutdown_t _ssspModuleStackInitialization(void)
171
{
172
  // local types
173
  /**
174
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
175
   */
176
  typedef enum {
177
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
178
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
179
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
180
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
181
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
182
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
183
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
184
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
185
  } sssp_modulestackinitstage_t;
186

    
187
  typedef struct {
188
    bool loop     : 1;
189
    bool wfe      : 1;
190
    bool wfe_next : 1;
191
  } flags_t;
192

    
193
  // local variables
194
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
195
  sssp_modulestackinitstage_t stage = STAGE_3_1;
196
  eventmask_t eventmask = 0;
197
  eventflags_t ioflags;
198
  event_source_t eventSourceTimeout;
199
  event_source_t eventSourceDelay;
200
  event_listener_t eventListenerTimeout;
201
  event_listener_t eventListenerDelay;
202
  event_listener_t eventListenerCan;
203
  virtual_timer_t timerTimeout;
204
  virtual_timer_t timerDelay;
205
  CANTxFrame canTxFrame;
206
  CANRxFrame canRxFrame;
207
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
208
  aos_ssspmoduleid_t lastid = 0;
209
#endif
210
  flags_t flags;
211

    
212
  // initialize local varibles
213
  chEvtObjectInit(&eventSourceTimeout);
214
  chEvtObjectInit(&eventSourceDelay);
215
  chVTObjectInit(&timerTimeout);
216
  chVTObjectInit(&timerDelay);
217
  canTxFrame.RTR = CAN_RTR_DATA;
218
  canTxFrame.IDE = CAN_IDE_STD;
219
  flags.loop = true;
220
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
221
  flags.wfe_next = true;
222

    
223
  // initialize system variables
224
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
225
  aos.sssp.moduleId = 0;
226

    
227
  // listen to events (timout, delay, CAN receive)
228
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
229
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
230
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
231

    
232
  /*
233
   * FSM in a loop.
234
   *
235
   * This is a fully event-based FSM for the module stack initialization
236
   * sequence, defined by SSSP as startup stage 3. There are five different
237
   * events that can occur at this point:
238
   *  I/O events: The input level of an input pin has changed. Such events must
239
   *              be handled differently depending on the current state. Most
240
   *              of the time, however, such events can be ignored.
241
   *  OS events:  Such events are only available after this stage completed and
242
   *              thus should never occur. However, there is an optional hook
243
   *              to handle such events, nevertheless.
244
   *  CAN events: At least one CAN message was received. Note that this event
245
   *              will only fire again if all input buffers have been cleared.
246
   *  timeouts:   If some module does not support the sequence of there is any
247
   *              issue, such a case is detected via timeouts and must be
248
   *              handled accordingly (see abort state). In some cases, it is
249
   *              possible that a timeout event occurres 'simultaneously' with
250
   *              some other event. This can be caused by several timing issues
251
   *              and is a valid situation. As a result, any other events
252
   *              should be handled before the timeout event. If the other
253
   *              events are expected and valid, this implementation requires
254
   *              the timeout event flag to be cleared explicitely. Otherwise
255
   *              it is evaluated at the end of each iteration of the loop.
256
   *  delays:     Depending on the current state, delays are required by SSSP
257
   *              for timing of the sequential activation of signals.
258
   */
259
  aosDbgPrintf("SSSP stack initialization sequence:\n");
260
  while (flags.loop) {
261
#if (AMIROOS_CFG_DBG == true)
262
    switch (stage) {
263
      case STAGE_3_1:
264
        aosDbgPrintf(">>> 3-1\n");
265
        break;
266
      case STAGE_3_2:
267
        aosDbgPrintf(">>> 3-2\n");
268
        break;
269
      case STAGE_3_3_WAITFORFIRSTID:
270
        aosDbgPrintf(">>> 3-3 (1st ID)\n");
271
        break;
272
      case STAGE_3_3_WAITFORIDORSIG:
273
        aosDbgPrintf(">>> 3-3 (ID/sig)\n");
274
        break;
275
      case STAGE_3_3_WAITFORID:
276
        aosDbgPrintf(">>> 3-3 (ID)\n");
277
        break;
278
      case STAGE_3_4_FINISH:
279
        aosDbgPrintf(">>> 3-4 (finish)\n");
280
        break;
281
      case STAGE_3_4_ABORT_ACTIVE:
282
        aosDbgPrintf(">>> 3-4 (avtive abort)\n");
283
        break;
284
      case STAGE_3_4_ABORT:
285
        aosDbgPrintf(">>> 3-4 (abort)\n");
286
        break;
287
    }
288
#endif
289

    
290
    // reset wfe flag for the next iteration
291
    flags.wfe_next = true;
292

    
293
    // waiting for events may be skipped
294
    if (flags.wfe) {
295
      // wait for any event to occur
296
      aosDbgPrintf("WFE...");
297
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT));
298
      aosDbgPrintf("\t0x%08X", eventmask);
299
    } else {
300
      aosDbgPrintf("WFE skipped");
301
    }
302
    aos_timestamp_t uptime;
303
    aosSysGetUptime(&uptime);
304
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / 1000));
305

    
306
    /*
307
     * execute some general tasks and high priority events
308
     */
309
    // no event occurred at all
310
    if ((flags.wfe) && (eventmask == 0)) {
311
      aosDbgPrintf("ERR: no evt\n");
312
      // enforce timeout event
313
      chEvtBroadcast(&eventSourceTimeout);
314
      continue;
315
    }
316
    // if an IO event occurred
317
    if (eventmask & IOEVENT_MASK) {
318
      ioflags = chEvtGetAndClearFlags(&_eventListenerIO);
319
      aosDbgPrintf("INFO: IO evt (0x%08X)\n", ioflags);
320
      // a power-down event occurred
321
      if (ioflags & MODULE_SSSP_EVENTFLAGS_PD) {
322
        aosDbgPrintf("PD evt\n");
323
        // deactivate S and UP
324
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
325
  #if (AMIROOS_CFG_SSSP_STACK_END != true)
326
        apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
327
  #endif
328
        // set shutdown flag and exit the loop
329
        shutdown = AOS_SHUTDOWN_PASSIVE;
330
        break;
331
      }
332
      // the S signal was deactivated
333
      if (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC) {
334
        apalControlGpioState_t sstate;
335
        apalControlGpioGet(&moduleSsspGpioSync, &sstate);
336
        if (sstate == APAL_GPIO_OFF) {
337
          aosDbgPrintf("-S evt\n");
338
          // either finish or abort
339
          if ((stage == STAGE_3_3_WAITFORID) && (aos.sssp.moduleId != 0)) {
340
            stage = STAGE_3_4_FINISH;
341
          } else if (stage != STAGE_3_4_ABORT) {
342
            stage = STAGE_3_4_ABORT_ACTIVE;
343
          }
344
        }
345
      }
346
    }
347
    // an OS event occurred
348
    if (eventmask & OSEVENT_MASK) {
349
      aosDbgPrintf("WARN: OS evt\n");
350
      // get the flags
351
      eventflags_t oseventflags = chEvtGetAndClearFlags(&_eventListenerOS);
352
      // there should be no OS events at this point
353
#ifdef MODULE_SSSP_STARTUP_3_OSEVENT_HOOK
354
      MODULE_SSSP_STARTUP_3_OSEVENT_HOOK(eventmask, eventflags);
355
#else
356
      _unexpectedEventError(eventmask, oseventflags);
357
#endif
358
    }
359
    // if a CAN event occurred
360
    if ((eventmask & CANEVENT_MASK)) {
361
      // fetch message
362
      if (flags.wfe) {
363
        canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE);
364
        aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
365
      }
366
      // identify and handle abort messgaes
367
      if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
368
        stage = STAGE_3_4_ABORT;
369
      }
370
      // warn if a unexpected message was received
371
      else if ((canRxFrame.SID != SSSP_STACKINIT_CANMSGID_INIT) &&
372
               (canRxFrame.SID != SSSP_STACKINIT_CANMSGID_MODULEID)) {
373
        aosDbgPrintf("WARN: unknown msg\n");
374
      }
375
      // any further pending messages are fetched at the end of the loop
376
    }
377
    // if a timeout event occurred
378
    if (eventmask & TIMEOUTEVENT_MASK) {
379
      // is handled at the end of the loop (or must be cleared by FSM)
380
    }
381
    // if a delay event occurred
382
    if (eventmask & DELAYEVENT_MASK) {
383
      // is handled by FSM
384
    }
385

    
386
    /*
387
     * this is the actual FSM
388
     */
389
    switch (stage) {
390
      case STAGE_3_1:
391
      {
392
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
393

    
394
        // there was no event at all (skipped wfe)
395
        if (eventmask == 0 && flags.wfe == false) {
396
#if (AMIROOS_CFG_SSSP_MASTER == true)
397
          // initialize the stage by transmitting an according CAN message
398
          aosDbgPrintf("CAN -> init\n");
399
          canTxFrame.DLC = 0;
400
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
401
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
402
            chEvtBroadcast(&eventSourceTimeout);
403
            break;
404
          }
405
          // activate S
406
          aosDbgPrintf("S+\n");
407
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
408
#if (AMIROOS_CFG_SSSP_STACK_START == true)
409
          // proceed immediately
410
          stage = STAGE_3_2;
411
          flags.wfe_next = false;
412
#else
413
          // set the timeout timer
414
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
415
          // proceed
416
          stage = STAGE_3_3_WAITFORFIRSTID;
417
#endif
418
#else
419
          // set the timeout timer
420
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
421
#endif
422
        }
423

    
424
#if (AMIROOS_CFG_SSSP_MASTER != true)
425
        // a CAN message was received
426
        else if (eventmask & CANEVENT_MASK) {
427
          // if an initiation message was received
428
          if (canRxFrame.DLC == 0 &&
429
              canRxFrame.RTR == CAN_RTR_DATA &&
430
              canRxFrame.IDE == CAN_IDE_STD &&
431
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
432
            aosDbgPrintf("init msg\n");
433
            // reset the timeout timer and clear pending flags
434
            chVTReset(&timerTimeout);
435
            chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
436
            eventmask &= ~TIMEOUTEVENT_MASK;
437
            // activate S
438
            aosDbgPrintf("S+\n");
439
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
440
#if (AMIROOS_CFG_SSSP_STACK_START == true)
441
            // proceed
442
            stage = STAGE_3_2;
443
            flags.wfe_next = false;
444
#else
445
            // set the timeout timer
446
            chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
447
            // proceed
448
            stage = STAGE_3_3_WAITFORFIRSTID;
449
#endif
450
          }
451
        }
452
#endif
453

    
454
        break;
455
      } /* end of STAGE_3_1 */
456

    
457
      case STAGE_3_2:
458
      {
459
#if (AMIROOS_CFG_SSSP_STACK_START == true)
460
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
461

    
462
        // if this stage was just entered
463
        if (flags.wfe == false) {
464
          // set the module ID
465
          aos.sssp.moduleId = 1;
466
          // broadcast module ID
467
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
468
          canTxFrame.DLC = 4;
469
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
470
          _canSerialize32(canTxFrame.data8, aos.sssp.moduleId);
471
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
472
            chEvtBroadcast(&eventSourceTimeout);
473
            break;
474
          }
475
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
476
          lastid = aos.sssp.moduleId;
477
#endif
478
#if (AMIROOS_CFG_SSSP_STACK_END == true)
479
          // sequence is already over
480
          // deactivate S
481
          aosDbgPrintf("S-\n");
482
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
483
          // proceed
484
          stage = STAGE_3_3_WAITFORID;
485
#else
486
          // set the delay timer so the UP signal is activated later
487
          chVTSet(&timerDelay, LL_US2ST(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
488
#endif
489
        }
490

    
491
        // if a delay event occurred
492
        if (eventmask & DELAYEVENT_MASK) {
493
          // activate UP
494
          aosDbgPrintf("UP+\n");
495
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
496
          // deactivate S
497
          aosDbgPrintf("S-\n");
498
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
499
          // explicitely clear timeout event flag
500
          chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
501
          eventmask &= ~TIMEOUTEVENT_MASK;
502
          // proceed
503
          stage = STAGE_3_3_WAITFORID;
504
        }
505
#endif
506

    
507
        break;
508
      } /* end of STAGE_3_2 */
509

    
510
      case STAGE_3_3_WAITFORFIRSTID:
511
      {
512
#if (AMIROOS_CFG_SSSP_STACK_START != true)
513
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
514

    
515
        // a CAN message was received
516
        if (eventmask & CANEVENT_MASK) {
517
          // if an ID message was received
518
          if (canRxFrame.DLC == 4 &&
519
              canRxFrame.RTR == CAN_RTR_DATA &&
520
              canRxFrame.IDE == CAN_IDE_STD &&
521
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
522
            aosDbgPrintf("ID (%u)\n", _canDeserialize32(canRxFrame.data8));
523
            // validate received ID
524
            if (lastid < _canDeserialize32(canRxFrame.data8)) {
525
              // store received ID
526
              lastid = _canDeserialize32(canRxFrame.data8);
527
              // restart timeout timer
528
              chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
529
              // proceed
530
              stage = STAGE_3_3_WAITFORIDORSIG;
531
            } else {
532
              aosDbgPrintf("ERR: invalid ID\n");
533
              // abort
534
              stage = STAGE_3_4_ABORT_ACTIVE;
535
              flags.wfe_next = false;
536
            }
537
            // explicitely clear timeout event flag
538
            chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
539
            eventmask &= ~TIMEOUTEVENT_MASK;
540
          }
541
        }
542
#endif
543
        break;
544
      } /* end of STAGE_3_3_WAITFORFIRSTID */
545

    
546
      case STAGE_3_3_WAITFORIDORSIG:
547
      {
548
#if (AMIROOS_CFG_SSSP_STACK_START != true)
549
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
550

    
551
        // a CAN message was received
552
        if (eventmask & CANEVENT_MASK) {
553
          // if an ID message was received
554
          if (canRxFrame.DLC == 4 &&
555
              canRxFrame.RTR == CAN_RTR_DATA &&
556
              canRxFrame.IDE == CAN_IDE_STD &&
557
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
558
            aosDbgPrintf("ID (%u)\n", _canDeserialize32(canRxFrame.data8));
559
            // validate received ID
560
            if (lastid < _canDeserialize32(canRxFrame.data8)) {
561
              // store received ID
562
              lastid = _canDeserialize32(canRxFrame.data8);
563
              // restart timeout timer
564
              chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
565
            } else {
566
              aosDbgPrintf("ERR: invalid ID\n");
567
              // abort
568
              stage = STAGE_3_4_ABORT_ACTIVE;
569
              flags.wfe_next = false;
570
            }
571
            // explicitely clear timeout event flag
572
            chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
573
            eventmask &= ~TIMEOUTEVENT_MASK;
574
          }
575
        }
576

    
577
        // if an IO event was received (DN signal)
578
        if ((eventmask & IOEVENT_MASK) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
579
          aosDbgPrintf("DN <-\n");
580
          // reset timeout timer
581
          chVTReset(&timerTimeout);
582
          chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
583
          eventmask &= ~TIMEOUTEVENT_MASK;
584
          // increment and broadcast ID
585
          aos.sssp.moduleId = lastid + 1;
586
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
587
          canTxFrame.DLC = 4;
588
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
589
          _canSerialize32(canTxFrame.data8, aos.sssp.moduleId);
590
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
591
            chEvtBroadcast(&eventSourceTimeout);
592
            break;
593
          }
594
          // set delay timer
595
          chVTSet(&timerDelay, LL_US2ST(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
596
        }
597

    
598
        // if a delay event occurred
599
        if (eventmask & DELAYEVENT_MASK) {
600
#if (AMIROOS_CFG_SSSP_STACK_END != true)
601
          // activate UP
602
          aosDbgPrintf("UP+\n");
603
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
604
#endif
605
          // deactivate S
606
          aosDbgPrintf("S-\n");
607
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
608
          // reset the timeout timer
609
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
610
          chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
611
          eventmask &= ~TIMEOUTEVENT_MASK;
612
          // proceed
613
          stage = STAGE_3_3_WAITFORID;
614
        }
615
#endif
616

    
617
        break;
618
      } /* end of STAGE_3_3_WAITFORIDORSIG */
619

    
620
      case STAGE_3_3_WAITFORID:
621
      {
622
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
623

    
624
#if (AMIROOS_CFG_SSSP_STACK_END != true)
625
        // a CAN message was received
626
        if (eventmask & CANEVENT_MASK) {
627
          // if an ID message was received
628
          if (canRxFrame.DLC == 4 &&
629
              canRxFrame.RTR == CAN_RTR_DATA &&
630
              canRxFrame.IDE == CAN_IDE_STD &&
631
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
632
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
633
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
634
            lastid = _canDeserialize32(canRxFrame.data8);
635
            aosDbgPrintf("ID (%u)\n", lastid);
636
#endif
637
            // restart timeout timer
638
            chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
639
            chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
640
            eventmask &= ~TIMEOUTEVENT_MASK;
641
          }
642
        }
643
#endif
644

    
645
        break;
646
      } /* end of STAGE_3_3_WAITFORID */
647

    
648
      case STAGE_3_4_FINISH:
649
      {
650
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
651

    
652
        // if an IO event was received (S signal)
653
        if ((eventmask & IOEVENT_MASK) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
654
          // reset the timeout timer
655
          chVTReset(&timerTimeout);
656
          chEvtWaitAnyTimeout(TIMEOUTEVENT_MASK, TIME_IMMEDIATE);
657
          eventmask &= ~TIMEOUTEVENT_MASK;
658
          //set the delay timer
659
          chVTSet(&timerDelay, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
660
        }
661

    
662
        // if a CAN event was received
663
        if (eventmask & CANEVENT_MASK) {
664
          // if an abort message was received
665
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
666
            aosDbgPrintf("abort msg\n");
667
            // reset the delay timer
668
            chVTReset(&timerDelay);
669
            chEvtWaitAnyTimeout(DELAYEVENT_MASK, TIME_IMMEDIATE);
670
            eventmask &= ~DELAYEVENT_MASK;
671
            // proceed
672
            stage = STAGE_3_4_ABORT;
673
          }
674
        }
675

    
676
        // if a delay timer event occurred
677
        if (eventmask & DELAYEVENT_MASK) {
678
          aosDbgPrintf("sequence sucessful\n");
679
          // sequence finished sucessfully
680
          flags.loop = false;
681
        }
682

    
683
        break;
684
      } /* end of STAGE_3_4_FINISH */
685

    
686
      case STAGE_3_4_ABORT_ACTIVE:
687
      {
688
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
689

    
690
        // emit abort message
691
        canTxFrame.DLC = 0;
692
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
693
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
694
        aosDbgPrintf("CAN -> abort\n");
695
        // clear timeout flag
696
        eventmask &= ~TIMEOUTEVENT_MASK;
697
        // proceed immediately
698
        stage = STAGE_3_4_ABORT;
699
        flags.wfe_next = false;
700
        break;
701
      } /* end of STAGE_3_4_ABORT_ACTIVE */
702

    
703
      case STAGE_3_4_ABORT:
704
      {
705
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
706

    
707
        // deactivate S
708
        aosDbgPrintf("S-\n");
709
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
710
        // invalidate module ID
711
        aos.sssp.moduleId = 0;
712

    
713
        // if an IO event was received (S signal)
714
        if ((eventmask & IOEVENT_MASK) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
715
          aosDbgPrintf("sequence aborted\n");
716
          // exit the sequence
717
          flags.loop = false;
718
        }
719

    
720
        break;
721
      } /* end of STAGE_3_4_ABORT */
722
    }
723

    
724
    // fetch pending CAN message (if any)
725
    if ((eventmask & CANEVENT_MASK) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
726
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
727
      flags.wfe_next = false;
728
    }
729

    
730
    // handle unhandled timeout events
731
    if (eventmask & TIMEOUTEVENT_MASK) {
732
      aosDbgPrintf("ERR: timeout evt\n");
733
      // abort
734
      flags.wfe_next = false;
735
      stage = STAGE_3_4_ABORT_ACTIVE;
736
    }
737

    
738
    // apply wfe value for next iteration
739
    flags.wfe = flags.wfe_next;
740
  }
741
  aosDbgPrintf("\n");
742

    
743
  // unregister all events (timeout, delay, CAN receive)
744
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
745
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
746
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
747
  // clear any pending events (timeout, delay, CAN receive)
748
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
749

    
750
  // reset all control signals
751
#if (AMIROOS_CFG_SSSP_STACK_END != true)
752
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
753
#endif
754
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
755

    
756
  return shutdown;
757
}
758

    
759
/**
760
 * @brief   Application entry point.
761
 */
762
int main(void)
763
{
764
  // local variables
765
  eventmask_t eventmask = 0;
766
  eventflags_t eventflags = 0;
767
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
768
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
769
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
770
#endif
771

    
772
  /*
773
   * ##########################################################################
774
   * # system initialization                                                  #
775
   * ##########################################################################
776
   */
777

    
778
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
779
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
780
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
781
#else
782
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
783
#endif
784
#endif
785

    
786
  /* hardware, kernel, and operating system initialization */
787
  // ChibiOS/HAL and custom hal additions (if any)
788
  halInit();
789
#ifdef MODULE_INIT_HAL_EXTRA
790
  MODULE_INIT_HAL_EXTRA();
791
#endif
792

    
793
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
794
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
795
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
796
#else
797
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
798
#endif
799
#endif
800

    
801
  // ChibiOS/RT kernel and custom kernel additions (if any)
802
  chSysInit();
803
#ifdef MODULE_INIT_KERNEL_EXTRA
804
  MODULE_INIT_KERNEL_EXTRA();
805
#endif
806

    
807
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
808
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
809
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
810
#else
811
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
812
#endif
813
#endif
814

    
815
  // AMiRo-OS and custom OS additions (if any)
816
#if (AMIROOS_CFG_SHELL_ENABLE == true)
817
  aosSysInit(moduleShellPrompt);
818
#else
819
  aosSysInit();
820
#endif
821
#ifdef MODULE_INIT_OS_EXTRA
822
  MODULE_INIT_OS_EXTRA();
823
#endif
824

    
825
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
826
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
827
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
828
#else
829
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
830
#endif
831
#endif
832

    
833
#if (AMIROOS_CFG_TESTS_ENABLE == true)
834
  MODULE_INIT_TESTS();
835
#endif
836

    
837
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
838
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
839
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
840
#else
841
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
842
#endif
843
#endif
844

    
845
  /* event associations */
846
  chEvtRegisterMask(&aos.events.io, &_eventListenerIO, IOEVENT_MASK);
847
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
848

    
849
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
850
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
851
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
852
#else
853
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
854
#endif
855
#endif
856

    
857
  /* periphery communication initialization */
858
  // CAN (mandatory)
859
  canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
860
  // module specific initialization (if any)
861
#ifdef MODULE_INIT_PERIPHERY_COMM
862
  MODULE_INIT_PERIPHERY_COMM();
863
#endif
864
  // user interface (if any)
865
#ifdef MODULE_HAL_PROGIF
866
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
867
  aosIOChannelOutputEnable(&_stdiochannel);
868
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
869
#if (AMIROOS_CFG_SHELL_ENABLE == true)
870
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
871
  aosShellChannelInputEnable(&_stdshellchannel);
872
  aosShellChannelOutputEnable(&_stdshellchannel);
873
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
874
#endif
875
#endif
876

    
877
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
878
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
879
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
880
#else
881
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
882
#endif
883
#endif
884

    
885
  /* module is ready -> print welcome prompt */
886
  aosprintf("\n");
887
  aosprintf("######################################################################\n");
888
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
889
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
890
  aosprintf("# Copyright (C) 2016..2018  Thomas Schöpping et al.                  #\n");
891
  aosprintf("#                                                                    #\n");
892
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
893
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
894
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
895
  aosprintf("# The development of this software was supported by the Excellence   #\n");
896
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
897
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
898
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
899
  aosprintf("######################################################################\n");
900
  aosprintf("\n");
901

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

    
910
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
911
  while ((eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
912
    /*
913
     * This code is executed if the received event was not about the SYS_SYNC control signal.
914
     * The returned event could be caused by any listener (not only the argument).
915
     */
916
    // unexpected IO events
917
    if (eventmask & _eventListenerIO.events) {
918
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
919
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
920
      MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
921
#else
922
      _unexpectedEventError(eventmask, eventflags);
923
#endif
924
    }
925
    // unexpected OS event
926
    else if (eventmask & _eventListenerOS.events) {
927
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
928
      _unexpectedEventError(eventmask, eventflags);
929
    }
930
#if (AMIROOS_CFG_DBG == true)
931
    // unknown event (must never occur, thus disabled for release builds)
932
    else {
933
      _unexpectedEventError(eventmask, 0);
934
    }
935
#endif
936
  }
937

    
938
  /*
939
   * There must be no delays at this point, thus no hook is allowed.
940
   */
941

    
942
  /* SSSP startup stage 3 (module stack initialization) */
943
  shutdown = _ssspModuleStackInitialization();
944

    
945
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
946
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
947
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
948
#else
949
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
950
#endif
951
#endif
952

    
953
  /* completely start AMiRo-OS */
954
  if (shutdown == AOS_SHUTDOWN_NONE) {
955
    aosSysStart();
956
  }
957

    
958
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
959
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
960
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
961
#else
962
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
963
#endif
964
#endif
965

    
966
  /*
967
   * ##########################################################################
968
   * # infinite loop                                                          #
969
   * ##########################################################################
970
   */
971

    
972
  // sleep until a shutdown event is received
973
  while (shutdown == AOS_SHUTDOWN_NONE) {
974
    // wait for an event
975
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
976
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, US2ST_LLD(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
977
#else
978
    eventmask = chEvtWaitOne(ALL_EVENTS);
979
#endif
980

    
981
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
982
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
983
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
984
#else
985
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
986
#endif
987
#endif
988

    
989
    switch (eventmask) {
990
      // if this was an I/O event
991
      case IOEVENT_MASK:
992
        // evaluate flags
993
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
994
        // PD event
995
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
996
          shutdown = AOS_SHUTDOWN_PASSIVE;
997
        }
998
        // all other events
999
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1000
        else {
1001
          MODULE_MAIN_LOOP_IO_EVENT(eventmask, eventflags);
1002
        }
1003
#endif
1004
        break;
1005

    
1006
      // if this was an OS event
1007
      case OSEVENT_MASK:
1008
        // evaluate flags
1009
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1010
        switch (eventflags) {
1011
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1012
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1013
            break;
1014
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1015
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1016
            break;
1017
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1018
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1019
            break;
1020
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1021
            shutdown = AOS_SHUTDOWN_RESTART;
1022
            break;
1023
          default:
1024
            _unexpectedEventError(eventmask, eventflags);
1025
            break;
1026
        }
1027
        break;
1028

    
1029
      // if this was any other event (should be impossible to occur)
1030
      default:
1031
        eventflags = 0;
1032
        _unexpectedEventError(eventmask, eventflags);
1033
        break;
1034
    }
1035

    
1036
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1037
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1038
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1039
#else
1040
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1041
#endif
1042
#endif
1043
  }
1044

    
1045
  /*
1046
   * ##########################################################################
1047
   * # system shutdown                                                        #
1048
   * ##########################################################################
1049
   */
1050

    
1051
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1052
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1053
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1054
#else
1055
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1056
#endif
1057
#endif
1058

    
1059
  // initialize/acknowledge shutdown
1060
  aosSysShutdownInit(shutdown);
1061

    
1062
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1063
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1064
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1065
#else
1066
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1067
#endif
1068
#endif
1069

    
1070
  // stop system threads
1071
  aosSysStop();
1072

    
1073
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1074
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1075
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1076
#else
1077
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1078
#endif
1079
#endif
1080

    
1081
  // deinitialize system
1082
  aosSysDeinit();
1083

    
1084
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1085
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1086
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1087
#else
1088
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1089
#endif
1090
#endif
1091

    
1092
  /* stop all periphery communication */
1093
  // CAN (mandatory)
1094
  canStop(&MODULE_HAL_CAN);
1095
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1096
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1097
#endif
1098

    
1099
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1100
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1101
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1102
#else
1103
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1104
#endif
1105
#endif
1106

    
1107
  // finally hand over to bootloader
1108
  aosSysShutdownFinal(&MODULE_HAL_EXT, shutdown);
1109

    
1110
  /*
1111
   * ##########################################################################
1112
   * # after shutdown/restart                                                 #
1113
   * ##########################################################################
1114
   *
1115
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1116
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1117
   *       which subsystems should NOT be shut down.
1118
   */
1119

    
1120
  // return an error, since this code should not be executed
1121
  return -1;
1122
}