Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_main.cpp @ 9461fadc

History | View | Annotate | Download (42.021 KB)

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

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
#include <amiroos.h>
20
#include <module.h>
21

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

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

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

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

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

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

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

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

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

    
69
/**
70
 * @brief   CAN message identifier for calender synchronization message.
71
 */
72
#define CALENDERSYNC_CANMSGID                   0x004
73

    
74
/**
75
 * @brief   Listener object for I/O events.
76
 */
77
static event_listener_t _eventListenerIO;
78

    
79
/**
80
 * @brief   Listener object for OS events.
81
 */
82
static event_listener_t _eventListenerOS;
83

    
84
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
85
/**
86
 * @brief   I/O channel for the programmer interface.
87
 */
88
static AosIOChannel _stdiochannel;
89

    
90
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
91
/**
92
 * @brief   I/O shell channel for the programmer interface.
93
 */
94
static AosShellChannel _stdshellchannel;
95
#endif
96
#endif
97

    
98
/*
99
 * hook to add further static variables
100
 */
101
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
102
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
103
#endif
104

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

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

    
130
  chSysLockFromISR();
131
  chEvtBroadcastI((event_source_t*)par);
132
  chSysUnlockFromISR();
133

    
134
  return;
135
}
136

    
137
/**
138
 * @brief   Helper function to serialize data.
139
 *
140
 * @param[out]  dst   Pointer to the output buffer.
141
 * @param[in]   src   Data to be serialized.
142
 * @param[in]   n     Number of bytes to serialize.
143
 */
144
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
145
{
146
  aosDbgCheck(dst != NULL);
147
  aosDbgCheck(n > 0 && n <= 8);
148

    
149
  for (uint8_t byte = 0; byte < n; ++byte) {
150
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
151
  }
152

    
153
  return;
154
}
155

    
156
/**
157
 * @brief   Helper function to deserialize data.
158
 *
159
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
160
 * @param[in] n     Number of bytes to deserialize.
161
 *
162
 * @return    The deserialized 32 bit data.
163
 */
164
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
165
{
166
  aosDbgCheck(src != NULL);
167
  aosDbgCheck(n > 0 && n <= 8);
168

    
169
  uint64_t result = 0;
170
  for (uint8_t byte = 0; byte < n; ++byte) {
171
    result |= ((uint64_t)src[byte]) << (byte * 8);
172
  }
173

    
174
  return result;
175
}
176

    
177
/**
178
 * @brief   Converter function to encode a TM value to a single unsigned 64 bit integer.
179
 *
180
 * @details Contents of the TM struct are mapped as follows:
181
 *            bits  |63     62|61      53|52    50|49         26|25     22|21     17|16     12|11      6|5       0|
182
 *            #bits |       2 |        9 |      3 |          24 |       4 |       5 |       5 |       6 |       6 |
183
 *            value |   isdst |     yday |   wday |        year |     mon |    mday |    hour |     min |     sec |
184
 *            range | special | [0, 365] | [0, 6] | [1900, ...] | [0, 11] | [1, 31] | [0, 23] | [0, 59] | [0, 61] |
185
 *          The Daylight Saving Time Flag (isdsst) is encoded as follows:
186
 *            DST not in effect         -> 0
187
 *            DST in effect             -> 1
188
 *            no information available  -> 2
189
 *
190
 * @param[in] src   Pointer to the TM struct to encode.
191
 *
192
 * @return  An unsigned 64 bit integer, which holds the encoded time value.
193
 */
194
inline uint64_t _TM2U64(struct tm* src)
195
{
196
  aosDbgCheck(src != NULL);
197

    
198
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
199
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
200
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
201
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
202
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
203
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
204
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
205
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
206
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
207
}
208

    
209
/**
210
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
211
 *
212
 * @details For information on the encoding, please refer to @p _TM2U64 function.
213
 *
214
 * @param[out] dst  The TM struct to fill with the decoded values.
215
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
216
 */
217
inline void _U642TM(struct tm* dst, const uint64_t src)
218
{
219
  aosDbgCheck(dst != NULL);
220

    
221
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
222
  dst->tm_min  = (src >> 6)  & 0x0000003F;
223
  dst->tm_hour = (src >> 12) & 0x0000001F;
224
  dst->tm_mday = (src >> 17) & 0x0000001F;
225
  dst->tm_mon  = (src >> 22) & 0x0000000F;
226
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
227
  dst->tm_wday = (src >> 50) & 0x00000007;
228
  dst->tm_yday = (src >> 53) & 0x000001FF;
229
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
230

    
231
  return;
232
}
233

    
234
/**
235
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
236
 *
237
 * @return Shutdown value.
238
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
239
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
240
 */
