GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/tc_handler.c Lines: 384 564 68.1 %
Date: 2018-10-05 11:31:25 Branches: 110 240 45.8 %

Line Branch Exec Source
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 "tc_handler.h"
37
#include "math.h"
38
39
//***********
40
// RTEMS TASK
41
42
1
rtems_task actn_task( rtems_task_argument unused )
43
{
44
    /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
45
     *
46
     * @param unused is the starting argument of the RTEMS task
47
     *
48
     * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
49
     * on the incoming TeleCommand.
50
     *
51
     */
52
53
    int result;
54
    rtems_status_code status;       // RTEMS status code
55
    ccsdsTelecommandPacket_t __attribute__((aligned(4))) TC;    // TC sent to the ACTN task
56
    size_t size;                    // size of the incoming TC packet
57
    unsigned char subtype;          // subtype of the current TC packet
58
    unsigned char time[BYTES_PER_TIME];
59
    rtems_id queue_rcv_id;
60
    rtems_id queue_snd_id;
61
62
1
    memset(&TC, 0, sizeof(ccsdsTelecommandPacket_t));
63
1
    size = 0;
64
1
    queue_rcv_id = RTEMS_ID_NONE;
65
1
    queue_snd_id = RTEMS_ID_NONE;
66
67
1
    status =  get_message_queue_id_recv( &queue_rcv_id );
68
    if (status != RTEMS_SUCCESSFUL)
69
    {
70
        PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
71
    }
72
73
1
    status =  get_message_queue_id_send( &queue_snd_id );
74
    if (status != RTEMS_SUCCESSFUL)
75
    {
76
        PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
77
    }
78
79
1
    result = LFR_SUCCESSFUL;
80
1
    subtype = 0;          // subtype of the current TC packet
81
82
    BOOT_PRINTF("in ACTN *** \n");
83
84
    while(1)
85
    {
86
64
        status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
87
                                              RTEMS_WAIT, RTEMS_NO_TIMEOUT);
88
64
        getTime( time );    // set time to the current time
89
64
        if (status!=RTEMS_SUCCESSFUL)
90
        {
91
            PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
92
        }
93
        else
94
        {
95
64
            subtype = TC.serviceSubType;
96




64
            switch(subtype)
97
            {
98
            case TC_SUBTYPE_RESET:
99
1
                result = action_reset( &TC, queue_snd_id, time );
100
                close_action( &TC, result, queue_snd_id );
101
                break;
102
            case TC_SUBTYPE_LOAD_COMM:
103
                result = action_load_common_par( &TC );
104
                close_action( &TC, result, queue_snd_id );
105
                break;
106
            case TC_SUBTYPE_LOAD_NORM:
107
                result = action_load_normal_par( &TC, queue_snd_id, time );
108
                close_action( &TC, result, queue_snd_id );
109
                break;
110
            case TC_SUBTYPE_LOAD_BURST:
111
                result = action_load_burst_par( &TC, queue_snd_id, time );
112
                close_action( &TC, result, queue_snd_id );
113
                break;
114
            case TC_SUBTYPE_LOAD_SBM1:
115
                result = action_load_sbm1_par( &TC, queue_snd_id, time );
116
                close_action( &TC, result, queue_snd_id );
117
                break;
118
            case TC_SUBTYPE_LOAD_SBM2:
119
                result = action_load_sbm2_par( &TC, queue_snd_id, time );
120
                close_action( &TC, result, queue_snd_id );
121
                break;
122
            case TC_SUBTYPE_DUMP:
123
26
                result = action_dump_par( &TC,  queue_snd_id );
124
26
                close_action( &TC, result, queue_snd_id );
125
26
                break;
126
            case TC_SUBTYPE_ENTER:
127
12
                result = action_enter_mode( &TC, queue_snd_id );
128
12
                close_action( &TC, result, queue_snd_id );
129
12
                break;
130
            case TC_SUBTYPE_UPDT_INFO:
131
                result = action_update_info( &TC, queue_snd_id );
132
                close_action( &TC, result, queue_snd_id );
133
                break;
134
            case TC_SUBTYPE_EN_CAL:
135
                result = action_enable_calibration( &TC, queue_snd_id, time );
136
                close_action( &TC, result, queue_snd_id );
137
                break;
138
            case TC_SUBTYPE_DIS_CAL:
139
                result = action_disable_calibration( &TC, queue_snd_id, time );
140
                close_action( &TC, result, queue_snd_id );
141
                break;
142
            case TC_SUBTYPE_LOAD_K:
143
                result = action_load_kcoefficients( &TC, queue_snd_id, time );
144
                close_action( &TC, result, queue_snd_id );
145
                break;
146
            case TC_SUBTYPE_DUMP_K:
147
                result = action_dump_kcoefficients( &TC, queue_snd_id, time );
148
                close_action( &TC, result, queue_snd_id );
149
                break;
150
            case TC_SUBTYPE_LOAD_FBINS:
151
                result = action_load_fbins_mask( &TC, queue_snd_id, time );
152
                close_action( &TC, result, queue_snd_id );
153
                break;
154
            case TC_SUBTYPE_LOAD_FILTER_PAR:
155
25
                result = action_load_filter_par( &TC, queue_snd_id, time );
156
25
                close_action( &TC, result, queue_snd_id );
157
25
                break;
158
            case TC_SUBTYPE_UPDT_TIME:
159
                result = action_update_time( &TC );
160
                close_action( &TC, result, queue_snd_id );
161
                break;
162
            default:
163
                break;
164
            }
165
        }
166
    }
