GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/tc_handler.c Lines: 120 559 21.5 %
Date: 2018-10-22 12:27:55 Branches: 32 240 13.3 %

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
1
        status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
87
                                              RTEMS_WAIT, RTEMS_NO_TIMEOUT);
88
1
        getTime( time );    // set time to the current time
89
1
        if (status!=RTEMS_SUCCESSFUL)
90
        {
91
            PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
92
        }
93
        else
94
        {
95
1
            subtype = TC.serviceSubType;
96




1
            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
                result = action_dump_par( &TC,  queue_snd_id );
124
                close_action( &TC, result, queue_snd_id );
125
                break;
126
            case TC_SUBTYPE_ENTER:
127
                result = action_enter_mode( &TC, queue_snd_id );
128
                close_action( &TC, result, queue_snd_id );
129
                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
                result = action_load_filter_par( &TC, queue_snd_id, time );
156
                close_action( &TC, result, queue_snd_id );
157
                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
#ifdef GCOV_ENABLED
183
#ifndef GCOV_USE_EXIT
184
    extern void gcov_exit (void);
185
    gcov_exit();
186
#endif
187
#endif
188
1
    exit(0);
189
190
    send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
191
192
    return LFR_DEFAULT;
193
}
194
195
int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
196
{
197
    /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
198
     *
199
     * @param TC points to the TeleCommand packet that is being processed
200
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
201
     *
202
     */
203
204
    rtems_status_code status;
205
    unsigned char requestedMode;
206
    unsigned int transitionCoarseTime;
207
    unsigned char * bytePosPtr;
208
209
    bytePosPtr = (unsigned char *) &TC->packetID;
210
    requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
211
    copyInt32ByChar( (char*) &transitionCoarseTime, &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
212
    transitionCoarseTime = transitionCoarseTime & COARSE_TIME_MASK;
213
    status = check_mode_value( requestedMode );
214
215
    if ( status != LFR_SUCCESSFUL )     // the mode value is inconsistent
216
    {
217
        send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
218
    }
219
220
    else                                // the mode value is valid, check the transition
221
    {
222
        status = check_mode_transition(requestedMode);
223
        if (status != LFR_SUCCESSFUL)
224
        {
225
            PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
226
                    send_tm_lfr_tc_exe_not_executable( TC, queue_id );
227
        }
228
    }
229
230
    if ( status == LFR_SUCCESSFUL )     // the transition is valid, check the date
231
    {
232
        status = check_transition_date( transitionCoarseTime );
233
        if (status != LFR_SUCCESSFUL)
234
        {
235
            PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
236
            send_tm_lfr_tc_exe_not_executable(TC, queue_id );
237
        }
238
    }
239
240
    if ( status == LFR_SUCCESSFUL )     // the date is valid, enter the mode
241
    {
242
        PRINTF1("OK  *** in action_enter_mode *** enter mode %d\n", requestedMode);
243
244
        switch(requestedMode)
245
        {
246
        case LFR_MODE_STANDBY:
247
            status = enter_mode_standby();
248
            break;
249
        case LFR_MODE_NORMAL:
250
            status = enter_mode_normal( transitionCoarseTime );
251
            break;
252
        case LFR_MODE_BURST:
253
            status = enter_mode_burst( transitionCoarseTime );
254
            break;
255
        case LFR_MODE_SBM1:
256
            status = enter_mode_sbm1( transitionCoarseTime );
257
            break;
258
        case LFR_MODE_SBM2:
259
            status = enter_mode_sbm2( transitionCoarseTime );
260
            break;
261
        default:
262
            break;
263
        }
264
265
        if (status != RTEMS_SUCCESSFUL)
266
        {
267
            status = LFR_EXE_ERROR;
268
        }
269
    }
270
271
    return status;
272
}
273
274
int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
275
{
276
    /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
277
     *
278
     * @param TC points to the TeleCommand packet that is being processed
279
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
280
     *
281
     * @return LFR directive status code:
282
     * - LFR_DEFAULT
283
     * - LFR_SUCCESSFUL
284
     *
285
     */
286
287
    unsigned int val;
288
    unsigned int status;
289
    unsigned char mode;
290
    unsigned char * bytePosPtr;
291
    int pos;
292
    float value;
293
294
    pos = INIT_CHAR;
295
    value = INIT_FLOAT;
296
297
    status = LFR_DEFAULT;
298
299
    bytePosPtr = (unsigned char *) &TC->packetID;
300
301
    // check LFR mode
302
    mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
303
    status = check_update_info_hk_lfr_mode( mode );
304
    if (status == LFR_SUCCESSFUL)  // check TDS mode
305
    {
306
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
307
        status = check_update_info_hk_tds_mode( mode );
308
    }
309
    if (status == LFR_SUCCESSFUL)  // check THR mode
310
    {
311
        mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_THR_MODE);
312
        status = check_update_info_hk_thr_mode( mode );
313
    }
314
    if (status == LFR_SUCCESSFUL) // check reaction wheels frequencies
315
    {
316
        status = check_all_sy_lfr_rw_f(TC, &pos, &value);
317
    }
318
319
    // if the parameters checking succeeds, udpate all parameters
320
    if (status == LFR_SUCCESSFUL)
321
    {
322
        // pa_bia_status_info
323
        // => pa_bia_mode_mux_set       3 bits
324
        // => pa_bia_mode_hv_enabled    1 bit
325
        // => pa_bia_mode_bias1_enabled 1 bit
326
        // => pa_bia_mode_bias2_enabled 1 bit
327
        // => pa_bia_mode_bias3_enabled 1 bit
328
        // => pa_bia_on_off (cp_dpu_bias_on_off)
329
        pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & BITS_BIA; // [1111 1110]
330
        pa_bia_status_info = pa_bia_status_info
331
                | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 1);
332
333
        // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be copied in HK packets)
334
        getReactionWheelsFrequencies( TC );
335
        set_hk_lfr_sc_rw_f_flags();
336
        build_sy_lfr_rw_masks();
337
338
        // once the masks are built, they have to be merged with the fbins_mask
339
        merge_fbins_masks();
340
341
        // increase the TC_LFR_UPDATE_INFO counter
342
        if (status == LFR_SUCCESSFUL)  // if the parameter check is successful
343
        {
344
            val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
345
                    + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
346
            val++;
347
            housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
348
            housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
349
        }
350
    }
