Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 9ebb11a9

History | View | Annotate | Download (43.687 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
/**
20
 * @file    aos_main.cpp
21
 * @brief   Main function.
22
 * @details Main function with SSSP and initialization,
23
 *          extendable via hooks.
24
 *
25
 * @addtogroup aos_system
26
 * @{
27
 */
28

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

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

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

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

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

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

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

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

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

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

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

    
81
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
82

    
83
/**
84
 * @brief   CAN message identifier for calender synchronization message.
85
 */
86
#define CALENDERSYNC_CANMSGID                   0x004
87

    
88
/**
89
 * @brief   Listener object for I/O events.
90
 */
91
static event_listener_t _eventListenerIO;
92

    
93
/**
94
 * @brief   Listener object for OS events.
95
 */
96
static event_listener_t _eventListenerOS;
97

    
98
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
99
/**
100
 * @brief   I/O channel for the programmer interface.
101
 */
102
static AosIOChannel _stdiochannel;
103

    
104
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
105
/**
106
 * @brief   I/O shell channel for the programmer interface.
107
 */
108
static AosShellChannel _stdshellchannel;
109
#endif
110
#endif
111

    
112
/*
113
 * hook to add further static variables
114
 */
115
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
116
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
117
#endif
118

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

    
136
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
137
/**
138
 * @brief   Callback function to be used during SSSP stack initialization sequence.
139
 *
140
 * @param[in] par   A pointer to an @p event_source_t to be fired.
141
 */
142
static void _ssspTimerCallback(void* par)
143
{
144
  aosDbgCheck(par != NULL);
145

    
146
  chSysLockFromISR();
147
  chEvtBroadcastI((event_source_t*)par);
148
  chSysUnlockFromISR();
149

    
150
  return;
151
}
152
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
153

    
154
/**
155
 * @brief   Helper function to serialize data.
156
 *
157
 * @param[out]  dst   Pointer to the output buffer.
158
 * @param[in]   src   Data to be serialized.
159
 * @param[in]   n     Number of bytes to serialize.
160
 */
161
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
162
{
163
  aosDbgCheck(dst != NULL);
164
  aosDbgCheck(n > 0 && n <= 8);
165

    
166
  for (uint8_t byte = 0; byte < n; ++byte) {
167
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
168
  }
169

    
170
  return;
171
}
172

    
173
/**
174
 * @brief   Helper function to deserialize data.
175
 *
176
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
177
 * @param[in] n     Number of bytes to deserialize.
178
 *
179
 * @return    The deserialized 32 bit data.
180
 */
181
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
182
{
183
  aosDbgCheck(src != NULL);
184
  aosDbgCheck(n > 0 && n <= 8);
185

    
186
  uint64_t result = 0;
187
  for (uint8_t byte = 0; byte < n; ++byte) {
188
    result |= ((uint64_t)src[byte]) << (byte * 8);
189
  }
190

    
191
  return result;
192
}
193

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

    
215
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
216
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
217
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
218
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
219
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
220
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
221
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
222
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
223
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
224
}
225

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

    
238
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
239
  dst->tm_min  = (src >> 6)  & 0x0000003F;
240
  dst->tm_hour = (src >> 12) & 0x0000001F;
241
  dst->tm_mday = (src >> 17) & 0x0000001F;
242
  dst->tm_mon  = (src >> 22) & 0x0000000F;
243
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
244
  dst->tm_wday = (src >> 50) & 0x00000007;
245
  dst->tm_yday = (src >> 53) & 0x000001FF;
246
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
247

    
248
  return;
249
}
250

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

    
276
  typedef struct {
277
    bool loop     : 1;
278
    bool wfe      : 1;
279
    bool wfe_next : 1;
280
  } flags_t;
281

    
282
  // local variables
283
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
284
  sssp_modulestackinitstage_t stage = STAGE_3_1;
285
  eventmask_t eventmask = 0;
286
  eventflags_t ioflags;
287
  event_source_t eventSourceTimeout;
288
  event_source_t eventSourceDelay;
