Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ c53ef0b1

History | View | Annotate | Download (36.665 KB)

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

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

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

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

    
19
/**
20
 * @file    aos_main.cpp
21
 * @brief   Main function.
22
 *
23
 * @addtogroup aos_system
24
 * @{
25
 */
26

    
27
#include <amiroos.h>
28

    
29
/*
30
 * hook to add further includes
31
 */
32
#if defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER)
33
#include AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER
34
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_INCLUDE_HEADER) */
35

    
36
/******************************************************************************/
37
/* LOCAL DEFINITIONS                                                          */
38
/******************************************************************************/
39

    
40
/**
41
 * @brief   Event mask to identify GPIO events.
42
 */
43
#define EVENTMASK_GPIO                          EVENT_MASK(0)
44

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

    
50
#if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__)
51

    
52

    
53
#if (AMIROOS_CFG_SSSP_MSI == true) || defined(__DOXYGEN__)
54

    
55
/**
56
 * @brief   Event mask to identify SSSP timeout events (MSI only).
57
 */
58
#define EVENTMASK_SSSPTIMEOUT                   EVENT_MASK(2)
59

    
60
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
61

    
62
/**
63
 * @brief   Event mask to identify SSSP delay events.
64
 */
65
#define EVENTMASK_SSSPDELAY                     EVENT_MASK(3)
66

    
67
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
68

    
69
/******************************************************************************/
70
/* EXPORTED VARIABLES                                                         */
71
/******************************************************************************/
72

    
73
/******************************************************************************/
74
/* LOCAL TYPES                                                                */
75
/******************************************************************************/
76

    
77
/******************************************************************************/
78
/* LOCAL VARIABLES                                                            */
79
/******************************************************************************/
80

    
81
/**
82
 * @brief   Listener object for GPIO events.
83
 */
84
static event_listener_t _eventListenerGPIO;
85

    
86
/**
87
 * @brief   Listener object for OS events.
88
 */
89
static event_listener_t _eventListenerOS;
90

    
91
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
92

    
93
/**
94
 * @brief   I/O channel for the programmer interface.
95
 */
96
static AosIOChannel _stdiochannel;
97

    
98
#endif /* defined(MODULE_HAL_PROGIF) */
99

    
100
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
101

    
102
/**
103
 * @brief   I/O shell channel for the programmer interface.
104
 */
105
static AosShellChannel _stdshellchannel;
106

    
107
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
108

    
109
/*
110
 * hook to add further static variables
111
 */
112
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
113
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
114
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES) */
115

    
116
/******************************************************************************/
117
/* LOCAL FUNCTIONS                                                            */
118
/******************************************************************************/
119

    
120
/**
121
 * @brief   Prints an error message about an unexpected event.
122
 *
123
 * @param[in] mask    The event mask.
124
 * @param[in] flags   The event flags.
125
 */
126
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
127
{
128
#if (AMIROOS_CFG_DBG == true)
129
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
130
#else /* (AMIROOS_CFG_DBG == true) */
131
  (void)(mask);
132
  (void)(flags);
133
#endif /* (AMIROOS_CFG_DBG == true) */
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
#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
178

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

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

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

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

    
233
  return;
234
}
235

    
236
#endif /* (HAL_USE_RTC == TRUE) */
237

    
238
/**
239
 * @brief   Application entry point.
240
 */
241
int main(void)
242
{
243
  // local variables
244
  eventmask_t eventmask = 0;
245
  eventflags_t eventflags = 0;
246
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
247
#if defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES)
248
  AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES
249
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_THREAD_VARIABLES) */
250

    
251
  /*
252
   * ##########################################################################
253
   * # system initialization                                                  #
254
   * ##########################################################################
255
   */
256

    
257
  /* hardware, kernel, and operating system initialization */
258
  // ChibiOS/HAL and custom hal additions (if any)
259
  halInit();
260
#if defined(MODULE_INIT_HAL_EXTRA)
261
  MODULE_INIT_HAL_EXTRA();
262
#endif /* defined(MODULE_INIT_HAL_EXTRA) */
263

    
264
  // ChibiOS/RT kernel and custom kernel additions (if any)
265
  chSysInit();
266
#if defined(MODULE_INIT_KERNEL_EXTRA)
267
  MODULE_INIT_KERNEL_EXTRA();
268
#endif /* defined(MODULE_INIT_KERNEL_EXTRA) */
269

    
270
  // AMiRo-OS, additional interrupts and custom OS additions (if any)
