Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 1c1b3372

History | View | Annotate | Download (44.918 KB)

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

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 53710ca3 Marc Rothmann
/**
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 e545e620 Thomas Schöpping
#include <amiroos.h>
30 cb835a3e Thomas Schöpping
#include <module.h>
31 e545e620 Thomas Schöpping
32 b6b45e4c Thomas Schöpping
/*
33
 * hook to add further includes
34
 */
35 512abac1 Thomas Schöpping
#if defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER)
36
#include AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER
37 b6b45e4c Thomas Schöpping
#endif
38
39 e545e620 Thomas Schöpping
/**
40
 * @brief   Event mask to identify I/O events.
41
 */
42 6b53f6bf Thomas Schöpping
#define IOEVENT_MASK                            EVENT_MASK(0)
43 e545e620 Thomas Schöpping
44
/**
45
 * @brief   Event mask to identify OS events.
46
 */
47 6b53f6bf Thomas Schöpping
#define OSEVENT_MASK                            EVENT_MASK(1)
48 e545e620 Thomas Schöpping
49
/**
50 933df08e Thomas Schöpping
 * @brief   Event mask to idetify CAN events.
51
 */
52
#define CANEVENT_MASK                           EVENT_MASK(2)
53
54
/**
55
 * @brief   Event mask to idetify timeout events.
56
 */
57
#define TIMEOUTEVENT_MASK                       EVENT_MASK(3)
58
59
/**
60
 * @brief   Event mask to idetify signal delay events.
61
 */
62
#define DELAYEVENT_MASK                         EVENT_MASK(4)
63
64 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
65
66 933df08e Thomas Schöpping
/**
67
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
68
 */
69
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
70
71
/**
72
 * @brief   CAN message identifier for transmitting module IDs during the SSSP stack initialization sequence.
73
 */
74
#define SSSP_STACKINIT_CANMSGID_MODULEID        0x002
75
76
/**
77
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
78
 */
79
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
80
81 1d3e002f Thomas Schöpping
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
82
83
/**
84
 * @brief   Default shutdown mode if SSSP is unavailable.
85
 */
86
#define AOS_SHUTDOWN_DEFAULT                    AOS_SHUTDOWN_DEEPSLEEP
87
88
#endif /* AMIROOS_CFG_SSSP_ENABLE */
89 9ebb11a9 Thomas Schöpping
90 933df08e Thomas Schöpping
/**
91 9461fadc Thomas Schöpping
 * @brief   CAN message identifier for calender synchronization message.
92
 */
93
#define CALENDERSYNC_CANMSGID                   0x004
94
95
/**
96 e545e620 Thomas Schöpping
 * @brief   Listener object for I/O events.
97
 */
98
static event_listener_t _eventListenerIO;
99
100
/**
101
 * @brief   Listener object for OS events.
102
 */
103
static event_listener_t _eventListenerOS;
104
105
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
106
/**
107 ba516b61 Thomas Schöpping
 * @brief   I/O channel for the programmer interface.
108 e545e620 Thomas Schöpping
 */
109 ba516b61 Thomas Schöpping
static AosIOChannel _stdiochannel;
110
111 b8268050 Thomas Schöpping
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
112 ba516b61 Thomas Schöpping
/**
113
 * @brief   I/O shell channel for the programmer interface.
114
 */
115
static AosShellChannel _stdshellchannel;
116 1d3e002f Thomas Schöpping
#endif /* AMIROOS_CFG_SHELL_ENABLE == true */
117
#endif /* defined(MODULE_HAL_PROGIF) */
118 e545e620 Thomas Schöpping
119 b6b45e4c Thomas Schöpping
/*
120
 * hook to add further static variables
121
 */
122
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
123
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
124
#endif
125
126 e545e620 Thomas Schöpping
/**
127
 * @brief   Prints an error message about an unexpected event.
128
 *
129
 * @param[in] mask    The event mask.
130
 * @param[in] flags   The event flags.
131
 */
132 933df08e Thomas Schöpping
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
133 e545e620 Thomas Schöpping
{
134 6b53f6bf Thomas Schöpping
#if (AMIROOS_CFG_DBG == true)
135 1e5f7648 Thomas Schöpping
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
136 6b53f6bf Thomas Schöpping
#else
137 933df08e Thomas Schöpping
  (void)(mask);
138
  (void)(flags);
139 6b53f6bf Thomas Schöpping
#endif
140 3e1a9c79 Thomas Schöpping
  return;
141 933df08e Thomas Schöpping
}
142
143 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
144 933df08e Thomas Schöpping
/**
145
 * @brief   Callback function to be used during SSSP stack initialization sequence.
146
 *
147
 * @param[in] par   A pointer to an @p event_source_t to be fired.
148
 */
149
static void _ssspTimerCallback(void* par)
150
{
151
  aosDbgCheck(par != NULL);
152
153
  chSysLockFromISR();
154
  chEvtBroadcastI((event_source_t*)par);
155
  chSysUnlockFromISR();
156
157 e545e620 Thomas Schöpping
  return;
158
}
159 9ebb11a9 Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
160 e545e620 Thomas Schöpping
161
/**
162 9461fadc Thomas Schöpping
 * @brief   Helper function to serialize data.
163 933df08e Thomas Schöpping
 *
164
 * @param[out]  dst   Pointer to the output buffer.
165 9461fadc Thomas Schöpping
 * @param[in]   src   Data to be serialized.
166
 * @param[in]   n     Number of bytes to serialize.
167 933df08e Thomas Schöpping
 */
168 9461fadc Thomas Schöpping
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
169 933df08e Thomas Schöpping
{
170
  aosDbgCheck(dst != NULL);
171 9461fadc Thomas Schöpping
  aosDbgCheck(n > 0 && n <= 8);
172 933df08e Thomas Schöpping
173 9461fadc Thomas Schöpping
  for (uint8_t byte = 0; byte < n; ++byte) {
174 933df08e Thomas Schöpping
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
175
  }
176
177
  return;
178
}
179
180
/**
181 9461fadc Thomas Schöpping
 * @brief   Helper function to deserialize data.
182 933df08e Thomas Schöpping
 *
183
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
184 9461fadc Thomas Schöpping
 * @param[in] n     Number of bytes to deserialize.
185 933df08e Thomas Schöpping
 *
186
 * @return    The deserialized 32 bit data.
187
 */
