amiro-os / core / src / aos_sssp.c @ cda14729
History | View | Annotate | Download (18.761 KB)
1 | cda14729 | Thomas Schöpping | /*
|
---|---|---|---|
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_sssp.c
|
||
21 | * @brief SSSP related code.
|
||
22 | *
|
||
23 | * @addtogroup aos_sssp
|
||
24 | * @{
|
||
25 | */
|
||
26 | |||
27 | #include <amiroos.h> |
||
28 | |||
29 | #if (AMIROOS_CFG_SSSP_ENABLE == true) || defined(__DOXYGEN__) |
||
30 | |||
31 | /******************************************************************************/
|
||
32 | /* LOCAL DEFINITIONS */
|
||
33 | /******************************************************************************/
|
||
34 | |||
35 | /******************************************************************************/
|
||
36 | /* EXPORTED VARIABLES */
|
||
37 | /******************************************************************************/
|
||
38 | |||
39 | /******************************************************************************/
|
||
40 | /* LOCAL TYPES */
|
||
41 | /******************************************************************************/
|
||
42 | |||
43 | /******************************************************************************/
|
||
44 | /* LOCAL VARIABLES */
|
||
45 | /******************************************************************************/
|
||
46 | |||
47 | #if (AMIROOS_CFG_SSSP_MASTER == true) || defined (__DOXYGEN__) |
||
48 | |||
49 | /**
|
||
50 | * @brief A timer event based delays.
|
||
51 | */
|
||
52 | static virtual_timer_t _delayTimer;
|
||
53 | |||
54 | /**
|
||
55 | * @brief Event source for the delay timer.
|
||
56 | */
|
||
57 | static event_source_t _eventSourceDelay;
|
||
58 | |||
59 | /**
|
||
60 | * @brief Event listener for the delay event.
|
||
61 | */
|
||
62 | static event_listener_t _eventListenerDelay;
|
||
63 | |||
64 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
65 | |||
66 | /******************************************************************************/
|
||
67 | /* LOCAL FUNCTIONS */
|
||
68 | /******************************************************************************/
|
||
69 | |||
70 | #if (AMIROOS_CFG_SSSP_MASTER == true) || defined (__DOXYGEN__) |
||
71 | |||
72 | /**
|
||
73 | * @brief General callback function to be used for any local timers.
|
||
74 | *
|
||
75 | * @param[in] par A pointer to an @p event_source_t to be fired.
|
||
76 | */
|
||
77 | static void _timerCallback(void* par) |
||
78 | { |
||
79 | aosDbgCheck(par != NULL);
|
||
80 | |||
81 | chSysLockFromISR(); |
||
82 | chEvtBroadcastI((event_source_t*)par); |
||
83 | chSysUnlockFromISR(); |
||
84 | |||
85 | return;
|
||
86 | } |
||
87 | |||
88 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
89 | |||
90 | /**
|
||
91 | * @brief Waits for the S signal to switch to the desired state.
|
||
92 | *
|
||
93 | * @param[in] listener Pointer to the GPIO event listener to be used.
|
||
94 | * @param[in] flags Event flags to listen to by the event listener (indicating a S signal event).
|
||
95 | * @param[in] signalstate Desired state of the S signal ti be waited for.
|
||
96 | * @param[out] received Output variable to store the received event mask to.
|
||
97 | *
|
||
98 | * @return Status, indicating whether the expected event was received.
|
||
99 | */
|
||
100 | static inline aos_status_t _waitForS(event_listener_t* listener, eventflags_t flags, apalControlGpioState_t signalstate, eventmask_t* received) |
||
101 | { |
||
102 | aosDbgCheck(listener != NULL);
|
||
103 | aosDbgCheck(flags != 0);
|
||
104 | aosDbgCheck(received != NULL);
|
||
105 | |||
106 | // wait for the next event (do not apply any filters in order not to miss any events)
|
||
107 | *received = chEvtWaitOne(ALL_EVENTS); |
||
108 | // if the correct event was triggered
|
||
109 | if (*received == listener->events) {
|
||
110 | apalControlGpioState_t s; |
||
111 | apalControlGpioGet(&moduleSsspGpioS, &s); |
||
112 | // only check for the expected event
|
||
113 | if (flags & listener->flags && s == signalstate) {
|
||
114 | // unset the expected flags but keep any other ones
|
||
115 | listener->flags &= ~flags; |
||
116 | return AOS_SUCCESS;
|
||
117 | } |
||
118 | } |
||
119 | |||
120 | return AOS_FAILURE;
|
||
121 | } |
||
122 | |||
123 | #if (AMIROOS_CFG_SSSP_MASTER == true) || defined(__DOXYGEN__) |
||
124 | |||
125 | /**
|
||
126 | * @brief Uses the local delay timer to setup a timed event and waits for it to fire.
|
||
127 | *
|
||
128 | * @param[in] dt Delay time in microseconds to be set to the timer.
|
||
129 | * @param[in] mask Event mask to be used for the delay timer.
|
||
130 | * @param[in] arm_timer Flag to indicate whether the timer has to be armed yet (i.e. on first call of this function).
|
||
131 | * @param[out] received Output variable to store the received event mask to.
|
||
132 | *
|
||
133 | * @return Status, indicating whether the expected event (delay timer) was received.
|
||
134 | */
|
||
135 | static inline aos_status_t _delay(uint32_t dt, eventmask_t mask, bool arm_timer, eventmask_t* received) |
||
136 | { |
||
137 | aosDbgCheck(dt != TIME_IMMEDIATE); |
||
138 | aosDbgCheck(mask != 0);
|
||
139 | aosDbgCheck(received != NULL);
|
||
140 | |||
141 | // arm the delay timer once
|
||
142 | if (arm_timer) {
|
||
143 | chEvtRegisterMask(&_eventSourceDelay, &_eventListenerDelay, mask); |
||
144 | chVTSet(&_delayTimer, chTimeUS2I(dt), _timerCallback, &_eventSourceDelay); |
||
145 | } |
||
146 | |||
147 | // wait for any event to occur (do not apply any filters in order not to miss any events)
|
||
148 | *received = chEvtWaitOne(ALL_EVENTS); |
||
149 | |||
150 | // if the timer event was received, cleanup
|
||
151 | if (*received & _eventListenerDelay.events) {
|
||
152 | chEvtUnregister(&_eventSourceDelay, &_eventListenerDelay); |
||
153 | return AOS_SUCCESS;
|
||
154 | } |
||
155 | |||
156 | return AOS_FAILURE;
|
||
157 | } |
||
158 | |||
159 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
160 | |||
161 | /******************************************************************************/
|
||
162 | /* EXPORTED FUNCTIONS */
|
||
163 | /******************************************************************************/
|
||
164 | |||
165 | /**
|
||
166 | * @brief Initialize all SSSP related data.
|
||
167 | */
|
||
168 | void aosSsspInit(void) |
||
169 | { |
||
170 | #if (AMIROOS_CFG_SSSP_MSI == true) |
||
171 | // module ID is initialized as 'invalid'
|
||
172 | aos.sssp.moduleId = AOS_SSSP_MODULEID_INVALID; |
||
173 | #endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
||
174 | |||
175 | #if (AMIROOS_CFG_SSSP_STARTUP == true) |
||
176 | // AMiRo-OS has to perform the basic initialization
|
||
177 | aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_1_1; |
||
178 | #if (AMIROOS_CFG_DBG == true) |
||
179 | // check whether the initial signal configuration is correct
|
||
180 | { |
||
181 | apalControlGpioState_t state; |
||
182 | // S signal
|
||
183 | apalControlGpioGet(&moduleSsspGpioS, &state); |
||
184 | aosDbgAssert(state == APAL_GPIO_ON); |
||
185 | // PD signal
|
||
186 | apalControlGpioGet(&moduleSsspGpioPD, &state); |
||
187 | aosDbgAssert(state == APAL_GPIO_OFF); |
||
188 | } |
||
189 | #endif /* (AMIROOS_CFG_DBG == true) */ |
||
190 | #else /* (AMIROOS_CFG_SSSP_STARTUP == true) */ |
||
191 | // basic initialization was already performed by a bootloader
|
||
192 | aos.sssp.stage = AOS_SSSP_STAGE_STARTUP_2_1; |
||
193 | #if (AMIROOS_CFG_DBG == true) |
||
194 | // check whether the initial signal configuration is correct
|
||
195 | { |
||
196 | apalControlGpioState_t state; |
||
197 | // S signal
|
||
198 | apalControlGpioGet(&moduleSsspGpioS, &state); |
||
199 | aosDbgAssert(state == APAL_GPIO_ON); |
||
200 | // PD signal
|
||
201 | apalControlGpioGet(&moduleSsspGpioPD, &state); |
||
202 | aosDbgAssert(state == APAL_GPIO_OFF); |
||
203 | } |
||
204 | #endif /* (AMIROOS_CFG_DBG == true) */ |
||
205 | #endif /* (AMIROOS_CFG_SSSP_STARTUP == true) */ |
||
206 | |||
207 | #if (AMIROOS_CFG_SSSP_MASTER == true) |
||
208 | // initialize static variables
|
||
209 | chVTObjectInit(&_delayTimer); |
||
210 | chEvtObjectInit(&_eventSourceDelay); |
||
211 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
212 | |||
213 | return;
|
||
214 | } |
||
215 | |||
216 | /**
|
||
217 | * @brief Proceed to the next SSSP stage.
|
||
218 | *
|
||
219 | * @param[in] listener An optional listener, in case the system has to wait for a specific event.
|
||
220 | * @param[in] flags The relevant flags to wait for (mandatory if a listener is given).
|
||
221 | * @param[in] mask If the stage transition involves a timer event (handled internally by this function),
|
||
222 | * the given input value of this parameter defines the mask to be used for that event.
|
||
223 | * In case a listener was specified, the according mask is retrieved from the listener but this parameter is still used as input for sanity checks.
|
||
224 | * @param[out] received Output variable to store the received event mask to.
|
||
225 | *
|
||
226 | * @return Status, indicating whether proceeding in the protocol was successful.
|
||
227 | */
|
||
228 | aos_status_t aosSsspProceed(event_listener_t* listener, eventflags_t flags, eventmask_t mask, eventmask_t* received) |
||
229 | { |
||
230 | // local variables
|
||
231 | #pragma GCC diagnostic push
|
||
232 | #pragma GCC diagnostic ignored "-Wunused-but-set-variable" |
||
233 | static aos_ssspstage_t laststage = AOS_SSSP_STAGE_UNDEFINED;
|
||
234 | #pragma GCC diagnostic pop
|
||
235 | aos_ssspstage_t nextstage = aos.sssp.stage; |
||
236 | |||
237 | // behaviour depends on current SSSP stage of the system
|
||
238 | switch (aos.sssp.stage) {
|
||
239 | #if (AMIROOS_CFG_SSSP_STARTUP == true) |
||
240 | |||
241 | /*
|
||
242 | * Deactivate S signal.
|
||
243 | * Master node delays execution by one period AOS_SSSP_DELAY.
|
||
244 | */
|
||
245 | case AOS_SSSP_STAGE_STARTUP_1_1:
|
||
246 | { |
||
247 | #if (AMIROOS_CFG_SSSP_MASTER == true) |
||
248 | aosDbgCheck(listener == NULL);
|
||
249 | aosDbgCheck(flags == 0);
|
||
250 | aosDbgCheck(mask != 0);
|
||
251 | aosDbgCheck(received != NULL);
|
||
252 | |||
253 | // delay execution and deactivate the S signal on success
|
||
254 | if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_1_1), received) == AOS_SUCCESS) {
|
||
255 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
256 | nextstage = AOS_SSSP_STAGE_STARTUP_1_2; |
||
257 | } |
||
258 | #else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
259 | aosDbgCheck(listener == NULL);
|
||
260 | aosDbgCheck(flags == 0);
|
||
261 | aosDbgCheck(mask == 0);
|
||
262 | aosDbgCheck(received == NULL);
|
||
263 | |||
264 | // deactivate S signal and proceed
|
||
265 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
266 | nextstage = AOS_SSSP_STAGE_STARTUP_1_2; |
||
267 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
268 | break;
|
||
269 | } |
||
270 | |||
271 | /*
|
||
272 | * Wait for the S signal to become inactive.
|
||
273 | */
|
||
274 | case AOS_SSSP_STAGE_STARTUP_1_2:
|
||
275 | { |
||
276 | aosDbgCheck(listener != NULL);
|
||
277 | aosDbgCheck(flags != 0);
|
||
278 | aosDbgCheck(mask == listener->events); |
||
279 | aosDbgCheck(received != NULL);
|
||
280 | |||
281 | // wait for the S signal to become inactive and proceed on success
|
||
282 | if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
||
283 | nextstage = AOS_SSSP_STAGE_STARTUP_1_3; |
||
284 | } |
||
285 | break;
|
||
286 | } |
||
287 | |||
288 | /*
|
||
289 | * Wait for the S signal to be activated by the master module.
|
||
290 | * The master delays execution by one period AOS_SSSP_DELAY.
|
||
291 | */
|
||
292 | case AOS_SSSP_STAGE_STARTUP_1_3:
|
||
293 | { |
||
294 | #if (AMIROOS_CFG_SSSP_MASTER == true) |
||
295 | aosDbgCheck(listener == NULL);
|
||
296 | aosDbgCheck(flags == 0);
|
||
297 | aosDbgCheck(mask != 0);
|
||
298 | aosDbgCheck(received != NULL);
|
||
299 | |||
300 | // delay execution and deactivate the S signal on success
|
||
301 | if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_1_3), received) == AOS_SUCCESS) {
|
||
302 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
||
303 | nextstage = AOS_SSSP_STAGE_STARTUP_2_1; |
||
304 | } |
||
305 | #else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
306 | aosDbgCheck(listener != NULL);
|
||
307 | aosDbgCheck(flags != 0);
|
||
308 | aosDbgCheck(mask == listener->events); |
||
309 | aosDbgCheck(received != NULL);
|
||
310 | |||
311 | // wait for the S signal to become active and activate it as well and proceed on success
|
||
312 | if (_waitForS(listener, flags, APAL_GPIO_ON, received) == AOS_SUCCESS) {
|
||
313 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
||
314 | nextstage = AOS_SSSP_STAGE_STARTUP_2_1; |
||
315 | } |
||
316 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
317 | break;
|
||
318 | } |
||
319 | |||
320 | #endif /* (AMIROOS_CFG_SSSP_STARTUP == true) */ |
||
321 | |||
322 | /*
|
||
323 | * Deactivate S signal.
|
||
324 | * Master node delays execution by one period AOS_SSSP_DELAY
|
||
325 | */
|
||
326 | case AOS_SSSP_STAGE_STARTUP_2_1:
|
||
327 | { |
||
328 | #if (AMIROOS_CFG_SSSP_MASTER == true) |
||
329 | aosDbgCheck(listener == NULL);
|
||
330 | aosDbgCheck(flags == 0);
|
||
331 | aosDbgCheck(mask != 0);
|
||
332 | aosDbgCheck(received != NULL);
|
||
333 | |||
334 | // delay execution and deactivate the S signal on success
|
||
335 | if (_delay(AOS_SSSP_DELAY, mask, (laststage != AOS_SSSP_STAGE_STARTUP_2_1), received) == AOS_SUCCESS) {
|
||
336 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
337 | nextstage = AOS_SSSP_STAGE_STARTUP_2_2; |
||
338 | } |
||
339 | #else /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
340 | aosDbgCheck(listener == NULL);
|
||
341 | aosDbgCheck(flags == 0);
|
||
342 | aosDbgCheck(mask == 0);
|
||
343 | aosDbgCheck(received == NULL);
|
||
344 | |||
345 | // deactivate S signal and proceed
|
||
346 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
347 | nextstage = AOS_SSSP_STAGE_STARTUP_2_2; |
||
348 | mask = 0;
|
||
349 | #endif /* (AMIROOS_CFG_SSSP_MASTER == true) */ |
||
350 | break;
|
||
351 | } |
||
352 | |||
353 | /*
|
||
354 | * Wait for the S signal to become inactive.
|
||
355 | */
|
||
356 | case AOS_SSSP_STAGE_STARTUP_2_2:
|
||
357 | { |
||
358 | aosDbgCheck(listener != NULL);
|
||
359 | aosDbgCheck(flags != 0);
|
||
360 | aosDbgCheck(mask == listener->events); |
||
361 | aosDbgCheck(received != NULL);
|
||
362 | |||
363 | // wait for the S signal to become inactive and proceed on success
|
||
364 | if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
||
365 | #if (AMIROOS_CFG_SSSP_MSI == true) |
||
366 | nextstage = AOS_SSSP_STAGE_STARTUP_3; |
||
367 | #else /* (AMIROOS_CFG_SSSP_MSI == true) */ |
||
368 | nextstage = AOS_SSSP_STAGE_OPERATION; |
||
369 | #endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
||
370 | } |
||
371 | break;
|
||
372 | } |
||
373 | |||
374 | #if (AMIROOS_CFG_SSSP_MSI == true) |
||
375 | |||
376 | //TODO
|
||
377 | |||
378 | #endif /* (AMIROOS_CFG_SSSP_MSI == true) */ |
||
379 | |||
380 | /*
|
||
381 | * Delay execution by one perion AOS_SSSP_DELAY, deactivate the SYNC signal and proceed.
|
||
382 | * NOTE: Actually only the module that initiated the shutdown has to delay execution here.
|
||
383 | * For the sake of simlicity though, each module delays execution.
|
||
384 | */
|
||
385 | case AOS_SSSP_STAGE_SHUTDOWN_1_2:
|
||
386 | { |
||
387 | aosDbgCheck(listener == NULL);
|
||
388 | aosDbgCheck(flags == 0);
|
||
389 | aosDbgCheck(mask == 0);
|
||
390 | aosDbgCheck(received == NULL);
|
||
391 | |||
392 | // delay execution
|
||
393 | aosThdUSleep(AOS_SSSP_DELAY); |
||
394 | // deactivate S signal
|
||
395 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
396 | nextstage = AOS_SSSP_STAGE_SHUTDOWN_1_3; |
||
397 | break;
|
||
398 | } |
||
399 | |||
400 | #if (AMIROOS_CFG_SSSP_SHUTDOWN == true) |
||
401 | |||
402 | /*
|
||
403 | * Wait for S signal to become inactive.
|
||
404 | */
|
||
405 | case AOS_SSSP_STAGE_SHUTDOWN_1_3:
|
||
406 | { |
||
407 | aosDbgCheck(listener != NULL);
|
||
408 | aosDbgCheck(flags != 0);
|
||
409 | aosDbgCheck(mask == listener->events); |
||
410 | aosDbgCheck(received != NULL);
|
||
411 | |||
412 | // wait for the S signal to become inactive and proceed on success
|
||
413 | if (_waitForS(listener, flags, APAL_GPIO_OFF, received) == AOS_SUCCESS) {
|
||
414 | nextstage = AOS_SSSP_STAGE_SHUTDOWN_2_1; |
||
415 | } |
||
416 | break;
|
||
417 | } |
||
418 | |||
419 | /*
|
||
420 | * Evaluate PD signal to determine whether a shutdown or restart is requested.
|
||
421 | * The logical state is returned by the function call.
|
||
422 | */
|
||
423 | case AOS_SSSP_STAGE_SHUTDOWN_2_1:
|
||
424 | { |
||
425 | aosDbgCheck(listener == NULL);
|
||
426 | aosDbgCheck(flags == 0);
|
||
427 | aosDbgCheck(mask == 0);
|
||
428 | aosDbgCheck(received != NULL);
|
||
429 | |||
430 | // evaluate PD signal
|
||
431 | apalControlGpioState_t pd; |
||
432 | apalControlGpioGet(&moduleSsspGpioPD, &pd); |
||
433 | *received = (pd == APAL_GPIO_ON) ? (eventmask_t)~0 : 0; |
||
434 | nextstage = AOS_SSSP_STAGE_SHUTDOWN_2_2; |
||
435 | break;
|
||
436 | } |
||
437 | |||
438 | /*
|
||
439 | * Proceed with no further actions required.
|
||
440 | */
|
||
441 | case AOS_SSSP_STAGE_SHUTDOWN_2_2:
|
||
442 | { |
||
443 | aosDbgCheck(listener == NULL);
|
||
444 | aosDbgCheck(flags == 0);
|
||
445 | aosDbgCheck(mask == 0);
|
||
446 | aosDbgCheck(received == NULL);
|
||
447 | |||
448 | nextstage = AOS_SSSP_STAGE_SHUTDOWN_2_3; |
||
449 | break;
|
||
450 | } |
||
451 | |||
452 | #endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */ |
||
453 | |||
454 | default:
|
||
455 | { |
||
456 | // this case must never occur!
|
||
457 | aosDbgAssertMsg(false, "Invalid SSSP stage tranition occurred"); |
||
458 | break;
|
||
459 | } |
||
460 | } /* end of switch (aos.sssp.stage) */
|
||
461 | |||
462 | // outro and return
|
||
463 | laststage = aos.sssp.stage; |
||
464 | const aos_status_t status = (nextstage > aos.sssp.stage) ? AOS_SUCCESS : AOS_FAILURE;
|
||
465 | aos.sssp.stage = nextstage; |
||
466 | |||
467 | return status;
|
||
468 | } |
||
469 | |||
470 | void aosSsspShutdownInit(void) |
||
471 | { |
||
472 | // activate S signal
|
||
473 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
||
474 | // proceed to shutdown phase
|
||
475 | aos.sssp.stage = AOS_SSSP_STAGE_SHUTDOWN_1_2; |
||
476 | |||
477 | return;
|
||
478 | } |
||
479 | |||
480 | #if (AMIROOS_CFG_SSSP_SHUTDOWN == true) || defined(__DOXYGEN__) |
||
481 | |||
482 | /**
|
||
483 | * @brief Sequnetially broadcast an identifier via S to specify a specific way to shutdown or restart.
|
||
484 | *
|
||
485 | * @param[in] identifier Identifier to be broadcasted.
|
||
486 | */
|
||
487 | void aosSsspShutdownBroadcastIdentifier(unsigned int identifier) |
||
488 | { |
||
489 | // only broadcast anything if a identifier greater than 0 was specified
|
||
490 | if (identifier > 0) { |
||
491 | // broadcast identifier
|
||
492 | for (unsigned int pulse = 0; pulse < identifier; ++pulse) { |
||
493 | // wait one delay time with S being deactivated
|
||
494 | aosThdUSleep(AOS_SSSP_DELAY); |
||
495 | |||
496 | // activate S for one AOS_SSSP_DELAY.
|
||
497 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_ON); |
||
498 | aosThdUSleep(AOS_SSSP_DELAY); |
||
499 | apalControlGpioSet(&moduleSsspGpioS, APAL_GPIO_OFF); |
||
500 | } |
||
501 | } |
||
502 | |||
503 | // let a timeout pass and return
|
||
504 | aosThdUSleep(AOS_SSSP_TIMEOUT); |
||
505 | |||
506 | return;
|
||
507 | } |
||
508 | |||
509 | /**
|
||
510 | * @brief Wait for a pulse during the SSSP shutdown disambiguation procedure.
|
||
511 | * @details Whenever a pulse is received, the identifier is incremented.
|
||
512 | * Otherwise the internal timer is configured and will eventually trigger a timeout event.
|
||
513 | *
|
||
514 | * @param[in] gpiolistener Event listener for GPIO events.
|
||
515 | * @param[in] sflags Event flags to be set by edges on the S signal.
|
||
516 | * @param[in] timermask Event maks to use for the internal timer.
|
||
517 | * @param[in,out] identifier Identifier variable to increment.
|
||
518 | *
|
||
519 | * @return The event mask of whatever event was received during this function call.
|
||
520 | */
|
||
521 | eventmask_t aosSsspShutdownWaitForIdentifierPulse(event_listener_t* gpiolistener, const eventflags_t sflags, eventmask_t timermask, unsigned int* identifier) |
||
522 | { |
||
523 | aosDbgCheck(gpiolistener != NULL);
|
||
524 | aosDbgCheck(sflags != 0);
|
||
525 | aosDbgCheck(timermask != 0);
|
||
526 | aosDbgCheck(identifier != NULL);
|
||
527 | |||
528 | // local variables
|
||
529 | eventmask_t mask; |
||
530 | eventflags_t flags; |
||
531 | apalControlGpioState_t sstate; |
||
532 | |||
533 | // arm the timer once
|
||
534 | if (!chVTIsArmed(&_delayTimer)) {
|
||
535 | chEvtRegisterMask(&_eventSourceDelay, &_eventListenerDelay, timermask); |
||
536 | chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_eventSourceDelay); |
||
537 | } |
||
538 | |||
539 | // wait for any event to occur (do not apply any filters in order not to miss any events)
|
||
540 | mask = chEvtWaitOne(ALL_EVENTS); |
||
541 | |||
542 | // GPIO event
|
||
543 | if (mask & gpiolistener->events) {
|
||
544 | // retreive flags without clearing them
|
||
545 | flags = gpiolistener->flags; |
||
546 | apalControlGpioGet(&moduleSsspGpioS, &sstate); |
||
547 | if (flags == sflags) {
|
||
548 | apalControlGpioGet(&moduleSsspGpioS, &sstate); |
||
549 | // if this was the end of a pulse
|
||
550 | if (sstate == APAL_GPIO_OFF) {
|
||
551 | // restart the timer
|
||
552 | chVTReset(&_delayTimer); |
||
553 | chVTSet(&_delayTimer, chTimeUS2I(AOS_SSSP_TIMEOUT), _timerCallback, &_eventSourceDelay); |
||
554 | // increment the identifier
|
||
555 | ++(*identifier); |
||
556 | } |
||
557 | } |
||
558 | } |
||
559 | // timer event
|
||
560 | else if (mask & _eventListenerDelay.events) { |
||
561 | // unregister event
|
||
562 | chEvtUnregister(&_eventSourceDelay, &_eventListenerDelay); |
||
563 | } |
||
564 | // any further events must be handled externally
|
||
565 | |||
566 | return mask;
|
||
567 | } |
||
568 | |||
569 | #endif /* (AMIROOS_CFG_SSSP_SHUTDOWN == true) */ |
||
570 | |||
571 | #endif /* (AMIROOS_CFG_SSSP_ENABLE == true) */ |
||
572 | |||
573 | /** @} */ |