289
  event_listener_t eventListenerTimeout;
290
  event_listener_t eventListenerDelay;
291
  event_listener_t eventListenerCan;
292
  virtual_timer_t timerTimeout;
293
  virtual_timer_t timerDelay;
294
  CANTxFrame canTxFrame;
295
  CANRxFrame canRxFrame;
296
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
297
  aos_ssspmoduleid_t lastid = 0;
298
#endif
299
  flags_t flags;
300

    
301
  // initialize local varibles
302
  chEvtObjectInit(&eventSourceTimeout);
303
  chEvtObjectInit(&eventSourceDelay);
304
  chVTObjectInit(&timerTimeout);
305
  chVTObjectInit(&timerDelay);
306
  canTxFrame.RTR = CAN_RTR_DATA;
307
  canTxFrame.IDE = CAN_IDE_STD;
308
  flags.loop = true;
309
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
310
  flags.wfe_next = true;
311

    
312
  // initialize system variables
313
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
314
  aos.sssp.moduleId = 0;
315

    
316
  // listen to events (timout, delay, CAN receive)
317
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
318
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
319
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
320

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

    
379
    // reset wfe flag for the next iteration
380
    flags.wfe_next = true;
381

    
382
    // waiting for events may be skipped
383
    if (flags.wfe) {
384
      // wait for any event to occur
385
      aosDbgPrintf("WFE...");
386
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT));
387
      aosDbgPrintf("\t0x%08X", eventmask);
388
    } else {
389
      aosDbgPrintf("WFE skipped");
390
    }
391
    aos_timestamp_t uptime;
392
    aosSysGetUptime(&uptime);
393
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / 1000));
394

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

    
475
    /*
476
     * this is the actual FSM
477
     */
478
    switch (stage) {
479
      case STAGE_3_1:
480
      {
481
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
482

    
483
        // there was no event at all (skipped wfe)
484
        if (eventmask == 0 && flags.wfe == false) {
485
#if (AMIROOS_CFG_SSSP_MASTER == true)
486
          // initialize the stage by transmitting an according CAN message
487
          aosDbgPrintf("CAN -> init\n");
488
          canTxFrame.DLC = 0;
489
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
490
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
491
            chEvtBroadcast(&eventSourceTimeout);
492
            break;
493
          }
494
          // activate S
495
          aosDbgPrintf("S+\n");
496
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
497
#if (AMIROOS_CFG_SSSP_STACK_START == true)
498
          // proceed immediately
499
          stage = STAGE_3_2;
500
          flags.wfe_next = false;
501
#else
502
          // set the timeout timer
503
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
504
          // proceed
505
          stage = STAGE_3_3_WAITFORFIRSTID;
506
#endif
507
#else
508
          // set the timeout timer
509
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
510
#endif
511
        }
512

    
513
#if (AMIROOS_CFG_SSSP_MASTER != true)
514
        // a CAN message was received
515
        else if (eventmask & eventListenerCan.events) {
516
          // if an initiation message was received
517
          if (canRxFrame.DLC == 0 &&
518
              canRxFrame.RTR == CAN_RTR_DATA &&
519
              canRxFrame.IDE == CAN_IDE_STD &&
520
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
521
            aosDbgPrintf("init msg\n");
522
            // reset the timeout timer and clear pending flags
523
            chVTReset(&timerTimeout);
524
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
525
            eventmask &= ~(eventListenerTimeout.events);
526
            // activate S
527
            aosDbgPrintf("S+\n");
528
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
529
#if (AMIROOS_CFG_SSSP_STACK_START == true)
530
            // proceed
531
            stage = STAGE_3_2;
532
            flags.wfe_next = false;
533
#else
534
            // set the timeout timer
535
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
536
            // proceed
537
            stage = STAGE_3_3_WAITFORFIRSTID;
538
#endif
539
          }
540
        }
541
#endif
542

    
543
        break;
544
      } /* end of STAGE_3_1 */
545

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

    
551
        // if this stage was just entered