241
aos_shutdown_t _ssspModuleStackInitialization(void)
242
{
243
  // local types
244
  /**
245
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
246
   */
247
  typedef enum {
248
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
249
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
250
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
251
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
252
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
253
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
254
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
255
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
256
  } sssp_modulestackinitstage_t;
257

    
258
  typedef struct {
259
    bool loop     : 1;
260
    bool wfe      : 1;
261
    bool wfe_next : 1;
262
  } flags_t;
263

    
264
  // local variables
265
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
266
  sssp_modulestackinitstage_t stage = STAGE_3_1;
267
  eventmask_t eventmask = 0;
268
  eventflags_t ioflags;
269
  event_source_t eventSourceTimeout;
270
  event_source_t eventSourceDelay;
271
  event_listener_t eventListenerTimeout;
272
  event_listener_t eventListenerDelay;
273
  event_listener_t eventListenerCan;
274
  virtual_timer_t timerTimeout;
275
  virtual_timer_t timerDelay;
276
  CANTxFrame canTxFrame;
277
  CANRxFrame canRxFrame;
278
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
279
  aos_ssspmoduleid_t lastid = 0;
280
#endif
281
  flags_t flags;
282

    
283
  // initialize local varibles
284
  chEvtObjectInit(&eventSourceTimeout);
285
  chEvtObjectInit(&eventSourceDelay);
286
  chVTObjectInit(&timerTimeout);
287
  chVTObjectInit(&timerDelay);
288
  canTxFrame.RTR = CAN_RTR_DATA;
289
  canTxFrame.IDE = CAN_IDE_STD;
290
  flags.loop = true;
291
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
292
  flags.wfe_next = true;
293

    
294
  // initialize system variables
295
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
296
  aos.sssp.moduleId = 0;
297

    
298
  // listen to events (timout, delay, CAN receive)
299
  chEvtRegisterMask(&eventSourceTimeout, &eventListenerTimeout, TIMEOUTEVENT_MASK);
300
  chEvtRegisterMask(&eventSourceDelay, &eventListenerDelay, DELAYEVENT_MASK);
301
  chEvtRegisterMask(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan, CANEVENT_MASK);
302

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

    
361
    // reset wfe flag for the next iteration
362
    flags.wfe_next = true;
363

    
364
    // waiting for events may be skipped
365
    if (flags.wfe) {
366
      // wait for any event to occur
367
      aosDbgPrintf("WFE...");
368
      eventmask = chEvtWaitAnyTimeout(ALL_EVENTS, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT));
369
      aosDbgPrintf("\t0x%08X", eventmask);
370
    } else {
371
      aosDbgPrintf("WFE skipped");
372
    }
373
    aos_timestamp_t uptime;
374
    aosSysGetUptime(&uptime);
375
    aosDbgPrintf("\t%04ums\n", (uint32_t)(uptime / 1000));
376

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

    
457
    /*
458
     * this is the actual FSM
459
     */
460
    switch (stage) {
461
      case STAGE_3_1:
462
      {
463
        aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
464

    
465
        // there was no event at all (skipped wfe)
466
        if (eventmask == 0 && flags.wfe == false) {
467
#if (AMIROOS_CFG_SSSP_MASTER == true)
468
          // initialize the stage by transmitting an according CAN message
469
          aosDbgPrintf("CAN -> init\n");
470
          canTxFrame.DLC = 0;
471
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_INIT;
472
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
473
            chEvtBroadcast(&eventSourceTimeout);
474
            break;
475
          }
476
          // activate S
477
          aosDbgPrintf("S+\n");
478
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
479
#if (AMIROOS_CFG_SSSP_STACK_START == true)
480
          // proceed immediately
481
          stage = STAGE_3_2;
482
          flags.wfe_next = false;
483
#else
484
          // set the timeout timer
485
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
486
          // proceed
487
          stage = STAGE_3_3_WAITFORFIRSTID;
488
#endif
489
#else
490
          // set the timeout timer
491
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
492
#endif
493
        }
494

    
495
#if (AMIROOS_CFG_SSSP_MASTER != true)
496
        // a CAN message was received
497
        else if (eventmask & eventListenerCan.events) {
498
          // if an initiation message was received
499
          if (canRxFrame.DLC == 0 &&
500
              canRxFrame.RTR == CAN_RTR_DATA &&
501
              canRxFrame.IDE == CAN_IDE_STD &&
502
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_INIT) {
503
            aosDbgPrintf("init msg\n");
504
            // reset the timeout timer and clear pending flags
505
            chVTReset(&timerTimeout);
506
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
507
            eventmask &= ~(eventListenerTimeout.events);
508
            // activate S
509
            aosDbgPrintf("S+\n");
510
            apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_ON);
511
#if (AMIROOS_CFG_SSSP_STACK_START == true)
512
            // proceed
513
            stage = STAGE_3_2;
514
            flags.wfe_next = false;
515
#else
516
            // set the timeout timer
517
            chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
518
            // proceed
519
            stage = STAGE_3_3_WAITFORFIRSTID;
520
#endif
521
          }
522
        }