167
}
168
169
//***********
170
// TC ACTIONS
171
172
1
int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
173
{
174
    /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
175
     *
176
     * @param TC points to the TeleCommand packet that is being processed
177
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
178
     *
179
     */
180
181
    PRINTF("this is the end!!!\n");
182
1
    exit(0);
183
184
    send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
185
186
    return LFR_DEFAULT;
187
}
188
189
12
int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
190
{
191
    /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
192
     *
193
     * @param TC points to the TeleCommand packet that is being processed
194
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
195
     *
196
     */
197
198
    rtems_status_code status;
199
    unsigned char requestedMode;
200
    unsigned int transitionCoarseTime;
201
    unsigned char * bytePosPtr;
202
203
12
    bytePosPtr = (unsigned char *) &TC->packetID;
204
12
    requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
205
12
    copyInt32ByChar( (char*) &transitionCoarseTime, &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
206
12
    transitionCoarseTime = transitionCoarseTime & COARSE_TIME_MASK;
207
12
    status = check_mode_value( requestedMode );
208
209
12
    if ( status != LFR_SUCCESSFUL )     // the mode value is inconsistent
210
    {
211
        send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
212
    }
213
214
    else                                // the mode value is valid, check the transition
215
    {
216
12
        status = check_mode_transition(requestedMode);
217
12
        if (status != LFR_SUCCESSFUL)
218
        {
219
            PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
220
2
                    send_tm_lfr_tc_exe_not_executable( TC, queue_id );
221
        }
222
    }
223
224
12
    if ( status == LFR_SUCCESSFUL )     // the transition is valid, check the date
225
    {
226
10
        status = check_transition_date( transitionCoarseTime );
227
10
        if (status != LFR_SUCCESSFUL)
228
        {
229
            PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
230
            send_tm_lfr_tc_exe_not_executable(TC, queue_id );
231
        }
232
    }
233
234
12
    if ( status == LFR_SUCCESSFUL )     // the date is valid, enter the mode
235
    {
236
        PRINTF1("OK  *** in action_enter_mode *** enter mode %d\n", requestedMode);
237
238

10
        switch(requestedMode)
239
        {
240
        case LFR_MODE_STANDBY:
241
2
            status = enter_mode_standby();
242
2
            break;
243
        case LFR_MODE_NORMAL:
244
2
            status = enter_mode_normal( transitionCoarseTime );
245
2
            break;
246
        case LFR_MODE_BURST:
247
2
            status = enter_mode_burst( transitionCoarseTime );
248
2
            break;
249
        case LFR_MODE_SBM1:
250
2
            status = enter_mode_sbm1( transitionCoarseTime );
251
2
            break;
252
        case LFR_MODE_SBM2:
253
2
            status = enter_mode_sbm2( transitionCoarseTime );
254
            break;
255
        default:
256
            break;
257
        }
258
259
10
        if (status != RTEMS_SUCCESSFUL)
260
        {
261
            status = LFR_EXE_ERROR;
262
        }
263
    }
264
265
12
    return status;
266
}
267
268
int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
269
{
270
    /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
271
     *
272
     * @param TC points to the TeleCommand packet that is being processed
273
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
274
     *
275
     * @return LFR directive status code:
276
     * - LFR_DEFAULT
277
     * - LFR_SUCCESSFUL
278
     *
279
     */
280
281
    unsigned int val;
282
    unsigned int status;
283
    unsigned char mode;
284
    unsigned char * bytePosPtr;
285
    int pos;
286
    float value;
287
288
    pos = INIT_CHAR;
289
    value = INIT_FLOAT;
290
291
    status = LFR_DEFAULT;
292
293
    bytePosPtr = (unsigned char *) &TC->packetID;
294
295
    // check LFR mode
296
    mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
297
    status = check_update_info_hk_lfr_mode( mode );
298
    if (status == LFR_SUCCESSFUL)  // check TDS mode
299
    {
300
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
301
        status = check_update_info_hk_tds_mode( mode );
302
    }
303
    if (status == LFR_SUCCESSFUL)  // check THR mode
304
    {
305
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_THR_MODE);
306
        status = check_update_info_hk_thr_mode( mode );
307
    }
308
    if (status == LFR_SUCCESSFUL) // check reaction wheels frequencies
309
    {
310
        status = check_all_sy_lfr_rw_f(TC, &pos, &value);
311
    }
312
313
    // if the parameters checking succeeds, udpate all parameters
314
    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
        pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & BITS_BIA; // [1111 1110]
324
        pa_bia_status_info = pa_bia_status_info
325
                | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 1);
326
327
        // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be copied in HK packets)
328
        getReactionWheelsFrequencies( TC );
329
        set_hk_lfr_sc_rw_f_flags();
330
        build_sy_lfr_rw_masks();
331
332
        // once the masks are built, they have to be merged with the fbins_mask
333
        merge_fbins_masks();
334
335
        // increase the TC_LFR_UPDATE_INFO counter
336
        if (status == LFR_SUCCESSFUL)  // if the parameter check is successful
337
        {
338
            val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
339
                    + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
340
            val++;
341
            housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
342
            housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
343
        }
344
    }
345
346
    return status;
347
}
348
349
int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
350
{
351
    /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
352
     *
353
     * @param TC points to the TeleCommand packet that is being processed
354
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
355
     *
356
     */
357
358
    int result;
359
360
    result = LFR_DEFAULT;
361
362
    setCalibration( true );
363
364
    result = LFR_SUCCESSFUL;
365
366
    return result;
367
}
368
369
int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
370
{
371
    /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
372
     *
373
     * @param TC points to the TeleCommand packet that is being processed
374
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
375
     *
376
     */
377
378
    int result;
379
380
    result = LFR_DEFAULT;
381
382
    setCalibration( false );
383
384
    result = LFR_SUCCESSFUL;
385
386
    return result;
387
}
388
389
int action_update_time(ccsdsTelecommandPacket_t *TC)
390
{
391
    /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
392
     *
393
     * @param TC points to the TeleCommand packet that is being processed
394
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
395
     *
396
     * @return LFR_SUCCESSFUL
397
     *
398
     */
399
400
    unsigned int val;
401
402
    time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
403
            + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES)