552
        if (flags.wfe == false) {
553
          // set the module ID
554
          aos.sssp.moduleId = 1;
555
          // broadcast module ID
556
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
557
          canTxFrame.DLC = 4;
558
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
559
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
560
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
561
            chEvtBroadcast(&eventSourceTimeout);
562
            break;
563
          }
564
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
565
          lastid = aos.sssp.moduleId;
566
#endif
567
#if (AMIROOS_CFG_SSSP_STACK_END == true)
568
          // sequence is already over
569
          // deactivate S
570
          aosDbgPrintf("S-\n");
571
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
572
          // proceed
573
          stage = STAGE_3_3_WAITFORID;
574
#else
575
          // set the delay timer so the UP signal is activated later
576
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
577
#endif
578
        }
579

    
580
        // if a delay event occurred
581
        if (eventmask & eventListenerDelay.events) {
582
          // activate UP
583
          aosDbgPrintf("UP+\n");
584
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
585
          // deactivate S
586
          aosDbgPrintf("S-\n");
587
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
588
          // explicitely clear timeout event flag
589
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
590
          eventmask &= ~(eventListenerTimeout.events);
591
          // proceed
592
          stage = STAGE_3_3_WAITFORID;
593
        }
594
#endif
595

    
596
        break;
597
      } /* end of STAGE_3_2 */
598

    
599
      case STAGE_3_3_WAITFORFIRSTID:
600
      {
601
#if (AMIROOS_CFG_SSSP_STACK_START != true)
602
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
603

    
604
        // a CAN message was received
605
        if (eventmask & eventListenerCan.events) {
606
          // if an ID message was received
607
          if (canRxFrame.DLC == 4 &&
608
              canRxFrame.RTR == CAN_RTR_DATA &&
609
              canRxFrame.IDE == CAN_IDE_STD &&
610
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
611
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
612
            // validate received ID
613
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
614
              // store received ID
615
              lastid = _deserialize(canRxFrame.data8, 4);
616
              // restart timeout timer
617
              chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
618
              // proceed
619
              stage = STAGE_3_3_WAITFORIDORSIG;
620
            } else {
621
              aosDbgPrintf("ERR: invalid ID\n");
622
              // abort
623
              stage = STAGE_3_4_ABORT_ACTIVE;
624
              flags.wfe_next = false;
625
            }
626
            // explicitely clear timeout event flag
627
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
628
            eventmask &= ~(eventListenerTimeout.events);
629
          }
630
        }
631
#endif
632
        break;
633
      } /* end of STAGE_3_3_WAITFORFIRSTID */
634

    
635
      case STAGE_3_3_WAITFORIDORSIG:
636
      {
637
#if (AMIROOS_CFG_SSSP_STACK_START != true)
638
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
639

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

    
666
        // if an IO event was received (DN signal)
667
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
668
          aosDbgPrintf("DN <-\n");
669
          // reset timeout timer
670
          chVTReset(&timerTimeout);
671
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
672
          eventmask &= ~(eventListenerTimeout.events);
673
          // increment and broadcast ID
674
          aos.sssp.moduleId = lastid + 1;
675
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
676
          canTxFrame.DLC = 4;
677
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
678
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
679
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
680
            chEvtBroadcast(&eventSourceTimeout);
681
            break;
682
          }
683
          // set delay timer
684
          chVTSet(&timerDelay, chTimeUS2I(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
685
        }
686

    
687
        // if a delay event occurred
688
        if (eventmask & eventListenerDelay.events) {
689
#if (AMIROOS_CFG_SSSP_STACK_END != true)
690
          // activate UP
691
          aosDbgPrintf("UP+\n");
692
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
693
#endif
694
          // deactivate S
695
          aosDbgPrintf("S-\n");
696
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
697
          // reset the timeout timer
698
          chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
699
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
700
          eventmask &= ~(eventListenerTimeout.events);
701
          // proceed
702
          stage = STAGE_3_3_WAITFORID;
703
        }
704
#endif
705

    
706
        break;
707
      } /* end of STAGE_3_3_WAITFORIDORSIG */