523
#endif
524

    
525
        break;
526
      } /* end of STAGE_3_1 */
527

    
528
      case STAGE_3_2:
529
      {
530
#if (AMIROOS_CFG_SSSP_STACK_START == true)
531
        aos.sssp.stage = AOS_SSSP_STARTUP_3_2;
532

    
533
        // if this stage was just entered
534
        if (flags.wfe == false) {
535
          // set the module ID
536
          aos.sssp.moduleId = 1;
537
          // broadcast module ID
538
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
539
          canTxFrame.DLC = 4;
540
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
541
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
542
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
543
            chEvtBroadcast(&eventSourceTimeout);
544
            break;
545
          }
546
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
547
          lastid = aos.sssp.moduleId;
548
#endif
549
#if (AMIROOS_CFG_SSSP_STACK_END == true)
550
          // sequence is already over
551
          // deactivate S
552
          aosDbgPrintf("S-\n");
553
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
554
          // proceed
555
          stage = STAGE_3_3_WAITFORID;
556
#else
557
          // set the delay timer so the UP signal is activated later
558
          chVTSet(&timerDelay, LL_US2ST(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
559
#endif
560
        }
561

    
562
        // if a delay event occurred
563
        if (eventmask & eventListenerDelay.events) {
564
          // activate UP
565
          aosDbgPrintf("UP+\n");
566
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
567
          // deactivate S
568
          aosDbgPrintf("S-\n");
569
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
570
          // explicitely clear timeout event flag
571
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
572
          eventmask &= ~(eventListenerTimeout.events);
573
          // proceed
574
          stage = STAGE_3_3_WAITFORID;
575
        }
576
#endif
577

    
578
        break;
579
      } /* end of STAGE_3_2 */
580

    
581
      case STAGE_3_3_WAITFORFIRSTID:
582
      {
583
#if (AMIROOS_CFG_SSSP_STACK_START != true)
584
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
585

    
586
        // a CAN message was received
587
        if (eventmask & eventListenerCan.events) {
588
          // if an ID message was received
589
          if (canRxFrame.DLC == 4 &&
590
              canRxFrame.RTR == CAN_RTR_DATA &&
591
              canRxFrame.IDE == CAN_IDE_STD &&
592
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
593
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
594
            // validate received ID
595
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
596
              // store received ID
597
              lastid = _deserialize(canRxFrame.data8, 4);
598
              // restart timeout timer
599
              chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
600
              // proceed
601
              stage = STAGE_3_3_WAITFORIDORSIG;
602
            } else {
603
              aosDbgPrintf("ERR: invalid ID\n");
604
              // abort
605
              stage = STAGE_3_4_ABORT_ACTIVE;
606
              flags.wfe_next = false;
607
            }
608
            // explicitely clear timeout event flag
609
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
610
            eventmask &= ~(eventListenerTimeout.events);
611
          }
612
        }
613
#endif
614
        break;
615
      } /* end of STAGE_3_3_WAITFORFIRSTID */
616

    
617
      case STAGE_3_3_WAITFORIDORSIG:
