Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_main.cpp @ 3106e8cc

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

    
29
#include <amiroos.h>
30

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

    
38
/******************************************************************************/
39
/* LOCAL DEFINITIONS                                                          */
40
/******************************************************************************/
41

    
42
/**
43
 * @brief   Event mask to identify I/O events.
44
 */
45
#define IOEVENT_MASK                            EVENT_MASK(0)
46

    
47
/**
48
 * @brief   Event mask to identify OS events.
49
 */
50
#define OSEVENT_MASK                            EVENT_MASK(1)
51

    
52
/**
53
 * @brief   Event mask to idetify CAN events.
54
 */
55
#define CANEVENT_MASK                           EVENT_MASK(2)
56

    
57
/**
58
 * @brief   Event mask to idetify timeout events.
59
 */
60
#define TIMEOUTEVENT_MASK                       EVENT_MASK(3)
61

    
62
/**
63
 * @brief   Event mask to idetify signal delay events.
64
 */
65
#define DELAYEVENT_MASK                         EVENT_MASK(4)
66

    
67
#if ((AMIROOS_CFG_SSSP_ENABLE == true) && (HAL_USE_CAN == TRUE)) || defined(__DOXYGEN__)
68
#define SSSP_STAGE3_ENABLE                      true
69
#else /* (AMIROOS_CFG_SSSP_ENABLE == true) && (HAL_USE_CAN == TRUE) */
70
#define SSSP_STAGE3_ENABLE                      false
71
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) && (HAL_USE_CAN == TRUE) */
72

    
73
#if (SSSP_STAGE3_ENABLE == true) || defined(__DOXYGEN__)
74

    
75
/**
76
 * @brief   CAN message identifier for initialization of the SSSP stack initialization sequence.
77
 */
78
#define SSSP_STACKINIT_CANMSGID_INIT            0x003
79

    
80
/**
81
 * @brief   CAN message identifier for transmitting module IDs during the SSSP stack initialization sequence.
82
 */
83
#define SSSP_STACKINIT_CANMSGID_MODULEID        0x002
84

    
85
/**
86
 * @brief   CAN message identifier for abortion of the SSSP stack initialization sequence.
87
 */
88
#define SSSP_STACKINIT_CANMSGID_ABORT           0x001
89

    
90
#endif /* (SSSP_STAGE3_ENABLE == true) */
91

    
92
#if (AMIROOS_CFG_SSSP_ENABLE != true) || defined(__DOXYGEN__)
93
/**
94
 * @brief   Default shutdown mode if SSSP is unavailable.
95
 */
96
#define AOS_SHUTDOWN_DEFAULT                    AOS_SHUTDOWN_DEEPSLEEP
97
#endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */
98

    
99
#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
100
/**
101
 * @brief   CAN message identifier for calender synchronization message.
102
 */
103
#define CALENDERSYNC_CANMSGID                   0x004
104
#endif /* (HAL_USE_CAN == TRUE) */
105

    
106
/******************************************************************************/
107
/* EXPORTED VARIABLES                                                         */
108
/******************************************************************************/
109

    
110
/******************************************************************************/
111
/* LOCAL TYPES                                                                */
112
/******************************************************************************/
113

    
114
/******************************************************************************/
115
/* LOCAL VARIABLES                                                            */
116
/******************************************************************************/
117

    
118
/**
119
 * @brief   Listener object for I/O events.
120
 */
121
static event_listener_t _eventListenerIO;
122

    
123
/**
124
 * @brief   Listener object for OS events.
125
 */
126
static event_listener_t _eventListenerOS;
127

    
128
#if defined(MODULE_HAL_PROGIF) || defined(__DOXYGEN__)
129
/**
130
 * @brief   I/O channel for the programmer interface.
131
 */
132
static AosIOChannel _stdiochannel;
133

    
134
#if (AMIROOS_CFG_SHELL_ENABLE == true) || (AMIROOS_CFG_TESTS_ENABLE == true) || defined(__DOXYGEN__)
135
/**
136
 * @brief   I/O shell channel for the programmer interface.
137
 */
138
static AosShellChannel _stdshellchannel;
139
#endif /* (AMIROOS_CFG_SHELL_ENABLE == true) || (AMIROOS_CFG_TESTS_ENABLE == true)*/
140
#endif /* defined(MODULE_HAL_PROGIF) */
141

    
142
/*
143
 * hook to add further static variables
144
 */
145
#if defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES)
146
AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES
147
#endif /* defined(AMIROOS_CFG_MAIN_EXTRA_STATIC_VARIABLES) */
148

    
149
/******************************************************************************/
150
/* LOCAL FUNCTIONS                                                            */
151
/******************************************************************************/
152

    
153
/**
154
 * @brief   Prints an error message about an unexpected event.
155
 *
156
 * @param[in] mask    The event mask.
157
 * @param[in] flags   The event flags.
158
 */