351
352
    return status;
353
}
354
355
int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
356
{
357
    /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
358
     *
359
     * @param TC points to the TeleCommand packet that is being processed
360
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
361
     *
362
     */
363
364
    int result;
365
366
    result = LFR_DEFAULT;
367
368
    setCalibration( true );
369
370
    result = LFR_SUCCESSFUL;
371
372
    return result;
373
}
374
375
int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
376
{
377
    /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
378
     *
379
     * @param TC points to the TeleCommand packet that is being processed
380
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
381
     *
382
     */
383
384
    int result;
385
386
    result = LFR_DEFAULT;
387
388
    setCalibration( false );
389
390
    result = LFR_SUCCESSFUL;
391
392
    return result;
393
}
394
395
int action_update_time(ccsdsTelecommandPacket_t *TC)
396
{
397
    /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
398
     *
399
     * @param TC points to the TeleCommand packet that is being processed
400
     * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
401
     *
402
     * @return LFR_SUCCESSFUL
403
     *
404
     */
405
406
    unsigned int val;
407
408
    time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
409
            + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES)
410
            + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
411
            + TC->dataAndCRC[BYTE_3];
412
413
    val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
414
            + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
415
    val++;
416
    housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
417
    housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
418
419
    oneTcLfrUpdateTimeReceived = 1;
420
421
    return LFR_SUCCESSFUL;
422
}
423
424
//*******************
425
// ENTERING THE MODES
426
int check_mode_value( unsigned char requestedMode )
427
{
428
    int status;
429
430
    status = LFR_DEFAULT;
431
432
    if ( (requestedMode != LFR_MODE_STANDBY)
433
         && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
434
         && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
435
    {
436
        status = LFR_DEFAULT;
437
    }
438
    else
439
    {
440
        status = LFR_SUCCESSFUL;
441
    }
442
443
    return status;
444
}
445
446
int check_mode_transition( unsigned char requestedMode )
447
{
448
    /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
449
     *
450
     * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
451
     *
452
     * @return LFR directive status codes:
453
     * - LFR_SUCCESSFUL - the transition is authorized
454
     * - LFR_DEFAULT - the transition is not authorized
455
     *
456
     */
457
458
    int status;
459
460
    switch (requestedMode)
461
    {
462
    case LFR_MODE_STANDBY:
463
        if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
464
            status = LFR_DEFAULT;
465
        }
466
        else
467
        {
468
            status = LFR_SUCCESSFUL;
469
        }
470
        break;
471
    case LFR_MODE_NORMAL:
472
        if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
473
            status = LFR_DEFAULT;
474
        }
475
        else {
476
            status = LFR_SUCCESSFUL;
477
        }
478
        break;
479
    case LFR_MODE_BURST:
480
        if ( lfrCurrentMode == LFR_MODE_BURST ) {
481
            status = LFR_DEFAULT;
482
        }
483
        else {
484
            status = LFR_SUCCESSFUL;
485
        }
486
        break;
487
    case LFR_MODE_SBM1:
488
        if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
489
            status = LFR_DEFAULT;
490
        }
491
        else {
492
            status = LFR_SUCCESSFUL;
493
        }
494
        break;
495
    case LFR_MODE_SBM2:
496
        if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
497
            status = LFR_DEFAULT;
498
        }
499
        else {
500
            status = LFR_SUCCESSFUL;
501
        }
502
        break;
503
    default:
504
        status = LFR_DEFAULT;
505
        break;
506
    }
507
508
    return status;