271
#if (AMIROOS_CFG_SHELL_ENABLE == true)
272
  aosSysInit(moduleShellPrompt);
273
#else /* (AMIROOS_CFG_SHELL_ENABLE == true) */
274
  aosSysInit(NULL);
275
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
276
#if defined(MODULE_INIT_INTERRUPTS)
277
  MODULE_INIT_INTERRUPTS();
278
#endif
279
#if defined(MODULE_INIT_OS_EXTRA)
280
  MODULE_INIT_OS_EXTRA();
281
#endif /* defined(MODULE_INIT_OS_EXTRA) */
282

    
283
  /* event associations */
284
#if (AMIROOS_CFG_SSSP_ENABLE == true)
285
  {
286
    eventflags_t flagsmask = AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK | moduleSsspEventflagPD() | moduleSsspEventflagS();
287
#if (AMIROOS_CFG_SSSP_MSI == true)
288
#if (AMIROOS_CFG_SSSP_STACK_START != true)
289
    flagsmask |= moduleSsspEventflagDN();
290
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
291
#if (AMIROOS_CFG_SSSP_STACK_END != true)
292
    flagsmask |= moduleSsspEventflagUP();
293
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
294
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
295
    chEvtRegisterMaskWithFlags(&aos.events.gpio, &_eventListenerGPIO, EVENTMASK_GPIO, flagsmask);
296
  }
297
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
298
  if (AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK) {
299
    chEvtRegisterMaskWithFlags(&aos.events.gpio, &_eventListenerGPIO, EVENTMASK_GPIO, AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK);
300
  }
301
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
302
  chEvtRegisterMask(&aos.events.os, &_eventListenerOS, EVENTMASK_OS);
303

    
304
#if (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_STARTUP == true)
305

    
306
  /* perform SSSP basic initialization stage */
307

    
308
#if defined(MODULE_SSSP_BASICINIT_HOOK)
309
#if defined(MODULE_SSSP_BASICINIT_HOOK_ARGS)
310
  MODULE_SSSP_BASICINIT_HOOK(MODULE_SSSP_BASICINIT_HOOK_ARGS);
311
#else /* defined(MODULE_SSSP_BASICINIT_HOOK_ARGS) */
312
  MODULE_SSSP_BASICINIT_HOOK();
313
#endif /* defined(MODULE_SSSP_BASICINIT_HOOK_ARGS) */
314
#endif /* defined(MODULE_SSSP_BASICINIT_HOOK) */
315

    
316
  // proceed to startup stage 1.2
317
#if (AMIROOS_CFG_SSSP_MASTER == true)
318
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(NULL, EVENTMASK_SSSPDELAY, &eventmask) != AOS_SUCCESS)) {
319
    /*
320
     * This code is executed if the received event was not about the delay.
321
     * The received event could be casued by any listener.
322
     */
323
    // GPIO event
324
    if (eventmask & _eventListenerGPIO.events) {
325
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
326
      // PD event
327
      if (eventflags & moduleSsspEventflagPD()) {
328
        shutdown = AOS_SHUTDOWN_PASSIVE;
329
      } else {
330
#if defined(MODULE_SSSP_STARTUP_1_1_GPIOEVENT_HOOK)
331
        MODULE_SSSP_STARTUP_1_1_GPIOEVENT_HOOK(eventmask, eventflags);
332
#else /* defined(MODULE_SSSP_STARTUP_1_1_GPIOEVENT_HOOK) */
333
        /* silently ignore any other GPIO events */
334
#endif /* defined(MODULE_SSSP_STARTUP_1_1_GPIOEVENT_HOOK) */
335
      }
336
    }
337
    // OS event
338
    else if (eventmask & _eventListenerOS.events) {
339
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
340
      _unexpectedEventError(eventmask, eventflags);
341
    }
342
    // unknown event
343
    else {
344
      _unexpectedEventError(eventmask, 0);
345
    }
346
  }
347
  if (shutdown == AOS_SHUTDOWN_NONE) {
348
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_1_2);
349
  }
350
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
351
  if (shutdown == AOS_SHUTDOWN_NONE) {
352
    aosSsspProceed(NULL, 0, NULL);
353
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_1_2);
354
  }
355
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
356

    
357
  // proceed to startup stage 1.3