159
static inline void _unexpectedEventError(const eventmask_t mask, const eventflags_t flags)
160
{
161
#if (AMIROOS_CFG_DBG == true)
162
  aosprintf("CTRL: unexpected/unknown event received. mask: 0x%08X; flags: 0x%08X\n", mask, flags);
163
#else /* (AMIROOS_CFG_DBG == true) */
164
  (void)(mask);
165
  (void)(flags);
166
#endif /* (AMIROOS_CFG_DBG == true) */
167
  return;
168
}
169

    
170
#if (SSSP_STAGE3_ENABLE == true) || defined(__DOXYGEN__)
171
/**
172
 * @brief   Callback function to be used during SSSP stack initialization sequence.
173
 *
174
 * @param[in] par   A pointer to an @p event_source_t to be fired.
175
 */
176
static void _ssspTimerCallback(void* par)
177
{
178
  aosDbgCheck(par != NULL);
179

    
180
  chSysLockFromISR();
181
  chEvtBroadcastI((event_source_t*)par);
182
  chSysUnlockFromISR();
183

    
184
  return;
185
}
186
#endif /* (SSSP_STAGE3_ENABLE == true) */
187

    
188
/**
189
 * @brief   Helper function to serialize data.
190
 *
191
 * @param[out]  dst   Pointer to the output buffer.
192
 * @param[in]   src   Data to be serialized.
193
 * @param[in]   n     Number of bytes to serialize.
194
 */
195
inline void _serialize(uint8_t* dst, const uint64_t src, const uint8_t n)
196
{
197
  aosDbgCheck(dst != NULL);
198
  aosDbgCheck(n > 0 && n <= 8);
199

    
200
  for (uint8_t byte = 0; byte < n; ++byte) {
201
    dst[byte] = (uint8_t)((src >> (byte * 8)) & 0xFF);
202
  }
203

    
204
  return;
205
}
206

    
207
/**
208
 * @brief   Helper function to deserialize data.
209
 *
210
 * @param[in] src   Pointer to the buffer of data to be deserialzed.
211
 * @param[in] n     Number of bytes to deserialize.
212
 *
213
 * @return    The deserialized 32 bit data.
214
 */
215
inline uint64_t _deserialize(uint8_t* src, const uint8_t n)
216
{
217
  aosDbgCheck(src != NULL);
218
  aosDbgCheck(n > 0 && n <= 8);
219

    
220
  uint64_t result = 0;
221
  for (uint8_t byte = 0; byte < n; ++byte) {
222
    result |= ((uint64_t)src[byte]) << (byte * 8);
223
  }
224

    
225
  return result;
226
}
227

    
228
#if (HAL_USE_RTC == TRUE) || defined(__DOXYGEN__)
229

    
230
/**
231
 * @brief   Converter function to encode a TM value to a single unsigned 64 bit integer.
232
 *
233
 * @details Contents of the TM struct are mapped as follows:
234
 *            bits  |63     62|61      53|52    50|49         26|25     22|21     17|16     12|11      6|5       0|
235
 *            #bits |       2 |        9 |      3 |          24 |       4 |       5 |       5 |       6 |       6 |
236
 *            value |   isdst |     yday |   wday |        year |     mon |    mday |    hour |     min |     sec |
237
 *            range | special | [0, 365] | [0, 6] | [1900, ...] | [0, 11] | [1, 31] | [0, 23] | [0, 59] | [0, 61] |
238
 *          The Daylight Saving Time Flag (isdsst) is encoded as follows:
239
 *            DST not in effect         -> 0
240
 *            DST in effect             -> 1
241
 *            no information available  -> 2
242
 *
243
 * @param[in] src   Pointer to the TM struct to encode.
244
 *
245
 * @return  An unsigned 64 bit integer, which holds the encoded time value.
246
 */
247
inline uint64_t _TM2U64(struct tm* src)
248
{
249
  aosDbgCheck(src != NULL);
250

    
251
  return (((uint64_t)(src->tm_sec  & 0x0000003F) << (0))               |
252
          ((uint64_t)(src->tm_min  & 0x0000003F) << (6))               |
253
          ((uint64_t)(src->tm_hour & 0x0000001F) << (12))              |
254
          ((uint64_t)(src->tm_mday & 0x0000001F) << (17))              |
255
          ((uint64_t)(src->tm_mon  & 0x0000000F) << (22))              |
256
          ((uint64_t)(src->tm_year & 0x00FFFFFF) << (26))              |
257
          ((uint64_t)(src->tm_wday & 0x00000007) << (50))              |
258
          ((uint64_t)(src->tm_yday & 0x000001FF) << (53))              |
259
          ((uint64_t)((src->tm_isdst == 0) ? 0 : (src->tm_isdst > 0) ? 1 : 2) << (62)));
260
}
261

    
262
/**
263
 * @brief   Converter functiomn to retrieve the encoded TM value from an unsigned 64 bit integer.
264
 *
265
 * @details For information on the encoding, please refer to @p _TM2U64 function.
266
 *
267
 * @param[out] dst  The TM struct to fill with the decoded values.
268
 * @param[in]  src  Unsigned 64 bit integer holding the encoded TM value.
269
 */