618
      {
619
#if (AMIROOS_CFG_SSSP_STACK_START != true)
620
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
621

    
622
        // a CAN message was received
623
        if (eventmask & eventListenerCan.events) {
624
          // if an ID message was received
625
          if (canRxFrame.DLC == 4 &&
626
              canRxFrame.RTR == CAN_RTR_DATA &&
627
              canRxFrame.IDE == CAN_IDE_STD &&
628
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
629
            aosDbgPrintf("ID (%u)\n", (uint32_t)_deserialize(canRxFrame.data8, 4));
630
            // validate received ID
631
            if (lastid < _deserialize(canRxFrame.data8, 4)) {
632
              // store received ID
633
              lastid = _deserialize(canRxFrame.data8, 4);
634
              // restart timeout timer
635
              chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
636
            } else {
637
              aosDbgPrintf("ERR: invalid ID\n");
638
              // abort
639
              stage = STAGE_3_4_ABORT_ACTIVE;
640
              flags.wfe_next = false;
641
            }
642
            // explicitely clear timeout event flag
643
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
644
            eventmask &= ~(eventListenerTimeout.events);
645
          }
646
        }
647

    
648
        // if an IO event was received (DN signal)
649
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_DN)) {
650
          aosDbgPrintf("DN <-\n");
651
          // reset timeout timer
652
          chVTReset(&timerTimeout);
653
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
654
          eventmask &= ~(eventListenerTimeout.events);
655
          // increment and broadcast ID
656
          aos.sssp.moduleId = lastid + 1;
657
          aosDbgPrintf("CAN -> ID (%u)\n", aos.sssp.moduleId);
658
          canTxFrame.DLC = 4;
659
          canTxFrame.SID = SSSP_STACKINIT_CANMSGID_MODULEID;
660
          _serialize(canTxFrame.data8, aos.sssp.moduleId, 4);
661
          if (canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_IMMEDIATE) != MSG_OK) {
662
            chEvtBroadcast(&eventSourceTimeout);
663
            break;
664
          }
665
          // set delay timer
666
          chVTSet(&timerDelay, LL_US2ST(AMIROOS_CFG_SSSP_SIGNALDELAY), _ssspTimerCallback, &eventSourceDelay);
667
        }
668

    
669
        // if a delay event occurred
670
        if (eventmask & eventListenerDelay.events) {
671
#if (AMIROOS_CFG_SSSP_STACK_END != true)
672
          // activate UP
673
          aosDbgPrintf("UP+\n");
674
          apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_ON);
675
#endif
676
          // deactivate S
677
          aosDbgPrintf("S-\n");
678
          apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
679
          // reset the timeout timer
680
          chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
681
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
682
          eventmask &= ~(eventListenerTimeout.events);
683
          // proceed
684
          stage = STAGE_3_3_WAITFORID;
685
        }
686
#endif
687

    
688
        break;
689
      } /* end of STAGE_3_3_WAITFORIDORSIG */
690

    
691
      case STAGE_3_3_WAITFORID:
692
      {
693
        aos.sssp.stage = AOS_SSSP_STARTUP_3_3;
694

    
695
#if (AMIROOS_CFG_SSSP_STACK_END != true)
696
        // a CAN message was received
697
        if (eventmask & eventListenerCan.events) {
698
          // if an ID message was received
699
          if (canRxFrame.DLC == 4 &&
700
              canRxFrame.RTR == CAN_RTR_DATA &&
701
              canRxFrame.IDE == CAN_IDE_STD &&
702
              canRxFrame.SID == SSSP_STACKINIT_CANMSGID_MODULEID) {
703
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
704
            // Plausibility of the received ID is not checked at this point but is done by other modules still in a previous stage.
705
            lastid = _deserialize(canRxFrame.data8, 4);
706
            aosDbgPrintf("ID (%u)\n", lastid);
707
#endif
708
            // restart timeout timer
709
            chVTSet(&timerTimeout, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceTimeout);
710
            chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
711
            eventmask &= ~(eventListenerTimeout.events);
712
          }
713
        }
714
#endif
715

    
716
        break;
717
      } /* end of STAGE_3_3_WAITFORID */
718

    
719
      case STAGE_3_4_FINISH:
720
      {
721
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
722

    
723
        // if an IO event was received (S signal)
724
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
725
          // reset the timeout timer
726
          chVTReset(&timerTimeout);
727
          chEvtWaitAnyTimeout(eventListenerTimeout.events, TIME_IMMEDIATE);
728
          eventmask &= ~(eventListenerTimeout.events);
729
          //set the delay timer
730
          chVTSet(&timerDelay, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT), _ssspTimerCallback, &eventSourceDelay);
731
        }
732

    
733
        // if a CAN event was received