358
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(&_eventListenerGPIO, EVENTMASK_GPIO, &eventmask) != AOS_SUCCESS)) {
359
    /*
360
     * This code is executed if the received event was not about a deactivation of the snychronization signal.
361
     * The received event could be caused by any listener.
362
     */
363
    // GPIO event
364
    if (eventmask & _eventListenerGPIO.events) {
365
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
366
      // PD event
367
      if (eventflags & moduleSsspEventflagPD()) {
368
        shutdown = AOS_SHUTDOWN_PASSIVE;
369
      } else {
370
#if defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK)
371
        MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK(eventmask, eventflags);
372
#else /* defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK) */
373
        /* silently ignore any other GPIO events */
374
#endif /* defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK) */
375
      }
376
    }
377
    // OS event
378
    else if (eventmask & _eventListenerOS.events) {
379
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
380
      _unexpectedEventError(eventmask, eventflags);
381
    }
382
    // unknown event
383
    else {
384
      _unexpectedEventError(eventmask, 0);
385
    }
386
  }
387
  if (shutdown == AOS_SHUTDOWN_NONE) {
388
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_1_3);
389
  }
390

    
391
  // proceed to startup stage 2.1
392
#if (AMIROOS_CFG_SSSP_MASTER == true)
393
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(NULL, EVENTMASK_SSSPDELAY, &eventmask) != AOS_SUCCESS)) {
394
    /*
395
     * This code is executed if the received event was not about the delay.
396
     * The received event could be caused by any listener.
397
     */
398
    // GPIO event
399
    if (eventmask & _eventListenerGPIO.events) {
400
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
401
      // PD event
402
      if (eventflags & moduleSsspEventflagPD()) {
403
        shutdown = AOS_SHUTDOWN_PASSIVE;
404
      } else {
405
#if defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK)
406
        MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK(eventmask, eventflags);
407
#else /* defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK) */
408
        /* silently ignore any other GPIO events */
409
#endif /* defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK) */
410
      }
411
    }
412
    // OS event
413
    else if (eventmask & _eventListenerOS.events) {
414
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
415
      _unexpectedEventError(eventmask, eventflags);
416
    }
417
    // unknown event
418
    else {
419
      _unexpectedEventError(eventmask, 0);
420
    }
421
  }
422
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
423
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(&_eventListenerGPIO, EVENTMASK_GPIO, &eventmask) != AOS_SUCCESS)) {
424
    /*
425
     * This code is executed if the received event was not about a deactivation of the snychronization signal.
426
     * The received event could be caused by any listener.
427
     */
428
    // GPIO event
429
    if (eventmask & _eventListenerGPIO.events) {
430
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
431
      // PD event
432
      if (eventflags & moduleSsspEventflagPD()) {
433
        shutdown = AOS_SHUTDOWN_PASSIVE;
434
      } else {
435
#if defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK)
436
        MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK(eventmask, eventflags);
437
#else /* defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK) */
438
        /* silently ignore any other GPIO events */
439
#endif /* defined(MODULE_SSSP_STARTUP_1_2_GPIOEVENT_HOOK) */
440
      }
441
    }
442
    // OS event
443
    else if (eventmask & _eventListenerOS.events) {
444
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
445
      _unexpectedEventError(eventmask, eventflags);
446
    }
447
    // unknown event
448
    else {
449
      _unexpectedEventError(eventmask, 0);
450
    }
451
  }
452
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
453
  if (shutdown == AOS_SHUTDOWN_NONE) {
454
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_2_1);
455
  }
456

    
457
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (AMIROOS_CFG_SSSP_STARTUP == true) */
458

    
459
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1)
460
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS)
461
  AMIROOS_CFG_MAIN_INIT_HOOK_1(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS);
462
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS) */
463
  AMIROOS_CFG_MAIN_INIT_HOOK_1();
464
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1_ARGS) */
465
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_1) */
466

    
467
  /* periphery communication interfaces initialization */
468
#if defined(MODULE_INIT_PERIPHERY_IF)
469
  // module specific initialization
470
  MODULE_INIT_PERIPHERY_IF();
471
#endif /* defined(MODULE_INIT_PERIPHERY_IF) */
472
#if defined(MODULE_HAL_PROGIF)
473
  // user interface
474
  aosIOChannelInit(&_stdiochannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
475
  aosIOChannelOutputEnable(&_stdiochannel);
476
  aosIOStreamAddChannel(&aos.iostream, &_stdiochannel);
477
#if (AMIROOS_CFG_SHELL_ENABLE == true)
478
  aosShellChannelInit(&_stdshellchannel, (BaseAsynchronousChannel*)&MODULE_HAL_PROGIF);
479
  aosShellChannelInputEnable(&_stdshellchannel);
480
  aosShellChannelOutputEnable(&_stdshellchannel);
481
  aosShellStreamAddChannel(&aos.shell.stream, &_stdshellchannel);
482
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) */
483
#endif /* defined(MODULE_HAL_PROGIF) */
484

    
485
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2)
486
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS)
487
  AMIROOS_CFG_MAIN_INIT_HOOK_2(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS);