270
inline void _U642TM(struct tm* dst, const uint64_t src)
271
{
272
  aosDbgCheck(dst != NULL);
273

    
274
  dst->tm_sec  = (src >> 0)  & 0x0000003F;
275
  dst->tm_min  = (src >> 6)  & 0x0000003F;
276
  dst->tm_hour = (src >> 12) & 0x0000001F;
277
  dst->tm_mday = (src >> 17) & 0x0000001F;
278
  dst->tm_mon  = (src >> 22) & 0x0000000F;
279
  dst->tm_year = (src >> 26) & 0x00FFFFFF;
280
  dst->tm_wday = (src >> 50) & 0x00000007;
281
  dst->tm_yday = (src >> 53) & 0x000001FF;
282
  dst->tm_isdst = (((src >> 62) & 0x03) == 0) ? 0 : (((src >> 62) & 0x03) > 0) ? 1 : -1;
283

    
284
  return;
285
}
286

    
287
#endif /* (HAL_USE_RTC == TRUE) */
288

    
289
#if (SSSP_STAGE3_ENABLE) || defined(__DOXYGEN__)
290
/**
291
 * @brief   Implementation of the SSSP module stack initialization sequence (startup phase 3).
292
 *
293
 * @return Shutdown value.
294
 * @retval AOS_SHUTDOWN_NONE      No shutdown signal received
295
 * @retval AOS_SHUTDOWN_PASSIVE   Shutdown signal received.
296
 */
297
aos_shutdown_t _ssspModuleStackInitialization(void)
298
{
299
  // local types
300
  /**
301
   * @brief   States for the internal state machine to implement SSSP startup stage 3.
302
   */
303
  typedef enum {
304
    STAGE_3_1,                  /**< Initiation of SSSP startup stage 3. */
305
    STAGE_3_2,                  /**< Starting the sequence and broadcasting the first ID. */
306
    STAGE_3_3_WAITFORFIRSTID,   /**< Waiting for first ID after initiation. */
307
    STAGE_3_3_WAITFORIDORSIG,   /**< Waiting for next ID or activation of neighbor signal. */
308
    STAGE_3_3_WAITFORID,        /**< Waiting for next ID (after the module has set its own ID). */
309
    STAGE_3_4_FINISH,           /**< Successful finish of stage 3. */
310
    STAGE_3_4_ABORT_ACTIVE,     /**< Aborting stage 3 (active). */
311
    STAGE_3_4_ABORT,            /**< Aborting stage 3 (passive). */
312
  } sssp_modulestackinitstage_t;
313

    
314
  typedef struct {
315
    bool loop     : 1;
316
    bool wfe      : 1;
317
    bool wfe_next : 1;
318
  } flags_t;
319

    
320
  // local variables
321
  aos_shutdown_t shutdown = AOS_SHUTDOWN_NONE;
322
  sssp_modulestackinitstage_t stage = STAGE_3_1;
323
  eventmask_t eventmask = 0;
324
  eventflags_t ioflags = 0;
325
  event_source_t eventSourceTimeout;
326
  event_source_t eventSourceDelay;
327
  event_listener_t eventListenerTimeout;
328
  event_listener_t eventListenerDelay;
329
  event_listener_t eventListenerCan;
330
  virtual_timer_t timerTimeout;
331
  virtual_timer_t timerDelay;
332
  CANTxFrame canTxFrame;
333
  CANRxFrame canRxFrame;
334
#if (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true)
335
  aos_ssspmoduleid_t lastid = 0;
336
#endif /* (AMIROOS_CFG_SSSP_STACK_START != true) || (AMIROOS_CFG_DBG == true) */
337
  flags_t flags;
338
  aos_timestamp_t uptime;
339

    
340
  // initialize local varibles
341
  chEvtObjectInit(&eventSourceTimeout);
342
  chEvtObjectInit(&eventSourceDelay);
343
  chVTObjectInit(&timerTimeout);
344
  chVTObjectInit(&timerDelay);
345
  canTxFrame.RTR = CAN_RTR_DATA;
346
  canTxFrame.IDE = CAN_IDE_STD;
347
  flags.loop = true;
348
  flags.wfe = false; // do not wait for events in the initial iteration of the FSM loop
349
  flags.wfe_next = true;
350

    
351
  // initialize system variables
352
  aos.sssp.stage = AOS_SSSP_STARTUP_3_1;
353
  aos.sssp.moduleId = 0;
354

    
355
  // listen to events (timout, delay, CAN receive)
356