Line data Source code
1 : /*------------------------------------------------------------------------------
2 : -- Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3 : -- This file is a part of the LFR FSW
4 : -- Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5 : --
6 : -- This program is free software; you can redistribute it and/or modify
7 : -- it under the terms of the GNU General Public License as published by
8 : -- the Free Software Foundation; either version 2 of the License, or
9 : -- (at your option) any later version.
10 : --
11 : -- This program is distributed in the hope that it will be useful,
12 : -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : -- GNU General Public License for more details.
15 : --
16 : -- You should have received a copy of the GNU General Public License
17 : -- along with this program; if not, write to the Free Software
18 : -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 : -------------------------------------------------------------------------------*/
20 : /*-- Author : Paul Leroy
21 : -- Contact : Alexis Jeandet
22 : -- Mail : alexis.jeandet@lpp.polytechnique.fr
23 : ----------------------------------------------------------------------------*/
24 : /** Functions and tasks related to TeleCommand handling.
25 : *
26 : * @file
27 : * @author P. LEROY
28 : *
29 : * A group of functions to handle TeleCommands:\n
30 : * action launching\n
31 : * TC parsing\n
32 : * ...
33 : *
34 : */
35 :
36 : #include <math.h>
37 : #include <string.h>
38 :
39 : #include "fsw_compile_warnings.h"
40 : #include "fsw_debug.h"
41 : #include "fsw_housekeeping.h"
42 : #include "hw/lfr_regs.h"
43 : #include "tc_tm/tc_handler.h"
44 :
45 : //***********
46 : // RTEMS TASK
47 :
48 1 : LFR_NO_RETURN rtems_task actn_task(rtems_task_argument unused)
49 : {
50 : /** This RTEMS task is responsible for launching actions upton the reception of valid
51 : * TeleCommands.
52 : *
53 : * @param unused is the starting argument of the RTEMS task
54 : *
55 : * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it
56 : * launches specific actions depending on the incoming TeleCommand.
57 : *
58 : */
59 :
60 : IGNORE_UNUSED_PARAMETER(unused);
61 1 : int result = LFR_SUCCESSFUL;
62 : rtems_status_code status; // RTEMS status code
63 : ccsdsTelecommandPacket_t __attribute__((aligned(4))) TC; // TC sent to the ACTN task
64 1 : size_t size = 0; // size of the incoming TC packet
65 1 : unsigned char subtype = 0; // subtype of the current TC packet
66 : unsigned char time[BYTES_PER_TIME];
67 1 : rtems_id queue_rcv_id = RTEMS_ID_NONE;
68 1 : rtems_id queue_snd_id = RTEMS_ID_NONE;
69 :
70 1 : memset(&TC, 0, sizeof(ccsdsTelecommandPacket_t));
71 :
72 1 : DEBUG_CHECK_STATUS(get_message_queue_id_recv(&queue_rcv_id));
73 1 : DEBUG_CHECK_STATUS(get_message_queue_id_send(&queue_snd_id));
74 :
75 : BOOT_PRINTF("in ACTN *** \n");
76 :
77 : while (1)
78 : {
79 28 : status = rtems_message_queue_receive(
80 : queue_rcv_id, (char*)&TC, &size, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
81 : DEBUG_CHECK_STATUS(status);
82 28 : getTime(time); // set time to the current time
83 28 : if (status == RTEMS_SUCCESSFUL)
84 : {
85 28 : subtype = TC.serviceSubType;
86 28 : switch (subtype)
87 : {
88 : case TC_SUBTYPE_RESET:
89 1 : result = action_reset();
90 0 : close_action(&TC, result, queue_snd_id);
91 0 : break;
92 : case TC_SUBTYPE_LOAD_COMM:
93 0 : result = action_load_common_par(&TC);
94 0 : close_action(&TC, result, queue_snd_id);
95 0 : break;
96 : case TC_SUBTYPE_LOAD_NORM:
97 0 : result = action_load_normal_par(&TC, queue_snd_id, time);
98 0 : close_action(&TC, result, queue_snd_id);
99 0 : break;
100 : case TC_SUBTYPE_LOAD_BURST:
101 0 : result = action_load_burst_par(&TC, queue_snd_id, time);
102 0 : close_action(&TC, result, queue_snd_id);
103 0 : break;
104 : case TC_SUBTYPE_LOAD_SBM1:
105 0 : result = action_load_sbm1_par(&TC, queue_snd_id, time);
106 0 : close_action(&TC, result, queue_snd_id);
107 0 : break;
108 : case TC_SUBTYPE_LOAD_SBM2:
109 0 : result = action_load_sbm2_par(&TC, queue_snd_id, time);
110 0 : close_action(&TC, result, queue_snd_id);
111 0 : break;
112 : case TC_SUBTYPE_DUMP:
113 11 : result = action_dump_par(&TC, queue_snd_id);
114 11 : close_action(&TC, result, queue_snd_id);
115 11 : break;
116 : case TC_SUBTYPE_ENTER:
117 6 : result = action_enter_mode(&TC, queue_snd_id);
118 6 : close_action(&TC, result, queue_snd_id);
119 6 : break;
120 : case TC_SUBTYPE_UPDT_INFO:
121 0 : result = action_update_info(&TC);
122 0 : close_action(&TC, result, queue_snd_id);
123 0 : break;
124 : case TC_SUBTYPE_EN_CAL:
125 0 : result = action_enable_calibration();
126 0 : close_action(&TC, result, queue_snd_id);
127 0 : break;
128 : case TC_SUBTYPE_DIS_CAL:
129 0 : result = action_disable_calibration();
130 0 : close_action(&TC, result, queue_snd_id);
131 0 : break;
132 : case TC_SUBTYPE_LOAD_K:
133 0 : result = action_load_kcoefficients(&TC, queue_snd_id, time);
134 0 : close_action(&TC, result, queue_snd_id);
135 0 : break;
136 : case TC_SUBTYPE_DUMP_K:
137 0 : result = action_dump_kcoefficients(&TC, queue_snd_id, time);
138 0 : close_action(&TC, result, queue_snd_id);
139 0 : break;
140 : case TC_SUBTYPE_LOAD_FBINS:
141 10 : result = action_load_fbins_mask(&TC, queue_snd_id, time);
142 10 : close_action(&TC, result, queue_snd_id);
143 10 : break;
144 : case TC_SUBTYPE_LOAD_FILTER_PAR:
145 0 : result = action_load_filter_par(&TC, queue_snd_id);
146 0 : close_action(&TC, result, queue_snd_id);
147 0 : break;
148 : case TC_SUBTYPE_UPDT_TIME:
149 0 : result = action_update_time(&TC);
150 0 : close_action(&TC, result, queue_snd_id);
151 : break;
152 : default:
153 : break;
154 : }
155 : }
156 : }
157 : }
158 :
159 : //***********
160 : // TC ACTIONS
161 :
162 1 : int action_reset()
163 : {
164 : /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
165 : *
166 : * @param TC points to the TeleCommand packet that is being processed
167 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
168 : *
169 : */
170 :
171 : LFR_PRINTF("this is the end!!!\n");
172 : #ifdef GCOV_ENABLED
173 : #ifndef GCOV_USE_EXIT
174 : extern void gcov_exit(void);
175 : gcov_exit();
176 : #endif
177 : #endif
178 1 : exit(0);
179 :
180 : #ifdef ENABLE_DEAD_CODE
181 : send_tm_lfr_tc_exe_not_implemented(TC, queue_id, time);
182 : #endif
183 :
184 : return LFR_DEFAULT;
185 : }
186 :
187 6 : int action_enter_mode(const ccsdsTelecommandPacket_t* const TC, rtems_id queue_id)
188 : {
189 : /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been
190 : * received.
191 : *
192 : * @param TC points to the TeleCommand packet that is being processed
193 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
194 : *
195 : */
196 :
197 : rtems_status_code status;
198 : unsigned char requestedMode;
199 : unsigned int transitionCoarseTime;
200 6 : const unsigned char* const bytePosPtr = (const unsigned char*)&TC->packetID;
201 6 : requestedMode = bytePosPtr[BYTE_POS_CP_MODE_LFR_SET];
202 6 : copyInt32ByChar(
203 : (unsigned char*)&transitionCoarseTime, &bytePosPtr[BYTE_POS_CP_LFR_ENTER_MODE_TIME]);
204 6 : transitionCoarseTime = transitionCoarseTime & COARSE_TIME_MASK;
205 12 : status = check_mode_value(requestedMode);
206 : DEBUG_CHECK_STATUS(status);
207 :
208 6 : if (status != LFR_SUCCESSFUL) // the mode value is inconsistent
209 : {
210 0 : DEBUG_CHECK_STATUS(send_tm_lfr_tc_exe_inconsistent(
211 : TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode));
212 : }
213 :
214 : else // the mode value is valid, check the transition
215 : {
216 6 : status = check_mode_transition(requestedMode);
217 : DEBUG_CHECK_STATUS(status);
218 6 : if (status != LFR_SUCCESSFUL)
219 : {
220 : LFR_PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n");
221 1 : DEBUG_CHECK_STATUS(send_tm_lfr_tc_exe_not_executable(TC, queue_id));
222 : }
223 : }
224 :
225 6 : if (status == LFR_SUCCESSFUL) // the transition is valid, check the date
226 : {
227 5 : status = check_transition_date(transitionCoarseTime);
228 : DEBUG_CHECK_STATUS(status);
229 5 : if (status != LFR_SUCCESSFUL)
230 : {
231 : LFR_PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
232 0 : DEBUG_CHECK_STATUS(send_tm_lfr_tc_exe_not_executable(TC, queue_id));
233 : }
234 : }
235 :
236 6 : if (status == LFR_SUCCESSFUL) // the date is valid, enter the mode
237 : {
238 : LFR_PRINTF("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
239 :
240 5 : switch (requestedMode)
241 : {
242 : case LFR_MODE_STANDBY:
243 1 : status = enter_mode_standby();
244 1 : break;
245 : case LFR_MODE_NORMAL:
246 1 : status = enter_mode_normal(transitionCoarseTime);
247 1 : break;
248 : case LFR_MODE_BURST:
249 1 : status = enter_mode_burst(transitionCoarseTime);
250 1 : break;
251 : case LFR_MODE_SBM1:
252 1 : status = enter_mode_sbm1(transitionCoarseTime);
253 1 : break;
254 : case LFR_MODE_SBM2:
255 1 : status = enter_mode_sbm2(transitionCoarseTime);
256 : break;
257 : default:
258 : break;
259 : }
260 : DEBUG_CHECK_STATUS(status);
261 5 : if (status != RTEMS_SUCCESSFUL)
262 : {
263 0 : status = LFR_EXE_ERROR;
264 : }
265 : }
266 :
267 6 : return status;
268 : }
269 :
270 0 : int action_update_info(const ccsdsTelecommandPacket_t* const TC)
271 : {
272 : /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been
273 : * received.
274 : *
275 : * @param TC points to the TeleCommand packet that is being processed
276 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
277 : *
278 : * @return LFR directive status code:
279 : * - LFR_DEFAULT
280 : * - LFR_SUCCESSFUL
281 : *
282 : */
283 :
284 : unsigned int val;
285 0 : unsigned int status = LFR_DEFAULT;
286 : unsigned char mode;
287 0 : const unsigned char* const bytePosPtr = (const unsigned char*)&TC->packetID;
288 0 : int pos = 0;
289 0 : float value = 0.;
290 :
291 : // check LFR mode
292 0 : mode = (bytePosPtr[BYTE_POS_UPDATE_INFO_PARAMETERS_SET5] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
293 0 : status = check_update_info_hk_lfr_mode(mode);
294 : DEBUG_CHECK_STATUS(status);
295 0 : if (status == LFR_SUCCESSFUL) // check TDS mode
296 : {
297 0 : mode = (bytePosPtr[BYTE_POS_UPDATE_INFO_PARAMETERS_SET6] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
298 0 : status = check_update_info_hk_tds_mode(mode);
299 : DEBUG_CHECK_STATUS(status);
300 : }
301 0 : if (status == LFR_SUCCESSFUL) // check THR mode
302 : {
303 0 : mode = (bytePosPtr[BYTE_POS_UPDATE_INFO_PARAMETERS_SET6] & BITS_THR_MODE);
304 0 : status = check_update_info_hk_thr_mode(mode);
305 : DEBUG_CHECK_STATUS(status);
306 : }
307 0 : if (status == LFR_SUCCESSFUL) // check reaction wheels frequencies
308 : {
309 0 : status = check_all_sy_lfr_rw_f(TC, &pos, &value);
310 : DEBUG_CHECK_STATUS(status);
311 : }
312 :
313 : // if the parameters checking succeeds, udpate all parameters
314 0 : if (status == LFR_SUCCESSFUL)
315 : {
316 : // pa_bia_status_info
317 : // => pa_bia_mode_mux_set 3 bits
318 : // => pa_bia_mode_hv_enabled 1 bit
319 : // => pa_bia_mode_bias1_enabled 1 bit
320 : // => pa_bia_mode_bias2_enabled 1 bit
321 : // => pa_bia_mode_bias3_enabled 1 bit
322 : // => pa_bia_on_off (cp_dpu_bias_on_off)
323 0 : pa_bia_status_info
324 0 : = bytePosPtr[BYTE_POS_UPDATE_INFO_PARAMETERS_SET2] & BITS_BIA; // [1111 1110]
325 0 : pa_bia_status_info
326 0 : = pa_bia_status_info | (bytePosPtr[BYTE_POS_UPDATE_INFO_PARAMETERS_SET1] & 1);
327 :
328 : // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be
329 : // copied in HK packets)
330 0 : getReactionWheelsFrequencies(TC);
331 0 : set_hk_lfr_sc_rw_f_flags();
332 0 : build_sy_lfr_rw_masks();
333 :
334 : // once the masks are built, they have to be merged with the fbins_mask
335 0 : merge_fbins_masks();
336 :
337 : // increase the TC_LFR_UPDATE_INFO counter
338 0 : if (status == LFR_SUCCESSFUL) // if the parameter check is successful
339 : {
340 0 : val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
341 0 : + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
342 0 : val++;
343 0 : housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char)(val >> SHIFT_1_BYTE);
344 0 : housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char)(val);
345 : }
346 : }
347 :
348 0 : return status;
349 : }
350 :
351 0 : int action_enable_calibration()
352 : {
353 : /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has
354 : * been received.
355 : *
356 : * @param TC points to the TeleCommand packet that is being processed
357 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
358 : *
359 : */
360 0 : setCalibration(true);
361 0 : return LFR_SUCCESSFUL;
362 : }
363 :
364 0 : int action_disable_calibration()
365 : {
366 : /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has
367 : * been received.
368 : *
369 : * @param TC points to the TeleCommand packet that is being processed
370 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
371 : *
372 : */
373 :
374 0 : setCalibration(false);
375 0 : return LFR_SUCCESSFUL;
376 : }
377 :
378 0 : int action_update_time(const ccsdsTelecommandPacket_t* const TC)
379 : {
380 : /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been
381 : * received.
382 : *
383 : * @param TC points to the TeleCommand packet that is being processed
384 : * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
385 : *
386 : * @return LFR_SUCCESSFUL
387 : *
388 : */
389 :
390 : unsigned int val;
391 :
392 0 : time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
393 0 : + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES) + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
394 0 : + TC->dataAndCRC[BYTE_3];
395 :
396 0 : val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
397 0 : + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
398 0 : val++;
399 0 : housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char)(val >> SHIFT_1_BYTE);
400 0 : housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char)(val);
401 :
402 0 : oneTcLfrUpdateTimeReceived = 1;
403 :
404 0 : return LFR_SUCCESSFUL;
405 : }
406 :
407 : //*******************
408 : // ENTERING THE MODES
409 0 : int check_mode_value(unsigned char requestedMode)
410 : {
411 6 : int status = LFR_DEFAULT;
412 :
413 6 : if ((requestedMode != LFR_MODE_STANDBY) && (requestedMode != LFR_MODE_NORMAL)
414 : && (requestedMode != LFR_MODE_BURST) && (requestedMode != LFR_MODE_SBM1)
415 : && (requestedMode != LFR_MODE_SBM2))
416 : {
417 0 : status = LFR_DEFAULT;
418 : }
419 : else
420 : {
421 6 : status = LFR_SUCCESSFUL;
422 : }
423 :
424 6 : return status;
425 : }
426 :
427 6 : int check_mode_transition(unsigned char requestedMode)
428 : {
429 : /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
430 : *
431 : * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
432 : *
433 : * @return LFR directive status codes:
434 : * - LFR_SUCCESSFUL - the transition is authorized
435 : * - LFR_DEFAULT - the transition is not authorized
436 : *
437 : */
438 :
439 : int status;
440 :
441 6 : switch (requestedMode)
442 : {
443 : case LFR_MODE_STANDBY:
444 2 : if (lfrCurrentMode == LFR_MODE_STANDBY)
445 : {
446 1 : status = LFR_DEFAULT;
447 : }
448 : else
449 : {
450 1 : status = LFR_SUCCESSFUL;
451 : }
452 : break;
453 : case LFR_MODE_NORMAL:
454 1 : if (lfrCurrentMode == LFR_MODE_NORMAL)
455 : {
456 0 : status = LFR_DEFAULT;
457 : }
458 : else
459 : {
460 1 : status = LFR_SUCCESSFUL;
461 : }
462 : break;
463 : case LFR_MODE_BURST:
464 1 : if (lfrCurrentMode == LFR_MODE_BURST)
465 : {
466 0 : status = LFR_DEFAULT;
467 : }
468 : else
469 : {
470 1 : status = LFR_SUCCESSFUL;
471 : }
472 : break;
473 : case LFR_MODE_SBM1:
474 1 : if (lfrCurrentMode == LFR_MODE_SBM1)
475 : {
476 0 : status = LFR_DEFAULT;
477 : }
478 : else
479 : {
480 1 : status = LFR_SUCCESSFUL;
481 : }
482 : break;
483 : case LFR_MODE_SBM2:
484 1 : if (lfrCurrentMode == LFR_MODE_SBM2)
485 : {
486 0 : status = LFR_DEFAULT;
487 : }
488 : else
489 : {
490 1 : status = LFR_SUCCESSFUL;
491 : }
492 : break;
493 : default:
494 0 : status = LFR_DEFAULT;
495 : break;
496 : }
497 :
498 6 : return status;
499 : }
500 :
501 5 : void update_last_valid_transition_date(unsigned int transitionCoarseTime)
502 : {
503 5 : if (transitionCoarseTime == 0)
504 : {
505 1 : lastValidEnterModeTime = time_management_regs->coarse_time + 1;
506 : LFR_PRINTF("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n",
507 : lastValidEnterModeTime);
508 : }
509 : else
510 : {
511 4 : lastValidEnterModeTime = transitionCoarseTime;
512 : LFR_PRINTF("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
513 : }
514 5 : }
515 :
516 5 : int check_transition_date(unsigned int transitionCoarseTime)
517 : {
518 : int status;
519 : unsigned int localCoarseTime;
520 : unsigned int deltaCoarseTime;
521 :
522 5 : status = LFR_SUCCESSFUL;
523 :
524 5 : if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
525 : {
526 5 : status = LFR_SUCCESSFUL;
527 : }
528 : else
529 : {
530 0 : localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
531 :
532 : LFR_PRINTF("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
533 :
534 0 : if (transitionCoarseTime <= localCoarseTime) // SSS-CP-EQS-322
535 : {
536 0 : status = LFR_DEFAULT;
537 : LFR_PRINTF(
538 : "ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
539 : }
540 :
541 0 : if (status == LFR_SUCCESSFUL)
542 : {
543 0 : deltaCoarseTime = transitionCoarseTime - localCoarseTime;
544 0 : if (deltaCoarseTime > MAX_DELTA_COARSE_TIME) // SSS-CP-EQS-323
545 : {
546 0 : status = LFR_DEFAULT;
547 : LFR_PRINTF(
548 : "ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime);
549 : }
550 : }
551 : }
552 :
553 5 : return status;
554 : }
555 :
556 1 : int restart_asm_activities(unsigned char lfrRequestedMode)
557 : {
558 : rtems_status_code status;
559 :
560 1 : status = stop_spectral_matrices();
561 : DEBUG_CHECK_STATUS(status);
562 :
563 1 : thisIsAnASMRestart = 1;
564 :
565 1 : status = restart_asm_tasks(lfrRequestedMode);
566 : DEBUG_CHECK_STATUS(status);
567 :
568 1 : launch_spectral_matrix();
569 :
570 1 : return status;
571 : }
572 :
573 1 : int stop_spectral_matrices(void)
574 : {
575 : /** This function stops and restarts the current mode average spectral matrices activities.
576 : *
577 : * @return RTEMS directive status codes:
578 : * - RTEMS_SUCCESSFUL - task restarted successfully
579 : * - RTEMS_INVALID_ID - task id invalid
580 : * - RTEMS_ALREADY_SUSPENDED - task already suspended
581 : *
582 : */
583 :
584 : rtems_status_code status;
585 :
586 1 : status = RTEMS_SUCCESSFUL;
587 :
588 : // (1) mask interruptions
589 1 : LEON_Mask_interrupt(IRQ_SPECTRAL_MATRIX); // mask spectral matrix interrupt
590 :
591 : // (2) reset spectral matrices registers
592 : set_sm_irq_onNewMatrix(0); // stop the spectral matrices
593 1 : reset_sm_status();
594 :
595 : // (3) clear interruptions
596 1 : LEON_Clear_interrupt(IRQ_SPECTRAL_MATRIX); // clear spectral matrix interrupt
597 :
598 : // suspend several tasks
599 1 : if (lfrCurrentMode != LFR_MODE_STANDBY)
600 : {
601 1 : status = suspend_asm_tasks();
602 : DEBUG_CHECK_STATUS(status);
603 : }
604 :
605 1 : if (status != RTEMS_SUCCESSFUL)
606 : {
607 : LFR_PRINTF("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status);
608 : }
609 :
610 1 : return status;
611 : }
612 :
613 3 : int stop_current_mode(void)
614 : {
615 : /** This function stops the current mode by masking interrupt lines and suspending science
616 : * tasks.
617 : *
618 : * @return RTEMS directive status codes:
619 : * - RTEMS_SUCCESSFUL - task restarted successfully
620 : * - RTEMS_INVALID_ID - task id invalid
621 : * - RTEMS_ALREADY_SUSPENDED - task already suspended
622 : *
623 : */
624 :
625 : rtems_status_code status;
626 :
627 3 : status = RTEMS_SUCCESSFUL;
628 :
629 : // (1) mask interruptions
630 3 : LEON_Mask_interrupt(IRQ_WAVEFORM_PICKER); // mask waveform picker interrupt
631 3 : LEON_Mask_interrupt(IRQ_SPECTRAL_MATRIX); // clear spectral matrix interrupt
632 :
633 : // (2) reset waveform picker registers
634 3 : reset_wfp_burst_enable(); // reset burst and enable bits
635 3 : reset_wfp_status(); // reset all the status bits
636 :
637 : // (3) reset spectral matrices registers
638 : set_sm_irq_onNewMatrix(0); // stop the spectral matrices
639 3 : reset_sm_status();
640 :
641 : // reset lfr VHDL module
642 3 : reset_lfr();
643 :
644 3 : reset_extractSWF(); // reset the extractSWF flag to false
645 :
646 : // (4) clear interruptions
647 3 : LEON_Clear_interrupt(IRQ_WAVEFORM_PICKER); // clear waveform picker interrupt
648 3 : LEON_Clear_interrupt(IRQ_SPECTRAL_MATRIX); // clear spectral matrix interrupt
649 :
650 : // suspend several tasks
651 3 : if (lfrCurrentMode != LFR_MODE_STANDBY)
652 : {
653 3 : status = suspend_science_tasks();
654 : DEBUG_CHECK_STATUS(status);
655 : }
656 :
657 3 : if (status != RTEMS_SUCCESSFUL)
658 : {
659 : LFR_PRINTF("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status);
660 : }
661 :
662 3 : return status;
663 : }
664 :
665 0 : int enter_mode_standby(void)
666 : {
667 : /** This function is used to put LFR in the STANDBY mode.
668 : *
669 : * @param transitionCoarseTime is the requested transition time contained in the
670 : * TC_LFR_ENTER_MODE
671 : *
672 : * @return RTEMS directive status codes:
673 : * - RTEMS_SUCCESSFUL - task restarted successfully
674 : * - RTEMS_INVALID_ID - task id invalid
675 : * - RTEMS_INCORRECT_STATE - task never started
676 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
677 : *
678 : * The STANDBY mode does not depends on a specific transition date, the effect of the
679 : * TC_LFR_ENTER_MODE is immediate.
680 : *
681 : */
682 :
683 : int status;
684 :
685 1 : status = stop_current_mode(); // STOP THE CURRENT MODE
686 : DEBUG_CHECK_STATUS(status);
687 :
688 : #ifdef PRINT_TASK_STATISTICS
689 : rtems_cpu_usage_report();
690 : #endif
691 :
692 : #ifdef PRINT_STACK_REPORT
693 : LFR_PRINTF("stack report selected\n");
694 : rtems_stack_checker_report_usage();
695 : #endif
696 :
697 1 : return status;
698 : }
699 :
700 1 : int enter_mode_normal(unsigned int transitionCoarseTime)
701 : {
702 : /** This function is used to start the NORMAL mode.
703 : *
704 : * @param transitionCoarseTime is the requested transition time contained in the
705 : * TC_LFR_ENTER_MODE
706 : *
707 : * @return RTEMS directive status codes:
708 : * - RTEMS_SUCCESSFUL - task restarted successfully
709 : * - RTEMS_INVALID_ID - task id invalid
710 : * - RTEMS_INCORRECT_STATE - task never started
711 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
712 : *
713 : * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or
714 : * SBM2, the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
715 : *
716 : */
717 :
718 : int status;
719 :
720 : #ifdef PRINT_TASK_STATISTICS
721 : rtems_cpu_usage_reset();
722 : #endif
723 :
724 1 : status = RTEMS_UNSATISFIED;
725 :
726 1 : switch (lfrCurrentMode)
727 : {
728 : case LFR_MODE_STANDBY:
729 1 : status = restart_science_tasks(LFR_MODE_NORMAL); // restart science tasks
730 : DEBUG_CHECK_STATUS(status);
731 1 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
732 : {
733 1 : launch_spectral_matrix();
734 1 : launch_waveform_picker(LFR_MODE_NORMAL, transitionCoarseTime);
735 : }
736 : break;
737 : case LFR_MODE_BURST:
738 0 : status = stop_current_mode(); // stop the current mode
739 : DEBUG_CHECK_STATUS(status);
740 0 : status = restart_science_tasks(LFR_MODE_NORMAL); // restart the science tasks
741 : DEBUG_CHECK_STATUS(status);
742 0 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
743 : {
744 0 : launch_spectral_matrix();
745 0 : launch_waveform_picker(LFR_MODE_NORMAL, transitionCoarseTime);
746 : }
747 : break;
748 : case LFR_MODE_SBM1:
749 : case LFR_MODE_SBM2:
750 0 : status = restart_asm_activities(
751 : LFR_MODE_NORMAL); // this is necessary to restart ASM tasks to update the parameters
752 : DEBUG_CHECK_STATUS(status);
753 0 : status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of
754 : // close_action
755 0 : update_last_valid_transition_date(transitionCoarseTime);
756 : break;
757 : default:
758 : break;
759 : }
760 :
761 1 : if (status != RTEMS_SUCCESSFUL)
762 : {
763 : LFR_PRINTF("ERR *** in enter_mode_normal *** status = %d\n", status);
764 0 : status = RTEMS_UNSATISFIED;
765 : }
766 :
767 1 : return status;
768 : }
769 :
770 1 : int enter_mode_burst(unsigned int transitionCoarseTime)
771 : {
772 : /** This function is used to start the BURST mode.
773 : *
774 : * @param transitionCoarseTime is the requested transition time contained in the
775 : * TC_LFR_ENTER_MODE
776 : *
777 : * @return RTEMS directive status codes:
778 : * - RTEMS_SUCCESSFUL - task restarted successfully
779 : * - RTEMS_INVALID_ID - task id invalid
780 : * - RTEMS_INCORRECT_STATE - task never started
781 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
782 : *
783 : * The way the BURST mode is started does not depend on the LFR current mode.
784 : *
785 : */
786 :
787 :
788 : int status;
789 :
790 : #ifdef PRINT_TASK_STATISTICS
791 : rtems_cpu_usage_reset();
792 : #endif
793 :
794 1 : status = stop_current_mode(); // stop the current mode
795 : DEBUG_CHECK_STATUS(status);
796 1 : status = restart_science_tasks(LFR_MODE_BURST); // restart the science tasks
797 : DEBUG_CHECK_STATUS(status);
798 1 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
799 : {
800 1 : launch_spectral_matrix();
801 1 : launch_waveform_picker(LFR_MODE_BURST, transitionCoarseTime);
802 : }
803 :
804 1 : if (status != RTEMS_SUCCESSFUL)
805 : {
806 : LFR_PRINTF("ERR *** in enter_mode_burst *** status = %d\n", status);
807 0 : status = RTEMS_UNSATISFIED;
808 : }
809 :
810 1 : return status;
811 : }
812 :
813 1 : int enter_mode_sbm1(unsigned int transitionCoarseTime)
814 : {
815 : /** This function is used to start the SBM1 mode.
816 : *
817 : * @param transitionCoarseTime is the requested transition time contained in the
818 : * TC_LFR_ENTER_MODE
819 : *
820 : * @return RTEMS directive status codes:
821 : * - RTEMS_SUCCESSFUL - task restarted successfully
822 : * - RTEMS_INVALID_ID - task id invalid
823 : * - RTEMS_INCORRECT_STATE - task never started
824 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
825 : *
826 : * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or
827 : * SBM2, the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In
828 : * other cases, the acquisition is completely restarted.
829 : *
830 : */
831 :
832 : int status;
833 :
834 : #ifdef PRINT_TASK_STATISTICS
835 : rtems_cpu_usage_reset();
836 : #endif
837 :
838 1 : status = RTEMS_UNSATISFIED;
839 :
840 1 : switch (lfrCurrentMode)
841 : {
842 : case LFR_MODE_STANDBY:
843 0 : status = restart_science_tasks(LFR_MODE_SBM1); // restart science tasks
844 : DEBUG_CHECK_STATUS(status);
845 0 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
846 : {
847 0 : launch_spectral_matrix();
848 0 : launch_waveform_picker(LFR_MODE_SBM1, transitionCoarseTime);
849 : }
850 : break;
851 : case LFR_MODE_NORMAL: // lfrCurrentMode will be updated after the execution of close_action
852 : case LFR_MODE_SBM2:
853 0 : status = restart_asm_activities(LFR_MODE_SBM1);
854 : DEBUG_CHECK_STATUS(status);
855 0 : status = LFR_SUCCESSFUL;
856 0 : update_last_valid_transition_date(transitionCoarseTime);
857 0 : break;
858 : case LFR_MODE_BURST:
859 1 : status = stop_current_mode(); // stop the current mode
860 : DEBUG_CHECK_STATUS(status);
861 1 : status = restart_science_tasks(LFR_MODE_SBM1); // restart the science tasks
862 : DEBUG_CHECK_STATUS(status);
863 1 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
864 : {
865 1 : launch_spectral_matrix();
866 1 : launch_waveform_picker(LFR_MODE_SBM1, transitionCoarseTime);
867 : }
868 : break;
869 : default:
870 : break;
871 : }
872 :
873 1 : if (status != RTEMS_SUCCESSFUL)
874 : {
875 : LFR_PRINTF("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
876 0 : status = RTEMS_UNSATISFIED;
877 : }
878 :
879 1 : return status;
880 : }
881 :
882 1 : int enter_mode_sbm2(unsigned int transitionCoarseTime)
883 : {
884 : /** This function is used to start the SBM2 mode.
885 : *
886 : * @param transitionCoarseTime is the requested transition time contained in the
887 : * TC_LFR_ENTER_MODE
888 : *
889 : * @return RTEMS directive status codes:
890 : * - RTEMS_SUCCESSFUL - task restarted successfully
891 : * - RTEMS_INVALID_ID - task id invalid
892 : * - RTEMS_INCORRECT_STATE - task never started
893 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
894 : *
895 : * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or
896 : * SBM1, the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In
897 : * other cases, the acquisition is completely restarted.
898 : *
899 : */
900 :
901 : int status;
902 :
903 : #ifdef PRINT_TASK_STATISTICS
904 : rtems_cpu_usage_reset();
905 : #endif
906 :
907 1 : status = RTEMS_UNSATISFIED;
908 :
909 1 : switch (lfrCurrentMode)
910 : {
911 : case LFR_MODE_STANDBY:
912 0 : status = restart_science_tasks(LFR_MODE_SBM2); // restart science tasks
913 : DEBUG_CHECK_STATUS(status);
914 0 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
915 : {
916 0 : launch_spectral_matrix();
917 0 : launch_waveform_picker(LFR_MODE_SBM2, transitionCoarseTime);
918 : }
919 : break;
920 : case LFR_MODE_NORMAL:
921 : case LFR_MODE_SBM1:
922 1 : status = restart_asm_activities(LFR_MODE_SBM2);
923 : DEBUG_CHECK_STATUS(status);
924 1 : status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of
925 : // close_action
926 1 : update_last_valid_transition_date(transitionCoarseTime);
927 1 : break;
928 : case LFR_MODE_BURST:
929 0 : status = stop_current_mode(); // stop the current mode
930 : DEBUG_CHECK_STATUS(status);
931 0 : status = restart_science_tasks(LFR_MODE_SBM2); // restart the science tasks
932 : DEBUG_CHECK_STATUS(status);
933 0 : if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
934 : {
935 0 : launch_spectral_matrix();
936 0 : launch_waveform_picker(LFR_MODE_SBM2, transitionCoarseTime);
937 : }
938 : break;
939 : default:
940 : break;
941 : }
942 :
943 1 : if (status != RTEMS_SUCCESSFUL)
944 : {
945 : LFR_PRINTF("ERR *** in enter_mode_sbm2 *** status = %d\n", status);
946 0 : status = RTEMS_UNSATISFIED;
947 : }
948 :
949 1 : return status;
950 : }
951 :
952 3 : int restart_science_tasks(unsigned char lfrRequestedMode)
953 : {
954 : /** This function is used to restart all science tasks.
955 : *
956 : * @return RTEMS directive status codes:
957 : * - RTEMS_SUCCESSFUL - task restarted successfully
958 : * - RTEMS_INVALID_ID - task id invalid
959 : * - RTEMS_INCORRECT_STATE - task never started
960 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
961 : *
962 : * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
963 : *
964 : */
965 :
966 3 : rtems_status_code status = RTEMS_SUCCESSFUL;
967 : rtems_status_code ret;
968 :
969 3 : ret = RTEMS_SUCCESSFUL;
970 :
971 3 : status |= rtems_task_restart(Task_id[TASKID_AVF0], lfrRequestedMode);
972 : DEBUG_CHECK_STATUS(status);
973 :
974 3 : status |= rtems_task_restart(Task_id[TASKID_PRC0], lfrRequestedMode);
975 : DEBUG_CHECK_STATUS(status);
976 :
977 3 : status |= rtems_task_restart(Task_id[TASKID_WFRM], 1);
978 : DEBUG_CHECK_STATUS(status);
979 :
980 3 : status |= rtems_task_restart(Task_id[TASKID_CWF3], 1);
981 : DEBUG_CHECK_STATUS(status);
982 :
983 3 : status |= rtems_task_restart(Task_id[TASKID_CWF2], 1);
984 : DEBUG_CHECK_STATUS(status);
985 :
986 3 : status |= rtems_task_restart(Task_id[TASKID_CWF1], 1);
987 : DEBUG_CHECK_STATUS(status);
988 :
989 3 : status |= rtems_task_restart(Task_id[TASKID_AVF1], lfrRequestedMode);
990 : DEBUG_CHECK_STATUS(status);
991 :
992 3 : status |= rtems_task_restart(Task_id[TASKID_PRC1], lfrRequestedMode);
993 : DEBUG_CHECK_STATUS(status);
994 :
995 3 : status |= rtems_task_restart(Task_id[TASKID_AVF2], 1);
996 : DEBUG_CHECK_STATUS(status);
997 :
998 3 : status |= rtems_task_restart(Task_id[TASKID_PRC2], 1);
999 : DEBUG_CHECK_STATUS(status);
1000 :
1001 3 : if (status != RTEMS_SUCCESSFUL)
1002 : {
1003 0 : ret = RTEMS_UNSATISFIED;
1004 : }
1005 :
1006 3 : return ret;
1007 : }
1008 :
1009 1 : int restart_asm_tasks(unsigned char lfrRequestedMode)
1010 : {
1011 : /** This function is used to restart average spectral matrices tasks.
1012 : *
1013 : * @return RTEMS directive status codes:
1014 : * - RTEMS_SUCCESSFUL - task restarted successfully
1015 : * - RTEMS_INVALID_ID - task id invalid
1016 : * - RTEMS_INCORRECT_STATE - task never started
1017 : * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1018 : *
1019 : * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1020 : *
1021 : */
1022 :
1023 1 : rtems_status_code status= RTEMS_SUCCESSFUL;
1024 :
1025 1 : status |= rtems_task_restart(Task_id[TASKID_AVF0], lfrRequestedMode);
1026 : DEBUG_CHECK_STATUS(status);
1027 :
1028 1 : status |= rtems_task_restart(Task_id[TASKID_PRC0], lfrRequestedMode);
1029 : DEBUG_CHECK_STATUS(status);
1030 :
1031 1 : status |= rtems_task_restart(Task_id[TASKID_AVF1], lfrRequestedMode);
1032 : DEBUG_CHECK_STATUS(status);
1033 :
1034 1 : status |= rtems_task_restart(Task_id[TASKID_PRC1], lfrRequestedMode);
1035 : DEBUG_CHECK_STATUS(status);
1036 :
1037 1 : status |= rtems_task_restart(Task_id[TASKID_AVF2], 1);
1038 : DEBUG_CHECK_STATUS(status);
1039 :
1040 1 : status |= rtems_task_restart(Task_id[TASKID_PRC2], 1);
1041 : DEBUG_CHECK_STATUS(status);
1042 :
1043 1 : if (status != RTEMS_SUCCESSFUL)
1044 : {
1045 0 : status = RTEMS_UNSATISFIED;
1046 : }
1047 :
1048 1 : return status;
1049 : }
1050 :
1051 4 : int suspend_science_tasks(void)
1052 : {
1053 : /** This function suspends the science tasks.
1054 : *
1055 : * @return RTEMS directive status codes:
1056 : * - RTEMS_SUCCESSFUL - task restarted successfully
1057 : * - RTEMS_INVALID_ID - task id invalid
1058 : * - RTEMS_ALREADY_SUSPENDED - task already suspended
1059 : *
1060 : */
1061 :
1062 : rtems_status_code status;
1063 :
1064 : LFR_PRINTF("in suspend_science_tasks\n");
1065 :
1066 4 : status = rtems_task_suspend(Task_id[TASKID_AVF0]); // suspend AVF0
1067 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1068 : {
1069 : LFR_PRINTF("in suspend_science_task *** AVF0 ERR %d\n", status);
1070 : }
1071 : else
1072 : {
1073 4 : status = RTEMS_SUCCESSFUL;
1074 : }
1075 4 : if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1076 : {
1077 4 : status = rtems_task_suspend(Task_id[TASKID_PRC0]);
1078 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1079 : {
1080 : LFR_PRINTF("in suspend_science_task *** PRC0 ERR %d\n", status);
1081 : }
1082 : else
1083 : {
1084 4 : status = RTEMS_SUCCESSFUL;
1085 : }
1086 : }
1087 4 : if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1088 : {
1089 4 : status = rtems_task_suspend(Task_id[TASKID_AVF1]);
1090 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1091 : {
1092 : LFR_PRINTF("in suspend_science_task *** AVF1 ERR %d\n", status);
1093 : }
1094 : else
1095 : {
1096 4 : status = RTEMS_SUCCESSFUL;
1097 : }
1098 : }
1099 4 : if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1100 : {
1101 4 : status = rtems_task_suspend(Task_id[TASKID_PRC1]);
1102 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1103 : {
1104 : LFR_PRINTF("in suspend_science_task *** PRC1 ERR %d\n", status);
1105 : }
1106 : else
1107 : {
1108 4 : status = RTEMS_SUCCESSFUL;
1109 : }
1110 : }
1111 4 : if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1112 : {
1113 4 : status = rtems_task_suspend(Task_id[TASKID_AVF2]);
1114 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1115 : {
1116 : LFR_PRINTF("in suspend_science_task *** AVF2 ERR %d\n", status);
1117 : }
1118 : else
1119 : {
1120 4 : status = RTEMS_SUCCESSFUL;
1121 : }
1122 : }
1123 4 : if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1124 : {
1125 4 : status = rtems_task_suspend(Task_id[TASKID_PRC2]);
1126 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1127 : {
1128 : LFR_PRINTF("in suspend_science_task *** PRC2 ERR %d\n", status);
1129 : }
1130 : else
1131 : {
1132 4 : status = RTEMS_SUCCESSFUL;
1133 : }
1134 : }
1135 4 : if (status == RTEMS_SUCCESSFUL) // suspend WFRM
1136 : {
1137 4 : status = rtems_task_suspend(Task_id[TASKID_WFRM]);
1138 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1139 : {
1140 : LFR_PRINTF("in suspend_science_task *** WFRM ERR %d\n", status);
1141 : }
1142 : else
1143 : {
1144 4 : status = RTEMS_SUCCESSFUL;
1145 : }
1146 : }
1147 4 : if (status == RTEMS_SUCCESSFUL) // suspend CWF3
1148 : {
1149 4 : status = rtems_task_suspend(Task_id[TASKID_CWF3]);
1150 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1151 : {
1152 : LFR_PRINTF("in suspend_science_task *** CWF3 ERR %d\n", status);
1153 : }
1154 : else
1155 : {
1156 4 : status = RTEMS_SUCCESSFUL;
1157 : }
1158 : }
1159 4 : if (status == RTEMS_SUCCESSFUL) // suspend CWF2
1160 : {
1161 4 : status = rtems_task_suspend(Task_id[TASKID_CWF2]);
1162 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1163 : {
1164 : LFR_PRINTF("in suspend_science_task *** CWF2 ERR %d\n", status);
1165 : }
1166 : else
1167 : {
1168 4 : status = RTEMS_SUCCESSFUL;
1169 : }
1170 : }
1171 4 : if (status == RTEMS_SUCCESSFUL) // suspend CWF1
1172 : {
1173 4 : status = rtems_task_suspend(Task_id[TASKID_CWF1]);
1174 4 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1175 : {
1176 : LFR_PRINTF("in suspend_science_task *** CWF1 ERR %d\n", status);
1177 : }
1178 : else
1179 : {
1180 4 : status = RTEMS_SUCCESSFUL;
1181 : }
1182 : }
1183 :
1184 4 : return status;
1185 : }
1186 :
1187 1 : int suspend_asm_tasks(void)
1188 : {
1189 : /** This function suspends the science tasks.
1190 : *
1191 : * @return RTEMS directive status codes:
1192 : * - RTEMS_SUCCESSFUL - task restarted successfully
1193 : * - RTEMS_INVALID_ID - task id invalid
1194 : * - RTEMS_ALREADY_SUSPENDED - task already suspended
1195 : *
1196 : */
1197 :
1198 : rtems_status_code status;
1199 :
1200 : LFR_PRINTF("in suspend_science_tasks\n");
1201 :
1202 1 : status = rtems_task_suspend(Task_id[TASKID_AVF0]); // suspend AVF0
1203 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1204 : {
1205 : LFR_PRINTF("in suspend_science_task *** AVF0 ERR %d\n", status);
1206 : }
1207 : else
1208 : {
1209 1 : status = RTEMS_SUCCESSFUL;
1210 : }
1211 :
1212 1 : if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1213 : {
1214 1 : status = rtems_task_suspend(Task_id[TASKID_PRC0]);
1215 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1216 : {
1217 : LFR_PRINTF("in suspend_science_task *** PRC0 ERR %d\n", status);
1218 : }
1219 : else
1220 : {
1221 1 : status = RTEMS_SUCCESSFUL;
1222 : }
1223 : }
1224 :
1225 1 : if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1226 : {
1227 1 : status = rtems_task_suspend(Task_id[TASKID_AVF1]);
1228 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1229 : {
1230 : LFR_PRINTF("in suspend_science_task *** AVF1 ERR %d\n", status);
1231 : }
1232 : else
1233 : {
1234 1 : status = RTEMS_SUCCESSFUL;
1235 : }
1236 : }
1237 :
1238 1 : if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1239 : {
1240 1 : status = rtems_task_suspend(Task_id[TASKID_PRC1]);
1241 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1242 : {
1243 : LFR_PRINTF("in suspend_science_task *** PRC1 ERR %d\n", status);
1244 : }
1245 : else
1246 : {
1247 1 : status = RTEMS_SUCCESSFUL;
1248 : }
1249 : }
1250 :
1251 1 : if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1252 : {
1253 1 : status = rtems_task_suspend(Task_id[TASKID_AVF2]);
1254 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1255 : {
1256 : LFR_PRINTF("in suspend_science_task *** AVF2 ERR %d\n", status);
1257 : }
1258 : else
1259 : {
1260 1 : status = RTEMS_SUCCESSFUL;
1261 : }
1262 : }
1263 :
1264 1 : if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1265 : {
1266 1 : status = rtems_task_suspend(Task_id[TASKID_PRC2]);
1267 1 : if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1268 : {
1269 : LFR_PRINTF("in suspend_science_task *** PRC2 ERR %d\n", status);
1270 : }
1271 : else
1272 : {
1273 1 : status = RTEMS_SUCCESSFUL;
1274 : }
1275 : }
1276 :
1277 1 : return status;
1278 : }
1279 :
1280 3 : void launch_waveform_picker(unsigned char mode, unsigned int transitionCoarseTime)
1281 : {
1282 :
1283 3 : WFP_reset_current_ring_nodes();
1284 :
1285 3 : reset_waveform_picker_regs();
1286 :
1287 3 : set_wfp_burst_enable_register(mode);
1288 :
1289 3 : LEON_Clear_interrupt(IRQ_WAVEFORM_PICKER);
1290 3 : LEON_Unmask_interrupt(IRQ_WAVEFORM_PICKER);
1291 :
1292 3 : if (transitionCoarseTime == 0)
1293 : {
1294 : // instant transition means transition on the next valid date
1295 : // this is mandatory to have a good snapshot period and a good correction of the snapshot
1296 : // period
1297 3 : waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1298 : }
1299 : else
1300 : {
1301 0 : waveform_picker_regs->start_date = transitionCoarseTime;
1302 : }
1303 :
1304 3 : update_last_valid_transition_date(waveform_picker_regs->start_date);
1305 3 : }
1306 :
1307 4 : void launch_spectral_matrix(void)
1308 : {
1309 4 : SM_reset_current_ring_nodes();
1310 :
1311 4 : reset_spectral_matrix_regs();
1312 :
1313 4 : reset_nb_sm();
1314 :
1315 : set_sm_irq_onNewMatrix(1);
1316 :
1317 4 : LEON_Clear_interrupt(IRQ_SPECTRAL_MATRIX);
1318 4 : LEON_Unmask_interrupt(IRQ_SPECTRAL_MATRIX);
1319 4 : }
1320 :
1321 5 : void set_sm_irq_onNewMatrix(unsigned char value)
1322 : {
1323 13 : if (value == 1)
1324 : {
1325 4 : spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1326 : }
1327 : else
1328 : {
1329 18 : spectral_matrix_regs->config
1330 9 : = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX; // 1110
1331 : }
1332 5 : }
1333 :
1334 5 : void set_sm_irq_onError(unsigned char value)
1335 : {
1336 5 : if (value == 1)
1337 : {
1338 0 : spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1339 : }
1340 : else
1341 : {
1342 5 : spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR; // 1101
1343 : }
1344 5 : }
1345 :
1346 : //*****************************
1347 : // CONFIGURE CALIBRATION SIGNAL
1348 0 : void setCalibrationPrescaler(unsigned int prescaler)
1349 : {
1350 : // prescaling of the master clock (25 MHz)
1351 : // master clock is divided by 2^prescaler
1352 1 : time_management_regs->calPrescaler = prescaler;
1353 0 : }
1354 :
1355 0 : void setCalibrationDivisor(unsigned int divisionFactor)
1356 : {
1357 : // division of the prescaled clock by the division factor
1358 1 : time_management_regs->calDivisor = divisionFactor;
1359 0 : }
1360 :
1361 1 : void setCalibrationData(void)
1362 : {
1363 : /** This function is used to store the values used to drive the DAC in order to generate the SCM
1364 : * calibration signal
1365 : *
1366 : * @param void
1367 : *
1368 : * @return void
1369 : *
1370 : */
1371 :
1372 : unsigned short data;
1373 : float val;
1374 1 : float Ts = (float)(1. / CAL_FS);
1375 :
1376 1 : time_management_regs->calDataPtr = 0;
1377 :
1378 :
1379 : // build the signal for the SCM calibration
1380 257 : for (unsigned int k = 0; k < CAL_NB_PTS; k++)
1381 : {
1382 256 : val = (float)(CAL_A0 * sin(CAL_W0 * k * Ts) + CAL_A1 * sin(CAL_W1 * k * Ts));
1383 256 : data = (unsigned short)((val * CAL_SCALE_FACTOR) + CONST_2048);
1384 256 : time_management_regs->calData = data & CAL_DATA_MASK;
1385 : }
1386 1 : }
1387 :
1388 0 : void setCalibrationReload(bool state)
1389 : {
1390 1 : if (state == true)
1391 : {
1392 2 : time_management_regs->calDACCtrl
1393 1 : = time_management_regs->calDACCtrl | BIT_CAL_RELOAD; // [0001 0000]
1394 : }
1395 : else
1396 : {
1397 0 : time_management_regs->calDACCtrl
1398 0 : = time_management_regs->calDACCtrl & MASK_CAL_RELOAD; // [1110 1111]
1399 : }
1400 0 : }
1401 :
1402 0 : void setCalibrationEnable(bool state)
1403 : {
1404 : // this bit drives the multiplexer
1405 1 : if (state == true)
1406 : {
1407 0 : time_management_regs->calDACCtrl
1408 0 : = time_management_regs->calDACCtrl | BIT_CAL_ENABLE; // [0100 0000]
1409 : }
1410 : else
1411 : {
1412 2 : time_management_regs->calDACCtrl
1413 1 : = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1414 : }
1415 0 : }
1416 :
1417 :
1418 1 : void setCalibration(bool state)
1419 : {
1420 1 : if (state == true)
1421 : {
1422 : setCalibrationEnable(true);
1423 : setCalibrationReload(false);
1424 0 : set_hk_lfr_calib_enable(true);
1425 : }
1426 : else
1427 : {
1428 : setCalibrationEnable(false);
1429 : setCalibrationReload(true);
1430 1 : set_hk_lfr_calib_enable(false);
1431 : }
1432 1 : }
1433 :
1434 1 : void configureCalibration()
1435 : {
1436 1 : setCalibration(false);
1437 : setCalibrationPrescaler(0); // 25 MHz => 25 000 000
1438 : setCalibrationDivisor(CAL_F_DIVISOR); // => 160 256 (39 - 1)
1439 1 : setCalibrationData();
1440 1 : }
1441 :
1442 : //****************
1443 : // CLOSING ACTIONS
1444 26 : void update_last_TC_exe(const ccsdsTelecommandPacket_t* const TC, const unsigned char* const time)
1445 : {
1446 : /** This function is used to update the HK packets statistics after a successful TC execution.
1447 : *
1448 : * @param TC points to the TC being processed
1449 : * @param time is the time used to date the TC execution
1450 : *
1451 : */
1452 :
1453 : unsigned int val;
1454 :
1455 26 : housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1456 26 : housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1457 26 : housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1458 26 : housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1459 26 : housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1460 26 : housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1461 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1462 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1463 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1464 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1465 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1466 26 : housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1467 :
1468 52 : val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256)
1469 26 : + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1470 26 : val++;
1471 26 : housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char)(val >> SHIFT_1_BYTE);
1472 26 : housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char)(val);
1473 26 : }
1474 :
1475 1 : void update_last_TC_rej(const ccsdsTelecommandPacket_t* const TC, const unsigned char* const time)
1476 : {
1477 : /** This function is used to update the HK packets statistics after a TC rejection.
1478 : *
1479 : * @param TC points to the TC being processed
1480 : * @param time is the time used to date the TC rejection
1481 : *
1482 : */
1483 :
1484 : unsigned int val;
1485 :
1486 1 : housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1487 1 : housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1488 1 : housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1489 1 : housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1490 1 : housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1491 1 : housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1492 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1493 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1494 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1495 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1496 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1497 1 : housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1498 :
1499 2 : val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256)
1500 1 : + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1501 1 : val++;
1502 1 : housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char)(val >> SHIFT_1_BYTE);
1503 1 : housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char)(val);
1504 1 : }
1505 :
1506 27 : void close_action(const ccsdsTelecommandPacket_t* const TC, int result, rtems_id queue_id)
1507 : {
1508 : /** This function is the last step of the TC execution workflow.
1509 : *
1510 : * @param TC points to the TC being processed
1511 : * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1512 : * @param queue_id is the id of the RTEMS message queue used to send TM packets
1513 : * @param time is the time used to date the TC execution
1514 : *
1515 : */
1516 :
1517 : unsigned char requestedMode;
1518 :
1519 27 : if (result == LFR_SUCCESSFUL)
1520 : {
1521 52 : if (!((TC->serviceType == TC_TYPE_TIME) & (TC->serviceSubType == TC_SUBTYPE_UPDT_TIME))
1522 26 : & !((TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_UPDT_INFO)))
1523 : {
1524 26 : send_tm_lfr_tc_exe_success(TC, queue_id);
1525 : }
1526 26 : if ((TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER))
1527 : {
1528 : //**********************************
1529 : // UPDATE THE LFRMODE LOCAL VARIABLE
1530 5 : requestedMode = TC->dataAndCRC[1];
1531 5 : updateLFRCurrentMode(requestedMode);
1532 : }
1533 : }
1534 1 : else if (result == LFR_EXE_ERROR)
1535 : {
1536 0 : send_tm_lfr_tc_exe_error(TC, queue_id);
1537 : }
1538 27 : }
1539 :
1540 : //****************
1541 : // OTHER FUNCTIONS
1542 1 : void updateLFRCurrentMode(unsigned char requestedMode)
1543 : {
1544 : /** This function updates the value of the global variable lfrCurrentMode.
1545 : *
1546 : * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1547 : *
1548 : */
1549 :
1550 : // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet
1551 : // structure
1552 6 : housekeeping_packet.lfr_status_word[0]
1553 6 : = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1554 : + (unsigned char)(requestedMode << STATUS_WORD_LFR_MODE_SHIFT);
1555 6 : lfrCurrentMode = requestedMode;
1556 1 : }
1557 :
1558 0 : void set_lfr_soft_reset(unsigned char value)
1559 : {
1560 8 : if (value == 1)
1561 : {
1562 4 : time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1563 : }
1564 : else
1565 : {
1566 4 : time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1567 : }
1568 0 : }
1569 :
1570 4 : void reset_lfr(void)
1571 : {
1572 : set_lfr_soft_reset(1);
1573 :
1574 : set_lfr_soft_reset(0);
1575 :
1576 4 : set_hk_lfr_sc_potential_flag(true);
1577 4 : }
|