188 9461fadc Thomas Schöpping
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
189 933df08e Thomas Schöpping
{
190
  aosDbgCheck(src != NULL);
191 9461fadc Thomas Schöpping
  aosDbgCheck(n > 0 && n <= 8);
192 933df08e Thomas Schöpping
193 9461fadc Thomas Schöpping
  uint64_t result = 0;
194
  for (uint8_t byte = 0; byte < n; ++byte) {
195
    result |= ((uint64_t)src[byte]) << (byte * 8);
196
  }
197
198
  return result;
199
}
200
201
/**
202
 * @brief   Converter function to encode a TM value to a single unsigned 64 bit integer.
203
 *
204
 * @details Contents of the TM struct are mapped as follows:
205
 *            bits  |63     62|61      53|52    50|49         26|25     22|21     17|16     12|11      6|5       0|
206
 *            #bits |       2 |        9 |      3 |          24 |       4 |       5 |       5 |       6 |       6 |
207
 *            value |   isdst |     yday |   wday |        year |     mon |    mday |    hour |     min |     sec |
208
 *            range | special | [0, 365] | [0, 6] | [1900, ...] | [0, 11] | [1, 31] | [0, 23] | [0, 59] | [0, 61] |
209
 *          The Daylight Saving Time Flag (isdsst) is encoded as follows:
210
 *            DST not in effect         -> 0
211
 *            DST in effect             -> 1
212
 *            no information available  -> 2
213
 *
214
 * @param[in] src   Pointer to the TM struct to encode.
215
 *
216
 * @return  An unsigned 64 bit integer, which holds the encoded time value.
217
 */
218
inline uint64_t _TM2U64(struct tm* src)
219
{
220
  aosDbgCheck(src != NULL);
221
222
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
223
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
224
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
225
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
226
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
227
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
228
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
229
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
230
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
231
}
232
233
/**
234
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
235
 *
236
 * @details For information on the encoding, please refer to @p _TM2U64 function.
237
 *
238
 * @param[out] dst  The TM struct to fill with the decoded values.
239
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
240
 */
241
inline void _U642TM(struct tm* dst, const uint64_t src)
242
{
243
  aosDbgCheck(dst != NULL);
244
245
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
246
  dst->tm_min  = (src >> 6)  & 0x0000003F;
247
  dst->tm_hour = (src >> 12) & 0x0000001F;
248
  dst->tm_mday = (src >> 17) & 0x0000001F;
249
  dst->tm_mon  = (src >> 22) & 0x0000000F;
250
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
251
  dst->tm_wday = (src >> 50) & 0x00000007;
252
  dst->tm_yday = (src >> 53) & 0x000001FF;
253
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
254
255
  return;
256 933df08e Thomas Schöpping
}
257
258 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
259 933df08e Thomas Schöpping
/**
260
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
261
 *
262
 * @return Shutdown value.
263
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
264
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
265
 */
266
aos_shutdown_t _ssspModuleStackInitialization(void)
267
{
268
  // local types
269
  /**
270
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
271
   */
272
  typedef enum {
273
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
274
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
275
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
276
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
277
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
278
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
279
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
280
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
281
  } sssp_modulestackinitstage_t;
282
283
  typedef struct {
284
    bool loop     : 1;
285
    bool wfe      : 1;
286
    bool wfe_next : 1;
287
  } flags_t;
288
289
  // local variables
290
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
291
  sssp_modulestackinitstage_t stage = STAGE_3_1;
292
  eventmask_t eventmask = 0;
293 1d3e002f Thomas Schöpping
  eventflags_t ioflags = 0;
294 933df08e Thomas Schöpping
  event_source_t eventSourceTimeout;
295
  event_source_t eventSourceDelay;
296
  event_listener_t eventListenerTimeout;
297
  event_listener_t eventListenerDelay;
298
  event_listener_t eventListenerCan;
299
  virtual_timer_t timerTimeout;
300
  virtual_timer_t timerDelay;
301
  CANTxFrame canTxFrame;
302
  CANRxFrame canRxFrame;
303
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
304
  aos_ssspmoduleid_t lastid = 0;
305
#endif
306
  flags_t flags;
307 1d3e002f Thomas Schöpping
  aos_timestamp_t uptime;
308 933df08e Thomas Schöpping
309
  // initialize local varibles
310
  chEvtObjectInit(&eventSourceTimeout);
311
  chEvtObjectInit(&eventSourceDelay);
312
  chVTObjectInit(&timerTimeout);
313
  chVTObjectInit(&timerDelay);
314
  canTxFrame.RTR = CAN_RTR_DATA;
315
  canTxFrame.IDE = CAN_IDE_STD;
316
  flags.loop = true;
317
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
318
  flags.wfe_next = true;
319
320
  // initialize system variables
321
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
322
  aos.sssp.moduleId = 0;
323
324
  // listen to events (timout, delay, CAN receive)
325
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
326
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
327
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
328
329
  /*
330
   * FSM in a loop.
331
   *
332
   * This is a fully event-based FSM for the module stack initialization
333
   * sequence, defined by SSSP as startup stage 3. There are five different
334
   * events that can occur at this point:
335
   *  I/O events: The input level of an input pin has changed. Such events must
336
   *              be handled differently depending on the current state. Most
337
   *              of the time, however, such events can be ignored.
338
   *  OS events:  Such events are only available after this stage completed and
339
   *              thus should never occur. However, there is an optional hook
340
   *              to handle such events, nevertheless.
341
   *  CAN events: At least one CAN message was received. Note that this event
342
   *              will only fire again if all input buffers have been cleared.
343
   *  timeouts:   If some module does not support the sequence of there is any
344
   *              issue, such a case is detected via timeouts and must be
345
   *              handled accordingly (see abort state). In some cases, it is
346
   *              possible that a timeout event occurres 'simultaneously' with
347
   *              some other event. This can be caused by several timing issues
348
   *              and is a valid situation. As a result, any other events
349
   *              should be handled before the timeout event. If the other
350
   *              events are expected and valid, this implementation requires
351
   *              the timeout event flag to be cleared explicitely. Otherwise
352
   *              it is evaluated at the end of each iteration of the loop.
353
   *  delays:     Depending on the current state, delays are required by SSSP
354
   *              for timing of the sequential activation of signals.
355
   */
356
  aosDbgPrintf("SSSP stack initialization sequence:\n");
357
  while (flags.loop) {
358
#if (AMIROOS_CFG_DBG == true)
359
    switch (stage) {
360
      case STAGE_3_1:
361
        aosDbgPrintf(">>> 3-1\n");
362
        break;
363
      case STAGE_3_2:
364
        aosDbgPrintf(">>> 3-2\n");
365
        break;
366
      case STAGE_3_3_WAITFORFIRSTID:
367
        aosDbgPrintf(">>> 3-3 (1st ID)\n");
368
        break;
369
      case STAGE_3_3_WAITFORIDORSIG:
370
        aosDbgPrintf(">>> 3-3 (ID/sig)\n");
371
        break;
372
      case STAGE_3_3_WAITFORID:
373
        aosDbgPrintf(">>> 3-3 (ID)\n");
374
        break;
375
      case STAGE_3_4_FINISH:
376
        aosDbgPrintf(">>> 3-4 (finish)\n");
377
        break;
378
      case STAGE_3_4_ABORT_ACTIVE:
379 9461fadc Thomas Schöpping
        aosDbgPrintf(">>> 3-4 (active abort)\n");
380 933df08e Thomas Schöpping
        break;
381
      case STAGE_3_4_ABORT:
382
        aosDbgPrintf(">>> 3-4 (abort)\n");
383
        break;
384
    }
385
#endif
386
387
    // reset wfe flag for the next iteration
388
    flags.wfe_next = true;
389
390 1d3e002f Thomas Schöpping
    // waiting for events (may be skipped)
391 933df08e Thomas Schöpping
    if (flags.wfe) {
392
      // wait for any event to occur
393
      aosDbgPrintf("WFE...");
394 1e5f7648 Thomas Schöpping
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT));
395 933df08e Thomas Schöpping
      aosDbgPrintf("\t0x%08X", eventmask);
396
    } else {
397
      aosDbgPrintf("WFE skipped");
398 1d3e002f Thomas Schöpping
      eventmask = 0;
399 933df08e Thomas Schöpping
    }
