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