488
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS) */
489
  AMIROOS_CFG_MAIN_INIT_HOOK_2();
490
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2_ARGS) */
491
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_2) */
492

    
493
  /* module is ready -> print welcome prompt */
494
  aosprintf("\n");
495
  aosprintf("######################################################################\n");
496
  aosprintf("# AMiRo-OS is an operating system designed for the Autonomous Mini   #\n");
497
  aosprintf("# Robot (AMiRo) platform.                                            #\n");
498
  aosprintf("# Copyright (C) 2016..2019  Thomas Schöpping et al.                  #\n");
499
  aosprintf("#                                                                    #\n");
500
  aosprintf("# This is free software; see the source for copying conditions.      #\n");
501
  aosprintf("# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n");
502
  aosprintf("# A PARTICULAR PURPOSE.                                              #\n");
503
  aosprintf("# The development of this software was supported by the Excellence   #\n");
504
  aosprintf("# Cluster EXC 227 Cognitive Interaction Technology. The Excellence   #\n");
505
  aosprintf("# Cluster EXC 227 is a grant of the Deutsche Forschungsgemeinschaft  #\n");
506
  aosprintf("# (DFG) in the context of the German Excellence Initiative.          #\n");
507
  aosprintf("######################################################################\n");
508
  aosprintf("\n");
509

    
510
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3)
511
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS)
512
  AMIROOS_CFG_MAIN_INIT_HOOK_3(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS);
513
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS) */
514
  AMIROOS_CFG_MAIN_INIT_HOOK_3();
515
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3_ARGS) */
516
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_3) */
517

    
518
#if (AMIROOS_CFG_TESTS_ENABLE == true)
519
#if defined(MODULE_INIT_TESTS)
520
  MODULE_INIT_TESTS();
521
#else /* defined(MODULE_INIT_TESTS) */
522
  #warning "AMIROOS_CFG_TESTS_ENABLE set to true, but MODULE_INIT_TESTS() not defined"
523
#endif /* defined(MODULE_INIT_TESTS) */
524
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) */
525

    
526
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4)
527
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS)
528
  AMIROOS_CFG_MAIN_INIT_HOOK_4(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS);
529
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS) */
530
  AMIROOS_CFG_MAIN_INIT_HOOK_4();
531
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4_ARGS) */
532
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_4) */
533

    
534
#if (AMIROOS_CFG_SSSP_ENABLE == true)
535

    
536
  // proceed to startup stage 2.2
537
#if (AMIROOS_CFG_SSSP_MASTER == true)
538
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(NULL, EVENTMASK_SSSPDELAY, &eventmask) != AOS_SUCCESS)) {
539
    /*
540
     * This code is executed if the received event was not about the delay.
541
     * The received event could be caused by any listener.
542
     */
543
    // GPIO event
544
    if (eventmask & _eventListenerGPIO.events) {
545
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
546
      // PD event
547
      if (eventflags & moduleSsspEventflagPD()) {
548
        shutdown = AOS_SHUTDOWN_PASSIVE;
549
      } else {
550
#if defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK)
551
        MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK(eventmask, eventflags);
552
#else /* defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK) */
553
        /* silently ignore any other GPIO events */
554
#endif /* defined(MODULE_SSSP_STARTUP_1_3_GPIOEVENT_HOOK) */
555
      }
556
    }
557
    // OS event
558
    else if (eventmask & _eventListenerOS.events) {
559
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
560
      _unexpectedEventError(eventmask, eventflags);
561
    }
562
    // unknown event
563
    else {
564
      _unexpectedEventError(eventmask, 0);
565
    }
566
  }
567
  if (shutdown == AOS_SHUTDOWN_NONE) {
568
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_2_2);
569
  }
570
#else /* (AMIROOS_CFG_SSSP_MASTER == true) */
571
  if (shutdown == AOS_SHUTDOWN_NONE) {
572
    aosSsspProceed(NULL, 0, NULL);
573
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_2_2);
574
  }
575
#endif /* (AMIROOS_CFG_SSSP_MASTER == true) */
576

    
577
  // proceed to startup stage 3 (MSI is enabled), or to operation phase (no MSI)