400
    aosSysGetUptime(&uptime);
401 1d3e002f Thomas Schöpping
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
402 933df08e Thomas Schöpping
403
    /*
404
     * execute some general tasks and high priority events
405
     */
406
    // no event occurred at all
407
    if ((flags.wfe) && (eventmask == 0)) {
408
      aosDbgPrintf("ERR: no evt\n");
409
      // enforce timeout event
410
      chEvtBroadcast(&eventSourceTimeout);
411
      continue;
412
    }
413
    // if an IO event occurred
414 9461fadc Thomas Schöpping
    if (eventmask & _eventListenerIO.events) {
415 933df08e Thomas Schöpping
      ioflags = chEvtGetAndClearFlags(&_eventListenerIO);
416
      aosDbgPrintf("INFO: IO evt (0x%08X)\n", ioflags);
417
      // a power-down event occurred
418
      if (ioflags & MODULE_SSSP_EVENTFLAGS_PD) {
419
        aosDbgPrintf("PD evt\n");
420
        // deactivate S and UP
421 1d3e002f Thomas Schöpping
        aosDbgPrintf("disabling S\n");
422 933df08e Thomas Schöpping
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
423 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_STACK_END != true)
424 1d3e002f Thomas Schöpping
        aosDbgPrintf("disabling UP\n");
425 933df08e Thomas Schöpping
        apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
426 9ebb11a9 Thomas Schöpping
#endif
427 933df08e Thomas Schöpping
        // set shutdown flag and exit the loop
428
        shutdown = AOS_SHUTDOWN_PASSIVE;
429
        break;
430
      }
431
      // the S signal was deactivated
432
      if (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC) {
433
        apalControlGpioState_t sstate;
434
        apalControlGpioGet(&moduleSsspGpioSync, &sstate);
435 1d3e002f Thomas Schöpping
        if (sstate == APAL_GPIO_ON) {
436
          aosDbgPrintf("S evt (enabled)\n");
437
        } else {
438
          aosDbgPrintf("S evt (disabled)\n");
439 933df08e Thomas Schöpping
          // either finish or abort
440
          if ((stage == STAGE_3_3_WAITFORID) && (aos.sssp.moduleId != 0)) {
441
            stage = STAGE_3_4_FINISH;
442
          } else if (stage != STAGE_3_4_ABORT) {
443
            stage = STAGE_3_4_ABORT_ACTIVE;
444
          }
445
        }
446
      }
447
    }
448
    // an OS event occurred
449 9461fadc Thomas Schöpping
    if (eventmask & _eventListenerOS.events) {
450 933df08e Thomas Schöpping
      aosDbgPrintf("WARN: OS evt\n");
451
      // get the flags
452
      eventflags_t oseventflags = chEvtGetAndClearFlags(&_eventListenerOS);
453
      // there should be no OS events at this point
454
#ifdef MODULE_SSSP_STARTUP_3_OSEVENT_HOOK
455
      MODULE_SSSP_STARTUP_3_OSEVENT_HOOK(eventmask, eventflags);
456
#else
457
      _unexpectedEventError(eventmask, oseventflags);
458
#endif
459
    }
460
    // if a CAN event occurred
461 9461fadc Thomas Schöpping
    if ((eventmask & eventListenerCan.events)) {
462 1d3e002f Thomas Schöpping
      aosDbgPrintf("CAN evt\n");
463 933df08e Thomas Schöpping
      // fetch message
464
      if (flags.wfe) {
465
        canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE);
466
        aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
467
      }
468
      // identify and handle abort messgaes
469
      if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
470
        stage = STAGE_3_4_ABORT;
471
      }
472
      // warn if a unexpected message was received
473
      else if ((canRxFrame.SID != SSSP_STACKINIT_CANMSGID_INIT) &&
474
               (canRxFrame.SID != SSSP_STACKINIT_CANMSGID_MODULEID)) {
475
        aosDbgPrintf("WARN: unknown msg\n");
476
      }