708

    
709
      case STAGE_3_3_WAITFORID:
710
      {
711
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
712

    
713
#if (AMIROOS_CFG_SSSP_STACK_END != true)
714
        // a CAN message was received
715
        if (eventmask & eventListenerCan.events) {
716
          // if an ID message was received
717
          if (canRxFrame.DLC == 4 &&
718
              canRxFrame.RTR == CAN_RTR_DATA &&
719
              canRxFrame.IDE == CAN_IDE_STD &&
720
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
721
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
722
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
723
            lastid = _deserialize(canRxFrame.data8, 4);
724
            aosDbgPrintf("ID (%u)\n", lastid);
725
#endif
726
            // restart timeout timer
727
            chVTSet(&timerTimeout, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
728
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
729
            eventmask &= ~(eventListenerTimeout.events);
730
          }
731
        }
732
#endif
733

    
734
        break;
735
      } /* end of STAGE_3_3_WAITFORID */
736

    
737
      case STAGE_3_4_FINISH:
738
      {
739
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
740

    
741
        // if an IO event was received (S signal)
742
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
743
          // reset the timeout timer
744
          chVTReset(&timerTimeout);
745
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
746
          eventmask &= ~(eventListenerTimeout.events);
747
          //set the delay timer
748
          chVTSet(&timerDelay, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
749
        }
750

    
751
        // if a CAN event was received
752
        if (eventmask & eventListenerCan.events) {
753
          // if an abort message was received
754
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
755
            aosDbgPrintf("abort msg\n");
756
            // reset the delay timer
757
            chVTReset(&timerDelay);
758
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
759
            eventmask &= ~(eventListenerDelay.events);
760
            // proceed
761
            stage = STAGE_3_4_ABORT;
762
          }
763
        }
764

    
765
        // if a delay timer event occurred
766
        if (eventmask & eventListenerDelay.events) {
767
          aosDbgPrintf("sequence sucessful\n");
768
          // sequence finished sucessfully
769
          flags.loop = false;
770
        }
771

    
772
        break;
773
      } /* end of STAGE_3_4_FINISH */
774

    
775
      case STAGE_3_4_ABORT_ACTIVE:
776
      {
777
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
778

    
779
        // emit abort message
780
        canTxFrame.DLC = 0;
781
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
782
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
783
        aosDbgPrintf("CAN -> abort\n");
784
        // clear timeout flag
785
        eventmask &= ~(eventListenerTimeout.events);
786
        // proceed immediately
787
        stage = STAGE_3_4_ABORT;
788
        flags.wfe_next = false;
789
        break;
790
      } /* end of STAGE_3_4_ABORT_ACTIVE */
791

    
792
      case STAGE_3_4_ABORT:
793
      {
794
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
795

    
796
        // deactivate S
797
        aosDbgPrintf("S-\n");
798
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
799
        // invalidate module ID
800
        aos.sssp.moduleId = 0;
801

    
802
        // if an IO event was received (S signal)
803
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
804
          aosDbgPrintf("sequence aborted\n");
805
          // exit the sequence
806
          flags.loop = false;
807
        }
808

    
809
        break;
810
      } /* end of STAGE_3_4_ABORT */
811
    }
812

    
813
    // fetch pending CAN message (if any)
814
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
815
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
816
      flags.wfe_next = false;
817
    }
818

    
819
    // handle unhandled timeout events
820
    if (eventmask & eventListenerTimeout.events) {
821
      aosDbgPrintf("ERR: timeout evt\n");
822
      // abort
823
      flags.wfe_next = false;
824
      stage = STAGE_3_4_ABORT_ACTIVE;
825
    }
826

    
827
    // apply wfe value for next iteration
828
    flags.wfe = flags.wfe_next;
829
  } /* end of FSM loop */
830
  aosDbgPrintf("\n");
831

    
832
  // unregister all events (timeout, delay, CAN receive)
833
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
834
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
835
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
836
  // clear any pending events (timeout, delay, CAN receive)
837
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
838

    
839
  // reset all control signals