734
        if (eventmask & eventListenerCan.events) {
735
          // if an abort message was received
736
          if (canRxFrame.SID == SSSP_STACKINIT_CANMSGID_ABORT) {
737
            aosDbgPrintf("abort msg\n");
738
            // reset the delay timer
739
            chVTReset(&timerDelay);
740
            chEvtWaitAnyTimeout(eventListenerDelay.events, TIME_IMMEDIATE);
741
            eventmask &= ~(eventListenerDelay.events);
742
            // proceed
743
            stage = STAGE_3_4_ABORT;
744
          }
745
        }
746

    
747
        // if a delay timer event occurred
748
        if (eventmask & eventListenerDelay.events) {
749
          aosDbgPrintf("sequence sucessful\n");
750
          // sequence finished sucessfully
751
          flags.loop = false;
752
        }
753

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

    
757
      case STAGE_3_4_ABORT_ACTIVE:
758
      {
759
        aos.sssp.stage = AOS_SSSP_STARTUP_3_4;
760

    
761
        // emit abort message
762
        canTxFrame.DLC = 0;
763
        canTxFrame.SID = SSSP_STACKINIT_CANMSGID_ABORT;
764
        canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canTxFrame, TIME_INFINITE);
765
        aosDbgPrintf("CAN -> abort\n");
766
        // clear timeout flag
767
        eventmask &= ~(eventListenerTimeout.events);
768
        // proceed immediately
769
        stage = STAGE_3_4_ABORT;
770
        flags.wfe_next = false;
771
        break;
772
      } /* end of STAGE_3_4_ABORT_ACTIVE */
773

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

    
778
        // deactivate S
779
        aosDbgPrintf("S-\n");
780
        apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
781
        // invalidate module ID
782
        aos.sssp.moduleId = 0;
783

    
784
        // if an IO event was received (S signal)
785
        if ((eventmask & _eventListenerIO.events) && (ioflags & MODULE_SSSP_EVENTFLAGS_SYNC)) {
786
          aosDbgPrintf("sequence aborted\n");
787
          // exit the sequence
788
          flags.loop = false;
789
        }
790

    
791
        break;
792
      } /* end of STAGE_3_4_ABORT */
793
    }
794

    
795
    // fetch pending CAN message (if any)
796
    if ((eventmask & eventListenerCan.events) && (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &canRxFrame, TIME_IMMEDIATE) == MSG_OK)) {
797
      aosDbgPrintf("CAN <- 0x%03X\n", canRxFrame.SID);
798
      flags.wfe_next = false;
799
    }
800

    
801
    // handle unhandled timeout events
802
    if (eventmask & eventListenerTimeout.events) {
803
      aosDbgPrintf("ERR: timeout evt\n");
804
      // abort
805
      flags.wfe_next = false;
806
      stage = STAGE_3_4_ABORT_ACTIVE;
807
    }
808

    
809
    // apply wfe value for next iteration
810
    flags.wfe = flags.wfe_next;
811
  }
812
  aosDbgPrintf("\n");
813

    
814
  // unregister all events (timeout, delay, CAN receive)
815
  chEvtUnregister(&eventSourceTimeout, &eventListenerTimeout);
816
  chEvtUnregister(&eventSourceDelay, &eventListenerDelay);
817
  chEvtUnregister(&MODULE_HAL_CAN.rxfull_event, &eventListenerCan);
818
  // clear any pending events (timeout, delay, CAN receive)
819
  chEvtWaitAllTimeout(TIMEOUTEVENT_MASK | DELAYEVENT_MASK | CANEVENT_MASK, TIME_IMMEDIATE);
820

    
821
  // reset all control signals
822
#if (AMIROOS_CFG_SSSP_STACK_END != true)
823
  apalControlGpioSet(&moduleSsspGpioUp, APAL_GPIO_OFF);
824
#endif
825
  apalControlGpioSet(&moduleSsspGpioSync, APAL_GPIO_OFF);
826

    
827
  return shutdown;
828
}
829

    
830
/**
831
 * @brief   Application entry point.
832
 */