404
            + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
405
            + TC->dataAndCRC[BYTE_3];
406
407
    val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
408
            + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
409
    val++;
410
    housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
411
    housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
412
413
    oneTcLfrUpdateTimeReceived = 1;
414
415
    return LFR_SUCCESSFUL;
416
}
417
418
//*******************
419
// ENTERING THE MODES
420
12
int check_mode_value( unsigned char requestedMode )
421
{
422
    int status;
423
424
12
    status = LFR_DEFAULT;
425
426
12
    if ( (requestedMode != LFR_MODE_STANDBY)
427
         && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
428
         && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
429
    {
430
        status = LFR_DEFAULT;
431
    }
432
    else
433
    {
434
12
        status = LFR_SUCCESSFUL;
435
    }
436
437
12
    return status;
438
}
439
440
12
int check_mode_transition( unsigned char requestedMode )
441
{
442
    /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
443
     *
444
     * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
445
     *
446
     * @return LFR directive status codes:
447
     * - LFR_SUCCESSFUL - the transition is authorized
448
     * - LFR_DEFAULT - the transition is not authorized
449
     *
450
     */
451
452
    int status;
453
454

12
    switch (requestedMode)
455
    {
456
    case LFR_MODE_STANDBY:
457
4
        if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
458
2
            status = LFR_DEFAULT;
459
        }
460
        else
461
        {
462
2
            status = LFR_SUCCESSFUL;
463
        }
464
        break;
465
    case LFR_MODE_NORMAL:
466
2
        if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
467
            status = LFR_DEFAULT;
468
        }
469
        else {
470
2
            status = LFR_SUCCESSFUL;
471
        }
472
        break;
473
    case LFR_MODE_BURST:
474
2
        if ( lfrCurrentMode == LFR_MODE_BURST ) {
475
            status = LFR_DEFAULT;
476
        }
477
        else {
478
2
            status = LFR_SUCCESSFUL;
479
        }
480
        break;
481
    case LFR_MODE_SBM1:
482
2
        if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
483
            status = LFR_DEFAULT;
484
        }
485
        else {
486
2
            status = LFR_SUCCESSFUL;
487
        }
488
        break;
489
    case LFR_MODE_SBM2:
490
2
        if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
491
            status = LFR_DEFAULT;
492
        }
493
        else {
494
2
            status = LFR_SUCCESSFUL;
495
        }
496
        break;
497
    default:
498
        status = LFR_DEFAULT;
499
        break;
500
    }
501
502
12
    return status;
503
}
504
505
9
void update_last_valid_transition_date( unsigned int transitionCoarseTime )
506
{
507
9
    if (transitionCoarseTime == 0)
508
    {
509
2
        lastValidEnterModeTime = time_management_regs->coarse_time + 1;
510
        PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", lastValidEnterModeTime);
511
    }
512
    else
513
    {
514
7
        lastValidEnterModeTime = transitionCoarseTime;
515
        PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
516
    }
517
9
}
518
519
10
int check_transition_date( unsigned int transitionCoarseTime )
520
{
521
    int status;
522
    unsigned int localCoarseTime;
523
    unsigned int deltaCoarseTime;
524
525
10
    status = LFR_SUCCESSFUL;
526
527
10
    if (transitionCoarseTime == 0)  // transition time = 0 means an instant transition
528
    {
529
10
        status = LFR_SUCCESSFUL;
530
    }
531
    else
532
    {
533
        localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
534
535
        PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
536
537
        if ( transitionCoarseTime <= localCoarseTime )   // SSS-CP-EQS-322
538
        {
539
            status = LFR_DEFAULT;
540
            PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
541
        }
542
543
        if (status == LFR_SUCCESSFUL)
544
        {
545
            deltaCoarseTime = transitionCoarseTime - localCoarseTime;
546
            if ( deltaCoarseTime > MAX_DELTA_COARSE_TIME )  // SSS-CP-EQS-323
547
            {
548
                status = LFR_DEFAULT;
549
                PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
550
            }
551
        }
552
    }
553
554
10
    return status;
555
}
556
557
2
int restart_asm_activities( unsigned char lfrRequestedMode )
558
{
559
    rtems_status_code status;
560
561
2
    status = stop_spectral_matrices();
562
563
2
    thisIsAnASMRestart = 1;
564
565
2
    status = restart_asm_tasks( lfrRequestedMode );
566
567
2
    launch_spectral_matrix();
568
569
2
    return status;
570
}
571
572
2
int stop_spectral_matrices( void )
573
{
574
    /** This function stops and restarts the current mode average spectral matrices activities.
575
     *
576
     * @return RTEMS directive status codes:
577
     * - RTEMS_SUCCESSFUL - task restarted successfully
578
     * - RTEMS_INVALID_ID - task id invalid
579
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
580
     *
581
     */
582
583
    rtems_status_code status;
584
585
2
    status = RTEMS_SUCCESSFUL;
586
587
    // (1) mask interruptions
588
2
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // mask spectral matrix interrupt
589
590
    // (2) reset spectral matrices registers
591
2
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
592
2
    reset_sm_status();
593
594
    // (3) clear interruptions
595
2
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
596
597
    // suspend several tasks
598
2
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
599
2
        status = suspend_asm_tasks();
600
    }
601
602
    if (status != RTEMS_SUCCESSFUL)
603
    {
604
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
605
    }
606
607
2
    return status;