578
  while ((shutdown == AOS_SHUTDOWN_NONE) && (aosSsspProceed(&_eventListenerGPIO, EVENTMASK_GPIO, &eventmask) != AOS_SUCCESS)) {
579
    /*
580
     * This code is executed if the received event was not about a deactivation of the snychronization signal.
581
     * The received event could be caused by any listener.
582
     */
583
    // GPIO event
584
    if (eventmask & _eventListenerGPIO.events) {
585
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
586
      // PD event
587
      if (eventflags & moduleSsspEventflagPD()) {
588
        shutdown = AOS_SHUTDOWN_PASSIVE;
589
      } else {
590
#if defined(MODULE_SSSP_STARTUP_2_2_GPIOEVENT_HOOK)
591
        MODULE_SSSP_STARTUP_2_2_GPIOEVENT_HOOK(eventmask, eventflags);
592
#else /* defined(MODULE_SSSP_STARTUP_2_2_GPIOEVENT_HOOK) */
593
        /* silently ignore any other GPIO events */
594
#endif /* defined(MODULE_SSSP_STARTUP_2_2_GPIOEVENT_HOOK) */
595
      }
596
    }
597
    // OS event
598
    else if (eventmask & _eventListenerOS.events) {
599
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
600
      _unexpectedEventError(eventmask, eventflags);
601
    }
602
    // unknown event
603
    else {
604
      _unexpectedEventError(eventmask, 0);
605
    }
606
  }
607
  if (shutdown == AOS_SHUTDOWN_NONE) {
608
#if (AMIROOS_CFG_SSSP_MSI == true)
609
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_STARTUP_3);
610
#else /* (AMIROOS_CFG_SSSP_MSI == true) */
611
    aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_OPERATION);
612
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
613
  }
614

    
615
  /*
616
   * There must be no delay at this point, thus no hook allowed.
617
   */
618

    
619
#if (AMIROOS_CFG_SSSP_MSI == true)
620
  {
621
    // initialize temporary MSI data
622
    aos_ssspmsidata_t msidata;
623
    aosSsspMsiInit(&msidata, EVENTMASK_SSSPDELAY, EVENTMASK_SSSPTIMEOUT, &_eventListenerGPIO);
624

    
625
    // execute module stack initialization (MSI) but react to unrelated events as well
626
    while ((shutdown == AOS_SHUTDOWN_NONE) && (aos.sssp.stage != AOS_SSSP_STAGE_OPERATION)) {
627
      // execute MSI routine
628
      aosSsspMsi(&msidata, &eventmask);
629
      // handly event (if any)
630
      if (eventmask) {
631
        // GPIO event
632
        if (eventmask & _eventListenerGPIO.events) {
633
          eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
634
          // PD event
635
          if (eventflags & moduleSsspEventflagPD()) {
636
            shutdown = AOS_SHUTDOWN_PASSIVE;
637
          } else {
638
  #if defined(MODULE_SSSP_STARTUP_3_GPIOEVENT_HOOK)
639
            MODULE_SSSP_STARTUP_3_GPIOEVENT_HOOK(eventmask, eventflags);
640
  #else /* defined(MODULE_SSSP_STARTUP_3_GPIOEVENT_HOOK) */
641
            /* silently ignore any other GPIO events */
642
  #endif /* defined(MODULE_SSSP_STARTUP_3_GPIOEVENT_HOOK) */
643
          }
644
        }
645
        // OS event
646
        else if (eventmask & _eventListenerOS.events) {
647
          eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
648
          _unexpectedEventError(eventmask, eventflags);
649
        }
650
        // unknown event
651
        else {
652
          _unexpectedEventError(eventmask, 0);
653
        }
654
      }
655
    }
656
  }
657

    
658
#if (HAL_USE_RTC == TRUE)
659

    
660
  //TODO: Calendar synchronization
661

    
662
#endif /* (HAL_USE_RTC == TRUE) */
663
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
664

    
665
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
666

    
667
  /* completely start AMiRo-OS */
668
  if (shutdown == AOS_SHUTDOWN_NONE) {
669
    aosSysStart();
670
  }
671

    
672
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5)
673
#if defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS)
674
  AMIROOS_CFG_MAIN_INIT_HOOK_5(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS);
675
#else /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS) */
676
  AMIROOS_CFG_MAIN_INIT_HOOK_5();
677
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5_ARGS) */
678
#endif /* defined(AMIROOS_CFG_MAIN_INIT_HOOK_5) */
679

    
680
  /*
681
   * ##########################################################################
682
   * # infinite loop                                                          #
683
   * ##########################################################################
684
   */