833
int main(void)
834
{
835
  // local variables
836
  eventmask_t eventmask = 0;
837
  eventflags_t eventflags = 0;
838
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
839
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
840
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
841
#endif
842

    
843
  /*
844
   * ##########################################################################
845
   * # system initialization                                                  #
846
   * ##########################################################################
847
   */
848

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

    
857
  /* hardware, kernel, and operating system initialization */
858
  // ChibiOS/HAL and custom hal additions (if any)
859
  halInit();
860
#ifdef MODULE_INIT_HAL_EXTRA
861
  MODULE_INIT_HAL_EXTRA();
862
#endif
863

    
864
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
865
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
866
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
867
#else
868
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
869
#endif
870
#endif
871

    
872
  // ChibiOS/RT kernel and custom kernel additions (if any)
873
  chSysInit();
874
#ifdef MODULE_INIT_KERNEL_EXTRA
875
  MODULE_INIT_KERNEL_EXTRA();
876
#endif
877

    
878
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
879
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
880
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
881
#else
882
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
883
#endif
884
#endif
885

    
886
  // AMiRo-OS and custom OS additions (if any)
887
#if (AMIROOS_CFG_SHELL_ENABLE == true)
888
  aosSysInit(moduleShellPrompt);
889
#else
890
  aosSysInit();
891
#endif
892
#ifdef MODULE_INIT_OS_EXTRA
893
  MODULE_INIT_OS_EXTRA();
894
#endif
895

    
896
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
897
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
898
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
899
#else
900
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
901
#endif
902
#endif
903

    
904
#if (AMIROOS_CFG_TESTS_ENABLE == true)
905
#if defined(MODULE_INIT_TESTS)
906
  MODULE_INIT_TESTS();
907
#else
908
  #warning "MODULE_INIT_TESTS not defined"
909
#endif
910
#endif
911

    
912
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
913
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
914
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
915
#else
916
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
917
#endif
918
#endif
919

    
920
  /* event associations */
921
  chEvtRegisterMask(&aos.events.io, &_eventListenerIO, IOEVENT_MASK);
922
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, OSEVENT_MASK);
923

    
924
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
925
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
926
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
927
#else
928
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
929
#endif
930
#endif
931

    
932
  /* periphery communication initialization */
933
  // CAN (mandatory)
934
  canStart(&MODULE_HAL_CAN, &moduleHalCanConfig);
935
  // module specific initialization (if any)
936
#ifdef MODULE_INIT_PERIPHERY_COMM
937
  MODULE_INIT_PERIPHERY_COMM();
938
#endif
939
  // user interface (if any)
940
#ifdef MODULE_HAL_PROGIF
941
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
942
  aosIOChannelOutputEnable(&_stdiochannel);
943
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
944
#if (AMIROOS_CFG_SHELL_ENABLE == true)
945
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
946
  aosShellChannelInputEnable(&_stdshellchannel);
947
  aosShellChannelOutputEnable(&_stdshellchannel);
948
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
949
#endif
950
#endif
951

    
952
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6)
953
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS)
954
  AMIROOS_CFG_MAIN_INIT_HOOK_6(AMIROOS_CFG_MAIN_INIT_HOOK_6_ARGS);
955
#else
956
  AMIROOS_CFG_MAIN_INIT_HOOK_6();
957
#endif
958
#endif
959

    
960
  /* module is ready -> print welcome prompt */
961
  aosprintf("\n");
962
  aosprintf("######################################################################\n");
963
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
964
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
965
  aosprintf("# Copyright (C) 2016..2018  Thomas Schöpping et al.                  #\n");
966
  aosprintf("#                                                                    #\n");
967
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
968
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
969
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
970
  aosprintf("# The development of this software was supported by the Excellence   #\n");
971
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
972
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
973
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
974
  aosprintf("######################################################################\n");
975
  aosprintf("\n");
976

    
977
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7)
978
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS)
979
  AMIROOS_CFG_MAIN_INIT_HOOK_7(AMIROOS_CFG_MAIN_INIT_HOOK_7_ARGS);
980
#else
981
  AMIROOS_CFG_MAIN_INIT_HOOK_7();
982
#endif
983
#endif
984

    
985
  /* SSSP startup OS synchronization phase (end of startup stage 2) */
986
  while ((shutdown == AOS_SHUTDOWN_NONE) && (eventmask = aosSysSsspStartupOsInitSyncCheck(&_eventListenerIO)) != 0) {
987
    /*
988
     * This code is executed if the received event was not about the SYS_SYNC control signal.
989
     * The returned event could be caused by any listener (not only the argument).
990
     */
991
    // IO event
992
    if (eventmask & _eventListenerIO.events) {
993
      eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
994
      // PD event
995
      if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
996
        shutdown = AOS_SHUTDOWN_PASSIVE;
997
      } else {
998
#ifdef MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK
999
        MODULE_SSSP_STARTUP_2_2_IOEVENT_HOOK(eventmask, eventflags);
1000
#else
1001
        // ignore any other IO events
1002
#endif
1003
      }
1004
    }