509
}
510
511
1
void update_last_valid_transition_date( unsigned int transitionCoarseTime )
512
{
513
1
    if (transitionCoarseTime == 0)
514
    {
515
        lastValidEnterModeTime = time_management_regs->coarse_time + 1;
516
        PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", lastValidEnterModeTime);
517
    }
518
    else
519
    {
520
1
        lastValidEnterModeTime = transitionCoarseTime;
521
        PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
522
    }
523
1
}
524
525
int check_transition_date( unsigned int transitionCoarseTime )
526
{
527
    int status;
528
    unsigned int localCoarseTime;
529
    unsigned int deltaCoarseTime;
530
531
    status = LFR_SUCCESSFUL;
532
533
    if (transitionCoarseTime == 0)  // transition time = 0 means an instant transition
534
    {
535
        status = LFR_SUCCESSFUL;
536
    }
537
    else
538
    {
539
        localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
540
541
        PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
542
543
        if ( transitionCoarseTime <= localCoarseTime )   // SSS-CP-EQS-322
544
        {
545
            status = LFR_DEFAULT;
546
            PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
547
        }
548
549
        if (status == LFR_SUCCESSFUL)
550
        {
551
            deltaCoarseTime = transitionCoarseTime - localCoarseTime;
552
            if ( deltaCoarseTime > MAX_DELTA_COARSE_TIME )  // SSS-CP-EQS-323
553
            {
554
                status = LFR_DEFAULT;
555
                PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
556
            }
557
        }
558
    }
559
560
    return status;
561
}
562
563
int restart_asm_activities( unsigned char lfrRequestedMode )
564
{
565
    rtems_status_code status;
566
567
    status = stop_spectral_matrices();
568
569
    thisIsAnASMRestart = 1;
570
571
    status = restart_asm_tasks( lfrRequestedMode );
572
573
    launch_spectral_matrix();
574
575
    return status;
576
}
577
578
int stop_spectral_matrices( void )
579
{
580
    /** This function stops and restarts the current mode average spectral matrices activities.
581
     *
582
     * @return RTEMS directive status codes:
583
     * - RTEMS_SUCCESSFUL - task restarted successfully
584
     * - RTEMS_INVALID_ID - task id invalid
585
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
586
     *
587
     */
588
589
    rtems_status_code status;
590
591
    status = RTEMS_SUCCESSFUL;
592
593
    // (1) mask interruptions
594
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // mask spectral matrix interrupt
595
596
    // (2) reset spectral matrices registers
597
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
598
    reset_sm_status();
599
600
    // (3) clear interruptions
601
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
602
603
    // suspend several tasks
604
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
605
        status = suspend_asm_tasks();
606
    }
607
608
    if (status != RTEMS_SUCCESSFUL)
609
    {
610
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
611
    }
612
613
    return status;
614
}
615
616
int stop_current_mode( void )
617
{
618
    /** This function stops the current mode by masking interrupt lines and suspending science tasks.
619
     *
620
     * @return RTEMS directive status codes:
621
     * - RTEMS_SUCCESSFUL - task restarted successfully
622
     * - RTEMS_INVALID_ID - task id invalid
623
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
624
     *
625
     */
626
627
    rtems_status_code status;
628
629
    status = RTEMS_SUCCESSFUL;
630
631
    // (1) mask interruptions
632
    LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER );     // mask waveform picker interrupt
633
    LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX );     // clear spectral matrix interrupt
634
635
    // (2) reset waveform picker registers
636
    reset_wfp_burst_enable();                       // reset burst and enable bits
637
    reset_wfp_status();                             // reset all the status bits
638
639
    // (3) reset spectral matrices registers
640
    set_sm_irq_onNewMatrix( 0 );                    // stop the spectral matrices
641
    reset_sm_status();
642
643
    // reset lfr VHDL module
644
    reset_lfr();
645
646
    reset_extractSWF();                             // reset the extractSWF flag to false
647
648
    // (4) clear interruptions
649
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );    // clear waveform picker interrupt
650
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );    // clear spectral matrix interrupt
651
652
    // suspend several tasks
653
    if (lfrCurrentMode != LFR_MODE_STANDBY) {
654
        status = suspend_science_tasks();
655
    }
656
657
    if (status != RTEMS_SUCCESSFUL)
658
    {
659
        PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
660
    }
661
662
    return status;
663
}
664
665
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 TC_LFR_ENTER_MODE
670
     *
671
     * @return RTEMS directive status codes:
672
     * - RTEMS_SUCCESSFUL - task restarted successfully
673
     * - RTEMS_INVALID_ID - task id invalid
674
     * - RTEMS_INCORRECT_STATE - task never started
675
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
676
     *
677
     * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
678
     * is immediate.
679
     *
680
     */
681
682
    int status;
683
684
    status = stop_current_mode();       // STOP THE CURRENT MODE
685
686
#ifdef PRINT_TASK_STATISTICS
687
    rtems_cpu_usage_report();
688
#endif
689
690
#ifdef PRINT_STACK_REPORT
691
    PRINTF("stack report selected\n")
692
    rtems_stack_checker_report_usage();
693
#endif
694
695
    return status;