608
}
609
610
6
int stop_current_mode( void )
611
{
612
    /** This function stops the current mode by masking interrupt lines and suspending science tasks.
613
     *
614
     * @return RTEMS directive status codes:
615
     * - RTEMS_SUCCESSFUL - task restarted successfully
616
     * - RTEMS_INVALID_ID - task id invalid
617
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
618
     *
619
     */
620
621
    rtems_status_code status;
622
623
6
    status = RTEMS_SUCCESSFUL;
624
625
    // (1) mask interruptions
626
6
    LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER );     // mask waveform picker interrupt
627
6
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // clear spectral matrix interrupt
628
629
    // (2) reset waveform picker registers
630
6
    reset_wfp_burst_enable();                       // reset burst and enable bits
631
6
    reset_wfp_status();                             // reset all the status bits
632
633
    // (3) reset spectral matrices registers
634
6
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
635
6
    reset_sm_status();
636
637
    // reset lfr VHDL module
638
6
    reset_lfr();
639
640
6
    reset_extractSWF();                             // reset the extractSWF flag to false
641
642
    // (4) clear interruptions
643
6
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );    // clear waveform picker interrupt
644
6
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
645
646
    // suspend several tasks
647
6
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
648
6
        status = suspend_science_tasks();
649
    }
650
651
    if (status != RTEMS_SUCCESSFUL)
652
    {
653
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
654
    }
655
656
6
    return status;
657
}
658
659
2
int enter_mode_standby( void )
660
{
661
    /** This function is used to put LFR in the STANDBY mode.
662
     *
663
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
664
     *
665
     * @return RTEMS directive status codes:
666
     * - RTEMS_SUCCESSFUL - task restarted successfully
667
     * - RTEMS_INVALID_ID - task id invalid
668
     * - RTEMS_INCORRECT_STATE - task never started
669
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
670
     *
671
     * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
672
     * is immediate.
673
     *
674
     */
675
676
    int status;
677
678
2
    status = stop_current_mode();       // STOP THE CURRENT MODE
679
680
#ifdef PRINT_TASK_STATISTICS
681
    rtems_cpu_usage_report();
682
#endif
683
684
#ifdef PRINT_STACK_REPORT
685
    PRINTF("stack report selected\n")
686
    rtems_stack_checker_report_usage();
687
#endif
688
689
2
    return status;
690
}
691
692
2
int enter_mode_normal( unsigned int transitionCoarseTime )
693
{
694
    /** This function is used to start the NORMAL mode.
695
     *
696
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
697
     *
698
     * @return RTEMS directive status codes:
699
     * - RTEMS_SUCCESSFUL - task restarted successfully
700
     * - RTEMS_INVALID_ID - task id invalid
701
     * - RTEMS_INCORRECT_STATE - task never started
702
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
703
     *
704
     * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
705
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
706
     *
707
     */
708
709
    int status;
710
711
#ifdef PRINT_TASK_STATISTICS
712
    rtems_cpu_usage_reset();
713
#endif
714
715
2
    status = RTEMS_UNSATISFIED;
716
717

2
    switch( lfrCurrentMode )
718
    {
719
    case LFR_MODE_STANDBY:
720
2
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
721
2
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
722
        {
723
2
            launch_spectral_matrix( );
724
2
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
725
        }
726
        break;
727
    case LFR_MODE_BURST:
728
        status = stop_current_mode();           // stop the current mode
729
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
730
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
731
        {
732
            launch_spectral_matrix( );
733
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
734
        }
735
        break;
736
    case LFR_MODE_SBM1:
737
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
738
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
739
        update_last_valid_transition_date( transitionCoarseTime );
740
        break;
741
    case LFR_MODE_SBM2:
742
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
743
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
744
        update_last_valid_transition_date( transitionCoarseTime );
745
        break;
746
    default:
747
        break;
748
    }
749
750
2
    if (status != RTEMS_SUCCESSFUL)
751
    {
752
        PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
753
                status = RTEMS_UNSATISFIED;
754
    }
755
756
2
    return status;
757
}
758
759
2
int enter_mode_burst( unsigned int transitionCoarseTime )
760
{
761
    /** This function is used to start the BURST mode.
762
     *
763
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
764
     *
765
     * @return RTEMS directive status codes:
766
     * - RTEMS_SUCCESSFUL - task restarted successfully
767
     * - RTEMS_INVALID_ID - task id invalid
768
     * - RTEMS_INCORRECT_STATE - task never started
769
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
770
     *
771
     * The way the BURST mode is started does not depend on the LFR current mode.
772
     *
773
     */
774
775
776
    int status;
777
778
#ifdef PRINT_TASK_STATISTICS
779
    rtems_cpu_usage_reset();
780
#endif
781
782
2
    status = stop_current_mode();           // stop the current mode
783
2
    status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
784
2
    if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
785
    {
786
2
        launch_spectral_matrix( );
787
2
        launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
788
    }
789
790
2
    if (status != RTEMS_SUCCESSFUL)
791
    {
792
        PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
793
                status = RTEMS_UNSATISFIED;
794
    }
795
796
2
    return status;
797
}
798
799
2
int enter_mode_sbm1( unsigned int transitionCoarseTime )
800
{
801
    /** This function is used to start the SBM1 mode.
802
     *
803
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
804
     *
805
     * @return RTEMS directive status codes:
806
     * - RTEMS_SUCCESSFUL - task restarted successfully
807
     * - RTEMS_INVALID_ID - task id invalid
808
     * - RTEMS_INCORRECT_STATE - task never started
809
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
810
     *
811
     * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
812
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
813
     * cases, the acquisition is completely restarted.
814
     *
815
     */
816
817
    int status;
818
819
#ifdef PRINT_TASK_STATISTICS
820
    rtems_cpu_usage_reset();
821
#endif
822
823
2
    status = RTEMS_UNSATISFIED;
824
825

2
    switch( lfrCurrentMode )
826
    {
827
    case LFR_MODE_STANDBY:
828
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
829
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
830
        {
831
            launch_spectral_matrix( );
832
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
833
        }
834
        break;
835
    case LFR_MODE_NORMAL:                       // lfrCurrentMode will be updated after the execution of close_action
836
        status = restart_asm_activities( LFR_MODE_SBM1 );
837
        status = LFR_SUCCESSFUL;
838
        update_last_valid_transition_date( transitionCoarseTime );
839
        break;
840
    case LFR_MODE_BURST:
841
2
        status = stop_current_mode();           // stop the current mode
842
2
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
843
2
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
844
        {
845
2
            launch_spectral_matrix( );
846
2
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
847
        }
848
        break;
849
    case LFR_MODE_SBM2:
850
        status = restart_asm_activities( LFR_MODE_SBM1 );
851
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
852
        update_last_valid_transition_date( transitionCoarseTime );
853
        break;
854
    default:
855
        break;
856
    }
857
858
2
    if (status != RTEMS_SUCCESSFUL)
859
    {
860
        PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
861
        status = RTEMS_UNSATISFIED;
862
    }
863
864
2
    return status;
865
}
866
867
2
int enter_mode_sbm2( unsigned int transitionCoarseTime )
868
{
869
    /** This function is used to start the SBM2 mode.
870
     *
871
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
872
     *
873
     * @return RTEMS directive status codes:
874
     * - RTEMS_SUCCESSFUL - task restarted successfully
875
     * - RTEMS_INVALID_ID - task id invalid
876
     * - RTEMS_INCORRECT_STATE - task never started
877
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
878
     *
879
     * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
880
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
881
     * cases, the acquisition is completely restarted.
882
     *
883
     */
884
885
    int status;
886
887
#ifdef PRINT_TASK_STATISTICS
888
    rtems_cpu_usage_reset();
889
#endif
890
891
2
    status = RTEMS_UNSATISFIED;
892
893

2
    switch( lfrCurrentMode )
894
    {
895
    case LFR_MODE_STANDBY:
896
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
897
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
898
        {
899
            launch_spectral_matrix( );
900
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
901
        }
902
        break;
903
    case LFR_MODE_NORMAL:
904
        status = restart_asm_activities( LFR_MODE_SBM2 );
905
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
906
        update_last_valid_transition_date( transitionCoarseTime );
907
        break;
908
    case LFR_MODE_BURST:
909
        status = stop_current_mode();           // stop the current mode
910
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
911
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
912
        {
913
            launch_spectral_matrix( );
914
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
915
        }
916
        break;
917
    case LFR_MODE_SBM1:
918
2
        status = restart_asm_activities( LFR_MODE_SBM2 );
919
2
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
920
2
        update_last_valid_transition_date( transitionCoarseTime );
921
        break;
922
    default:
923
        break;
924
    }
925
926
2
    if (status != RTEMS_SUCCESSFUL)
927
    {
928
        PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
929
                status = RTEMS_UNSATISFIED;
930
    }
931
932
2
    return status;
933
}
934
935
6
int restart_science_tasks( unsigned char lfrRequestedMode )
936
{
937
    /** This function is used to restart all science tasks.
938
     *
939
     * @return RTEMS directive status codes:
940
     * - RTEMS_SUCCESSFUL - task restarted successfully
941
     * - RTEMS_INVALID_ID - task id invalid
942
     * - RTEMS_INCORRECT_STATE - task never started
943
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
944
     *
945
     * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
946
     *
947
     */
948
949
    rtems_status_code status[NB_SCIENCE_TASKS];
950
    rtems_status_code ret;
951
952
6
    ret = RTEMS_SUCCESSFUL;
953
954
6
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
955
6
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
956
    {
957
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
958
    }
959
960
6
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
961
6
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
962
    {
963
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
964
    }
965
966
6
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
967
6
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
968
    {
969
        PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[STATUS_2])
970
    }