1005
    // OS event
1006
    else if (eventmask & _eventListenerOS.events) {
1007
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1008
      _unexpectedEventError(eventmask, eventflags);
1009
    }
1010
    // unknown event
1011
    else {
1012
      _unexpectedEventError(eventmask, 0);
1013
    }
1014
  }
1015

    
1016
  /*
1017
   * There must be no delays at this point, thus no hook is allowed.
1018
   */
1019

    
1020
  /* SSSP startup stage 3 (module stack initialization) */
1021
  if (shutdown == AOS_SHUTDOWN_NONE) {
1022
    shutdown = _ssspModuleStackInitialization();
1023
  }
1024

    
1025
  /*
1026
   * There must be no delays at this point, thus no hook is allowed.
1027
   */
1028

    
1029
  /* snychronize calendars */
1030
  if (shutdown == AOS_SHUTDOWN_NONE) {
1031
#if (AMIROOS_CFG_SSSP_MASTER == true)
1032
    CANTxFrame frame;
1033
    struct tm t;
1034
    uint64_t encoded;
1035

    
1036
    frame.DLC = 8;
1037
    frame.RTR = CAN_RTR_DATA;
1038
    frame.IDE = CAN_IDE_STD;
1039
    frame.SID = CALENDERSYNC_CANMSGID;
1040

    
1041
    aosDbgPrintf("transmitting current date/time...\t");
1042
    // get current date & time
1043
    aosSysGetDateTime(&t);
1044
    // encode
1045
    encoded = _TM2U64(&t);
1046
    // serialize
1047
    _serialize(frame.data8, encoded, 8);
1048
    // transmit
1049
    canTransmitTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, TIME_IMMEDIATE);
1050

    
1051
    aosDbgPrintf("done\n");
1052
#else
1053
    CANRxFrame frame;
1054
    uint64_t encoded;
1055
    struct tm t;
1056

    
1057
    aosDbgPrintf("receiving current date/time...\t");
1058
    // receive message
1059
    if (canReceiveTimeout(&MODULE_HAL_CAN, CAN_ANY_MAILBOX, &frame, LL_US2ST(AOS_SYSTEM_SSSP_TIMEOUT)) == MSG_OK) {
1060
      // validate message
1061
      if (frame.DLC == 8 &&
1062
          frame.RTR == CAN_RTR_DATA &&
1063
          frame.IDE == CAN_IDE_STD &&
1064
          frame.SID == CALENDERSYNC_CANMSGID) {
1065
        // deserialize
1066
        encoded = _deserialize(frame.data8, 8);
1067
        // decode
1068
        _U642TM(&t, encoded);
1069
        // set current date & time
1070
        aosSysSetDateTime(&t);
1071
        aosDbgPrintf("success\n");
1072
      } else {
1073
        aosDbgPrintf("fail (invalid message)\n");
1074
      }
1075
    } else {
1076
      aosDbgPrintf("fail (timeout)\n");
1077
    }
1078
#endif
1079
    aosDbgPrintf("\n");
1080
  }
1081

    
1082
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8)
1083
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS)
1084
  AMIROOS_CFG_MAIN_INIT_HOOK_8(AMIROOS_CFG_MAIN_INIT_HOOK_8_ARGS);
1085
#else
1086
  AMIROOS_CFG_MAIN_INIT_HOOK_8();
1087
#endif
1088
#endif
1089

    
1090
  /* completely start AMiRo-OS */
1091
  if (shutdown == AOS_SHUTDOWN_NONE) {
1092
    aosSysStart();
1093
  }
1094

    
1095
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9)
1096
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS)
1097
  AMIROOS_CFG_MAIN_INIT_HOOK_9(AMIROOS_CFG_MAIN_INIT_HOOK_9_ARGS);
1098
#else
1099
  AMIROOS_CFG_MAIN_INIT_HOOK_9();
1100
#endif
1101
#endif
1102

    
1103
  /*
1104
   * ##########################################################################
1105
   * # infinite loop                                                          #
1106
   * ##########################################################################
1107
   */
1108

    
1109
  // sleep until a shutdown event is received