840
#if (AMIROOS_CFG_SSSP_STACK_END != true)
841
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
842
#endif
843
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
844

    
845
  return shutdown;
846
}
847
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
848

    
849
/**
850
 * @brief   Application entry point.
851
 */
852
int main(void)
853
{
854
  // local variables
855
  eventmask_t eventmask = 0;
856
  eventflags_t eventflags = 0;
857
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
858
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
859
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
860
#endif
861

    
862
  /*
863
   * ##########################################################################
864
   * # system initialization                                                  #
865
   * ##########################################################################
866
   */
867

    
868
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0)
869
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS)
870
  AMIROOS_CFG_MAIN_INIT_HOOK_0(AMIROOS_CFG_MAIN_INIT_HOOK_0_ARGS);
871
#else
872
  AMIROOS_CFG_MAIN_INIT_HOOK_0();
873
#endif
874
#endif
875

    
876
  /* hardware, kernel, and operating system initialization */
877
  // ChibiOS/HAL and custom hal additions (if any)
878
  halInit();
879
#ifdef MODULE_INIT_HAL_EXTRA
880
  MODULE_INIT_HAL_EXTRA();
881
#endif
882

    
883
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
884
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
885
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
886
#else
887
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
888
#endif
889
#endif
890

    
891
  // ChibiOS/RT kernel and custom kernel additions (if any)
892
  chSysInit();
893
#ifdef MODULE_INIT_KERNEL_EXTRA
894
  MODULE_INIT_KERNEL_EXTRA();
895
#endif
896

    
897
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
898
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
899
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
900
#else
901
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
902
#endif
903
#endif
904

    
905
  // AMiRo-OS and custom OS additions (if any)
906
#if (AMIROOS_CFG_SHELL_ENABLE == true)
907
  aosSysInit(moduleShellPrompt);
908
#else
909
  aosSysInit();
910
#endif
911
#ifdef MODULE_INIT_OS_EXTRA
912
  MODULE_INIT_OS_EXTRA();
913
#endif
914

    
915
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
916
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
917
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
918
#else
919
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
920
#endif
921
#endif
922

    
923
#if (AMIROOS_CFG_TESTS_ENABLE == true)
924
#if defined(MODULE_INIT_TESTS)
925
  MODULE_INIT_TESTS();
926
#else
927
  #warning "MODULE_INIT_TESTS not defined"
928
#endif
929
#endif
930

    
931
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
932
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
933
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
934
#else
935
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
936
#endif
937
#endif
938

    
939
  /* event associations */
940
#if (AMIROOS_CFG_SSSP_ENABLE == true)
941
#if (AMIROOS_CFG_SSSP_STACK_START == true) && (AMIROOS_CFG_SSSP_STACK_END == true)
942
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC);
943
#elif (AMIROOS_CFG_SSSP_STACK_START == true)
944
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_UP);
945
#elif (AMIROOS_CFG_SSSP_STACK_END == true)
946
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_DN);
947
#else
948
  chEvtRegisterMaskWithFlags(&aos.events.io, &_eventListenerIO, IOEVENT_MASK, MODULE_SSSP_EVENTFLAGS_PD | MODULE_SSSP_EVENTFLAGS_SYNC | MODULE_SSSP_EVENTFLAGS_DN | MODULE_SSSP_EVENTFLAGS_UP);
949
#endif
950
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
951
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
952

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

    
961
  /* periphery communication initialization */
962
  // CAN (mandatory)
963
  canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
964
  // module specific initialization (if any)
965
#ifdef MODULE_INIT_PERIPHERY_COMM
966
  MODULE_INIT_PERIPHERY_COMM();
967
#endif
968
  // user interface (if any)
969
#ifdef MODULE_HAL_PROGIF
970
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
971
  aosIOChannelOutputEnable(&_stdiochannel);
972
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
973
#if (AMIROOS_CFG_SHELL_ENABLE == true)
974
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
975
  aosShellChannelInputEnable(&_stdshellchannel);
976
  aosShellChannelOutputEnable(&_stdshellchannel);
