Statistics
| Branch: | Tag: | Revision:

amiro-os / os / core / src / aos_main.cpp @ 6df420be

History | View | Annotate | Download (42.8 KB)

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