477
      // any further pending messages are fetched at the end of the loop
478
    }
479
    // if a timeout event occurred
480 9461fadc Thomas Schöpping
    if (eventmask & eventListenerTimeout.events) {
481 1d3e002f Thomas Schöpping
      aosDbgPrintf("timeout evt\n");
482 933df08e Thomas Schöpping
      // is handled at the end of the loop (or must be cleared by FSM)
483
    }
484
    // if a delay event occurred
485 9461fadc Thomas Schöpping
    if (eventmask & eventListenerDelay.events) {
486 1d3e002f Thomas Schöpping
      aosDbgPrintf("delay evt\n");
487 933df08e Thomas Schöpping
      // is handled by FSM
488
    }
489
490
    /*
491
     * this is the actual FSM
492
     */
493
    switch (stage) {
494
      case STAGE_3_1:
495
      {
496
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
497
498
        // there was no event at all (skipped wfe)
499
        if (eventmask == 0 && flags.wfe == false) {
500
#if (AMIROOS_CFG_SSSP_MASTER == true)
501
          // initialize the stage by transmitting an according CAN message
502
          aosDbgPrintf("CAN -> init\n");
503
          canTxFrame.DLC = 0;
504
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
505
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
506
            chEvtBroadcast(&eventSourceTimeout);
507
            break;
508
          }
509
          // activate S
510 1d3e002f Thomas Schöpping
          aosDbgPrintf("enabling S\n");
511 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
512
#if (AMIROOS_CFG_SSSP_STACK_START == true)
513
          // proceed immediately
514
          stage = STAGE_3_2;
515
          flags.wfe_next = false;
516
#else
517
          // set the timeout timer
518 1e5f7648 Thomas Schöpping
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
519 933df08e Thomas Schöpping
          // proceed
520
          stage = STAGE_3_3_WAITFORFIRSTID;
521
#endif
522
#else
523
          // set the timeout timer
524 1e5f7648 Thomas Schöpping
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
525 933df08e Thomas Schöpping
#endif
526
        }
527
528
#if (AMIROOS_CFG_SSSP_MASTER != true)
529
        // a CAN message was received
530 9461fadc Thomas Schöpping
        else if (eventmask & eventListenerCan.events) {
531 933df08e Thomas Schöpping
          // if an initiation message was received
532
          if (canRxFrame.DLC == 0 &&
533
              canRxFrame.RTR == CAN_RTR_DATA &&
534
              canRxFrame.IDE == CAN_IDE_STD &&
535
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
536
            aosDbgPrintf("init msg\n");
537
            // reset the timeout timer and clear pending flags
538
            chVTReset(&timerTimeout);
539 9461fadc Thomas Schöpping
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
540
            eventmask &= ~(eventListenerTimeout.events);
541 933df08e Thomas Schöpping
            // activate S
542 1d3e002f Thomas Schöpping
            aosDbgPrintf("enabling S\n");
543 933df08e Thomas Schöpping
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
544
#if (AMIROOS_CFG_SSSP_STACK_START == true)
545
            // proceed
546
            stage = STAGE_3_2;
547
            flags.wfe_next = false;
548
#else
549
            // set the timeout timer
550 1e5f7648 Thomas Schöpping
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
551 933df08e Thomas Schöpping
            // proceed
552
            stage = STAGE_3_3_WAITFORFIRSTID;
553
#endif
554
          }
555
        }
556
#endif
557
558
        break;
559
      } /* end of STAGE_3_1 */
560
561
      case STAGE_3_2:
562
      {
563
#if (AMIROOS_CFG_SSSP_STACK_START == true)
564
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
565
566
        // if this stage was just entered
567
        if (flags.wfe == false) {
568
          // set the module ID
569
          aos.sssp.moduleId = 1;
570
          // broadcast module ID
571
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
572
          canTxFrame.DLC = 4;
573
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
574 9461fadc Thomas Schöpping
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
575 933df08e Thomas Schöpping
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
576
            chEvtBroadcast(&eventSourceTimeout);
577
            break;
578
          }
579
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
580
          lastid = aos.sssp.moduleId;
581
#endif
582
#if (AMIROOS_CFG_SSSP_STACK_END == true)
583
          // sequence is already over
584
          // deactivate S
585 1d3e002f Thomas Schöpping
          aosDbgPrintf("disabling S\n");
586 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
587
          // proceed
588
          stage = STAGE_3_3_WAITFORID;
589
#else
590
          // set the delay timer so the UP signal is activated later
591 1e5f7648 Thomas Schöpping
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
592 933df08e Thomas Schöpping
#endif
593
        }
594
595
        // if a delay event occurred
596 9461fadc Thomas Schöpping
        if (eventmask & eventListenerDelay.events) {
597 933df08e Thomas Schöpping
          // activate UP
598 1d3e002f Thomas Schöpping
          aosDbgPrintf("enabling UP\n");
599 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
600
          // deactivate S
601 1d3e002f Thomas Schöpping
          aosDbgPrintf("disabling S\n");
602 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
603
          // explicitely clear timeout event flag
604 9461fadc Thomas Schöpping
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
605
          eventmask &= ~(eventListenerTimeout.events);
606 933df08e Thomas Schöpping
          // proceed
607
          stage = STAGE_3_3_WAITFORID;
608
        }
609
#endif
610
611
        break;
612
      } /* end of STAGE_3_2 */
613
614
      case STAGE_3_3_WAITFORFIRSTID:
615
      {
616
#if (AMIROOS_CFG_SSSP_STACK_START != true)
617
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
618
619
        // a CAN message was received
620 9461fadc Thomas Schöpping
        if (eventmask & eventListenerCan.events) {
621 933df08e Thomas Schöpping
          // if an ID message was received
622
          if (canRxFrame.DLC == 4 &&
623
              canRxFrame.RTR == CAN_RTR_DATA &&
624
              canRxFrame.IDE == CAN_IDE_STD &&
625
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
626 9461fadc Thomas Schöpping
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
627 933df08e Thomas Schöpping
            // validate received ID
628 9461fadc Thomas Schöpping
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
629 933df08e Thomas Schöpping
              // store received ID
630 9461fadc Thomas Schöpping
              lastid = _deserialize(canRxFrame.data8, 4);
631 933df08e Thomas Schöpping
              // restart timeout timer
632 1e5f7648 Thomas Schöpping
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
633 933df08e Thomas Schöpping
              // proceed
634
              stage = STAGE_3_3_WAITFORIDORSIG;
635
            } else {
636
              aosDbgPrintf("ERR: invalid ID\n");
637
              // abort
638
              stage = STAGE_3_4_ABORT_ACTIVE;
639
              flags.wfe_next = false;
640
            }
641
            // explicitely clear timeout event flag
642 9461fadc Thomas Schöpping
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
643
            eventmask &= ~(eventListenerTimeout.events);
644 933df08e Thomas Schöpping
          }
645
        }