696
}
697
698
int enter_mode_normal( unsigned int transitionCoarseTime )
699
{
700
    /** This function is used to start the NORMAL mode.
701
     *
702
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
703
     *
704
     * @return RTEMS directive status codes:
705
     * - RTEMS_SUCCESSFUL - task restarted successfully
706
     * - RTEMS_INVALID_ID - task id invalid
707
     * - RTEMS_INCORRECT_STATE - task never started
708
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
709
     *
710
     * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
711
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
712
     *
713
     */
714
715
    int status;
716
717
#ifdef PRINT_TASK_STATISTICS
718
    rtems_cpu_usage_reset();
719
#endif
720
721
    status = RTEMS_UNSATISFIED;
722
723
    switch( lfrCurrentMode )
724
    {
725
    case LFR_MODE_STANDBY:
726
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
727
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
728
        {
729
            launch_spectral_matrix( );
730
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
731
        }
732
        break;
733
    case LFR_MODE_BURST:
734
        status = stop_current_mode();           // stop the current mode
735
        status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
736
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
737
        {
738
            launch_spectral_matrix( );
739
            launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
740
        }
741
        break;
742
    case LFR_MODE_SBM1:
743
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
744
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
745
        update_last_valid_transition_date( transitionCoarseTime );
746
        break;
747
    case LFR_MODE_SBM2:
748
        status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
749
        status = LFR_SUCCESSFUL;                   // lfrCurrentMode will be updated after the execution of close_action
750
        update_last_valid_transition_date( transitionCoarseTime );
751
        break;
752
    default:
753
        break;
754
    }
755
756
    if (status != RTEMS_SUCCESSFUL)
757
    {
758
        PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
759
                status = RTEMS_UNSATISFIED;
760
    }
761
762
    return status;
763
}
764
765
int enter_mode_burst( unsigned int transitionCoarseTime )
766
{
767
    /** This function is used to start the BURST mode.
768
     *
769
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
770
     *
771
     * @return RTEMS directive status codes:
772
     * - RTEMS_SUCCESSFUL - task restarted successfully
773
     * - RTEMS_INVALID_ID - task id invalid
774
     * - RTEMS_INCORRECT_STATE - task never started
775
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
776
     *
777
     * The way the BURST mode is started does not depend on the LFR current mode.
778
     *
779
     */
780
781
782
    int status;
783
784
#ifdef PRINT_TASK_STATISTICS
785
    rtems_cpu_usage_reset();
786
#endif
787
788
    status = stop_current_mode();           // stop the current mode
789
    status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
790
    if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
791
    {
792
        launch_spectral_matrix( );
793
        launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
794
    }
795
796
    if (status != RTEMS_SUCCESSFUL)
797
    {
798
        PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
799
                status = RTEMS_UNSATISFIED;
800
    }
801
802
    return status;
803
}
804
805
int enter_mode_sbm1( unsigned int transitionCoarseTime )
806
{
807
    /** This function is used to start the SBM1 mode.
808
     *
809
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
810
     *
811
     * @return RTEMS directive status codes:
812
     * - RTEMS_SUCCESSFUL - task restarted successfully
813
     * - RTEMS_INVALID_ID - task id invalid
814
     * - RTEMS_INCORRECT_STATE - task never started
815
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
816
     *
817
     * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
818
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
819
     * cases, the acquisition is completely restarted.
820
     *
821
     */
822
823
    int status;
824
825
#ifdef PRINT_TASK_STATISTICS
826
    rtems_cpu_usage_reset();
827
#endif
828
829
    status = RTEMS_UNSATISFIED;
830
831
    switch( lfrCurrentMode )
832
    {
833
    case LFR_MODE_STANDBY:
834
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
835
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
836
        {
837
            launch_spectral_matrix( );
838
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
839
        }
840
        break;
841
    case LFR_MODE_NORMAL:                       // lfrCurrentMode will be updated after the execution of close_action
842
        status = restart_asm_activities( LFR_MODE_SBM1 );
843
        status = LFR_SUCCESSFUL;
844
        update_last_valid_transition_date( transitionCoarseTime );
845
        break;
846
    case LFR_MODE_BURST:
847
        status = stop_current_mode();           // stop the current mode
848
        status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
849
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
850
        {
851
            launch_spectral_matrix( );
852
            launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
853
        }
854
        break;
855
    case LFR_MODE_SBM2:
856
        status = restart_asm_activities( LFR_MODE_SBM1 );
857
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
858
        update_last_valid_transition_date( transitionCoarseTime );
859
        break;
860
    default:
861
        break;
862
    }
863
864
    if (status != RTEMS_SUCCESSFUL)
865
    {
866
        PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
867
        status = RTEMS_UNSATISFIED;
868
    }
869
870
    return status;
871
}
872
873
int enter_mode_sbm2( unsigned int transitionCoarseTime )
874
{
875
    /** This function is used to start the SBM2 mode.
876
     *
877
     * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
878
     *
879
     * @return RTEMS directive status codes:
880
     * - RTEMS_SUCCESSFUL - task restarted successfully
881
     * - RTEMS_INVALID_ID - task id invalid
882
     * - RTEMS_INCORRECT_STATE - task never started
883
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
884
     *
885
     * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
886
     * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
887
     * cases, the acquisition is completely restarted.
888
     *
889
     */
890
891
    int status;
892
893
#ifdef PRINT_TASK_STATISTICS
894
    rtems_cpu_usage_reset();
895
#endif
896
897
    status = RTEMS_UNSATISFIED;
898
899
    switch( lfrCurrentMode )
900
    {
901
    case LFR_MODE_STANDBY:
902
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
903
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
904
        {
905
            launch_spectral_matrix( );
906
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
907
        }
908
        break;
909
    case LFR_MODE_NORMAL:
910
        status = restart_asm_activities( LFR_MODE_SBM2 );
911
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
912
        update_last_valid_transition_date( transitionCoarseTime );
913
        break;
914
    case LFR_MODE_BURST:
915
        status = stop_current_mode();           // stop the current mode
916
        status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
917
        if (status == RTEMS_SUCCESSFUL)         // relaunch spectral_matrix and waveform_picker modules
918
        {
919
            launch_spectral_matrix( );
920
            launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
921
        }
922
        break;
923
    case LFR_MODE_SBM1:
924
        status = restart_asm_activities( LFR_MODE_SBM2 );
925
        status = LFR_SUCCESSFUL;                // lfrCurrentMode will be updated after the execution of close_action
926
        update_last_valid_transition_date( transitionCoarseTime );
927
        break;
928
    default:
929
        break;
930
    }
931
932
    if (status != RTEMS_SUCCESSFUL)
933
    {
934
        PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
935
                status = RTEMS_UNSATISFIED;
936
    }
937
938
    return status;
939
}
940
941
int restart_science_tasks( unsigned char lfrRequestedMode )
942
{
943
    /** This function is used to restart all science tasks.
944
     *
945
     * @return RTEMS directive status codes:
946
     * - RTEMS_SUCCESSFUL - task restarted successfully
947
     * - RTEMS_INVALID_ID - task id invalid
948
     * - RTEMS_INCORRECT_STATE - task never started
949
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
950
     *
951
     * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
952
     *
953
     */
954
955
    rtems_status_code status[NB_SCIENCE_TASKS];
956
    rtems_status_code ret;
957
958
    ret = RTEMS_SUCCESSFUL;
959
960
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
961
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
962
    {
963
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
964
    }
965
966
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
967
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
968
    {
969
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
970
    }
971
972
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
973
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
974
    {
975
        PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[STATUS_2])
976
    }