685

    
686
#if (AMIROOS_CFG_SSSP_ENABLE == true)
687
  /* ignore all SSSP signal events, except for PD and configured events */
688
  eventflags = moduleSsspEventflagS();
689
#if (AMIROOS_CFG_SSSP_MSI == true)
690
#if (AMIROOS_CFG_SSSP_STACK_START != true)
691
  eventflags |= moduleSsspEventflagDN();
692
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) */
693
#if (AMIROOS_CFG_SSSP_STACK_END != true)
694
  eventflags |= moduleSsspEventflagUP();
695
#endif /* (AMIROOS_CFG_SSSP_STACK_END != true) */
696
#endif /* (AMIROOS_CFG_SSSP_MSI == true) */
697
  eventflags &= ~((eventflags_t)AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK);
698
  _eventListenerGPIO.wflags &= ~eventflags;
699
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
700

    
701
  // sleep until a shutdown event is received
702
  while (shutdown == AOS_SHUTDOWN_NONE) {
703
    // wait for an event
704
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0)
705
    eventmask = chEvtWaitOneTimeout(ALL_EVENTS, chTimeUS2I(AMIROOS_CFG_MAIN_LOOP_TIMEOUT));
706
#else /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0) */
707
    eventmask = chEvtWaitOne(ALL_EVENTS);
708
#endif /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT != 0) */
709

    
710
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1)
711
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS)
712
    AMIROOS_CFG_MAIN_LOOP_HOOK_1(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS);
713
#else /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS) */
714
    AMIROOS_CFG_MAIN_LOOP_HOOK_1();
715
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1_ARGS) */
716
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_1) */
717

    
718
    switch (eventmask) {
719
      // if this was an GPIO event
720
      case EVENTMASK_GPIO:
721
        // evaluate flags
722
        eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
723
#if (AMIROOS_CFG_SSSP_ENABLE == true)
724
        // PD event
725
        if (eventflags & moduleSsspEventflagPD()) {
726
          aosSsspShutdownInit(false);
727
          shutdown = AOS_SHUTDOWN_PASSIVE;
728
        }
729
        // all other events
730
#if defined(MODULE_MAIN_LOOP_GPIOEVENT)
731
        else {
732
          MODULE_MAIN_LOOP_GPIOEVENT(eventflags);
733
        }
734
#endif /* defined(MODULE_MAIN_LOOP_GPIOEVENT) */
735
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
736
#if defined(MODULE_MAIN_LOOP_GPIOEVENT)
737
        MODULE_MAIN_LOOP_GPIOEVENT(eventflags);
738
#endif /* defined(MODULE_MAIN_LOOP_GPIOEVENT) */
739
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
740
        break;
741

    
742
      // if this was an OS event
743
      case EVENTMASK_OS:
744
        // evaluate flags
745
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
746
        switch (eventflags) {
747
#if (AMIROOS_CFG_BOOTLOADER == AOS_BOOTLOADER_NONE)
748
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_MASK:
749
            shutdown = AOS_SHUTDOWN_ACTIVE;
750
            break;
751
#elif (AMIROOS_CFG_BOOTLOADER == AOS_BOOTLOADER_AMiRoBLT)
752
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_HIBERNATE:
753
            shutdown = AOS_SHUTDOWN_HIBERNATE;
754
            break;
755
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_DEEPSLEEP:
756
            shutdown = AOS_SHUTDOWN_DEEPSLEEP;
757
            break;
758
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_TRANSPORTATION:
759
            shutdown = AOS_SHUTDOWN_TRANSPORTATION;
760
            break;
761
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_RESTART:
762
            shutdown = AOS_SHUTDOWN_RESTART;
763
            break;
764
          case AOS_SYSTEM_EVENTFLAGS_SHUTDOWN_PASSIVE:
765
            _unexpectedEventError(eventmask, eventflags);
766
            break;
767
#endif /* (AMIROOS_CFG_BOOTLOADER == X) */
768
          default:
769
            _unexpectedEventError(eventmask, eventflags);
770
            break;
771
        }
772
        break;
773

    
774
      // if this was any other event (should be impossible to occur)
775
      default:
776
        eventflags = 0;
777
#if (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0)
778
        _unexpectedEventError(eventmask, eventflags);
779
#endif /* (AMIROOS_CFG_MAIN_LOOP_TIMEOUT == 0) */
780
        break;
781
    }
782

    
783
#if (AMIROOS_CFG_SSSP_ENABLE == true)
784

    
785
    /*
786
     * Re-anable the S signal GPIO event.
787
     * Note that events for the optional signals UP and DN are not enabled as they are not utilized during SSSP shutdown phase.
788
     */