971
972
6
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
973
6
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
974
    {
975
        PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[STATUS_3])
976
    }
977
978
6
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
979
6
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
980
    {
981
        PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[STATUS_4])
982
    }
983
984
6
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
985
6
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
986
    {
987
        PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[STATUS_5])
988
    }
989
990
6
    status[STATUS_6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
991
6
    if (status[STATUS_6] != RTEMS_SUCCESSFUL)
992
    {
993
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_6])
994
    }
995
996
6
    status[STATUS_7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
997
6
    if (status[STATUS_7] != RTEMS_SUCCESSFUL)
998
    {
999
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_7])
1000
    }
1001
1002
6
    status[STATUS_8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1003
6
    if (status[STATUS_8] != RTEMS_SUCCESSFUL)
1004
    {
1005
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_8])
1006
    }
1007
1008
6
    status[STATUS_9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1009
6
    if (status[STATUS_9] != RTEMS_SUCCESSFUL)
1010
    {
1011
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_9])
1012
    }
1013
1014





54
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1015
12
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1016
12
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) ||
1017
12
         (status[STATUS_6] != RTEMS_SUCCESSFUL) || (status[STATUS_7] != RTEMS_SUCCESSFUL) ||
1018
12
         (status[STATUS_8] != RTEMS_SUCCESSFUL) || (status[STATUS_9] != RTEMS_SUCCESSFUL) )
1019
    {
1020
        ret = RTEMS_UNSATISFIED;
1021
    }
1022
1023
6
    return ret;