977
978
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
979
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
980
    {
981
        PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[STATUS_3])
982
    }
983
984
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
985
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
986
    {
987
        PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[STATUS_4])
988
    }
989
990
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
991
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
992
    {
993
        PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[STATUS_5])
994
    }
995
996
    status[STATUS_6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
997
    if (status[STATUS_6] != RTEMS_SUCCESSFUL)
998
    {
999
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_6])
1000
    }
1001
1002
    status[STATUS_7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1003
    if (status[STATUS_7] != RTEMS_SUCCESSFUL)
1004
    {
1005
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_7])
1006
    }
1007
1008
    status[STATUS_8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1009
    if (status[STATUS_8] != RTEMS_SUCCESSFUL)
1010
    {
1011
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_8])
1012
    }
1013
1014
    status[STATUS_9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1015
    if (status[STATUS_9] != RTEMS_SUCCESSFUL)
1016
    {
1017
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_9])
1018
    }
1019
1020
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1021
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1022
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) ||
1023
         (status[STATUS_6] != RTEMS_SUCCESSFUL) || (status[STATUS_7] != RTEMS_SUCCESSFUL) ||
1024
         (status[STATUS_8] != RTEMS_SUCCESSFUL) || (status[STATUS_9] != RTEMS_SUCCESSFUL) )
1025
    {
1026
        ret = RTEMS_UNSATISFIED;
1027
    }
1028
1029
    return ret;
1030
}
1031
1032
int restart_asm_tasks( unsigned char lfrRequestedMode )
1033
{
1034
    /** This function is used to restart average spectral matrices tasks.
1035
     *
1036
     * @return RTEMS directive status codes:
1037
     * - RTEMS_SUCCESSFUL - task restarted successfully
1038
     * - RTEMS_INVALID_ID - task id invalid
1039
     * - RTEMS_INCORRECT_STATE - task never started
1040
     * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1041
     *
1042
     * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1043
     *
1044
     */
1045
1046
    rtems_status_code status[NB_ASM_TASKS];
1047
    rtems_status_code ret;
1048
1049
    ret = RTEMS_SUCCESSFUL;
1050
1051
    status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
1052
    if (status[STATUS_0] != RTEMS_SUCCESSFUL)
1053
    {
1054
        PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
1055
    }
1056
1057
    status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
1058
    if (status[STATUS_1] != RTEMS_SUCCESSFUL)
1059
    {
1060
        PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
1061
    }
1062
1063
    status[STATUS_2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
1064
    if (status[STATUS_2] != RTEMS_SUCCESSFUL)
1065
    {
1066
        PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_2])
1067
    }
1068
1069
    status[STATUS_3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1070
    if (status[STATUS_3] != RTEMS_SUCCESSFUL)
1071
    {
1072
        PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_3])
1073
    }
1074
1075
    status[STATUS_4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1076
    if (status[STATUS_4] != RTEMS_SUCCESSFUL)
1077
    {
1078
        PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_4])
1079
    }
1080
1081
    status[STATUS_5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1082
    if (status[STATUS_5] != RTEMS_SUCCESSFUL)
1083
    {
1084
        PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_5])
1085
    }
1086
1087
    if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1088
         (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1089
         (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) )
1090
    {
1091
        ret = RTEMS_UNSATISFIED;
1092
    }
1093
1094
    return ret;
