Statistics
| Branch: | Tag: | Revision:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
860
  /*
861
   * ##########################################################################
862
   * # system initialization                                                  #
863
   * ##########################################################################
864
   */
865

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1066
    frame.DLC = 8;
1067
    frame.RTR = CAN_RTR_DATA;
1068
    frame.IDE = CAN_IDE_STD;
1069
    frame.SID = CALENDERSYNC_CANMSGID;
1070

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

    
1081
    aosDbgPrintf("done\n");
1082
#else
1083
    CANRxFrame frame;
1084
    uint64_t encoded;
1085
    struct tm t;
1086

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

    
1112
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1113
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1114
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1115
#else
1116
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1117
#endif
1118
#endif
1119

    
1120
  /* completely start AMiRo-OS */
1121
  if (shutdown == AOS_SHUTDOWN_NONE) {
1122
    aosSysStart();
1123
  }
1124

    
1125
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1126
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1127
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1128
#else
1129
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1130
#endif
1131
#endif
1132

    
1133
  /*
1134
   * ##########################################################################
1135
   * # infinite loop                                                          #
1136
   * ##########################################################################
1137
   */
1138

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

    
1148
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1149
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1150
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1151
#else
1152
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1153
#endif
1154
#endif
1155

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

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

    
1196
      // if this was any other event (should be impossible to occur)
1197
      default:
1198
        eventflags = 0;
1199
        _unexpectedEventError(eventmask, eventflags);
1200
        break;
1201
    }
1202

    
1203
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1204
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1205
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1206
#else
1207
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1208
#endif
1209
#endif
1210

    
1211
  }
1212
#endif
1213

    
1214
  /*
1215
   * ##########################################################################
1216
   * # system shutdown                                                        #
1217
   * ##########################################################################
1218
   */
1219

    
1220
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1221
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1222
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1223
#else
1224
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1225
#endif
1226
#endif
1227

    
1228
  // initialize/acknowledge shutdown
1229
  aosSysShutdownInit(shutdown);
1230

    
1231
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1232
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1233
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1234
#else
1235
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1236
#endif
1237
#endif
1238

    
1239
  // stop system threads
1240
  aosSysStop();
1241

    
1242
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1243
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1244
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1245
#else
1246
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1247
#endif
1248
#endif
1249

    
1250
  // deinitialize system
1251
  aosSysDeinit();
1252

    
1253
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1254
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1255
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1256
#else
1257
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1258
#endif
1259
#endif
1260

    
1261
  /* stop all periphery communication */
1262
  // CAN (mandatory)
1263
  canStop(&MODULE_HAL_CAN);
1264
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1265
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1266
#endif
1267

    
1268
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1269
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1270
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1271
#else
1272
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1273
#endif
1274
#endif
1275

    
1276
  // finally hand over to bootloader
1277
  aosSysShutdownFinal(shutdown);
1278

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

    
1289
  // return an error, since this code should not be executed
1290
  return -1;
1291
}
1292

    
1293
/** @} */