646
#endif
647
        break;
648
      } /* end of STAGE_3_3_WAITFORFIRSTID */
649
650
      case STAGE_3_3_WAITFORIDORSIG:
651
      {
652
#if (AMIROOS_CFG_SSSP_STACK_START != true)
653
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
654
655
        // a CAN message was received
656 9461fadc Thomas Schöpping
        if (eventmask & eventListenerCan.events) {
657 933df08e Thomas Schöpping
          // if an ID message was received
658
          if (canRxFrame.DLC == 4 &&
659
              canRxFrame.RTR == CAN_RTR_DATA &&
660
              canRxFrame.IDE == CAN_IDE_STD &&
661
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
662 9461fadc Thomas Schöpping
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
663 933df08e Thomas Schöpping
            // validate received ID
664 9461fadc Thomas Schöpping
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
665 933df08e Thomas Schöpping
              // store received ID
666 9461fadc Thomas Schöpping
              lastid = _deserialize(canRxFrame.data8, 4);
667 933df08e Thomas Schöpping
              // restart timeout timer
668 1e5f7648 Thomas Schöpping
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
669 933df08e Thomas Schöpping
            } else {
670
              aosDbgPrintf("ERR: invalid ID\n");
671
              // abort
672
              stage = STAGE_3_4_ABORT_ACTIVE;
673
              flags.wfe_next = false;
674
            }
675
            // explicitely clear timeout event flag
676 9461fadc Thomas Schöpping
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
677
            eventmask &= ~(eventListenerTimeout.events);
678 933df08e Thomas Schöpping
          }
679
        }
680
681
        // if an IO event was received (DN signal)
682 9461fadc Thomas Schöpping
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
683 1d3e002f Thomas Schöpping
          aosDbgPrintf("DN evt\n");
684 933df08e Thomas Schöpping
          // reset timeout timer
685
          chVTReset(&timerTimeout);
686 9461fadc Thomas Schöpping
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
687
          eventmask &= ~(eventListenerTimeout.events);
688 933df08e Thomas Schöpping
          // increment and broadcast ID
689
          aos.sssp.moduleId = lastid + 1;
690
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
691
          canTxFrame.DLC = 4;
692
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
693 9461fadc Thomas Schöpping
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
694 933df08e Thomas Schöpping
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
695
            chEvtBroadcast(&eventSourceTimeout);
696
            break;
697
          }
698
          // set delay timer
699 1e5f7648 Thomas Schöpping
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
700 933df08e Thomas Schöpping
        }
701
702
        // if a delay event occurred
703 9461fadc Thomas Schöpping
        if (eventmask & eventListenerDelay.events) {
704 933df08e Thomas Schöpping
#if (AMIROOS_CFG_SSSP_STACK_END != true)
705
          // activate UP
706 1d3e002f Thomas Schöpping
          aosDbgPrintf("enabling UP\n");
707 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
708
#endif
709
          // deactivate S
710 1d3e002f Thomas Schöpping
          aosDbgPrintf("disabling S\n");
711 933df08e Thomas Schöpping
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
712
          // reset the timeout timer
713 1e5f7648 Thomas Schöpping
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
714 9461fadc Thomas Schöpping
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
715
          eventmask &= ~(eventListenerTimeout.events);
716 933df08e Thomas Schöpping
          // proceed
717
          stage = STAGE_3_3_WAITFORID;
718
        }
719
#endif
720
721
        break;
722
      } /* end of STAGE_3_3_WAITFORIDORSIG */
723
724
      case STAGE_3_3_WAITFORID:
725
      {
726
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
727
728
#if (AMIROOS_CFG_SSSP_STACK_END != true)
729
        // a CAN message was received
730 9461fadc Thomas Schöpping
        if (eventmask & eventListenerCan.events) {
731 933df08e Thomas Schöpping
          // if an ID message was received
732
          if (canRxFrame.DLC == 4 &&
733
              canRxFrame.RTR == CAN_RTR_DATA &&
734
              canRxFrame.IDE == CAN_IDE_STD &&
735
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
736
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
737
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
738 9461fadc Thomas Schöpping
            lastid = _deserialize(canRxFrame.data8, 4);
739 933df08e Thomas Schöpping
            aosDbgPrintf("ID (%u)\n", lastid);
740
#endif
741
            // restart timeout timer
742 1e5f7648 Thomas Schöpping
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
743 9461fadc Thomas Schöpping
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
744
            eventmask &= ~(eventListenerTimeout.events);
745 933df08e Thomas Schöpping
          }
746
        }
747
#endif
748
749
        break;
750
      } /* end of STAGE_3_3_WAITFORID */
751
752
      case STAGE_3_4_FINISH:
753
      {
754
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
755
756
        // if an IO event was received (S signal)
757 9461fadc Thomas Schöpping
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
758 933df08e Thomas Schöpping
          // reset the timeout timer
759
          chVTReset(&timerTimeout);
760 9461fadc Thomas Schöpping
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
761
          eventmask &= ~(eventListenerTimeout.events);
762 933df08e Thomas Schöpping
          //set the delay timer
763 1e5f7648 Thomas Schöpping
          chVTSet(&timerDelay, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
764 933df08e Thomas Schöpping
        }
765
766
        // if a CAN event was received
767 9461fadc Thomas Schöpping
        if (eventmask & eventListenerCan.events) {
768 933df08e Thomas Schöpping
          // if an abort message was received
769
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
770
            aosDbgPrintf("abort msg\n");
771
            // reset the delay timer
772
            chVTReset(&timerDelay);
773 9461fadc Thomas Schöpping
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
774
            eventmask &= ~(eventListenerDelay.events);
775 933df08e Thomas Schöpping
            // proceed
776
            stage = STAGE_3_4_ABORT;
777
          }
778
        }