977
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
978
#endif
979
#endif
980

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

    
989
  /* module is ready -> print welcome prompt */
990
  aosprintf("\n");
991
  aosprintf("######################################################################\n");
992
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
993
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
994
  aosprintf("# Copyright (C) 2016..2018  Thomas Schöpping et al.                  #\n");
995
  aosprintf("#                                                                    #\n");
996
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
997
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
998
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
999
  aosprintf("# The development of this software was supported by the Excellence   #\n");
1000
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
1001
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
1002
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
1003
  aosprintf("######################################################################\n");
1004
  aosprintf("\n");
1005

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

    
1014
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1015
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
1016
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
1017
    /*
1018
     * This code is executed if the received event was not about the SYS_SYNC control signal.
1019
     * The returned event could be caused by any listener (not only the argument).
1020
     */
1021
    // IO event
1022
    if (eventmask & _eventListenerIO.events) {
1023
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1024
      // PD event
1025
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1026
        shutdown = AOS_SHUTDOWN_PASSIVE;
1027
      } else {
1028
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
1029
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1030
#else
1031
        // ignore any other IO events
1032
#endif
1033
      }
1034
    }
1035
    // OS event
1036
    else if (eventmask & _eventListenerOS.events) {
1037
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1038
      _unexpectedEventError(eventmask, eventflags);
1039
    }
1040
    // unknown event
1041
    else {
1042
      _unexpectedEventError(eventmask, 0);
1043
    }
1044
  }
1045

    
1046
  /*
1047
   * There must be no delays at this point, thus no hook is allowed.
1048
   */
1049

    
1050
  /* SSSP startup stage 3 (module stack initialization) */
1051
  if (shutdown == AOS_SHUTDOWN_NONE) {
1052
    shutdown = _ssspModuleStackInitialization();
1053
  }
1054
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1055

    
1056
  /*
1057
   * There must be no delays at this point, thus no hook is allowed.
1058
   */
1059

    
1060
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1061
  /* synchronize calendars */
1062
  if (shutdown == AOS_SHUTDOWN_NONE) {
1063
#if (AMIROOS_CFG_SSSP_MASTER == true)
1064
    CANTxFrame frame;
1065
    struct tm t;
1066
    uint64_t encoded;
1067

    
1068
    frame.DLC = 8;
1069
    frame.RTR = CAN_RTR_DATA;
1070
    frame.IDE = CAN_IDE_STD;
1071
    frame.SID = CALENDERSYNC_CANMSGID;
1072

    
1073
    aosDbgPrintf("transmitting current date/time...\t");
1074
    // get current date & time
1075
    aosSysGetDateTime(&t);
1076
    // encode
1077
    encoded = _TM2U64(&t);
1078
    // serialize
1079
    _serialize(frame.data8, encoded, 8);
1080
    // transmit
1081
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1082

    
1083
    aosDbgPrintf("done\n");
1084
#else /* AMIROOS_CFG_SSSP_MASTER == false */
1085
    CANRxFrame frame;
1086
    uint64_t encoded;
1087
    struct tm t;
1088

    
1089
    aosDbgPrintf("receiving current date/time...\t");
1090
    // receive message
1091
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, chTimeUS2I(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1092
      // validate message
1093
      if (frame.DLC == 8 &&
1094
          frame.RTR == CAN_RTR_DATA &&
1095
          frame.IDE == CAN_IDE_STD &&
1096
          frame.SID == CALENDERSYNC_CANMSGID) {
1097
        // deserialize
1098
        encoded = _deserialize(frame.data8, 8);
1099
        // decode
1100
        _U642TM(&t, encoded);
1101
        // set current date & time
1102
        aosSysSetDateTime(&t);
1103
        aosDbgPrintf("success\n");
1104
      } else {
1105
        aosDbgPrintf("fail (invalid message)\n");
1106
      }
1107
    } else {
1108
      aosDbgPrintf("fail (timeout)\n");
1109
    }
1110
#endif /* AMIROOS_CFG_SSSP_MASTER == false */
1111
    aosDbgPrintf("\n");
1112
  }