1024
}
1025
1026
2
int restart_asm_tasks( unsigned char lfrRequestedMode )
1027
{
1028
    /** This function is used to restart average spectral matrices tasks.
1029
     *
1030
     * @return RTEMS directive status codes:
1031
     * - RTEMS_SUCCESSFUL - task restarted successfully
1032
     * - RTEMS_INVALID_ID - task id invalid
1033
     * - RTEMS_INCORRECT_STATE - task never started
1034
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1035
     *
1036
     * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1037
     *
1038
     */
1039
1040
    rtems_status_code status[NB_ASM_TASKS];
1041
    rtems_status_code ret;
1042
1043
2
    ret = RTEMS_SUCCESSFUL;
1044
1045
2
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
1046
2
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
1047
    {
1048
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
1049
    }
1050
1051
2
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
1052
2
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
1053
    {
1054
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
1055
    }
1056
1057
2
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
1058
2
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
1059
    {
1060
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_2])
1061
    }
1062
1063
2
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1064
2
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
1065
    {
1066
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_3])
1067
    }
1068
1069
2
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1070
2
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
1071
    {
1072
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_4])
1073
    }
1074
1075
2
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1076
2
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
1077
    {
1078
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_5])
1079
    }
1080
1081



10
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1082
4
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1083
4
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) )
1084
    {
1085
        ret = RTEMS_UNSATISFIED;
1086
    }
1087
1088
2
    return ret;