779
780
        // if a delay timer event occurred
781 9461fadc Thomas Schöpping
        if (eventmask & eventListenerDelay.events) {
782 933df08e Thomas Schöpping
          aosDbgPrintf("sequence sucessful\n");
783
          // sequence finished sucessfully
784
          flags.loop = false;
785
        }
786
787
        break;
788
      } /* end of STAGE_3_4_FINISH */
789
790
      case STAGE_3_4_ABORT_ACTIVE:
791
      {
792
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
793
794
        // emit abort message
795
        canTxFrame.DLC = 0;
796
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
797
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
798
        aosDbgPrintf("CAN -> abort\n");
799
        // clear timeout flag
800 9461fadc Thomas Schöpping
        eventmask &= ~(eventListenerTimeout.events);
801 933df08e Thomas Schöpping
        // proceed immediately
802
        stage = STAGE_3_4_ABORT;
803
        flags.wfe_next = false;
804
        break;
805
      } /* end of STAGE_3_4_ABORT_ACTIVE */
806
807
      case STAGE_3_4_ABORT:
808
      {
809
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
810
811
        // deactivate S
812 1d3e002f Thomas Schöpping
        aosDbgPrintf("disabling SYNC\n");
813 933df08e Thomas Schöpping
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
814
        // invalidate module ID
815
        aos.sssp.moduleId = 0;
816
817
        // if an IO event was received (S signal)
818 9461fadc Thomas Schöpping
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
819 933df08e Thomas Schöpping
          aosDbgPrintf("sequence aborted\n");
820
          // exit the sequence
821
          flags.loop = false;
822
        }
823
824
        break;
825
      } /* end of STAGE_3_4_ABORT */
826 1d3e002f Thomas Schöpping
    } /* end of switch(stage) */
827 933df08e Thomas Schöpping
828
    // fetch pending CAN message (if any)
829 9461fadc Thomas Schöpping
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
830 933df08e Thomas Schöpping
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
831
      flags.wfe_next = false;
832
    }
833
834
    // handle unhandled timeout events
835 9461fadc Thomas Schöpping
    if (eventmask & eventListenerTimeout.events) {
836 933df08e Thomas Schöpping
      aosDbgPrintf("ERR: timeout evt\n");
837
      // abort
838
      flags.wfe_next = false;
839
      stage = STAGE_3_4_ABORT_ACTIVE;
840
    }
841
842
    // apply wfe value for next iteration
843
    flags.wfe = flags.wfe_next;
844 1e5f7648 Thomas Schöpping
  } /* end of FSM loop */
845 933df08e Thomas Schöpping
846
  // unregister all events (timeout, delay, CAN receive)
847
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
848
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
849
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
850
  // clear any pending events (timeout, delay, CAN receive)
851
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
852
853
  // reset all control signals
854
#if (AMIROOS_CFG_SSSP_STACK_END != true)
855 1d3e002f Thomas Schöpping
  aosDbgPrintf("disabling UP\n");
856 933df08e Thomas Schöpping
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
857
#endif
858 1d3e002f Thomas Schöpping
  aosDbgPrintf("disabling S\n");
859 933df08e Thomas Schöpping
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
860 1d3e002f Thomas Schöpping
  aosSysGetUptime(&uptime);
861
  aosDbgPrintf("done\t%04ums\n", (uint32_t)(uptime / MICROSECONDS_PER_MILLISECOND));
862 933df08e Thomas Schöpping
863
  return shutdown;
864
}
865 9ebb11a9 Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
866 933df08e Thomas Schöpping
867
/**
868 e545e620 Thomas Schöpping
 * @brief   Application entry point.
869
 */
870
int main(void)
871
{
872
  // local variables
873
  eventmask_t eventmask = 0;
874
  eventflags_t eventflags = 0;
875
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
876 b6b45e4c Thomas Schöpping
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
877
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
878 e545e620 Thomas Schöpping
#endif
879
880
  /*
881
   * ##########################################################################
882
   * # system initialization                                                  #
883
   * ##########################################################################
884
   */
885
886
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
887 b6b45e4c Thomas Schöpping
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
888
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
889
#else
890 e545e620 Thomas Schöpping
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
891
#endif
892 b6b45e4c Thomas Schöpping
#endif
893 e545e620 Thomas Schöpping
894
  /* hardware, kernel, and operating system initialization */
895
  // ChibiOS/HAL and custom hal additions (if any)
896
  halInit();
897
#ifdef MODULE_INIT_HAL_EXTRA
898
  MODULE_INIT_HAL_EXTRA();
899
#endif
900
901
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
902
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
903
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
904
#else
905
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
906
#endif
907
#endif
908
909
  // ChibiOS/RT kernel and custom kernel additions (if any)
910
  chSysInit();
911
#ifdef MODULE_INIT_KERNEL_EXTRA
912
  MODULE_INIT_KERNEL_EXTRA();
913
#endif
914
915
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
916
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
917
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
918
#else
919
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
920
#endif
921
#endif
922
923
  // AMiRo-OS and custom OS additions (if any)
924 6b53f6bf Thomas Schöpping
#if (AMIROOS_CFG_SHELL_ENABLE == true)
925
  aosSysInit(moduleShellPrompt);
926
#else
927
  aosSysInit();
928
#endif
929 e545e620 Thomas Schöpping
#ifdef MODULE_INIT_OS_EXTRA
930
  MODULE_INIT_OS_EXTRA();
931
#endif
932
933
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
934
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
935
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
936
#else
937
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
938
#endif
939
#endif
940
941
#if (AMIROOS_CFG_TESTS_ENABLE == true)
942 9461fadc Thomas Schöpping
#if defined(MODULE_INIT_TESTS)
943 e545e620 Thomas Schöpping
  MODULE_INIT_TESTS();
944 9461fadc Thomas Schöpping
#else
945
  #warning "MODULE_INIT_TESTS not defined"
946
#endif
947 e545e620 Thomas Schöpping
#endif
948
949
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
950
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
951
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
952
#else
953
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
954
#endif
955
#endif
956
957
  /* event associations */
958 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true)
959 1e5f7648 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_STACK_START == true) && (AMIROOS_CFG_SSSP_STACK_END == true)
960
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC);
961
#elif (AMIROOS_CFG_SSSP_STACK_START == true)
962
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_UP);
963
#elif (AMIROOS_CFG_SSSP_STACK_END == true)
964
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_DN);
965
#else
966
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_DN | MODULE_SSSP_EVENTFLAGS_UP);
967
#endif
968 1d3e002f Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
969 6b53f6bf Thomas Schöpping
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
970 e545e620 Thomas Schöpping
971
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
972
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
973
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
974
#else
975
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
976
#endif
977
#endif
978
979
  /* periphery communication initialization */