789
    chSysLock();
790
    _eventListenerGPIO.wflags |= moduleSsspEventflagS();
791
    chSysUnlock();
792

    
793
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
794

    
795
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2)
796
#if defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS)
797
    AMIROOS_CFG_MAIN_LOOP_HOOK_2(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS);
798
#else /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS) */
799
    AMIROOS_CFG_MAIN_LOOP_HOOK_2();
800
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2_ARGS) */
801
#endif /* defined(AMIROOS_CFG_MAIN_LOOP_HOOK_2) */
802
  }
803

    
804
  /*
805
   * ##########################################################################
806
   * # system shutdown                                                        #
807
   * ##########################################################################
808
   */
809

    
810
  aosDbgAssert(shutdown != AOS_SHUTDOWN_NONE);
811

    
812
  // initialize/acknowledge shutdown
813
  aosSysShutdownInit(shutdown);
814
#if (AMIROOS_CFG_SSSP_ENABLE == true)
815
  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_SHUTDOWN_1_2);
816
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
817

    
818
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1)
819
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS)
820
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS);
821
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS) */
822
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1();
823
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1_ARGS) */
824
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_1) */
825

    
826
  // wait for all threads to terminate
827
  aosSysStop();
828

    
829
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2)
830
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS)
831
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS);
832
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS) */
833
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2();
834
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2_ARGS) */
835
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_2) */
836

    
837
  // deinitialize system
838
  aosSysDeinit();
839

    
840
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3)
841
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS)
842
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS);
843
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS) */
844
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3();
845
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3_ARGS) */
846
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_3) */
847

    
848
  /* stop all periphery communication interfaces */
849
#if defined(MODULE_SHUTDOWN_PERIPHERY_IF)
850
  MODULE_SHUTDOWN_PERIPHERY_IF();
851
#endif /* defined(MODULE_SHUTDOWN_PERIPHERY_IF) */
852

    
853
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4)
854
#if defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS)
855
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS);
856
#else /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS) */
857
  AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4();
858
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4_ARGS) */
859
#endif /* defined(AMIROOS_CFG_MAIN_SHUTDOWN_HOOK_4) */
860

    
861
#if (AMIROOS_CFG_SSSP_ENABLE == true)
862

    
863
  // proceed to SSSP shutdown stage 1.3
864
  aosSsspProceed(NULL, 0, NULL);
865
  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_SHUTDOWN_1_3);
866

    
867
#if (AMIROOS_CFG_SSSP_SHUTDOWN == true)
868

    
869
  /* AMiRo-OS performs SSSP shutdown phase
870
   * NOTE:
871
   * The initiating module could deactivate PD at this point to indicate a restart rather than a shutdown request.
872
   * AMiRo-OS does not support restart though, thus the signal is not changed.
873
   */
874

    
875
  // proceed to SSSP shutdown stage 2.1
876
  while (aosSsspProceed(&_eventListenerGPIO, EVENTMASK_GPIO, &eventmask) != AOS_SUCCESS) {
877
    /*
878
     * This code is executed if the received event was not about a deactivation of the synchronization signal.
879
     * The received event could be caused by any listener.
880
     */
881
    // GPIO event
882
    if (eventmask & _eventListenerGPIO.events) {
883
      eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
884
#if defined(MODULE_SSSP_SHUTDOWN_1_3_GPIOEVENT_HOOK)
885
        MODULE_SSSP_SHUTDOWN_1_3_GPIOEVENT_HOOK(eventmask, eventflags);
886
#else /* defined(MODULE_SSSP_SHUTDOWN_1_3_GPIOEVENT_HOOK) */
887
        /* silently ignore any other GPIO events */
888
#endif /* defined(MODULE_SSSP_SHUTDOWN_1_3_GPIOEVENT_HOOK) */
889
    }
890
    // OS event
891
    else if (eventmask & _eventListenerOS.events) {
892
      eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
893
      _unexpectedEventError(eventmask, eventflags);
894
    }
895
    // unknown event
896
    else {
897
      _unexpectedEventError(eventmask, 0);
898
    }
899
  }
900
  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_SHUTDOWN_2_1);
901

    
902
  // proceed to SSSP shutdown stage 2.2
903
  aosSsspProceed(NULL, 0, &eventmask);
904
  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_SHUTDOWN_2_2);
905
  if (shutdown == AOS_SHUTDOWN_PASSIVE) {
906
    aosDbgPrintf("%s request received\n", eventmask ? "shutdown" : "restart");
907
  }