1089
}
1090
1091
7
int suspend_science_tasks( void )
1092
{
1093
    /** This function suspends the science tasks.
1094
     *
1095
     * @return RTEMS directive status codes:
1096
     * - RTEMS_SUCCESSFUL - task restarted successfully
1097
     * - RTEMS_INVALID_ID - task id invalid
1098
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1099
     *
1100
     */
1101
1102
    rtems_status_code status;
1103
1104
    PRINTF("in suspend_science_tasks\n")
1105
1106
7
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1107
7
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1108
    {
1109
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1110
    }
1111
    else
1112
    {
1113
7
        status = RTEMS_SUCCESSFUL;
1114
    }
1115
7
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1116
    {
1117
7
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1118
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1119
        {
1120
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1121
        }
1122
        else
1123
        {
1124
7
            status = RTEMS_SUCCESSFUL;
1125
        }
1126
    }
1127
7
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1128
    {
1129
7
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1130
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1131
        {
1132
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1133
        }
1134
        else
1135
        {
1136
7
            status = RTEMS_SUCCESSFUL;
1137
        }
1138
    }
1139
7
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1140
    {
1141
7
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1142
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1143
        {
1144
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1145
        }
1146
        else
1147
        {
1148
7
            status = RTEMS_SUCCESSFUL;
1149
        }
1150
    }
1151
7
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1152
    {
1153
7
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1154
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1155
        {
1156
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1157
        }
1158
        else
1159
        {
1160
7
            status = RTEMS_SUCCESSFUL;
1161
        }
1162
    }
1163
7
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1164
    {
1165
7
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1166
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1167
        {
1168
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1169
        }
1170
        else
1171
        {
1172
7
            status = RTEMS_SUCCESSFUL;
1173
        }
1174
    }
1175
7
    if (status == RTEMS_SUCCESSFUL)        // suspend WFRM
1176
    {
1177
7
        status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1178
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1179
        {
1180
            PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1181
        }
1182
        else
1183
        {
1184
7
            status = RTEMS_SUCCESSFUL;
1185
        }
1186
    }
1187
7
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF3
1188
    {
1189
7
        status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1190
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1191
        {
1192
            PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1193
        }
1194
        else
1195
        {
1196
7
            status = RTEMS_SUCCESSFUL;
1197
        }
1198
    }
1199
7
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF2
1200
    {
1201
7
        status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1202
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1203
        {
1204
            PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1205
        }
1206
        else
1207
        {
1208
7
            status = RTEMS_SUCCESSFUL;
1209
        }
1210
    }
1211
7
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF1
1212
    {
1213
7
        status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1214
7
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1215
        {
1216
            PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1217
        }
1218
        else
1219
        {
1220
7
            status = RTEMS_SUCCESSFUL;
1221
        }
1222
    }
1223
1224
7
    return status;
1225
}
1226
1227
2
int suspend_asm_tasks( void )
1228
{
1229
    /** This function suspends the science tasks.
1230
     *
1231
     * @return RTEMS directive status codes:
1232
     * - RTEMS_SUCCESSFUL - task restarted successfully
1233
     * - RTEMS_INVALID_ID - task id invalid
1234
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1235
     *
1236
     */
1237
1238
    rtems_status_code status;
1239
1240
    PRINTF("in suspend_science_tasks\n")
1241
1242
2
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1243
2
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1244
    {
1245
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1246
    }
1247
    else
1248
    {
1249
2
        status = RTEMS_SUCCESSFUL;
1250
    }
1251
1252
2
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1253
    {
1254
2
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1255
2
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1256
        {
1257
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1258
        }
1259
        else
1260
        {
1261
2
            status = RTEMS_SUCCESSFUL;
1262
        }
1263
    }
1264
1265
2
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1266
    {
1267
2
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1268
2
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1269
        {
1270
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1271
        }
1272
        else
1273
        {
1274
2
            status = RTEMS_SUCCESSFUL;
1275
        }
1276
    }
1277
1278
2
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1279
    {
1280
2
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1281
2
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1282
        {
1283
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1284
        }
1285
        else
1286
        {
1287
2
            status = RTEMS_SUCCESSFUL;
1288
        }
1289
    }
1290
1291
2
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1292
    {
1293
2
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1294
2
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1295
        {
1296
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1297
        }
1298
        else
1299
        {
1300
2
            status = RTEMS_SUCCESSFUL;
1301
        }
1302
    }
1303
1304
2
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1305
    {
1306
2
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1307
2
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1308
        {
1309
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1310
        }
1311
        else
1312
        {
1313
2
            status = RTEMS_SUCCESSFUL;
1314
        }
1315
    }
1316
1317
2
    return status;
1318
}
1319
1320
6
void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1321
{
1322
1323
6
    WFP_reset_current_ring_nodes();
1324
1325
6
    reset_waveform_picker_regs();
1326
1327
6
    set_wfp_burst_enable_register( mode );
1328
1329
6
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1330
6
    LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1331
1332
6
    if (transitionCoarseTime == 0)
1333
    {
1334
        // instant transition means transition on the next valid date
1335
        // this is mandatory to have a good snapshot period and a good correction of the snapshot period
1336
6
        waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1337
    }
1338
    else
1339
    {
1340
        waveform_picker_regs->start_date = transitionCoarseTime;
1341
    }
1342
1343
6
    update_last_valid_transition_date(waveform_picker_regs->start_date);
1344
1345
6
}
1346
1347
8
void launch_spectral_matrix( void )
1348
{
1349
8
    SM_reset_current_ring_nodes();
1350
1351
8
    reset_spectral_matrix_regs();
1352
1353
8
    reset_nb_sm();
1354
1355
8
    set_sm_irq_onNewMatrix( 1 );
1356
1357
8
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1358
8
    LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1359
1360
8
}
1361
1362
25
void set_sm_irq_onNewMatrix( unsigned char value )
1363
{
1364
25
    if (value == 1)
1365
    {
1366
8
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1367
    }
1368
    else
1369
    {
1370
17
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX;   // 1110
1371
    }
1372
25
}
1373
1374
9
void set_sm_irq_onError( unsigned char value )
1375
{
1376
9
    if (value == 1)
1377
    {
1378
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1379
    }
1380
    else
1381
    {
1382
9
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR;   // 1101
1383
    }
1384
9
}
1385
1386
//*****************************
1387
// CONFIGURE CALIBRATION SIGNAL
1388
1
void setCalibrationPrescaler( unsigned int prescaler )
1389
{
1390
    // prescaling of the master clock (25 MHz)
1391
    // master clock is divided by 2^prescaler
1392
1
    time_management_regs->calPrescaler = prescaler;
1393
1
}
1394
1395
1
void setCalibrationDivisor( unsigned int divisionFactor )
1396
{
1397
    // division of the prescaled clock by the division factor
1398
1
    time_management_regs->calDivisor = divisionFactor;
1399
1
}
1400
1401
1
void setCalibrationData( void )
1402
{
1403
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1404
     *
1405
     * @param void
1406
     *
1407
     * @return void
1408
     *
1409
     */
1410
1411
    unsigned int k;
1412
    unsigned short data;
1413
    float val;
1414
    float Ts;
1415
1416
1
    time_management_regs->calDataPtr = INIT_CHAR;
1417
1418
1
    Ts = 1 / CAL_FS;
1419
1420
    // build the signal for the SCM calibration
1421
257
    for (k = 0; k < CAL_NB_PTS; k++)
1422
    {
1423
512
        val = CAL_A0 *  sin( CAL_W0 * k * Ts )
1424
256
                        + CAL_A1 * sin(  CAL_W1 * k * Ts );
1425
256
        data = (unsigned short) ((val * CAL_SCALE_FACTOR) + CONST_2048);
1426
256
        time_management_regs->calData = data & CAL_DATA_MASK;
1427
    }
1428
1
}
1429
1430
void setCalibrationDataInterleaved( void )
1431
{
1432
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1433
     *
1434
     * @param void
1435
     *
1436
     * @return void
1437
     *
1438
     * In interleaved mode, one can store more values than in normal mode.
1439
     * The data are stored in bunch of 18 bits, 12 bits from one sample and 6 bits from another sample.
1440
     * T store 3 values, one need two write operations.
1441
     * s1 [ b11 b10 b9 b8 b7 b6 ] s0 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1442
     * s1 [ b5  b4  b3 b2 b1 b0 ] s2 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1443
     *
1444
     */
1445
1446
    unsigned int k;
1447
    float val;
1448
    float Ts;
1449
    unsigned short data[CAL_NB_PTS_INTER];
1450
    unsigned char *dataPtr;
1451
1452
    Ts = 1 / CAL_FS_INTER;
1453
1454
    time_management_regs->calDataPtr = INIT_CHAR;
1455
1456
    // build the signal for the SCM calibration
1457
    for (k=0; k<CAL_NB_PTS_INTER; k++)
1458
    {
1459
        val = sin( 2 * pi * CAL_F0 * k * Ts )
1460
                + sin(  2 * pi * CAL_F1 * k * Ts );
1461
        data[k] = (unsigned short) ((val * CONST_512) + CONST_2048);
1462
    }
1463
1464
    // write the signal in interleaved mode
1465
    for (k=0; k < STEPS_FOR_STORAGE_INTER; k++)
1466
    {
1467
        dataPtr = (unsigned char*) &data[ (k * BYTES_FOR_2_SAMPLES) + 2 ];
1468
        time_management_regs->calData = ( data[ k * BYTES_FOR_2_SAMPLES ]     & CAL_DATA_MASK )
1469
                + ( (dataPtr[0] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1470
        time_management_regs->calData = ( data[(k * BYTES_FOR_2_SAMPLES) + 1] & CAL_DATA_MASK )
1471
                + ( (dataPtr[1] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1472
    }
1473
}
1474
1475
1
void setCalibrationReload( bool state)
1476
{
1477
1
    if (state == true)
1478
    {
1479
1
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_RELOAD;   // [0001 0000]
1480
    }
1481
    else
1482
    {
1483
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_RELOAD;   // [1110 1111]
1484
    }
1485
1
}
1486
1487
1
void setCalibrationEnable( bool state )
1488
{
1489
    // this bit drives the multiplexer
1490
1
    if (state == true)
1491
    {
1492
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_ENABLE;   // [0100 0000]
1493
    }
1494
    else
1495
    {
1496
1
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1497
    }
1498
1
}
1499
1500
void setCalibrationInterleaved( bool state )
1501
{
1502
    // this bit drives the multiplexer
1503
    if (state == true)
1504
    {
1505
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_SET_INTERLEAVED;   // [0010 0000]
1506
    }
1507
    else
1508
    {
1509
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_SET_INTERLEAVED; // [1101 1111]
1510
    }
1511
}
1512
1513
1
void setCalibration( bool state )
1514
{
1515
1
    if (state == true)
1516
    {
1517
        setCalibrationEnable( true );
1518
        setCalibrationReload( false );
1519
        set_hk_lfr_calib_enable( true );
1520
    }
1521
    else
1522
    {
1523
1
        setCalibrationEnable( false );
1524
1
        setCalibrationReload( true );
1525
1
        set_hk_lfr_calib_enable( false );
1526
    }
1527
1
}
1528
1529
1
void configureCalibration( bool interleaved )
1530
{
1531
1
    setCalibration( false );
1532
1
    if ( interleaved == true )
1533
    {
1534
        setCalibrationInterleaved( true );
1535
        setCalibrationPrescaler( 0 );                   // 25 MHz   => 25 000 000
1536
        setCalibrationDivisor( CAL_F_DIVISOR_INTER );   //          => 240 384
1537
        setCalibrationDataInterleaved();
1538
    }
1539
    else
1540
    {
1541
1
        setCalibrationPrescaler( 0 );           // 25 MHz   => 25 000 000
1542
1
        setCalibrationDivisor( CAL_F_DIVISOR ); //          => 160 256 (39 - 1)
1543
1
        setCalibrationData();
1544
    }
1545
1
}
1546
1547
//****************
1548
// CLOSING ACTIONS
1549
61
void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1550
{
1551
    /** This function is used to update the HK packets statistics after a successful TC execution.
1552
     *
1553
     * @param TC points to the TC being processed
1554
     * @param time is the time used to date the TC execution
1555
     *
1556
     */
1557
1558
    unsigned int val;
1559
1560
61
    housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1561
61
    housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1562
61
    housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1563
61
    housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1564
61
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1565
61
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1566
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1567
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1568
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1569
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1570
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1571
61
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1572
1573
61
    val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1574
61
    val++;
1575
61
    housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1576
61
    housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1577
61
}
1578
1579
2
void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1580
{
1581
    /** This function is used to update the HK packets statistics after a TC rejection.
1582
     *
1583
     * @param TC points to the TC being processed
1584
     * @param time is the time used to date the TC rejection
1585
     *
1586
     */
1587
1588
    unsigned int val;
1589
1590
2
    housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1591
2
    housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1592
2
    housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1593
2
    housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1594
2
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1595
2
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1596
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1597
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1598
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1599
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1600
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1601
2
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1602
1603
2
    val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1604
2
    val++;
1605
2
    housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1606
2
    housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1607
2
}
1608
1609
63
void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1610
{
1611
    /** This function is the last step of the TC execution workflow.
1612
     *
1613
     * @param TC points to the TC being processed
1614
     * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1615
     * @param queue_id is the id of the RTEMS message queue used to send TM packets
1616
     * @param time is the time used to date the TC execution
1617
     *
1618
     */
1619
1620
    unsigned char requestedMode;
1621
1622
63
    if (result == LFR_SUCCESSFUL)
1623
    {
1624
122
        if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1625
             &
1626
61
             !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1627
             )
1628
        {
1629
61
            send_tm_lfr_tc_exe_success( TC, queue_id );
1630
        }
1631
61
        if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1632
        {
1633
            //**********************************
1634
            // UPDATE THE LFRMODE LOCAL VARIABLE
1635
10
            requestedMode = TC->dataAndCRC[1];
1636
10
            updateLFRCurrentMode( requestedMode );
1637
        }
1638
    }
1639
2
    else if (result == LFR_EXE_ERROR)
1640
    {
1641
        send_tm_lfr_tc_exe_error( TC, queue_id );
1642
    }
1643
63
}
1644
1645
//***************************
1646
// Interrupt Service Routines
1647
rtems_isr commutation_isr1( rtems_vector_number vector )
1648
{
1649
    if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1650
        PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1651
    }
1652
}
1653
1654
rtems_isr commutation_isr2( rtems_vector_number vector )
1655
{
1656
    if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1657
        PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1658
    }
1659
}
1660
1661
//****************
1662
// OTHER FUNCTIONS
1663
11
void updateLFRCurrentMode( unsigned char requestedMode )
1664
{
1665
    /** This function updates the value of the global variable lfrCurrentMode.
1666
     *
1667
     * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1668
     *
1669
     */
1670
1671
    // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1672
11
    housekeeping_packet.lfr_status_word[0] = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1673
            + (unsigned char) ( requestedMode << STATUS_WORD_LFR_MODE_SHIFT );
1674
11
    lfrCurrentMode = requestedMode;
1675
11
}
1676
1677
14
void set_lfr_soft_reset( unsigned char value )
1678
{
1679
14
    if (value == 1)
1680
    {
1681
7
        time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1682
    }
1683
    else
1684
    {
1685
7
        time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1686
    }
1687
14
}
1688
1689
7
void reset_lfr( void )
1690
{
1691
7
    set_lfr_soft_reset( 1 );
1692
1693
7
    set_lfr_soft_reset( 0 );
1694
1695
7
    set_hk_lfr_sc_potential_flag( true );
1696
7
}