980
  // CAN (mandatory)
981
  canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
982
  // module specific initialization (if any)
983
#ifdef MODULE_INIT_PERIPHERY_COMM
984
  MODULE_INIT_PERIPHERY_COMM();
985
#endif
986
  // user interface (if any)
987
#ifdef MODULE_HAL_PROGIF
988 ba516b61 Thomas Schöpping
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
989
  aosIOChannelOutputEnable(&_stdiochannel);
990
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
991
#if (AMIROOS_CFG_SHELL_ENABLE == true)
992 dd8738ea Thomas Schöpping
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
993 ba516b61 Thomas Schöpping
  aosShellChannelInputEnable(&_stdshellchannel);
994
  aosShellChannelOutputEnable(&_stdshellchannel);
995 6b53f6bf Thomas Schöpping
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
996 ba516b61 Thomas Schöpping
#endif
997 e545e620 Thomas Schöpping
#endif
998
999
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
1000
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
1001
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
1002
#else
1003
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
1004
#endif
1005
#endif
1006
1007
  /* module is ready -> print welcome prompt */
1008
  aosprintf("\n");
1009
  aosprintf("######################################################################\n");
1010
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
1011
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
1012 84f0ce9e Thomas Schöpping
  aosprintf("# Copyright (C) 2016..2019  Thomas Schöpping et al.                  #\n");
1013 e545e620 Thomas Schöpping
  aosprintf("#                                                                    #\n");
1014
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
1015
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
1016
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
1017
  aosprintf("# The development of this software was supported by the Excellence   #\n");
1018
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
1019
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
1020
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
1021
  aosprintf("######################################################################\n");
1022
  aosprintf("\n");
1023
1024
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7)
1025
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS)
1026
  AMIROOS_CFG_MAIN_INIT_HOOK_7(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS);
1027
#else
1028
  AMIROOS_CFG_MAIN_INIT_HOOK_7();
1029
#endif
1030
#endif
1031
1032 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1033 6b53f6bf Thomas Schöpping
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
1034 9461fadc Thomas Schöpping
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
1035 e545e620 Thomas Schöpping
    /*
1036
     * This code is executed if the received event was not about the SYS_SYNC control signal.
1037
     * The returned event could be caused by any listener (not only the argument).
1038
     */
1039 9461fadc Thomas Schöpping
    // IO event
1040 e545e620 Thomas Schöpping
    if (eventmask & _eventListenerIO.events) {
1041
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1042 9461fadc Thomas Schöpping
      // PD event
1043
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1044
        shutdown = AOS_SHUTDOWN_PASSIVE;
1045
      } else {
1046 933df08e Thomas Schöpping
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
1047 9461fadc Thomas Schöpping
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1048 e545e620 Thomas Schöpping
#else
1049 9461fadc Thomas Schöpping
        // ignore any other IO events
1050 e545e620 Thomas Schöpping
#endif
1051 9461fadc Thomas Schöpping
      }
1052 e545e620 Thomas Schöpping
    }
1053 9461fadc Thomas Schöpping
    // OS event
1054 e545e620 Thomas Schöpping
    else if (eventmask & _eventListenerOS.events) {
1055
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1056
      _unexpectedEventError(eventmask, eventflags);
1057
    }
1058 9461fadc Thomas Schöpping
    // unknown event
1059 e545e620 Thomas Schöpping
    else {
1060 933df08e Thomas Schöpping
      _unexpectedEventError(eventmask, 0);
1061 e545e620 Thomas Schöpping
    }
1062
  }
1063
1064 933df08e Thomas Schöpping
  /*
1065
   * There must be no delays at this point, thus no hook is allowed.
1066
   */
1067
1068
  /* SSSP startup stage 3 (module stack initialization) */
1069 9461fadc Thomas Schöpping
  if (shutdown == AOS_SHUTDOWN_NONE) {
1070
    shutdown = _ssspModuleStackInitialization();
1071
  }
1072 9ebb11a9 Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1073 9461fadc Thomas Schöpping
1074
  /*
1075
   * There must be no delays at this point, thus no hook is allowed.
1076
   */
1077
1078 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1079
  /* synchronize calendars */
1080 9461fadc Thomas Schöpping
  if (shutdown == AOS_SHUTDOWN_NONE) {
1081
#if (AMIROOS_CFG_SSSP_MASTER == true)
1082
    CANTxFrame frame;
1083
    struct tm t;
1084
    uint64_t encoded;
1085
1086
    frame.DLC = 8;
1087
    frame.RTR = CAN_RTR_DATA;
1088
    frame.IDE = CAN_IDE_STD;
1089
    frame.SID = CALENDERSYNC_CANMSGID;
1090
1091
    aosDbgPrintf("transmitting current date/time...\t");
1092
    // get current date & time
1093
    aosSysGetDateTime(&t);
1094
    // encode
1095
    encoded = _TM2U64(&t);
1096
    // serialize
1097
    _serialize(frame.data8, encoded, 8);
1098
    // transmit
1099
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1100
1101
    aosDbgPrintf("done\n");
1102 9ebb11a9 Thomas Schöpping
#else /* AMIROOS_CFG_SSSP_MASTER == false */
1103 9461fadc Thomas Schöpping
    CANRxFrame frame;
1104
    uint64_t encoded;
1105
    struct tm t;
1106
1107
    aosDbgPrintf("receiving current date/time...\t");
1108
    // receive message
1109 1e5f7648 Thomas Schöpping
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1110 9461fadc Thomas Schöpping
      // validate message
1111
      if (frame.DLC == 8 &&
1112
          frame.RTR == CAN_RTR_DATA &&
1113
          frame.IDE == CAN_IDE_STD &&
1114
          frame.SID == CALENDERSYNC_CANMSGID) {
1115
        // deserialize
1116
        encoded = _deserialize(frame.data8, 8);
1117
        // decode
1118
        _U642TM(&t, encoded);
1119
        // set current date & time
1120
        aosSysSetDateTime(&t);
1121
        aosDbgPrintf("success\n");
1122
      } else {
1123
        aosDbgPrintf("fail (invalid message)\n");
1124
      }
1125
    } else {
1126
      aosDbgPrintf("fail (timeout)\n");
1127
    }