1110
  while (shutdown == AOS_SHUTDOWN_NONE) {
1111
    // wait for an event
1112
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
1113
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, LL_US2ST(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
1114
#else
1115
    eventmask = chEvtWaitOne(ALL_EVENTS);
1116
#endif
1117

    
1118
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0)
1119
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS)
1120
    AMIROOS_CFG_MAIN_LOOP_HOOK_0(AMIROOS_CFG_MAIN_LOOP_HOOK_0_ARGS);
1121
#else
1122
    AMIROOS_CFG_MAIN_LOOP_HOOK_0();
1123
#endif
1124
#endif
1125

    
1126
    switch (eventmask) {
1127
      // if this was an I/O event
1128
      case IOEVENT_MASK:
1129
        // evaluate flags
1130
        eventflags = chEvtGetAndClearFlags(&_eventListenerIO);
1131
        // PD event
1132
        if (eventflags & MODULE_SSSP_EVENTFLAGS_PD) {
1133
          shutdown = AOS_SHUTDOWN_PASSIVE;
1134
        }
1135
        // all other events
1136
#ifdef MODULE_MAIN_LOOP_IO_EVENT
1137
        else {
1138
          MODULE_MAIN_LOOP_IO_EVENT(eventmask, eventflags);
1139
        }
1140
#endif
1141
        break;
1142

    
1143
      // if this was an OS event
1144
      case OSEVENT_MASK:
1145
        // evaluate flags
1146
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
1147
        switch (eventflags) {
1148
          case AOS_SYSTEM_EVENTFLAGS_HIBERNATE:
1149
            shutdown = AOS_SHUTDOWN_HIBERNATE;
1150
            break;
1151
          case AOS_SYSTEM_EVENTFLAGS_DEEPSLEEP:
1152
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
1153
            break;
1154
          case AOS_SYSTEM_EVENTFLAGS_TRANSPORTATION:
1155
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
1156
            break;
1157
          case AOS_SYSTEM_EVENTFLAGS_RESTART:
1158
            shutdown = AOS_SHUTDOWN_RESTART;
1159
            break;
1160
          default:
1161
            _unexpectedEventError(eventmask, eventflags);
1162
            break;
1163
        }
1164
        break;
1165

    
1166
      // if this was any other event (should be impossible to occur)
1167
      default:
1168
        eventflags = 0;
1169
        _unexpectedEventError(eventmask, eventflags);
1170
        break;
1171
    }
1172

    
1173
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
1174
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
1175
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
1176
#else
1177
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
1178
#endif
1179
#endif
1180
  }
1181

    
1182
  /*
1183
   * ##########################################################################
1184
   * # system shutdown                                                        #
1185
   * ##########################################################################
1186
   */
1187

    
1188
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0)
1189
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS)
1190
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0_ARGS);
1191
#else
1192
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_0();
1193
#endif
1194
#endif
1195

    
1196
  // initialize/acknowledge shutdown
1197
  aosSysShutdownInit(shutdown);
1198

    
1199
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
1200
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
1201
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
1202
#else
1203
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
1204
#endif
1205
#endif
1206

    
1207
  // stop system threads
1208
  aosSysStop();
1209

    
1210
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
1211
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
1212
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
1213
#else
1214
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
1215
#endif
1216
#endif
1217

    
1218
  // deinitialize system
1219
  aosSysDeinit();
1220

    
1221
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
1222
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
1223
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
1224
#else
1225
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
1226
#endif
1227
#endif
1228

    
1229
  /* stop all periphery communication */
1230
  // CAN (mandatory)
1231
  canStop(&MODULE_HAL_CAN);
1232
#ifdef MODULE_SHUTDOWN_PERIPHERY_COMM
1233
  MODULE_SHUTDOWN_PERIPHERY_COMM();
1234
#endif
1235

    
1236
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
1237
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
1238
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
1239
#else
1240
    AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
1241
#endif
1242
#endif
1243

    
1244
  // finally hand over to bootloader
1245
  aosSysShutdownFinal(&MODULE_HAL_EXT, shutdown);
1246

    
1247
  /*
1248
   * ##########################################################################
1249
   * # after shutdown/restart                                                 #
1250
   * ##########################################################################
1251
   *
1252
   * NOTE: This code will not be executed, since the bootloader callbacks will stop/restart the MCU.
1253
   *       It is included nevertheless for the sake of completeness and to explicitely indicate,
1254
   *       which subsystems should NOT be shut down.
1255
   */
1256

    
1257
  // return an error, since this code should not be executed
1258
  return -1;
1259
}