1095
}
1096
1097
1
int suspend_science_tasks( void )
1098
{
1099
    /** This function suspends the science tasks.
1100
     *
1101
     * @return RTEMS directive status codes:
1102
     * - RTEMS_SUCCESSFUL - task restarted successfully
1103
     * - RTEMS_INVALID_ID - task id invalid
1104
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1105
     *
1106
     */
1107
1108
    rtems_status_code status;
1109
1110
    PRINTF("in suspend_science_tasks\n")
1111
1112
1
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1113
1
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1114
    {
1115
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1116
    }
1117
    else
1118
    {
1119
1
        status = RTEMS_SUCCESSFUL;
1120
    }
1121
1
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1122
    {
1123
1
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1124
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1125
        {
1126
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1127
        }
1128
        else
1129
        {
1130
1
            status = RTEMS_SUCCESSFUL;
1131
        }
1132
    }
1133
1
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1134
    {
1135
1
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1136
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1137
        {
1138
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1139
        }
1140
        else
1141
        {
1142
1
            status = RTEMS_SUCCESSFUL;
1143
        }
1144
    }
1145
1
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1146
    {
1147
1
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1148
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1149
        {
1150
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1151
        }
1152
        else
1153
        {
1154
1
            status = RTEMS_SUCCESSFUL;
1155
        }
1156
    }
1157
1
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1158
    {
1159
1
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1160
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1161
        {
1162
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1163
        }
1164
        else
1165
        {
1166
1
            status = RTEMS_SUCCESSFUL;
1167
        }
1168
    }
1169
1
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1170
    {
1171
1
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1172
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1173
        {
1174
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1175
        }
1176
        else
1177
        {
1178
1
            status = RTEMS_SUCCESSFUL;
1179
        }
1180
    }
1181
1
    if (status == RTEMS_SUCCESSFUL)        // suspend WFRM
1182
    {
1183
1
        status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1184
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1185
        {
1186
            PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1187
        }
1188
        else
1189
        {
1190
1
            status = RTEMS_SUCCESSFUL;
1191
        }
1192
    }
1193
1
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF3
1194
    {
1195
1
        status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1196
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1197
        {
1198
            PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1199
        }
1200
        else
1201
        {
1202
1
            status = RTEMS_SUCCESSFUL;
1203
        }
1204
    }
1205
1
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF2
1206
    {
1207
1
        status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1208
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1209
        {
1210
            PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1211
        }
1212
        else
1213
        {
1214
1
            status = RTEMS_SUCCESSFUL;
1215
        }
1216
    }
1217
1
    if (status == RTEMS_SUCCESSFUL)        // suspend CWF1
1218
    {
1219
1
        status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1220
1
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1221
        {
1222
            PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1223
        }
1224
        else
1225
        {
1226
1
            status = RTEMS_SUCCESSFUL;
1227
        }
1228
    }
1229
1230
1
    return status;
1231
}
1232
1233
int suspend_asm_tasks( void )
1234
{
1235
    /** This function suspends the science tasks.
1236
     *
1237
     * @return RTEMS directive status codes:
1238
     * - RTEMS_SUCCESSFUL - task restarted successfully
1239
     * - RTEMS_INVALID_ID - task id invalid
1240
     * - RTEMS_ALREADY_SUSPENDED - task already suspended
1241
     *
1242
     */
1243
1244
    rtems_status_code status;
1245
1246
    PRINTF("in suspend_science_tasks\n")
1247
1248
            status = rtems_task_suspend( Task_id[TASKID_AVF0] );    // suspend AVF0
1249
    if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1250
    {
1251
        PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1252
    }
1253
    else
1254
    {
1255
        status = RTEMS_SUCCESSFUL;
1256
    }
1257
1258
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC0
1259
    {
1260
        status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1261
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1262
        {
1263
            PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1264
        }
1265
        else
1266
        {
1267
            status = RTEMS_SUCCESSFUL;
1268
        }
1269
    }
1270
1271
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF1
1272
    {
1273
        status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1274
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1275
        {
1276
            PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1277
        }
1278
        else
1279
        {
1280
            status = RTEMS_SUCCESSFUL;
1281
        }
1282
    }
1283
1284
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC1
1285
    {
1286
        status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1287
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1288
        {
1289
            PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1290
        }
1291
        else
1292
        {
1293
            status = RTEMS_SUCCESSFUL;
1294
        }
1295
    }
1296
1297
    if (status == RTEMS_SUCCESSFUL)        // suspend AVF2
1298
    {
1299
        status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1300
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1301
        {
1302
            PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1303
        }
1304
        else
1305
        {
1306
            status = RTEMS_SUCCESSFUL;
1307
        }
1308
    }
1309
1310
    if (status == RTEMS_SUCCESSFUL)        // suspend PRC2
1311
    {
1312
        status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1313
        if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1314
        {
1315
            PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1316
        }
1317
        else
1318
        {
1319
            status = RTEMS_SUCCESSFUL;
1320
        }
1321
    }
1322
1323
    return status;
1324
}
1325
1326
void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1327
{
1328
1329
    WFP_reset_current_ring_nodes();
1330
1331
    reset_waveform_picker_regs();
1332
1333
    set_wfp_burst_enable_register( mode );
1334
1335
    LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1336
    LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1337
1338
    if (transitionCoarseTime == 0)
1339
    {
1340
        // instant transition means transition on the next valid date
1341
        // this is mandatory to have a good snapshot period and a good correction of the snapshot period
1342
        waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1343
    }
1344
    else
1345
    {
1346
        waveform_picker_regs->start_date = transitionCoarseTime;
1347
    }
1348
1349
    update_last_valid_transition_date(waveform_picker_regs->start_date);
1350
1351
}
1352
1353
void launch_spectral_matrix( void )
1354
{
1355
    SM_reset_current_ring_nodes();
1356
1357
    reset_spectral_matrix_regs();
1358
1359
    reset_nb_sm();
1360
1361
    set_sm_irq_onNewMatrix( 1 );
1362
1363
    LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1364
    LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1365
1366
}
1367
1368
1
void set_sm_irq_onNewMatrix( unsigned char value )
1369
{
1370
1
    if (value == 1)
1371
    {
1372
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1373
    }
1374
    else
1375
    {
1376
1
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX;   // 1110
1377
    }
1378
1
}
1379
1380
1
void set_sm_irq_onError( unsigned char value )
1381
{
1382
1
    if (value == 1)
1383
    {
1384
        spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1385
    }
1386
    else
1387
    {
1388
1
        spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR;   // 1101
1389
    }
1390
1
}
1391
1392
//*****************************
1393
// CONFIGURE CALIBRATION SIGNAL
1394
1
void setCalibrationPrescaler( unsigned int prescaler )
1395
{
1396
    // prescaling of the master clock (25 MHz)
1397
    // master clock is divided by 2^prescaler
1398
1
    time_management_regs->calPrescaler = prescaler;
1399
1
}
1400
1401
1
void setCalibrationDivisor( unsigned int divisionFactor )
1402
{
1403
    // division of the prescaled clock by the division factor
1404
1
    time_management_regs->calDivisor = divisionFactor;
1405
1
}
1406
1407
1
void setCalibrationData( void )
1408
{
1409
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1410
     *
1411
     * @param void
1412
     *
1413
     * @return void
1414
     *
1415
     */
1416
1417
    unsigned int k;
1418
    unsigned short data;
1419
    float val;
1420
    float Ts;
1421
1422
1
    time_management_regs->calDataPtr = INIT_CHAR;
1423
1424
1
    Ts = 1 / CAL_FS;
1425
1426
    // build the signal for the SCM calibration
1427
257
    for (k = 0; k < CAL_NB_PTS; k++)
1428
    {
1429
512
        val = CAL_A0 *  sin( CAL_W0 * k * Ts )
1430
256
                        + CAL_A1 * sin(  CAL_W1 * k * Ts );
1431
256
        data = (unsigned short) ((val * CAL_SCALE_FACTOR) + CONST_2048);
1432
256
        time_management_regs->calData = data & CAL_DATA_MASK;
1433
    }
1434
1
}
1435
1436
void setCalibrationDataInterleaved( void )
1437
{
1438
    /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1439
     *
1440
     * @param void
1441
     *
1442
     * @return void
1443
     *
1444
     * In interleaved mode, one can store more values than in normal mode.
1445
     * The data are stored in bunch of 18 bits, 12 bits from one sample and 6 bits from another sample.
1446
     * T store 3 values, one need two write operations.
1447
     * s1 [ b11 b10 b9 b8 b7 b6 ] s0 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1448
     * s1 [ b5  b4  b3 b2 b1 b0 ] s2 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1449
     *
1450
     */
1451
1452
    unsigned int k;
1453
    float val;
1454
    float Ts;
1455
    unsigned short data[CAL_NB_PTS_INTER];
1456
    unsigned char *dataPtr;
1457
1458
    Ts = 1 / CAL_FS_INTER;
1459
1460
    time_management_regs->calDataPtr = INIT_CHAR;
1461
1462
    // build the signal for the SCM calibration
1463
    for (k=0; k<CAL_NB_PTS_INTER; k++)
1464
    {
1465
        val = sin( 2 * pi * CAL_F0 * k * Ts )
1466
                + sin(  2 * pi * CAL_F1 * k * Ts );
1467
        data[k] = (unsigned short) ((val * CONST_512) + CONST_2048);
1468
    }
1469
1470
    // write the signal in interleaved mode
1471
    for (k=0; k < STEPS_FOR_STORAGE_INTER; k++)
1472
    {
1473
        dataPtr = (unsigned char*) &data[ (k * BYTES_FOR_2_SAMPLES) + 2 ];
1474
        time_management_regs->calData = ( data[ k * BYTES_FOR_2_SAMPLES ]     & CAL_DATA_MASK )
1475
                + ( (dataPtr[0] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1476
        time_management_regs->calData = ( data[(k * BYTES_FOR_2_SAMPLES) + 1] & CAL_DATA_MASK )
1477
                + ( (dataPtr[1] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1478
    }
1479
}
1480
1481
1
void setCalibrationReload( bool state)
1482
{
1483
1
    if (state == true)
1484
    {
1485
1
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_RELOAD;   // [0001 0000]
1486
    }
1487
    else
1488
    {
1489
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_RELOAD;   // [1110 1111]
1490
    }
1491
1
}
1492
1493
1
void setCalibrationEnable( bool state )
1494
{
1495
    // this bit drives the multiplexer
1496
1
    if (state == true)
1497
    {
1498
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_ENABLE;   // [0100 0000]
1499
    }
1500
    else
1501
    {
1502
1
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1503
    }
1504
1
}
1505
1506
void setCalibrationInterleaved( bool state )
1507
{
1508
    // this bit drives the multiplexer
1509
    if (state == true)
1510
    {
1511
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_SET_INTERLEAVED;   // [0010 0000]
1512
    }
1513
    else
1514
    {
1515
        time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_SET_INTERLEAVED; // [1101 1111]
1516
    }
1517
}
1518
1519
1
void setCalibration( bool state )
1520
{
1521
1
    if (state == true)
1522
    {
1523
        setCalibrationEnable( true );
1524
        setCalibrationReload( false );
1525
        set_hk_lfr_calib_enable( true );
1526
    }
1527
    else
1528
    {
1529
1
        setCalibrationEnable( false );
1530
1
        setCalibrationReload( true );
1531
1
        set_hk_lfr_calib_enable( false );
1532
    }
1533
1
}
1534
1535
1
void configureCalibration( bool interleaved )
1536
{
1537
1
    setCalibration( false );
1538
1
    if ( interleaved == true )
1539
    {
1540
        setCalibrationInterleaved( true );
1541
        setCalibrationPrescaler( 0 );                   // 25 MHz   => 25 000 000
1542
        setCalibrationDivisor( CAL_F_DIVISOR_INTER );   //          => 240 384
1543
        setCalibrationDataInterleaved();
1544
    }
1545
    else
1546
    {
1547
1
        setCalibrationPrescaler( 0 );           // 25 MHz   => 25 000 000
1548
1
        setCalibrationDivisor( CAL_F_DIVISOR ); //          => 160 256 (39 - 1)
1549
1
        setCalibrationData();
1550
    }
1551
1
}
1552
1553
//****************
1554
// CLOSING ACTIONS
1555
void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1556
{
1557
    /** This function is used to update the HK packets statistics after a successful TC execution.
1558
     *
1559
     * @param TC points to the TC being processed
1560
     * @param time is the time used to date the TC execution
1561
     *
1562
     */
1563
1564
    unsigned int val;
1565
1566
    housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1567
    housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1568
    housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1569
    housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1570
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1571
    housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1572
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1573
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1574
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1575
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1576
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1577
    housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1578
1579
    val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1580
    val++;
1581
    housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1582
    housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1583
}
1584
1585
void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1586
{
1587
    /** This function is used to update the HK packets statistics after a TC rejection.
1588
     *
1589
     * @param TC points to the TC being processed
1590
     * @param time is the time used to date the TC rejection
1591
     *
1592
     */
1593
1594
    unsigned int val;
1595
1596
    housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1597
    housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1598
    housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1599
    housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1600
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1601
    housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1602
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1603
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1604
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1605
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1606
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1607
    housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1608
1609
    val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1610
    val++;
1611
    housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1612
    housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1613
}
1614
1615
void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1616
{
1617
    /** This function is the last step of the TC execution workflow.
1618
     *
1619
     * @param TC points to the TC being processed
1620
     * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1621
     * @param queue_id is the id of the RTEMS message queue used to send TM packets
1622
     * @param time is the time used to date the TC execution
1623
     *
1624
     */
1625
1626
    unsigned char requestedMode;
1627
1628
    if (result == LFR_SUCCESSFUL)
1629
    {
1630
        if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1631
             &
1632
             !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1633
             )
1634
        {
1635
            send_tm_lfr_tc_exe_success( TC, queue_id );
1636
        }
1637
        if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1638
        {
1639
            //**********************************
1640
            // UPDATE THE LFRMODE LOCAL VARIABLE
1641
            requestedMode = TC->dataAndCRC[1];
1642
            updateLFRCurrentMode( requestedMode );
1643
        }
1644
    }
1645
    else if (result == LFR_EXE_ERROR)
1646
    {
1647
        send_tm_lfr_tc_exe_error( TC, queue_id );
1648
    }
1649
}
1650
1651
//***************************
1652
// Interrupt Service Routines
1653
rtems_isr commutation_isr1( rtems_vector_number vector )
1654
{
1655
    if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1656
        PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1657
    }
1658
}
1659
1660
rtems_isr commutation_isr2( rtems_vector_number vector )
1661
{
1662
    if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1663
        PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1664
    }
1665
}
1666
1667
//****************
1668
// OTHER FUNCTIONS
1669
1
void updateLFRCurrentMode( unsigned char requestedMode )
1670
{
1671
    /** This function updates the value of the global variable lfrCurrentMode.
1672
     *
1673
     * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1674
     *
1675
     */
1676
1677
    // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1678
1
    housekeeping_packet.lfr_status_word[0] = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1679
            + (unsigned char) ( requestedMode << STATUS_WORD_LFR_MODE_SHIFT );
1680
1
    lfrCurrentMode = requestedMode;
1681
1
}
1682
1683
2
void set_lfr_soft_reset( unsigned char value )
1684
{
1685
2
    if (value == 1)
1686
    {
1687
1
        time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1688
    }
1689
    else
1690
    {
1691
1
        time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1692
    }
1693
2
}
1694
1695
1
void reset_lfr( void )
1696
{
1697
1
    set_lfr_soft_reset( 1 );
1698
1699
1
    set_lfr_soft_reset( 0 );
1700
1701
1
    set_hk_lfr_sc_potential_flag( true );
1702
1
}