1113
#endif /* AMIROOS_CFG_SSSP_ENABLE == true */
1114

    
1115
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1116
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1117
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1118
#else
1119
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1120
#endif
1121
#endif
1122

    
1123
  /* completely start AMiRo-OS */
1124
  if (shutdown == AOS_SHUTDOWN_NONE) {
1125
    aosSysStart();
1126
  }
1127

    
1128
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1129
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1130
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1131
#else
1132
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1133
#endif
1134
#endif
1135

    
1136
  /*
1137
   * ##########################################################################
1138
   * # infinite loop                                                          #
1139
   * ##########################################################################
1140
   */
1141

    
1142
  // sleep until a shutdown event is received
1143
  while (shutdown == AOS_SHUTDOWN_NONE) {
1144
    // wait for an event
1145
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1146
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1147
#else
1148
    eventmask = chEvtWaitOne(ALL_EVENTS);
1149
#endif
1150

    
1151
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1152
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1153
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1154
#else
1155
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1156
#endif
1157
#endif
1158

    
1159
    switch (eventmask) {
1160
      // if this was an I/O event
1161
      case IOEVENT_MASK:
1162
        // evaluate flags
1163
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1164
#if (AMIROOS_CFG_SSSP_ENABLE == true)
1165
        // PD event
1166
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1167
          shutdown = AOS_SHUTDOWN_PASSIVE;
1168
        }
1169
#endif
1170
        // all other events
1171
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1172
        else {
1173
          MODULE_MAIN_LOOP_IO_EVENT(eventmask, eventflags);
1174
        }
1175
#endif
1176
        break;
1177

    
1178
      // if this was an OS event
1179
      case OSEVENT_MASK:
1180
        // evaluate flags
1181
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1182
        switch (eventflags) {
1183
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1184
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1185
            break;
1186
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1187
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1188
            break;
1189
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1190
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1191
            break;
1192
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1193
            shutdown = AOS_SHUTDOWN_RESTART;
1194
            break;
1195
          default:
1196
            _unexpectedEventError(eventmask, eventflags);
1197
            break;
1198
        }
1199
        break;
1200

    
1201
      // if this was any other event (should be impossible to occur)
1202
      default:
1203
        eventflags = 0;
1204
        _unexpectedEventError(eventmask, eventflags);
1205
        break;
1206
    }
1207

    
1208
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1209
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1210
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1211
#else
1212
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1213
#endif
1214
#endif
1215
  }
1216

    
1217
  /*
1218
   * ##########################################################################
1219
   * # system shutdown                                                        #
1220
   * ##########################################################################
1221
   */
1222

    
1223
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1224
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1225
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1226
#else
1227
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1228
#endif
1229
#endif
1230

    
1231
  // initialize/acknowledge shutdown
1232
  aosSysShutdownInit(shutdown);
1233

    
1234
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1235
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1236
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1237
#else
1238
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1239
#endif
1240
#endif
1241

    
1242
  // stop system threads
1243
  aosSysStop();
1244

    
1245
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1246
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1247
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1248
#else
1249
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1250
#endif
1251
#endif
1252

    
1253
  // deinitialize system
1254
  aosSysDeinit();
1255

    
1256
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1257
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1258
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1259
#else
1260
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1261
#endif
1262
#endif
1263

    
1264
  /* stop all periphery communication */
1265
  // CAN (mandatory)
1266
  canStop(&MODULE_HAL_CAN);
1267
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1268
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1269
#endif
1270

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

    
1279
  // finally hand over to bootloader
1280
  aosSysShutdownFinal(shutdown);
1281

    
1282
  /*
1283
   * ##########################################################################
1284
   * # after shutdown/restart                                                 #
1285
   * ##########################################################################
1286
   *
1287
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1288
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1289
   *       which subsystems should NOT be shut down.
1290
   */
1291

    
1292
  // return an error, since this code should not be executed
1293
  return -1;
1294
}
1295

    
1296
/** @} */