1128 9ebb11a9 Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_MASTER == false */
1129 9461fadc Thomas Schöpping
    aosDbgPrintf("\n");
1130
  }
1131 9ebb11a9 Thomas Schöpping
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1132 933df08e Thomas Schöpping
1133 e545e620 Thomas Schöpping
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1134
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1135
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1136
#else
1137
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1138
#endif
1139
#endif
1140
1141
  /* completely start AMiRo-OS */
1142 933df08e Thomas Schöpping
  if (shutdown == AOS_SHUTDOWN_NONE) {
1143
    aosSysStart();
1144
  }
1145 e545e620 Thomas Schöpping
1146
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1147
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1148
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1149
#else
1150
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1151
#endif
1152
#endif
1153
1154
  /*
1155
   * ##########################################################################
1156
   * # infinite loop                                                          #
1157
   * ##########################################################################
1158
   */
1159
1160
  // sleep until a shutdown event is received
1161
  while (shutdown == AOS_SHUTDOWN_NONE) {
1162
    // wait for an event
1163
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1164 1e5f7648 Thomas Schöpping
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1165 e545e620 Thomas Schöpping
#else
1166
    eventmask = chEvtWaitOne(ALL_EVENTS);
1167
#endif
1168
1169
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1170
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1171
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1172
#else
1173
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1174
#endif
1175
#endif
1176
1177
    switch (eventmask) {
1178
      // if this was an I/O event
1179 6b53f6bf Thomas Schöpping
      case IOEVENT_MASK:
1180 e545e620 Thomas Schöpping
        // evaluate flags
1181
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1182 9ebb11a9 Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1183 e545e620 Thomas Schöpping
        // PD event
1184 6b53f6bf Thomas Schöpping
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1185 e545e620 Thomas Schöpping
          shutdown = AOS_SHUTDOWN_PASSIVE;
1186
        }
1187
        // all other events
1188
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1189
        else {
1190
          MODULE_MAIN_LOOP_IO_EVENT(eventmask, eventflags);
1191
        }
1192
#endif
1193 41fc7088 Thomas Schöpping
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1194
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1195
        MODULE_MAIN_LOOP_IO_EVENT(eventmask, eventflags);
1196
#endif
1197
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1198 e545e620 Thomas Schöpping
        break;
1199
1200
      // if this was an OS event
1201 6b53f6bf Thomas Schöpping
      case OSEVENT_MASK:
1202 e545e620 Thomas Schöpping
        // evaluate flags
1203
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1204
        switch (eventflags) {
1205 1d3e002f Thomas Schöpping
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1206 e545e620 Thomas Schöpping
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1207
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1208
            break;
1209
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1210
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1211
            break;
1212
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1213
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1214
            break;
1215
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1216
            shutdown = AOS_SHUTDOWN_RESTART;
1217
            break;
1218 1d3e002f Thomas Schöpping
#else /* AMIROOS_CFG_SSSP_ENABLE == false */
1219
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN:
1220
            shutdown = AOS_SHUTDOWN_DEFAULT;
1221
            break;
1222
#endif /* AMIROOS_CFG_SSSP_ENABLE */
1223 e545e620 Thomas Schöpping
          default:
1224
            _unexpectedEventError(eventmask, eventflags);
1225
            break;
1226
        }
1227
        break;
1228
1229
      // if this was any other event (should be impossible to occur)
1230
      default:
1231
        eventflags = 0;
1232 41fc7088 Thomas Schöpping
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0)
1233 e545e620 Thomas Schöpping
        _unexpectedEventError(eventmask, eventflags);
1234 41fc7088 Thomas Schöpping
#endif
1235 e545e620 Thomas Schöpping
        break;
1236
    }
1237
1238
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1239
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1240
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1241
#else
1242
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1243
#endif
1244
#endif
1245
  }
1246
1247
  /*
1248
   * ##########################################################################
1249
   * # system shutdown                                                        #
1250
   * ##########################################################################
1251
   */
1252
1253
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1254
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1255
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1256
#else
1257
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1258
#endif
1259
#endif
1260
1261
  // initialize/acknowledge shutdown
1262
  aosSysShutdownInit(shutdown);
1263
1264
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1265
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1266
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1267
#else
1268
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1269
#endif
1270
#endif
1271
1272
  // stop system threads
1273
  aosSysStop();
1274
1275
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1276
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1277
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1278
#else
1279
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1280
#endif
1281
#endif
1282
1283
  // deinitialize system
1284
  aosSysDeinit();
1285
1286
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1287
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1288
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1289
#else
1290
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1291
#endif
1292
#endif
1293
1294
  /* stop all periphery communication */
1295
  // CAN (mandatory)
1296
  canStop(&MODULE_HAL_CAN);
1297
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1298
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1299
#endif
1300
1301
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1302
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1303
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1304
#else
1305
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1306
#endif
1307
#endif
1308
1309
  // finally hand over to bootloader
1310 1e5f7648 Thomas Schöpping
  aosSysShutdownFinal(shutdown);
1311 e545e620 Thomas Schöpping
1312
  /*
1313
   * ##########################################################################
1314
   * # after shutdown/restart                                                 #
1315
   * ##########################################################################
1316
   *
1317
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1318
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1319
   *       which subsystems should NOT be shut down.
1320
   */
1321
1322
  // return an error, since this code should not be executed
1323
  return -1;
1324
}
1325 53710ca3 Marc Rothmann
1326
/** @} */