908
  /* NOTE:
909
   * Actually the call of aosSsspProceed() returned an indicator, whether a shutdown or restart has been initiated.
910
   * Since AMiRo-OS does not support restart, this return value is ignored and shutdown is assumed.
911
   */
912

    
913
  // the initiating module broadcasts the shutdown identifier
914
  if (shutdown != AOS_SHUTDOWN_PASSIVE) {
915
    // since AMiRo-OS does not support multiple ways to shutdown or restart, the special identifier 0 is broadcasted.
916
    aosSsspShutdownBroadcastIdentifier(0);
917
  }
918
  // passive modules receive the broadcasted identifier
919
  else {
920
    unsigned int identifier = 0;
921

    
922
    // receive the identifier, which specifies the type of shutdown/restart
923
    while ((eventmask = aosSsspShutdownWaitForIdentifierPulse(&_eventListenerGPIO, moduleSsspEventflagS(), EVENTMASK_SSSPDELAY, &identifier)) != EVENTMASK_SSSPDELAY) {
924
      // GPIO event
925
      if (eventmask & _eventListenerGPIO.events) {
926
        eventflags = chEvtGetAndClearFlags(&_eventListenerGPIO);
927
#if defined(MODULE_SSSP_SHUTDOWN_2_2_GPIOEVENT_HOOK)
928
        MODULE_SSSP_SHUTDOWN_2_2_GPIOEVENT_HOOK(eventmask, eventflags);
929
#else /* defined(MODULE_SSSP_SHUTDOWN_2_2_GPIOEVENT_HOOK) */
930
        /* silently ignore any other GPIO events */
931
#endif /* defined(MODULE_SSSP_SHUTDOWN_2_2_GPIOEVENT_HOOK) */
932
        /* silently ignore any GPIO events */
933
      }
934
      // OS event
935
      else if (eventmask & _eventListenerOS.events) {
936
        eventflags = chEvtGetAndClearFlags(&_eventListenerOS);
937
        _unexpectedEventError(eventmask, eventflags);
938
      }
939
      // unknown event
940
      else {
941
        _unexpectedEventError(eventmask, 0);
942
      }
943
    }
944

    
945
    // Since AMiRo-OS does not support multiple ways to shutdown or restart, the identifier is ignored.
946
  }
947

    
948
  // proceed to SSSP shutdown stage 2.3
949
  aosSsspProceed(NULL, 0, NULL);
950
  aosDbgAssert(aos.sssp.stage == AOS_SSSP_STAGE_SHUTDOWN_2_3);
951

    
952
  /*
953
   * Since AMiRo-OS does only support one basic shutdown and no restart at all, the final shutdown is kept very simple.
954
   */
955

    
956
  // disable interrupts
957
  irqDeinit();
958
  chSysDisable();
959

    
960
  chThdExit(MSG_OK);
961
  return MSG_OK;
962

    
963
#else /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */
964

    
965
  /* hand over to the bootloader to perform SSSP shutdown phase */
966
  aosSysShutdownToBootloader(shutdown);
967

    
968
  aosDbgAssertMsg(false, "AMiRo-OS must not proceed to this point!");
969
  chThdExit(MSG_RESET);
970
  return MSG_RESET;
971

    
972
#endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */
973

    
974
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) */
975

    
976
  /*
977
   * Depending on the configured bootloader, trivial shutdown is either executed by AMiRo-OS or by that bootloader.
978
   */
979
#if (AMIROOS_CFG_BOOTLOADER == AOS_BOOTLOADER_NONE)
980

    
981
  /* AMiRo-OS performs trivial shutdown */
982

    
983
  // disable interrupts
984
  irqDeinit();
985
  chSysDisable();
986

    
987
  chThdExit(MSG_OK);
988
  return MSG_OK;
989

    
990
#elif (AMIROOS_CFG_BOOTLOADER == AOS_BOOTLOADER_AMiRoBLT)
991

    
992
  /* AMiRo-BLT performns shutdown */
993
  aosSysShutdownToBootloader(shutdown);
994

    
995
  aosDbgAssertMsg(false, "AMiRo-OS must not proceed to this point!");
996
  chThdExit(MSG_RESET);
997
  return MSG_RESET;
998

    
999
#endif /* (AMIROOS_CFG_BOOTLOADER == X) */
1000
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
1001
}
1002

    
1003
/******************************************************************************/
1004
/* EXPORTED FUNCTIONS                                                         */
1005
/******************************************************************************/
1006

    
1007
/** @} */