##// END OF EJS Templates
Minor bugs corrected before logiscope analysis
paul -
r322:c0603702c8c8 R3_plus draft
parent child
Show More
@@ -1,131 +1,131
1 1 #ifndef FSW_MISC_H_INCLUDED
2 2 #define FSW_MISC_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <stdio.h>
6 6 #include <grspw.h>
7 7 #include <grlib_regs.h>
8 8
9 9 #include "fsw_params.h"
10 10 #include "fsw_spacewire.h"
11 11 #include "lfr_cpu_usage_report.h"
12 12
13 13 #define LFR_RESET_CAUSE_UNKNOWN_CAUSE 0
14 14 #define WATCHDOG_LOOP_PRINTF 10
15 15 #define WATCHDOG_LOOP_DEBUG 3
16 16
17 17 #define DUMB_MESSAGE_NB 15
18 18 #define NB_RTEMS_EVENTS 32
19 19 #define EVENT_12 12
20 20 #define EVENT_13 13
21 21 #define EVENT_14 14
22 22 #define DUMB_MESSAGE_0 "in DUMB *** default"
23 23 #define DUMB_MESSAGE_1 "in DUMB *** timecode_irq_handler"
24 24 #define DUMB_MESSAGE_2 "in DUMB *** f3 buffer changed"
25 25 #define DUMB_MESSAGE_3 "in DUMB *** in SMIQ *** Error sending event to AVF0"
26 26 #define DUMB_MESSAGE_4 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ"
27 27 #define DUMB_MESSAGE_5 "in DUMB *** waveforms_simulator_isr"
28 28 #define DUMB_MESSAGE_6 "VHDL SM *** two buffers f0 ready"
29 29 #define DUMB_MESSAGE_7 "ready for dump"
30 30 #define DUMB_MESSAGE_8 "VHDL ERR *** spectral matrix"
31 31 #define DUMB_MESSAGE_9 "tick"
32 32 #define DUMB_MESSAGE_10 "VHDL ERR *** waveform picker"
33 33 #define DUMB_MESSAGE_11 "VHDL ERR *** unexpected ready matrix values"
34 34 #define DUMB_MESSAGE_12 "WATCHDOG timer"
35 35 #define DUMB_MESSAGE_13 "TIMECODE timer"
36 36 #define DUMB_MESSAGE_14 "TIMECODE ISR"
37 37
38 38 enum lfr_reset_cause_t{
39 39 UNKNOWN_CAUSE,
40 40 POWER_ON,
41 41 TC_RESET,
42 42 WATCHDOG,
43 43 ERROR_RESET,
44 44 UNEXP_RESET
45 45 };
46 46
47 47 typedef struct{
48 48 unsigned char dpu_spw_parity;
49 49 unsigned char dpu_spw_disconnect;
50 50 unsigned char dpu_spw_escape;
51 51 unsigned char dpu_spw_credit;
52 52 unsigned char dpu_spw_write_sync;
53 53 unsigned char timecode_erroneous;
54 54 unsigned char timecode_missing;
55 55 unsigned char timecode_invalid;
56 56 unsigned char time_timecode_it;
57 57 unsigned char time_not_synchro;
58 58 unsigned char time_timecode_ctr;
59 59 unsigned char ahb_correctable;
60 60 } hk_lfr_le_t;
61 61
62 62 typedef struct{
63 63 unsigned char dpu_spw_early_eop;
64 64 unsigned char dpu_spw_invalid_addr;
65 65 unsigned char dpu_spw_eep;
66 66 unsigned char dpu_spw_rx_too_big;
67 67 } hk_lfr_me_t;
68 68
69 69 extern gptimer_regs_t *gptimer_regs;
70 70 extern void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int*, unsigned int* );
71 71 extern void CCR_getInstructionAndDataErrorCounters( unsigned int*, unsigned int* );
72 72
73 rtems_name name_hk_rate_monotonic = 0; // name of the HK rate monotonic
74 rtems_id HK_id = RTEMS_ID_NONE;// id of the HK rate monotonic period
75 rtems_name name_avgv_rate_monotonic = 0; // name of the AVGV rate monotonic
76 rtems_id AVGV_id = RTEMS_ID_NONE;// id of the AVGV rate monotonic period
73 extern rtems_name name_hk_rate_monotonic; // name of the HK rate monotonic
74 extern rtems_id HK_id;// id of the HK rate monotonic period
75 extern rtems_name name_avgv_rate_monotonic; // name of the AVGV rate monotonic
76 extern rtems_id AVGV_id;// id of the AVGV rate monotonic period
77 77
78 78 void timer_configure( unsigned char timer, unsigned int clock_divider,
79 79 unsigned char interrupt_level, rtems_isr (*timer_isr)() );
80 80 void timer_start( unsigned char timer );
81 81 void timer_stop( unsigned char timer );
82 82 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider);
83 83
84 84 // WATCHDOG
85 85 rtems_isr watchdog_isr( rtems_vector_number vector );
86 86 void watchdog_configure(void);
87 87 void watchdog_stop(void);
88 88 void watchdog_reload(void);
89 89 void watchdog_start(void);
90 90
91 91 // SERIAL LINK
92 92 int send_console_outputs_on_apbuart_port( void );
93 93 int enable_apbuart_transmitter( void );
94 94 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value);
95 95
96 96 // RTEMS TASKS
97 97 rtems_task load_task( rtems_task_argument argument );
98 98 rtems_task hous_task( rtems_task_argument argument );
99 99 rtems_task avgv_task( rtems_task_argument argument );
100 100 rtems_task dumb_task( rtems_task_argument unused );
101 101
102 102 void init_housekeeping_parameters( void );
103 103 void increment_seq_counter(unsigned short *packetSequenceControl);
104 104 void getTime( unsigned char *time);
105 105 unsigned long long int getTimeAsUnsignedLongLongInt( );
106 106 void send_dumb_hk( void );
107 107 void get_temperatures( unsigned char *temperatures );
108 108 void get_v_e1_e2_f3( unsigned char *spacecraft_potential );
109 109 void get_cpu_load( unsigned char *resource_statistics );
110 110 void set_hk_lfr_sc_potential_flag( bool state );
111 111 void set_sy_lfr_pas_filter_enabled( bool state );
112 112 void set_sy_lfr_watchdog_enabled( bool state );
113 113 void set_hk_lfr_calib_enable( bool state );
114 114 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause );
115 115 void hk_lfr_le_me_he_update();
116 116 void set_hk_lfr_time_not_synchro();
117 117
118 118 extern int sched_yield( void );
119 119 extern void rtems_cpu_usage_reset();
120 120 extern ring_node *current_ring_node_f3;
121 121 extern ring_node *ring_node_to_send_cwf_f3;
122 122 extern ring_node waveform_ring_f3[];
123 123 extern unsigned short sequenceCounterHK;
124 124
125 125 extern unsigned char hk_lfr_q_sd_fifo_size_max;
126 126 extern unsigned char hk_lfr_q_rv_fifo_size_max;
127 127 extern unsigned char hk_lfr_q_p0_fifo_size_max;
128 128 extern unsigned char hk_lfr_q_p1_fifo_size_max;
129 129 extern unsigned char hk_lfr_q_p2_fifo_size_max;
130 130
131 131 #endif // FSW_MISC_H_INCLUDED
@@ -1,102 +1,106
1 1 /** Global variables of the LFR flight software.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * Among global variables, there are:
7 7 * - RTEMS names and id.
8 8 * - APB configuration registers.
9 9 * - waveforms global buffers, used by the waveform picker hardware module to store data.
10 10 * - spectral matrices buffesr, used by the hardware module to store data.
11 11 * - variable related to LFR modes parameters.
12 12 * - the global HK packet buffer.
13 13 * - the global dump parameter buffer.
14 14 *
15 15 */
16 16
17 17 #include <rtems.h>
18 18 #include <grspw.h>
19 19
20 20 #include "ccsds_types.h"
21 21 #include "grlib_regs.h"
22 22 #include "fsw_params.h"
23 23 #include "fsw_params_wf_handler.h"
24 24
25 25 #define NB_OF_TASKS 20
26 26 #define NB_OF_MISC_NAMES 5
27 27
28 28 // RTEMS GLOBAL VARIABLES
29 29 rtems_name misc_name[NB_OF_MISC_NAMES] = {0};
30 30 rtems_name Task_name[NB_OF_TASKS] = {0}; /* array of task names */
31 31 rtems_id Task_id[NB_OF_TASKS] = {0}; /* array of task ids */
32 rtems_name timecode_timer_name = {0};
33 rtems_id timecode_timer_id = {0};
32 rtems_name timecode_timer_name = 0;
33 rtems_id timecode_timer_id = RTEMS_ID_NONE;
34 rtems_name name_hk_rate_monotonic = 0; // name of the HK rate monotonic
35 rtems_id HK_id = RTEMS_ID_NONE;// id of the HK rate monotonic period
36 rtems_name name_avgv_rate_monotonic = 0; // name of the AVGV rate monotonic
37 rtems_id AVGV_id = RTEMS_ID_NONE;// id of the AVGV rate monotonic period
34 38 int fdSPW = 0;
35 39 int fdUART = 0;
36 40 unsigned char lfrCurrentMode = 0;
37 41 unsigned char pa_bia_status_info = 0;
38 42 unsigned char thisIsAnASMRestart = 0;
39 43 unsigned char oneTcLfrUpdateTimeReceived = 0;
40 44
41 45 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
42 46 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
43 47 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
44 48 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
45 49 // F0 F1 F2 F3
46 50 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
47 51 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
48 52 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
49 53 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
50 54
51 55 //***********************************
52 56 // SPECTRAL MATRICES GLOBAL VARIABLES
53 57
54 58 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
55 59 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
56 60 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
57 61 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
58 62
59 63 // APB CONFIGURATION REGISTERS
60 64 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
61 65 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
62 66 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
63 67 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
64 68
65 69 // MODE PARAMETERS
66 70 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet = {0};
67 71 struct param_local_str param_local = {0};
68 72 unsigned int lastValidEnterModeTime = {0};
69 73
70 74 // HK PACKETS
71 75 Packet_TM_LFR_HK_t housekeeping_packet = {0};
72 76 unsigned char cp_rpw_sc_rw_f_flags = 0;
73 77 // message queues occupancy
74 78 unsigned char hk_lfr_q_sd_fifo_size_max = 0;
75 79 unsigned char hk_lfr_q_rv_fifo_size_max = 0;
76 80 unsigned char hk_lfr_q_p0_fifo_size_max = 0;
77 81 unsigned char hk_lfr_q_p1_fifo_size_max = 0;
78 82 unsigned char hk_lfr_q_p2_fifo_size_max = 0;
79 83 // sequence counters are incremented by APID (PID + CAT) and destination ID
80 84 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST = 0;
81 85 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2 = 0;
82 86 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID] = {0};
83 87 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID] = {0};
84 88 unsigned short sequenceCounterHK;
85 89 spw_stats grspw_stats = {0};
86 90
87 91 // TC_LFR_UPDATE_INFO
88 92 float cp_rpw_sc_rw1_f1 = INIT_FLOAT;
89 93 float cp_rpw_sc_rw1_f2 = INIT_FLOAT;
90 94 float cp_rpw_sc_rw2_f1 = INIT_FLOAT;
91 95 float cp_rpw_sc_rw2_f2 = INIT_FLOAT;
92 96 float cp_rpw_sc_rw3_f1 = INIT_FLOAT;
93 97 float cp_rpw_sc_rw3_f2 = INIT_FLOAT;
94 98 float cp_rpw_sc_rw4_f1 = INIT_FLOAT;
95 99 float cp_rpw_sc_rw4_f2 = INIT_FLOAT;
96 100
97 101 // TC_LFR_LOAD_FILTER_PAR
98 102 filterPar_t filterPar = {0};
99 103
100 104 fbins_masks_t fbins_masks = {0};
101 105 unsigned int acquisitionDurations[NB_ACQUISITION_DURATION]
102 106 = {ACQUISITION_DURATION_F0, ACQUISITION_DURATION_F1, ACQUISITION_DURATION_F2};
@@ -1,1631 +1,1631
1 1 /** Functions related to the SpaceWire interface.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle SpaceWire transmissions:
7 7 * - configuration of the SpaceWire link
8 8 * - SpaceWire related interruption requests processing
9 9 * - transmission of TeleMetry packets by a dedicated RTEMS task
10 10 * - reception of TeleCommands by a dedicated RTEMS task
11 11 *
12 12 */
13 13
14 14 #include "fsw_spacewire.h"
15 15
16 16 rtems_name semq_name = 0;
17 17 rtems_id semq_id = RTEMS_ID_NONE;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF = {0};
22 Header_TM_LFR_SCIENCE_SWF_t headerSW = {0};
22 Header_TM_LFR_SCIENCE_SWF_t headerSWF = {0};
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM = {0};
24 24
25 25 unsigned char previousTimecodeCtr = 0;
26 26 unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
27 27
28 28 //***********
29 29 // RTEMS TASK
30 30 rtems_task spiq_task(rtems_task_argument unused)
31 31 {
32 32 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
33 33 *
34 34 * @param unused is the starting argument of the RTEMS task
35 35 *
36 36 */
37 37
38 38 rtems_event_set event_out;
39 39 rtems_status_code status;
40 40 int linkStatus;
41 41
42 42 event_out = EVENT_SETS_NONE_PENDING;
43 43 linkStatus = 0;
44 44
45 45 BOOT_PRINTF("in SPIQ *** \n")
46 46
47 47 while(true){
48 48 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
49 49 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
50 50
51 51 // [0] SUSPEND RECV AND SEND TASKS
52 52 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
53 53 if ( status != RTEMS_SUCCESSFUL ) {
54 54 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
55 55 }
56 56 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
57 57 if ( status != RTEMS_SUCCESSFUL ) {
58 58 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
59 59 }
60 60
61 61 // [1] CHECK THE LINK
62 62 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
63 63 if ( linkStatus != SPW_LINK_OK) {
64 64 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
65 65 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
66 66 }
67 67
68 68 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
69 69 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
70 70 if ( linkStatus != SPW_LINK_OK ) // [2.a] not in run state, reset the link
71 71 {
72 72 spacewire_read_statistics();
73 73 status = spacewire_several_connect_attemps( );
74 74 }
75 75 else // [2.b] in run state, start the link
76 76 {
77 77 status = spacewire_stop_and_start_link( fdSPW ); // start the link
78 78 if ( status != RTEMS_SUCCESSFUL)
79 79 {
80 80 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
81 81 }
82 82 }
83 83
84 84 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
85 85 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
86 86 {
87 87 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
88 88 if ( status != RTEMS_SUCCESSFUL ) {
89 89 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
90 90 }
91 91 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
92 92 if ( status != RTEMS_SUCCESSFUL ) {
93 93 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
94 94 }
95 95 }
96 96 else // [3.b] the link is not in run state, go in STANDBY mode
97 97 {
98 98 status = enter_mode_standby();
99 99 if ( status != RTEMS_SUCCESSFUL )
100 100 {
101 101 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
102 102 }
103 103 {
104 104 updateLFRCurrentMode( LFR_MODE_STANDBY );
105 105 }
106 106 // wake the LINK task up to wait for the link recovery
107 107 status = rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
108 108 status = rtems_task_suspend( RTEMS_SELF );
109 109 }
110 110 }
111 111 }
112 112
113 113 rtems_task recv_task( rtems_task_argument unused )
114 114 {
115 115 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
116 116 *
117 117 * @param unused is the starting argument of the RTEMS task
118 118 *
119 119 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
120 120 * 1. It reads the incoming data.
121 121 * 2. Launches the acceptance procedure.
122 122 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
123 123 *
124 124 */
125 125
126 126 int len;
127 127 ccsdsTelecommandPacket_t currentTC;
128 128 unsigned char computed_CRC[ BYTES_PER_CRC ];
129 129 unsigned char currentTC_LEN_RCV[ BYTES_PER_PKT_LEN ];
130 130 unsigned char destinationID;
131 131 unsigned int estimatedPacketLength;
132 132 unsigned int parserCode;
133 133 rtems_status_code status;
134 134 rtems_id queue_recv_id;
135 135 rtems_id queue_send_id;
136 136
137 137 memset( &currentTC, 0, sizeof(ccsdsTelecommandPacket_t) );
138 138 destinationID = 0;
139 139 queue_recv_id = RTEMS_ID_NONE;
140 140 queue_send_id = RTEMS_ID_NONE;
141 141
142 142 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
143 143
144 144 status = get_message_queue_id_recv( &queue_recv_id );
145 145 if (status != RTEMS_SUCCESSFUL)
146 146 {
147 147 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
148 148 }
149 149
150 150 status = get_message_queue_id_send( &queue_send_id );
151 151 if (status != RTEMS_SUCCESSFUL)
152 152 {
153 153 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
154 154 }
155 155
156 156 BOOT_PRINTF("in RECV *** \n")
157 157
158 158 while(1)
159 159 {
160 160 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
161 161 if (len == -1){ // error during the read call
162 162 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
163 163 }
164 164 else {
165 165 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
166 166 PRINTF("in RECV *** packet lenght too short\n")
167 167 }
168 168 else {
169 169 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - PROTID_RES_APP); // => -3 is for Prot ID, Reserved and User App bytes
170 170 //PRINTF1("incoming TC with Length (byte): %d\n", len - 3);
171 171 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> SHIFT_1_BYTE);
172 172 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
173 173 // CHECK THE TC
174 174 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
175 175 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
176 176 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
177 177 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
178 178 || (parserCode == WRONG_SRC_ID) )
179 179 { // send TM_LFR_TC_EXE_CORRUPTED
180 180 PRINTF1("TC corrupted received, with code: %d\n", parserCode);
181 181 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
182 182 &&
183 183 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
184 184 )
185 185 {
186 186 if ( parserCode == WRONG_SRC_ID )
187 187 {
188 188 destinationID = SID_TC_GROUND;
189 189 }
190 190 else
191 191 {
192 192 destinationID = currentTC.sourceID;
193 193 }
194 194 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
195 195 computed_CRC, currentTC_LEN_RCV,
196 196 destinationID );
197 197 }
198 198 }
199 199 else
200 200 { // send valid TC to the action launcher
201 201 status = rtems_message_queue_send( queue_recv_id, &currentTC,
202 202 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + PROTID_RES_APP);
203 203 }
204 204 }
205 205 }
206 206
207 207 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
208 208
209 209 }
210 210 }
211 211
212 212 rtems_task send_task( rtems_task_argument argument)
213 213 {
214 214 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
215 215 *
216 216 * @param unused is the starting argument of the RTEMS task
217 217 *
218 218 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
219 219 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
220 220 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
221 221 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
222 222 * data it contains.
223 223 *
224 224 */
225 225
226 226 rtems_status_code status; // RTEMS status code
227 227 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
228 228 ring_node *incomingRingNodePtr;
229 229 int ring_node_address;
230 230 char *charPtr;
231 231 spw_ioctl_pkt_send *spw_ioctl_send;
232 232 size_t size; // size of the incoming TC packet
233 233 rtems_id queue_send_id;
234 234 unsigned int sid;
235 235 unsigned char sidAsUnsignedChar;
236 236 unsigned char type;
237 237
238 238 incomingRingNodePtr = NULL;
239 239 ring_node_address = 0;
240 240 charPtr = (char *) &ring_node_address;
241 241 size = 0;
242 242 queue_send_id = RTEMS_ID_NONE;
243 243 sid = 0;
244 244 sidAsUnsignedChar = 0;
245 245
246 246 init_header_cwf( &headerCWF );
247 247 init_header_swf( &headerSWF );
248 248 init_header_asm( &headerASM );
249 249
250 250 status = get_message_queue_id_send( &queue_send_id );
251 251 if (status != RTEMS_SUCCESSFUL)
252 252 {
253 253 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
254 254 }
255 255
256 256 BOOT_PRINTF("in SEND *** \n")
257 257
258 258 while(1)
259 259 {
260 260 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
261 261 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
262 262
263 263 if (status!=RTEMS_SUCCESSFUL)
264 264 {
265 265 PRINTF1("in SEND *** (1) ERR = %d\n", status)
266 266 }
267 267 else
268 268 {
269 269 if ( size == sizeof(ring_node*) )
270 270 {
271 271 charPtr[0] = incomingData[0];
272 272 charPtr[1] = incomingData[1];
273 273 charPtr[BYTE_2] = incomingData[BYTE_2];
274 274 charPtr[BYTE_3] = incomingData[BYTE_3];
275 275 incomingRingNodePtr = (ring_node*) ring_node_address;
276 276 sid = incomingRingNodePtr->sid;
277 277 if ( (sid==SID_NORM_CWF_LONG_F3)
278 278 || (sid==SID_BURST_CWF_F2 )
279 279 || (sid==SID_SBM1_CWF_F1 )
280 280 || (sid==SID_SBM2_CWF_F2 ))
281 281 {
282 282 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
283 283 }
284 284 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
285 285 {
286 286 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
287 287 }
288 288 else if ( (sid==SID_NORM_CWF_F3) )
289 289 {
290 290 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
291 291 }
292 292 else if (sid==SID_NORM_ASM_F0)
293 293 {
294 294 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
295 295 }
296 296 else if (sid==SID_NORM_ASM_F1)
297 297 {
298 298 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
299 299 }
300 300 else if (sid==SID_NORM_ASM_F2)
301 301 {
302 302 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
303 303 }
304 304 else if ( sid==TM_CODE_K_DUMP )
305 305 {
306 306 spw_send_k_dump( incomingRingNodePtr );
307 307 }
308 308 else
309 309 {
310 310 PRINTF1("unexpected sid = %d\n", sid);
311 311 }
312 312 }
313 313 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
314 314 {
315 315 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
316 316 sid = sidAsUnsignedChar;
317 317 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
318 318 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
319 319 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
320 320 {
321 321 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
322 322 }
323 323
324 324 status = write( fdSPW, incomingData, size );
325 325 if (status == -1){
326 326 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
327 327 }
328 328 }
329 329 else // the incoming message is a spw_ioctl_pkt_send structure
330 330 {
331 331 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
332 332 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
333 333 if (status == -1){
334 334 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
335 335 }
336 336 }
337 337 }
338 338
339 339 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
340 340
341 341 }
342 342 }
343 343
344 344 rtems_task link_task( rtems_task_argument argument )
345 345 {
346 346 rtems_event_set event_out;
347 347 rtems_status_code status;
348 348 int linkStatus;
349 349
350 350 event_out = EVENT_SETS_NONE_PENDING;
351 351 linkStatus = 0;
352 352
353 353 BOOT_PRINTF("in LINK ***\n")
354 354
355 355 while(1)
356 356 {
357 357 // wait for an RTEMS_EVENT
358 358 rtems_event_receive( RTEMS_EVENT_0,
359 359 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
360 360 PRINTF("in LINK *** wait for the link\n")
361 361 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
362 362 while( linkStatus != SPW_LINK_OK) // wait for the link
363 363 {
364 364 status = rtems_task_wake_after( SPW_LINK_WAIT ); // monitor the link each 100ms
365 365 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
366 366 watchdog_reload();
367 367 }
368 368
369 369 spacewire_read_statistics();
370 370 status = spacewire_stop_and_start_link( fdSPW );
371 371
372 372 if (status != RTEMS_SUCCESSFUL)
373 373 {
374 374 PRINTF1("in LINK *** ERR link not started %d\n", status)
375 375 }
376 376 else
377 377 {
378 378 PRINTF("in LINK *** OK link started\n")
379 379 }
380 380
381 381 // restart the SPIQ task
382 382 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
383 383 if ( status != RTEMS_SUCCESSFUL ) {
384 384 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
385 385 }
386 386
387 387 // restart RECV and SEND
388 388 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
389 389 if ( status != RTEMS_SUCCESSFUL ) {
390 390 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
391 391 }
392 392 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
393 393 if ( status != RTEMS_SUCCESSFUL ) {
394 394 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
395 395 }
396 396 }
397 397 }
398 398
399 399 //****************
400 400 // OTHER FUNCTIONS
401 401 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
402 402 {
403 403 /** This function opens the SpaceWire link.
404 404 *
405 405 * @return a valid file descriptor in case of success, -1 in case of a failure
406 406 *
407 407 */
408 408 rtems_status_code status;
409 409
410 410 status = RTEMS_SUCCESSFUL;
411 411
412 412 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
413 413 if ( fdSPW < 0 ) {
414 414 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
415 415 }
416 416 else
417 417 {
418 418 status = RTEMS_SUCCESSFUL;
419 419 }
420 420
421 421 return status;
422 422 }
423 423
424 424 int spacewire_start_link( int fd )
425 425 {
426 426 rtems_status_code status;
427 427
428 428 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
429 429 // -1 default hardcoded driver timeout
430 430
431 431 return status;
432 432 }
433 433
434 434 int spacewire_stop_and_start_link( int fd )
435 435 {
436 436 rtems_status_code status;
437 437
438 438 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
439 439 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
440 440 // -1 default hardcoded driver timeout
441 441
442 442 return status;
443 443 }
444 444
445 445 int spacewire_configure_link( int fd )
446 446 {
447 447 /** This function configures the SpaceWire link.
448 448 *
449 449 * @return GR-RTEMS-DRIVER directive status codes:
450 450 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
451 451 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
452 452 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
453 453 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
454 454 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
455 455 * - 5 EIO - Error when writing to grswp hardware registers.
456 456 * - 2 ENOENT - No such file or directory
457 457 */
458 458
459 459 rtems_status_code status;
460 460
461 461 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
462 462 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
463 463 spw_ioctl_packetsize packetsize;
464 464
465 465 packetsize.rxsize = SPW_RXSIZE;
466 466 packetsize.txdsize = SPW_TXDSIZE;
467 467 packetsize.txhsize = SPW_TXHSIZE;
468 468
469 469 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
470 470 if (status!=RTEMS_SUCCESSFUL) {
471 471 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
472 472 }
473 473 //
474 474 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
475 475 if (status!=RTEMS_SUCCESSFUL) {
476 476 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
477 477 }
478 478 //
479 479 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
480 480 if (status!=RTEMS_SUCCESSFUL) {
481 481 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
482 482 }
483 483 //
484 484 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
485 485 if (status!=RTEMS_SUCCESSFUL) {
486 486 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
487 487 }
488 488 //
489 489 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
490 490 if (status!=RTEMS_SUCCESSFUL) {
491 491 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
492 492 }
493 493 //
494 494 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
495 495 if (status!=RTEMS_SUCCESSFUL) {
496 496 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
497 497 }
498 498 //
499 499 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, CONF_TCODE_CTRL); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
500 500 if (status!=RTEMS_SUCCESSFUL) {
501 501 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
502 502 }
503 503 //
504 504 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_PACKETSIZE, packetsize); // set rxsize, txdsize and txhsize
505 505 if (status!=RTEMS_SUCCESSFUL) {
506 506 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_PACKETSIZE,\n")
507 507 }
508 508
509 509 return status;
510 510 }
511 511
512 512 int spacewire_several_connect_attemps( void )
513 513 {
514 514 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
515 515 *
516 516 * @return RTEMS directive status code:
517 517 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
518 518 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
519 519 *
520 520 */
521 521
522 522 rtems_status_code status_spw;
523 523 rtems_status_code status;
524 524 int i;
525 525
526 526 status_spw = RTEMS_SUCCESSFUL;
527 527
528 528 i = 0;
529 529 while (i < SY_LFR_DPU_CONNECT_ATTEMPT)
530 530 {
531 531 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
532 532
533 533 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
534 534
535 535 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
536 536
537 537 status_spw = spacewire_stop_and_start_link( fdSPW );
538 538
539 539 if ( status_spw != RTEMS_SUCCESSFUL )
540 540 {
541 541 i = i + 1;
542 542 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw);
543 543 }
544 544 else
545 545 {
546 546 i = SY_LFR_DPU_CONNECT_ATTEMPT;
547 547 }
548 548 }
549 549
550 550 return status_spw;
551 551 }
552 552
553 553 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
554 554 {
555 555 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
556 556 *
557 557 * @param val is the value, 0 or 1, used to set the value of the NP bit.
558 558 * @param regAddr is the address of the GRSPW control register.
559 559 *
560 560 * NP is the bit 20 of the GRSPW control register.
561 561 *
562 562 */
563 563
564 564 unsigned int *spwptr = (unsigned int*) regAddr;
565 565
566 566 if (val == 1) {
567 567 *spwptr = *spwptr | SPW_BIT_NP; // [NP] set the No port force bit
568 568 }
569 569 if (val== 0) {
570 570 *spwptr = *spwptr & SPW_BIT_NP_MASK;
571 571 }
572 572 }
573 573
574 574 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
575 575 {
576 576 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
577 577 *
578 578 * @param val is the value, 0 or 1, used to set the value of the RE bit.
579 579 * @param regAddr is the address of the GRSPW control register.
580 580 *
581 581 * RE is the bit 16 of the GRSPW control register.
582 582 *
583 583 */
584 584
585 585 unsigned int *spwptr = (unsigned int*) regAddr;
586 586
587 587 if (val == 1)
588 588 {
589 589 *spwptr = *spwptr | SPW_BIT_RE; // [RE] set the RMAP Enable bit
590 590 }
591 591 if (val== 0)
592 592 {
593 593 *spwptr = *spwptr & SPW_BIT_RE_MASK;
594 594 }
595 595 }
596 596
597 597 void spacewire_read_statistics( void )
598 598 {
599 599 /** This function reads the SpaceWire statistics from the grspw RTEMS driver.
600 600 *
601 601 * @param void
602 602 *
603 603 * @return void
604 604 *
605 605 * Once they are read, the counters are stored in a global variable used during the building of the
606 606 * HK packets.
607 607 *
608 608 */
609 609
610 610 rtems_status_code status;
611 611 spw_stats current;
612 612
613 613 memset(&current, 0, sizeof(spw_stats));
614 614
615 615 spacewire_get_last_error();
616 616
617 617 // read the current statistics
618 618 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
619 619
620 620 // clear the counters
621 621 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
622 622
623 623 // typedef struct {
624 624 // unsigned int tx_link_err; // NOT IN HK
625 625 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
626 626 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
627 627 // unsigned int rx_eep_err;
628 628 // unsigned int rx_truncated;
629 629 // unsigned int parity_err;
630 630 // unsigned int escape_err;
631 631 // unsigned int credit_err;
632 632 // unsigned int write_sync_err;
633 633 // unsigned int disconnect_err;
634 634 // unsigned int early_ep;
635 635 // unsigned int invalid_address;
636 636 // unsigned int packets_sent;
637 637 // unsigned int packets_received;
638 638 // } spw_stats;
639 639
640 640 // rx_eep_err
641 641 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
642 642 // rx_truncated
643 643 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
644 644 // parity_err
645 645 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
646 646 // escape_err
647 647 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
648 648 // credit_err
649 649 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
650 650 // write_sync_err
651 651 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
652 652 // disconnect_err
653 653 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
654 654 // early_ep
655 655 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
656 656 // invalid_address
657 657 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
658 658 // packets_sent
659 659 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
660 660 // packets_received
661 661 grspw_stats.packets_received= grspw_stats.packets_received + current.packets_received;
662 662
663 663 }
664 664
665 665 void spacewire_get_last_error( void )
666 666 {
667 667 static spw_stats previous = {0};
668 668 spw_stats current;
669 669 rtems_status_code status;
670 670
671 671 unsigned int hk_lfr_last_er_rid;
672 672 unsigned char hk_lfr_last_er_code;
673 673 int coarseTime;
674 674 int fineTime;
675 675 unsigned char update_hk_lfr_last_er;
676 676
677 677 memset(&current, 0, sizeof(spw_stats));
678 678 update_hk_lfr_last_er = 0;
679 679
680 680 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
681 681
682 682 // get current time
683 683 coarseTime = time_management_regs->coarse_time;
684 684 fineTime = time_management_regs->fine_time;
685 685
686 686 // typedef struct {
687 687 // unsigned int tx_link_err; // NOT IN HK
688 688 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
689 689 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
690 690 // unsigned int rx_eep_err;
691 691 // unsigned int rx_truncated;
692 692 // unsigned int parity_err;
693 693 // unsigned int escape_err;
694 694 // unsigned int credit_err;
695 695 // unsigned int write_sync_err;
696 696 // unsigned int disconnect_err;
697 697 // unsigned int early_ep;
698 698 // unsigned int invalid_address;
699 699 // unsigned int packets_sent;
700 700 // unsigned int packets_received;
701 701 // } spw_stats;
702 702
703 703 // tx_link_err *** no code associated to this field
704 704 // rx_rmap_header_crc_err *** LE *** in HK
705 705 if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
706 706 {
707 707 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
708 708 hk_lfr_last_er_code = CODE_HEADER_CRC;
709 709 update_hk_lfr_last_er = 1;
710 710 }
711 711 // rx_rmap_data_crc_err *** LE *** NOT IN HK
712 712 if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
713 713 {
714 714 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
715 715 hk_lfr_last_er_code = CODE_DATA_CRC;
716 716 update_hk_lfr_last_er = 1;
717 717 }
718 718 // rx_eep_err
719 719 if (previous.rx_eep_err != current.rx_eep_err)
720 720 {
721 721 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
722 722 hk_lfr_last_er_code = CODE_EEP;
723 723 update_hk_lfr_last_er = 1;
724 724 }
725 725 // rx_truncated
726 726 if (previous.rx_truncated != current.rx_truncated)
727 727 {
728 728 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
729 729 hk_lfr_last_er_code = CODE_RX_TOO_BIG;
730 730 update_hk_lfr_last_er = 1;
731 731 }
732 732 // parity_err
733 733 if (previous.parity_err != current.parity_err)
734 734 {
735 735 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
736 736 hk_lfr_last_er_code = CODE_PARITY;
737 737 update_hk_lfr_last_er = 1;
738 738 }
739 739 // escape_err
740 740 if (previous.parity_err != current.parity_err)
741 741 {
742 742 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
743 743 hk_lfr_last_er_code = CODE_ESCAPE;
744 744 update_hk_lfr_last_er = 1;
745 745 }
746 746 // credit_err
747 747 if (previous.credit_err != current.credit_err)
748 748 {
749 749 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
750 750 hk_lfr_last_er_code = CODE_CREDIT;
751 751 update_hk_lfr_last_er = 1;
752 752 }
753 753 // write_sync_err
754 754 if (previous.write_sync_err != current.write_sync_err)
755 755 {
756 756 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
757 757 hk_lfr_last_er_code = CODE_WRITE_SYNC;
758 758 update_hk_lfr_last_er = 1;
759 759 }
760 760 // disconnect_err
761 761 if (previous.disconnect_err != current.disconnect_err)
762 762 {
763 763 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
764 764 hk_lfr_last_er_code = CODE_DISCONNECT;
765 765 update_hk_lfr_last_er = 1;
766 766 }
767 767 // early_ep
768 768 if (previous.early_ep != current.early_ep)
769 769 {
770 770 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
771 771 hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
772 772 update_hk_lfr_last_er = 1;
773 773 }
774 774 // invalid_address
775 775 if (previous.invalid_address != current.invalid_address)
776 776 {
777 777 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
778 778 hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
779 779 update_hk_lfr_last_er = 1;
780 780 }
781 781
782 782 // if a field has changed, update the hk_last_er fields
783 783 if (update_hk_lfr_last_er == 1)
784 784 {
785 785 update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
786 786 }
787 787
788 788 previous = current;
789 789 }
790 790
791 791 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
792 792 {
793 793 unsigned char *coarseTimePtr;
794 794 unsigned char *fineTimePtr;
795 795
796 796 coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
797 797 fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
798 798
799 799 housekeeping_packet.hk_lfr_last_er_rid[0] = (unsigned char) ((rid & BYTE0_MASK) >> SHIFT_1_BYTE );
800 800 housekeeping_packet.hk_lfr_last_er_rid[1] = (unsigned char) (rid & BYTE1_MASK);
801 801 housekeeping_packet.hk_lfr_last_er_code = code;
802 802 housekeeping_packet.hk_lfr_last_er_time[0] = coarseTimePtr[0];
803 803 housekeeping_packet.hk_lfr_last_er_time[1] = coarseTimePtr[1];
804 804 housekeeping_packet.hk_lfr_last_er_time[BYTE_2] = coarseTimePtr[BYTE_2];
805 805 housekeeping_packet.hk_lfr_last_er_time[BYTE_3] = coarseTimePtr[BYTE_3];
806 806 housekeeping_packet.hk_lfr_last_er_time[BYTE_4] = fineTimePtr[BYTE_2];
807 807 housekeeping_packet.hk_lfr_last_er_time[BYTE_5] = fineTimePtr[BYTE_3];
808 808 }
809 809
810 810 void update_hk_with_grspw_stats( void )
811 811 {
812 812 //****************************
813 813 // DPU_SPACEWIRE_IF_STATISTICS
814 814 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (grspw_stats.packets_received >> SHIFT_1_BYTE);
815 815 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (grspw_stats.packets_received);
816 816 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (grspw_stats.packets_sent >> SHIFT_1_BYTE);
817 817 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (grspw_stats.packets_sent);
818 818
819 819 //******************************************
820 820 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
821 821 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) grspw_stats.parity_err;
822 822 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) grspw_stats.disconnect_err;
823 823 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) grspw_stats.escape_err;
824 824 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) grspw_stats.credit_err;
825 825 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) grspw_stats.write_sync_err;
826 826
827 827 //*********************************************
828 828 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
829 829 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) grspw_stats.early_ep;
830 830 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) grspw_stats.invalid_address;
831 831 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) grspw_stats.rx_eep_err;
832 832 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) grspw_stats.rx_truncated;
833 833 }
834 834
835 835 void spacewire_update_hk_lfr_link_state( unsigned char *hk_lfr_status_word_0 )
836 836 {
837 837 unsigned int *statusRegisterPtr;
838 838 unsigned char linkState;
839 839
840 840 statusRegisterPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_STATUS_REGISTER);
841 841 linkState =
842 842 (unsigned char) ( ( (*statusRegisterPtr) >> SPW_LINK_STAT_POS) & STATUS_WORD_LINK_STATE_BITS); // [0000 0111]
843 843
844 844 *hk_lfr_status_word_0 = *hk_lfr_status_word_0 & STATUS_WORD_LINK_STATE_MASK; // [1111 1000] set link state to 0
845 845
846 846 *hk_lfr_status_word_0 = *hk_lfr_status_word_0 | linkState; // update hk_lfr_dpu_spw_link_state
847 847 }
848 848
849 849 void increase_unsigned_char_counter( unsigned char *counter )
850 850 {
851 851 // update the number of valid timecodes that have been received
852 852 if (*counter == UINT8_MAX)
853 853 {
854 854 *counter = 0;
855 855 }
856 856 else
857 857 {
858 858 *counter = *counter + 1;
859 859 }
860 860 }
861 861
862 862 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
863 863 {
864 864 /** This function checks the coherency between the incoming timecode and the last valid timecode.
865 865 *
866 866 * @param currentTimecodeCtr is the incoming timecode
867 867 *
868 868 * @return returned codes::
869 869 * - LFR_DEFAULT
870 870 * - LFR_SUCCESSFUL
871 871 *
872 872 */
873 873
874 874 static unsigned char firstTickout = 1;
875 875 unsigned char ret;
876 876
877 877 ret = LFR_DEFAULT;
878 878
879 879 if (firstTickout == 0)
880 880 {
881 881 if (currentTimecodeCtr == 0)
882 882 {
883 883 if (previousTimecodeCtr == SPW_TIMECODE_MAX)
884 884 {
885 885 ret = LFR_SUCCESSFUL;
886 886 }
887 887 else
888 888 {
889 889 ret = LFR_DEFAULT;
890 890 }
891 891 }
892 892 else
893 893 {
894 894 if (currentTimecodeCtr == (previousTimecodeCtr +1))
895 895 {
896 896 ret = LFR_SUCCESSFUL;
897 897 }
898 898 else
899 899 {
900 900 ret = LFR_DEFAULT;
901 901 }
902 902 }
903 903 }
904 904 else
905 905 {
906 906 firstTickout = 0;
907 907 ret = LFR_SUCCESSFUL;
908 908 }
909 909
910 910 return ret;
911 911 }
912 912
913 913 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
914 914 {
915 915 unsigned int ret;
916 916
917 917 ret = LFR_DEFAULT;
918 918
919 919 if (timecode == internalTime)
920 920 {
921 921 ret = LFR_SUCCESSFUL;
922 922 }
923 923 else
924 924 {
925 925 ret = LFR_DEFAULT;
926 926 }
927 927
928 928 return ret;
929 929 }
930 930
931 931 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
932 932 {
933 933 // a tickout has been emitted, perform actions on the incoming timecode
934 934
935 935 unsigned char incomingTimecode;
936 936 unsigned char updateTime;
937 937 unsigned char internalTime;
938 938 rtems_status_code status;
939 939
940 940 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
941 941 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
942 942 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
943 943
944 944 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
945 945
946 946 // update the number of tickout that have been generated
947 947 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
948 948
949 949 //**************************
950 950 // HK_LFR_TIMECODE_ERRONEOUS
951 951 // MISSING and INVALID are handled by the timecode_timer_routine service routine
952 952 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
953 953 {
954 954 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
955 955 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
956 956 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_ERRONEOUS );
957 957 }
958 958
959 959 //************************
960 960 // HK_LFR_TIME_TIMECODE_IT
961 961 // check the coherency between the SpaceWire timecode and the Internal Time
962 962 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
963 963 {
964 964 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
965 965 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_IT );
966 966 }
967 967
968 968 //********************
969 969 // HK_LFR_TIMECODE_CTR
970 970 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
971 971 if (oneTcLfrUpdateTimeReceived == 1)
972 972 {
973 973 if ( incomingTimecode != updateTime )
974 974 {
975 975 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
976 976 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_CTR );
977 977 }
978 978 }
979 979
980 980 // launch the timecode timer to detect missing or invalid timecodes
981 981 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
982 982 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
983 983 if (status != RTEMS_SUCCESSFUL)
984 984 {
985 985 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
986 986 }
987 987 }
988 988
989 989 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
990 990 {
991 991 static unsigned char initStep = 1;
992 992
993 993 unsigned char currentTimecodeCtr;
994 994
995 995 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
996 996
997 997 if (initStep == 1)
998 998 {
999 999 if (currentTimecodeCtr == previousTimecodeCtr)
1000 1000 {
1001 1001 //************************
1002 1002 // HK_LFR_TIMECODE_MISSING
1003 1003 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
1004 1004 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
1005 1005 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
1006 1006 }
1007 1007 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
1008 1008 {
1009 1009 // the timecode value has changed and the value is valid, this is unexpected because
1010 1010 // the timer should not have fired, the timecode_irq_handler should have been raised
1011 1011 }
1012 1012 else
1013 1013 {
1014 1014 //************************
1015 1015 // HK_LFR_TIMECODE_INVALID
1016 1016 // the timecode value has changed and the value is not valid, no tickout has been generated
1017 1017 // this is why the timer has fired
1018 1018 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
1019 1019 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_INVALID );
1020 1020 }
1021 1021 }
1022 1022 else
1023 1023 {
1024 1024 initStep = 1;
1025 1025 //************************
1026 1026 // HK_LFR_TIMECODE_MISSING
1027 1027 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
1028 1028 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
1029 1029 }
1030 1030
1031 1031 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
1032 1032 }
1033 1033
1034 1034 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
1035 1035 {
1036 1036 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1037 1037 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1038 1038 header->reserved = DEFAULT_RESERVED;
1039 1039 header->userApplication = CCSDS_USER_APP;
1040 1040 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
1041 1041 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
1042 1042 header->packetLength[0] = INIT_CHAR;
1043 1043 header->packetLength[1] = INIT_CHAR;
1044 1044 // DATA FIELD HEADER
1045 1045 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1046 1046 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1047 1047 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1048 1048 header->destinationID = TM_DESTINATION_ID_GROUND;
1049 1049 header->time[BYTE_0] = INIT_CHAR;
1050 1050 header->time[BYTE_1] = INIT_CHAR;
1051 1051 header->time[BYTE_2] = INIT_CHAR;
1052 1052 header->time[BYTE_3] = INIT_CHAR;
1053 1053 header->time[BYTE_4] = INIT_CHAR;
1054 1054 header->time[BYTE_5] = INIT_CHAR;
1055 1055 // AUXILIARY DATA HEADER
1056 1056 header->sid = INIT_CHAR;
1057 1057 header->pa_bia_status_info = DEFAULT_HKBIA;
1058 1058 header->blkNr[0] = INIT_CHAR;
1059 1059 header->blkNr[1] = INIT_CHAR;
1060 1060 }
1061 1061
1062 1062 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
1063 1063 {
1064 1064 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1065 1065 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1066 1066 header->reserved = DEFAULT_RESERVED;
1067 1067 header->userApplication = CCSDS_USER_APP;
1068 1068 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1069 1069 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1070 1070 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1071 1071 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1072 1072 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> SHIFT_1_BYTE);
1073 1073 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1074 1074 // DATA FIELD HEADER
1075 1075 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1076 1076 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1077 1077 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1078 1078 header->destinationID = TM_DESTINATION_ID_GROUND;
1079 1079 header->time[BYTE_0] = INIT_CHAR;
1080 1080 header->time[BYTE_1] = INIT_CHAR;
1081 1081 header->time[BYTE_2] = INIT_CHAR;
1082 1082 header->time[BYTE_3] = INIT_CHAR;
1083 1083 header->time[BYTE_4] = INIT_CHAR;
1084 1084 header->time[BYTE_5] = INIT_CHAR;
1085 1085 // AUXILIARY DATA HEADER
1086 1086 header->sid = INIT_CHAR;
1087 1087 header->pa_bia_status_info = DEFAULT_HKBIA;
1088 1088 header->pktCnt = PKTCNT_SWF; // PKT_CNT
1089 1089 header->pktNr = INIT_CHAR;
1090 1090 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> SHIFT_1_BYTE);
1091 1091 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1092 1092 }
1093 1093
1094 1094 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
1095 1095 {
1096 1096 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1097 1097 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1098 1098 header->reserved = DEFAULT_RESERVED;
1099 1099 header->userApplication = CCSDS_USER_APP;
1100 1100 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1101 1101 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1102 1102 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1103 1103 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1104 1104 header->packetLength[0] = INIT_CHAR;
1105 1105 header->packetLength[1] = INIT_CHAR;
1106 1106 // DATA FIELD HEADER
1107 1107 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1108 1108 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1109 1109 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
1110 1110 header->destinationID = TM_DESTINATION_ID_GROUND;
1111 1111 header->time[BYTE_0] = INIT_CHAR;
1112 1112 header->time[BYTE_1] = INIT_CHAR;
1113 1113 header->time[BYTE_2] = INIT_CHAR;
1114 1114 header->time[BYTE_3] = INIT_CHAR;
1115 1115 header->time[BYTE_4] = INIT_CHAR;
1116 1116 header->time[BYTE_5] = INIT_CHAR;
1117 1117 // AUXILIARY DATA HEADER
1118 1118 header->sid = INIT_CHAR;
1119 1119 header->pa_bia_status_info = INIT_CHAR;
1120 1120 header->pa_lfr_pkt_cnt_asm = INIT_CHAR;
1121 1121 header->pa_lfr_pkt_nr_asm = INIT_CHAR;
1122 1122 header->pa_lfr_asm_blk_nr[0] = INIT_CHAR;
1123 1123 header->pa_lfr_asm_blk_nr[1] = INIT_CHAR;
1124 1124 }
1125 1125
1126 1126 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
1127 1127 Header_TM_LFR_SCIENCE_CWF_t *header )
1128 1128 {
1129 1129 /** This function sends CWF CCSDS packets (F2, F1 or F0).
1130 1130 *
1131 1131 * @param waveform points to the buffer containing the data that will be send.
1132 1132 * @param sid is the source identifier of the data that will be sent.
1133 1133 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1134 1134 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1135 1135 * contain information to setup the transmission of the data packets.
1136 1136 *
1137 1137 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1138 1138 *
1139 1139 */
1140 1140
1141 1141 unsigned int i;
1142 1142 int ret;
1143 1143 unsigned int coarseTime;
1144 1144 unsigned int fineTime;
1145 1145 rtems_status_code status;
1146 1146 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1147 1147 int *dataPtr;
1148 1148 unsigned char sid;
1149 1149
1150 1150 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1151 1151 spw_ioctl_send_CWF.options = 0;
1152 1152
1153 1153 ret = LFR_DEFAULT;
1154 1154 sid = (unsigned char) ring_node_to_send->sid;
1155 1155
1156 1156 coarseTime = ring_node_to_send->coarseTime;
1157 1157 fineTime = ring_node_to_send->fineTime;
1158 1158 dataPtr = (int*) ring_node_to_send->buffer_address;
1159 1159
1160 1160 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> SHIFT_1_BYTE);
1161 1161 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1162 1162 header->pa_bia_status_info = pa_bia_status_info;
1163 1163 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1164 1164 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> SHIFT_1_BYTE);
1165 1165 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1166 1166
1167 1167 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
1168 1168 {
1169 1169 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
1170 1170 spw_ioctl_send_CWF.hdr = (char*) header;
1171 1171 // BUILD THE DATA
1172 1172 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
1173 1173
1174 1174 // SET PACKET SEQUENCE CONTROL
1175 1175 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1176 1176
1177 1177 // SET SID
1178 1178 header->sid = sid;
1179 1179
1180 1180 // SET PACKET TIME
1181 1181 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
1182 1182 //
1183 1183 header->time[0] = header->acquisitionTime[0];
1184 1184 header->time[1] = header->acquisitionTime[1];
1185 1185 header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1186 1186 header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1187 1187 header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1188 1188 header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1189 1189
1190 1190 // SET PACKET ID
1191 1191 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
1192 1192 {
1193 1193 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> SHIFT_1_BYTE);
1194 1194 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
1195 1195 }
1196 1196 else
1197 1197 {
1198 1198 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1199 1199 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1200 1200 }
1201 1201
1202 1202 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1203 1203 if (status != RTEMS_SUCCESSFUL) {
1204 1204 ret = LFR_DEFAULT;
1205 1205 }
1206 1206 }
1207 1207
1208 1208 return ret;
1209 1209 }
1210 1210
1211 1211 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1212 1212 Header_TM_LFR_SCIENCE_SWF_t *header )
1213 1213 {
1214 1214 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1215 1215 *
1216 1216 * @param waveform points to the buffer containing the data that will be send.
1217 1217 * @param sid is the source identifier of the data that will be sent.
1218 1218 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1219 1219 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1220 1220 * contain information to setup the transmission of the data packets.
1221 1221 *
1222 1222 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1223 1223 *
1224 1224 */
1225 1225
1226 1226 unsigned int i;
1227 1227 int ret;
1228 1228 unsigned int coarseTime;
1229 1229 unsigned int fineTime;
1230 1230 rtems_status_code status;
1231 1231 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1232 1232 int *dataPtr;
1233 1233 unsigned char sid;
1234 1234
1235 1235 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1236 1236 spw_ioctl_send_SWF.options = 0;
1237 1237
1238 1238 ret = LFR_DEFAULT;
1239 1239
1240 1240 coarseTime = ring_node_to_send->coarseTime;
1241 1241 fineTime = ring_node_to_send->fineTime;
1242 1242 dataPtr = (int*) ring_node_to_send->buffer_address;
1243 1243 sid = ring_node_to_send->sid;
1244 1244
1245 1245 header->pa_bia_status_info = pa_bia_status_info;
1246 1246 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1247 1247
1248 1248 for (i=0; i<PKTCNT_SWF; i++) // send waveform
1249 1249 {
1250 1250 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1251 1251 spw_ioctl_send_SWF.hdr = (char*) header;
1252 1252
1253 1253 // SET PACKET SEQUENCE CONTROL
1254 1254 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1255 1255
1256 1256 // SET PACKET LENGTH AND BLKNR
1257 1257 if (i == (PKTCNT_SWF-1))
1258 1258 {
1259 1259 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1260 1260 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> SHIFT_1_BYTE);
1261 1261 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1262 1262 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> SHIFT_1_BYTE);
1263 1263 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1264 1264 }
1265 1265 else
1266 1266 {
1267 1267 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1268 1268 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> SHIFT_1_BYTE);
1269 1269 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1270 1270 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> SHIFT_1_BYTE);
1271 1271 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1272 1272 }
1273 1273
1274 1274 // SET PACKET TIME
1275 1275 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1276 1276 //
1277 1277 header->time[BYTE_0] = header->acquisitionTime[BYTE_0];
1278 1278 header->time[BYTE_1] = header->acquisitionTime[BYTE_1];
1279 1279 header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1280 1280 header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1281 1281 header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1282 1282 header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1283 1283
1284 1284 // SET SID
1285 1285 header->sid = sid;
1286 1286
1287 1287 // SET PKTNR
1288 1288 header->pktNr = i+1; // PKT_NR
1289 1289
1290 1290 // SEND PACKET
1291 1291 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1292 1292 if (status != RTEMS_SUCCESSFUL) {
1293 1293 ret = LFR_DEFAULT;
1294 1294 }
1295 1295 }
1296 1296
1297 1297 return ret;
1298 1298 }
1299 1299
1300 1300 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1301 1301 Header_TM_LFR_SCIENCE_CWF_t *header )
1302 1302 {
1303 1303 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1304 1304 *
1305 1305 * @param waveform points to the buffer containing the data that will be send.
1306 1306 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1307 1307 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1308 1308 * contain information to setup the transmission of the data packets.
1309 1309 *
1310 1310 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1311 1311 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1312 1312 *
1313 1313 */
1314 1314
1315 1315 unsigned int i;
1316 1316 int ret;
1317 1317 unsigned int coarseTime;
1318 1318 unsigned int fineTime;
1319 1319 rtems_status_code status;
1320 1320 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1321 1321 char *dataPtr;
1322 1322 unsigned char sid;
1323 1323
1324 1324 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1325 1325 spw_ioctl_send_CWF.options = 0;
1326 1326
1327 1327 ret = LFR_DEFAULT;
1328 1328 sid = ring_node_to_send->sid;
1329 1329
1330 1330 coarseTime = ring_node_to_send->coarseTime;
1331 1331 fineTime = ring_node_to_send->fineTime;
1332 1332 dataPtr = (char*) ring_node_to_send->buffer_address;
1333 1333
1334 1334 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> SHIFT_1_BYTE);
1335 1335 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1336 1336 header->pa_bia_status_info = pa_bia_status_info;
1337 1337 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1338 1338 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> SHIFT_1_BYTE);
1339 1339 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1340 1340
1341 1341 //*********************
1342 1342 // SEND CWF3_light DATA
1343 1343 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1344 1344 {
1345 1345 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1346 1346 spw_ioctl_send_CWF.hdr = (char*) header;
1347 1347 // BUILD THE DATA
1348 1348 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1349 1349
1350 1350 // SET PACKET SEQUENCE COUNTER
1351 1351 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1352 1352
1353 1353 // SET SID
1354 1354 header->sid = sid;
1355 1355
1356 1356 // SET PACKET TIME
1357 1357 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1358 1358 //
1359 1359 header->time[BYTE_0] = header->acquisitionTime[BYTE_0];
1360 1360 header->time[BYTE_1] = header->acquisitionTime[BYTE_1];
1361 1361 header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
1362 1362 header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
1363 1363 header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
1364 1364 header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
1365 1365
1366 1366 // SET PACKET ID
1367 1367 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
1368 1368 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1369 1369
1370 1370 // SEND PACKET
1371 1371 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1372 1372 if (status != RTEMS_SUCCESSFUL) {
1373 1373 ret = LFR_DEFAULT;
1374 1374 }
1375 1375 }
1376 1376
1377 1377 return ret;
1378 1378 }
1379 1379
1380 1380 void spw_send_asm_f0( ring_node *ring_node_to_send,
1381 1381 Header_TM_LFR_SCIENCE_ASM_t *header )
1382 1382 {
1383 1383 unsigned int i;
1384 1384 unsigned int length = 0;
1385 1385 rtems_status_code status;
1386 1386 unsigned int sid;
1387 1387 float *spectral_matrix;
1388 1388 int coarseTime;
1389 1389 int fineTime;
1390 1390 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1391 1391
1392 1392 sid = ring_node_to_send->sid;
1393 1393 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1394 1394 coarseTime = ring_node_to_send->coarseTime;
1395 1395 fineTime = ring_node_to_send->fineTime;
1396 1396
1397 1397 header->pa_bia_status_info = pa_bia_status_info;
1398 1398 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1399 1399
1400 1400 for (i=0; i<PKTCNT_ASM; i++)
1401 1401 {
1402 1402 if ((i==0) || (i==1))
1403 1403 {
1404 1404 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1405 1405 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1406 1406 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1407 1407 ];
1408 1408 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1409 1409 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1410 1410 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> SHIFT_1_BYTE ); // BLK_NR MSB
1411 1411 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1412 1412 }
1413 1413 else
1414 1414 {
1415 1415 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1416 1416 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1417 1417 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1418 1418 ];
1419 1419 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1420 1420 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1421 1421 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1422 1422 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1423 1423 }
1424 1424
1425 1425 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1426 1426 spw_ioctl_send_ASM.hdr = (char *) header;
1427 1427 spw_ioctl_send_ASM.options = 0;
1428 1428
1429 1429 // (2) BUILD THE HEADER
1430 1430 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1431 1431 header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1432 1432 header->packetLength[1] = (unsigned char) (length);
1433 1433 header->sid = (unsigned char) sid; // SID
1434 1434 header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1435 1435 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1436 1436
1437 1437 // (3) SET PACKET TIME
1438 1438 header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1439 1439 header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1440 1440 header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1441 1441 header->time[BYTE_3] = (unsigned char) (coarseTime);
1442 1442 header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1443 1443 header->time[BYTE_5] = (unsigned char) (fineTime);
1444 1444 //
1445 1445 header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1446 1446 header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1447 1447 header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1448 1448 header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1449 1449 header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1450 1450 header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1451 1451
1452 1452 // (4) SEND PACKET
1453 1453 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1454 1454 if (status != RTEMS_SUCCESSFUL) {
1455 1455 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1456 1456 }
1457 1457 }
1458 1458 }
1459 1459
1460 1460 void spw_send_asm_f1( ring_node *ring_node_to_send,
1461 1461 Header_TM_LFR_SCIENCE_ASM_t *header )
1462 1462 {
1463 1463 unsigned int i;
1464 1464 unsigned int length = 0;
1465 1465 rtems_status_code status;
1466 1466 unsigned int sid;
1467 1467 float *spectral_matrix;
1468 1468 int coarseTime;
1469 1469 int fineTime;
1470 1470 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1471 1471
1472 1472 sid = ring_node_to_send->sid;
1473 1473 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1474 1474 coarseTime = ring_node_to_send->coarseTime;
1475 1475 fineTime = ring_node_to_send->fineTime;
1476 1476
1477 1477 header->pa_bia_status_info = pa_bia_status_info;
1478 1478 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1479 1479
1480 1480 for (i=0; i<PKTCNT_ASM; i++)
1481 1481 {
1482 1482 if ((i==0) || (i==1))
1483 1483 {
1484 1484 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1485 1485 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1486 1486 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1487 1487 ];
1488 1488 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1489 1489 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1490 1490 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> SHIFT_1_BYTE ); // BLK_NR MSB
1491 1491 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1492 1492 }
1493 1493 else
1494 1494 {
1495 1495 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1496 1496 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1497 1497 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1498 1498 ];
1499 1499 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1500 1500 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1501 1501 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1502 1502 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1503 1503 }
1504 1504
1505 1505 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1506 1506 spw_ioctl_send_ASM.hdr = (char *) header;
1507 1507 spw_ioctl_send_ASM.options = 0;
1508 1508
1509 1509 // (2) BUILD THE HEADER
1510 1510 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1511 1511 header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1512 1512 header->packetLength[1] = (unsigned char) (length);
1513 1513 header->sid = (unsigned char) sid; // SID
1514 1514 header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1515 1515 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1516 1516
1517 1517 // (3) SET PACKET TIME
1518 1518 header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1519 1519 header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1520 1520 header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1521 1521 header->time[BYTE_3] = (unsigned char) (coarseTime);
1522 1522 header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1523 1523 header->time[BYTE_5] = (unsigned char) (fineTime);
1524 1524 //
1525 1525 header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1526 1526 header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1527 1527 header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1528 1528 header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1529 1529 header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1530 1530 header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1531 1531
1532 1532 // (4) SEND PACKET
1533 1533 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1534 1534 if (status != RTEMS_SUCCESSFUL) {
1535 1535 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1536 1536 }
1537 1537 }
1538 1538 }
1539 1539
1540 1540 void spw_send_asm_f2( ring_node *ring_node_to_send,
1541 1541 Header_TM_LFR_SCIENCE_ASM_t *header )
1542 1542 {
1543 1543 unsigned int i;
1544 1544 unsigned int length = 0;
1545 1545 rtems_status_code status;
1546 1546 unsigned int sid;
1547 1547 float *spectral_matrix;
1548 1548 int coarseTime;
1549 1549 int fineTime;
1550 1550 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1551 1551
1552 1552 sid = ring_node_to_send->sid;
1553 1553 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1554 1554 coarseTime = ring_node_to_send->coarseTime;
1555 1555 fineTime = ring_node_to_send->fineTime;
1556 1556
1557 1557 header->pa_bia_status_info = pa_bia_status_info;
1558 1558 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1559 1559
1560 1560 for (i=0; i<PKTCNT_ASM; i++)
1561 1561 {
1562 1562
1563 1563 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1564 1564 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1565 1565 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1566 1566 ];
1567 1567 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1568 1568 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1569 1569 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> SHIFT_1_BYTE ); // BLK_NR MSB
1570 1570 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1571 1571
1572 1572 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1573 1573 spw_ioctl_send_ASM.hdr = (char *) header;
1574 1574 spw_ioctl_send_ASM.options = 0;
1575 1575
1576 1576 // (2) BUILD THE HEADER
1577 1577 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1578 1578 header->packetLength[0] = (unsigned char) (length >> SHIFT_1_BYTE);
1579 1579 header->packetLength[1] = (unsigned char) (length);
1580 1580 header->sid = (unsigned char) sid; // SID
1581 1581 header->pa_lfr_pkt_cnt_asm = PKTCNT_ASM;
1582 1582 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1583 1583
1584 1584 // (3) SET PACKET TIME
1585 1585 header->time[BYTE_0] = (unsigned char) (coarseTime >> SHIFT_3_BYTES);
1586 1586 header->time[BYTE_1] = (unsigned char) (coarseTime >> SHIFT_2_BYTES);
1587 1587 header->time[BYTE_2] = (unsigned char) (coarseTime >> SHIFT_1_BYTE);
1588 1588 header->time[BYTE_3] = (unsigned char) (coarseTime);
1589 1589 header->time[BYTE_4] = (unsigned char) (fineTime >> SHIFT_1_BYTE);
1590 1590 header->time[BYTE_5] = (unsigned char) (fineTime);
1591 1591 //
1592 1592 header->acquisitionTime[BYTE_0] = header->time[BYTE_0];
1593 1593 header->acquisitionTime[BYTE_1] = header->time[BYTE_1];
1594 1594 header->acquisitionTime[BYTE_2] = header->time[BYTE_2];
1595 1595 header->acquisitionTime[BYTE_3] = header->time[BYTE_3];
1596 1596 header->acquisitionTime[BYTE_4] = header->time[BYTE_4];
1597 1597 header->acquisitionTime[BYTE_5] = header->time[BYTE_5];
1598 1598
1599 1599 // (4) SEND PACKET
1600 1600 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1601 1601 if (status != RTEMS_SUCCESSFUL) {
1602 1602 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1603 1603 }
1604 1604 }
1605 1605 }
1606 1606
1607 1607 void spw_send_k_dump( ring_node *ring_node_to_send )
1608 1608 {
1609 1609 rtems_status_code status;
1610 1610 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1611 1611 unsigned int packetLength;
1612 1612 unsigned int size;
1613 1613
1614 1614 PRINTF("spw_send_k_dump\n")
1615 1615
1616 1616 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1617 1617
1618 1618 packetLength = (kcoefficients_dump->packetLength[0] * CONST_256) + kcoefficients_dump->packetLength[1];
1619 1619
1620 1620 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1621 1621
1622 1622 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1623 1623
1624 1624 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1625 1625
1626 1626 if (status == -1){
1627 1627 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1628 1628 }
1629 1629
1630 1630 ring_node_to_send->status = INIT_CHAR;
1631 1631 }
@@ -1,1661 +1,1663
1 1 /** Functions and tasks related to TeleCommand handling.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle TeleCommands:\n
7 7 * action launching\n
8 8 * TC parsing\n
9 9 * ...
10 10 *
11 11 */
12 12
13 13 #include "tc_handler.h"
14 14 #include "math.h"
15 15
16 16 //***********
17 17 // RTEMS TASK
18 18
19 19 rtems_task actn_task( rtems_task_argument unused )
20 20 {
21 21 /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
22 22 *
23 23 * @param unused is the starting argument of the RTEMS task
24 24 *
25 25 * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
26 26 * on the incoming TeleCommand.
27 27 *
28 28 */
29 29
30 30 int result;
31 31 rtems_status_code status; // RTEMS status code
32 32 ccsdsTelecommandPacket_t TC; // TC sent to the ACTN task
33 33 size_t size; // size of the incoming TC packet
34 34 unsigned char subtype; // subtype of the current TC packet
35 35 unsigned char time[BYTES_PER_TIME];
36 36 rtems_id queue_rcv_id;
37 37 rtems_id queue_snd_id;
38 38
39 39 memset(&TC, 0, sizeof(ccsdsTelecommandPacket_t));
40 40 size = 0;
41 41 queue_rcv_id = RTEMS_ID_NONE;
42 42 queue_snd_id = RTEMS_ID_NONE;
43 43
44 44 status = get_message_queue_id_recv( &queue_rcv_id );
45 45 if (status != RTEMS_SUCCESSFUL)
46 46 {
47 47 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
48 48 }
49 49
50 50 status = get_message_queue_id_send( &queue_snd_id );
51 51 if (status != RTEMS_SUCCESSFUL)
52 52 {
53 53 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
54 54 }
55 55
56 56 result = LFR_SUCCESSFUL;
57 57 subtype = 0; // subtype of the current TC packet
58 58
59 59 BOOT_PRINTF("in ACTN *** \n");
60 60
61 61 while(1)
62 62 {
63 63 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
64 64 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
65 65 getTime( time ); // set time to the current time
66 66 if (status!=RTEMS_SUCCESSFUL)
67 67 {
68 68 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
69 69 }
70 70 else
71 71 {
72 72 subtype = TC.serviceSubType;
73 73 switch(subtype)
74 74 {
75 75 case TC_SUBTYPE_RESET:
76 76 result = action_reset( &TC, queue_snd_id, time );
77 77 close_action( &TC, result, queue_snd_id );
78 78 break;
79 79 case TC_SUBTYPE_LOAD_COMM:
80 80 result = action_load_common_par( &TC );
81 81 close_action( &TC, result, queue_snd_id );
82 82 break;
83 83 case TC_SUBTYPE_LOAD_NORM:
84 84 result = action_load_normal_par( &TC, queue_snd_id, time );
85 85 close_action( &TC, result, queue_snd_id );
86 86 break;
87 87 case TC_SUBTYPE_LOAD_BURST:
88 88 result = action_load_burst_par( &TC, queue_snd_id, time );
89 89 close_action( &TC, result, queue_snd_id );
90 90 break;
91 91 case TC_SUBTYPE_LOAD_SBM1:
92 92 result = action_load_sbm1_par( &TC, queue_snd_id, time );
93 93 close_action( &TC, result, queue_snd_id );
94 94 break;
95 95 case TC_SUBTYPE_LOAD_SBM2:
96 96 result = action_load_sbm2_par( &TC, queue_snd_id, time );
97 97 close_action( &TC, result, queue_snd_id );
98 98 break;
99 99 case TC_SUBTYPE_DUMP:
100 100 result = action_dump_par( &TC, queue_snd_id );
101 101 close_action( &TC, result, queue_snd_id );
102 102 break;
103 103 case TC_SUBTYPE_ENTER:
104 104 result = action_enter_mode( &TC, queue_snd_id );
105 105 close_action( &TC, result, queue_snd_id );
106 106 break;
107 107 case TC_SUBTYPE_UPDT_INFO:
108 108 result = action_update_info( &TC, queue_snd_id );
109 109 close_action( &TC, result, queue_snd_id );
110 110 break;
111 111 case TC_SUBTYPE_EN_CAL:
112 112 result = action_enable_calibration( &TC, queue_snd_id, time );
113 113 close_action( &TC, result, queue_snd_id );
114 114 break;
115 115 case TC_SUBTYPE_DIS_CAL:
116 116 result = action_disable_calibration( &TC, queue_snd_id, time );
117 117 close_action( &TC, result, queue_snd_id );
118 118 break;
119 119 case TC_SUBTYPE_LOAD_K:
120 120 result = action_load_kcoefficients( &TC, queue_snd_id, time );
121 121 close_action( &TC, result, queue_snd_id );
122 122 break;
123 123 case TC_SUBTYPE_DUMP_K:
124 124 result = action_dump_kcoefficients( &TC, queue_snd_id, time );
125 125 close_action( &TC, result, queue_snd_id );
126 126 break;
127 127 case TC_SUBTYPE_LOAD_FBINS:
128 128 result = action_load_fbins_mask( &TC, queue_snd_id, time );
129 129 close_action( &TC, result, queue_snd_id );
130 130 break;
131 131 case TC_SUBTYPE_LOAD_FILTER_PAR:
132 132 result = action_load_filter_par( &TC, queue_snd_id, time );
133 133 close_action( &TC, result, queue_snd_id );
134 134 break;
135 135 case TC_SUBTYPE_UPDT_TIME:
136 136 result = action_update_time( &TC );
137 137 close_action( &TC, result, queue_snd_id );
138 138 break;
139 139 default:
140 140 break;
141 141 }
142 142 }
143 143 }
144 144 }
145 145
146 146 //***********
147 147 // TC ACTIONS
148 148
149 149 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
150 150 {
151 151 /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
152 152 *
153 153 * @param TC points to the TeleCommand packet that is being processed
154 154 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
155 155 *
156 156 */
157 157
158 158 PRINTF("this is the end!!!\n");
159 159 exit(0);
160 160
161 161 send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
162 162
163 163 return LFR_DEFAULT;
164 164 }
165 165
166 166 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
167 167 {
168 168 /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
169 169 *
170 170 * @param TC points to the TeleCommand packet that is being processed
171 171 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
172 172 *
173 173 */
174 174
175 175 rtems_status_code status;
176 176 unsigned char requestedMode;
177 177 unsigned int *transitionCoarseTime_ptr;
178 178 unsigned int transitionCoarseTime;
179 179 unsigned char * bytePosPtr;
180 180
181 181 bytePosPtr = (unsigned char *) &TC->packetID;
182 182
183 183 requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
184 184 transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
185 185 transitionCoarseTime = (*transitionCoarseTime_ptr) & COARSE_TIME_MASK;
186 186
187 187 status = check_mode_value( requestedMode );
188 188
189 189 if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent
190 190 {
191 191 send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
192 192 }
193 193
194 194 else // the mode value is valid, check the transition
195 195 {
196 196 status = check_mode_transition(requestedMode);
197 197 if (status != LFR_SUCCESSFUL)
198 198 {
199 199 PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
200 200 send_tm_lfr_tc_exe_not_executable( TC, queue_id );
201 201 }
202 202 }
203 203
204 204 if ( status == LFR_SUCCESSFUL ) // the transition is valid, check the date
205 205 {
206 206 status = check_transition_date( transitionCoarseTime );
207 207 if (status != LFR_SUCCESSFUL)
208 208 {
209 209 PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
210 210 send_tm_lfr_tc_exe_not_executable(TC, queue_id );
211 211 }
212 212 }
213 213
214 214 if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode
215 215 {
216 216 PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
217 217
218 218 switch(requestedMode)
219 219 {
220 220 case LFR_MODE_STANDBY:
221 221 status = enter_mode_standby();
222 222 break;
223 223 case LFR_MODE_NORMAL:
224 224 status = enter_mode_normal( transitionCoarseTime );
225 225 break;
226 226 case LFR_MODE_BURST:
227 227 status = enter_mode_burst( transitionCoarseTime );
228 228 break;
229 229 case LFR_MODE_SBM1:
230 230 status = enter_mode_sbm1( transitionCoarseTime );
231 231 break;
232 232 case LFR_MODE_SBM2:
233 233 status = enter_mode_sbm2( transitionCoarseTime );
234 234 break;
235 235 default:
236 236 break;
237 237 }
238 238
239 239 if (status != RTEMS_SUCCESSFUL)
240 240 {
241 241 status = LFR_EXE_ERROR;
242 242 }
243 243 }
244 244
245 245 return status;
246 246 }
247 247
248 248 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
249 249 {
250 250 /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
251 251 *
252 252 * @param TC points to the TeleCommand packet that is being processed
253 253 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
254 254 *
255 255 * @return LFR directive status code:
256 256 * - LFR_DEFAULT
257 257 * - LFR_SUCCESSFUL
258 258 *
259 259 */
260 260
261 261 unsigned int val;
262 262 int result;
263 263 unsigned int status;
264 264 unsigned char mode;
265 265 unsigned char * bytePosPtr;
266 266
267 267 bytePosPtr = (unsigned char *) &TC->packetID;
268 268
269 269 // check LFR mode
270 270 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
271 271 status = check_update_info_hk_lfr_mode( mode );
272 272 if (status == LFR_SUCCESSFUL) // check TDS mode
273 273 {
274 274 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
275 275 status = check_update_info_hk_tds_mode( mode );
276 276 }
277 277 if (status == LFR_SUCCESSFUL) // check THR mode
278 278 {
279 279 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_THR_MODE);
280 280 status = check_update_info_hk_thr_mode( mode );
281 281 }
282 282 if (status == LFR_SUCCESSFUL) // if the parameter check is successful
283 283 {
284 284 val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
285 285 + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
286 286 val++;
287 287 housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
288 288 housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
289 289 }
290 290
291 291 // pa_bia_status_info
292 292 // => pa_bia_mode_mux_set 3 bits
293 293 // => pa_bia_mode_hv_enabled 1 bit
294 294 // => pa_bia_mode_bias1_enabled 1 bit
295 295 // => pa_bia_mode_bias2_enabled 1 bit
296 296 // => pa_bia_mode_bias3_enabled 1 bit
297 297 // => pa_bia_on_off (cp_dpu_bias_on_off)
298 298 pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & BITS_BIA; // [1111 1110]
299 299 pa_bia_status_info = pa_bia_status_info
300 300 | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 1);
301 301
302 302 // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be copied in HK packets)
303 303
304 304 cp_rpw_sc_rw_f_flags = bytePosPtr[ BYTE_POS_UPDATE_INFO_CP_RPW_SC_RW_F_FLAGS ];
305 305 getReactionWheelsFrequencies( TC );
306 306 build_sy_lfr_rw_masks();
307 307
308 308 // once the masks are built, they have to be merged with the fbins_mask
309 309 merge_fbins_masks();
310 310
311 311 result = status;
312 312
313 313 return result;
314 314 }
315 315
316 316 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
317 317 {
318 318 /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
319 319 *
320 320 * @param TC points to the TeleCommand packet that is being processed
321 321 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
322 322 *
323 323 */
324 324
325 325 int result;
326 326
327 327 result = LFR_DEFAULT;
328 328
329 329 setCalibration( true );
330 330
331 331 result = LFR_SUCCESSFUL;
332 332
333 333 return result;
334 334 }
335 335
336 336 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
337 337 {
338 338 /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
339 339 *
340 340 * @param TC points to the TeleCommand packet that is being processed
341 341 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
342 342 *
343 343 */
344 344
345 345 int result;
346 346
347 347 result = LFR_DEFAULT;
348 348
349 349 setCalibration( false );
350 350
351 351 result = LFR_SUCCESSFUL;
352 352
353 353 return result;
354 354 }
355 355
356 356 int action_update_time(ccsdsTelecommandPacket_t *TC)
357 357 {
358 358 /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
359 359 *
360 360 * @param TC points to the TeleCommand packet that is being processed
361 361 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
362 362 *
363 363 * @return LFR_SUCCESSFUL
364 364 *
365 365 */
366 366
367 367 unsigned int val;
368 368
369 369 time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
370 370 + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES)
371 371 + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
372 372 + TC->dataAndCRC[BYTE_3];
373 373
374 374 val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
375 375 + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
376 376 val++;
377 377 housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
378 378 housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
379 379
380 380 oneTcLfrUpdateTimeReceived = 1;
381 381
382 382 return LFR_SUCCESSFUL;
383 383 }
384 384
385 385 //*******************
386 386 // ENTERING THE MODES
387 387 int check_mode_value( unsigned char requestedMode )
388 388 {
389 389 int status;
390 390
391 391 status = LFR_DEFAULT;
392 392
393 393 if ( (requestedMode != LFR_MODE_STANDBY)
394 394 && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
395 395 && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
396 396 {
397 397 status = LFR_DEFAULT;
398 398 }
399 399 else
400 400 {
401 401 status = LFR_SUCCESSFUL;
402 402 }
403 403
404 404 return status;
405 405 }
406 406
407 407 int check_mode_transition( unsigned char requestedMode )
408 408 {
409 409 /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
410 410 *
411 411 * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
412 412 *
413 413 * @return LFR directive status codes:
414 414 * - LFR_SUCCESSFUL - the transition is authorized
415 415 * - LFR_DEFAULT - the transition is not authorized
416 416 *
417 417 */
418 418
419 419 int status;
420 420
421 421 switch (requestedMode)
422 422 {
423 423 case LFR_MODE_STANDBY:
424 424 if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
425 425 status = LFR_DEFAULT;
426 426 }
427 427 else
428 428 {
429 429 status = LFR_SUCCESSFUL;
430 430 }
431 431 break;
432 432 case LFR_MODE_NORMAL:
433 433 if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
434 434 status = LFR_DEFAULT;
435 435 }
436 436 else {
437 437 status = LFR_SUCCESSFUL;
438 438 }
439 439 break;
440 440 case LFR_MODE_BURST:
441 441 if ( lfrCurrentMode == LFR_MODE_BURST ) {
442 442 status = LFR_DEFAULT;
443 443 }
444 444 else {
445 445 status = LFR_SUCCESSFUL;
446 446 }
447 447 break;
448 448 case LFR_MODE_SBM1:
449 449 if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
450 450 status = LFR_DEFAULT;
451 451 }
452 452 else {
453 453 status = LFR_SUCCESSFUL;
454 454 }
455 455 break;
456 456 case LFR_MODE_SBM2:
457 457 if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
458 458 status = LFR_DEFAULT;
459 459 }
460 460 else {
461 461 status = LFR_SUCCESSFUL;
462 462 }
463 463 break;
464 464 default:
465 465 status = LFR_DEFAULT;
466 466 break;
467 467 }
468 468
469 469 return status;
470 470 }
471 471
472 472 void update_last_valid_transition_date( unsigned int transitionCoarseTime )
473 473 {
474 474 if (transitionCoarseTime == 0)
475 475 {
476 476 lastValidEnterModeTime = time_management_regs->coarse_time + 1;
477 477 PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", lastValidEnterModeTime);
478 478 }
479 479 else
480 480 {
481 481 lastValidEnterModeTime = transitionCoarseTime;
482 482 PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
483 483 }
484 484 }
485 485
486 486 int check_transition_date( unsigned int transitionCoarseTime )
487 487 {
488 488 int status;
489 489 unsigned int localCoarseTime;
490 490 unsigned int deltaCoarseTime;
491 491
492 492 status = LFR_SUCCESSFUL;
493 493
494 494 if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
495 495 {
496 496 status = LFR_SUCCESSFUL;
497 497 }
498 498 else
499 499 {
500 500 localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
501 501
502 502 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
503 503
504 504 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
505 505 {
506 506 status = LFR_DEFAULT;
507 507 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
508 508 }
509 509
510 510 if (status == LFR_SUCCESSFUL)
511 511 {
512 512 deltaCoarseTime = transitionCoarseTime - localCoarseTime;
513 513 if ( deltaCoarseTime > MAX_DELTA_COARSE_TIME ) // SSS-CP-EQS-323
514 514 {
515 515 status = LFR_DEFAULT;
516 516 PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
517 517 }
518 518 }
519 519 }
520 520
521 521 return status;
522 522 }
523 523
524 524 int restart_asm_activities( unsigned char lfrRequestedMode )
525 525 {
526 526 rtems_status_code status;
527 527
528 528 status = stop_spectral_matrices();
529 529
530 530 thisIsAnASMRestart = 1;
531 531
532 532 status = restart_asm_tasks( lfrRequestedMode );
533 533
534 534 launch_spectral_matrix();
535 535
536 536 return status;
537 537 }
538 538
539 539 int stop_spectral_matrices( void )
540 540 {
541 541 /** This function stops and restarts the current mode average spectral matrices activities.
542 542 *
543 543 * @return RTEMS directive status codes:
544 544 * - RTEMS_SUCCESSFUL - task restarted successfully
545 545 * - RTEMS_INVALID_ID - task id invalid
546 546 * - RTEMS_ALREADY_SUSPENDED - task already suspended
547 547 *
548 548 */
549 549
550 550 rtems_status_code status;
551 551
552 552 status = RTEMS_SUCCESSFUL;
553 553
554 554 // (1) mask interruptions
555 555 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // mask spectral matrix interrupt
556 556
557 557 // (2) reset spectral matrices registers
558 558 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
559 559 reset_sm_status();
560 560
561 561 // (3) clear interruptions
562 562 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
563 563
564 564 // suspend several tasks
565 565 if (lfrCurrentMode != LFR_MODE_STANDBY) {
566 566 status = suspend_asm_tasks();
567 567 }
568 568
569 569 if (status != RTEMS_SUCCESSFUL)
570 570 {
571 571 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
572 572 }
573 573
574 574 return status;
575 575 }
576 576
577 577 int stop_current_mode( void )
578 578 {
579 579 /** This function stops the current mode by masking interrupt lines and suspending science tasks.
580 580 *
581 581 * @return RTEMS directive status codes:
582 582 * - RTEMS_SUCCESSFUL - task restarted successfully
583 583 * - RTEMS_INVALID_ID - task id invalid
584 584 * - RTEMS_ALREADY_SUSPENDED - task already suspended
585 585 *
586 586 */
587 587
588 588 rtems_status_code status;
589 589
590 590 status = RTEMS_SUCCESSFUL;
591 591
592 592 // (1) mask interruptions
593 593 LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt
594 594 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
595 595
596 596 // (2) reset waveform picker registers
597 597 reset_wfp_burst_enable(); // reset burst and enable bits
598 598 reset_wfp_status(); // reset all the status bits
599 599
600 600 // (3) reset spectral matrices registers
601 601 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
602 602 reset_sm_status();
603 603
604 604 // reset lfr VHDL module
605 605 reset_lfr();
606 606
607 607 reset_extractSWF(); // reset the extractSWF flag to false
608 608
609 609 // (4) clear interruptions
610 610 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt
611 611 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
612 612
613 613 // suspend several tasks
614 614 if (lfrCurrentMode != LFR_MODE_STANDBY) {
615 615 status = suspend_science_tasks();
616 616 }
617 617
618 618 if (status != RTEMS_SUCCESSFUL)
619 619 {
620 620 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
621 621 }
622 622
623 623 return status;
624 624 }
625 625
626 626 int enter_mode_standby( void )
627 627 {
628 628 /** This function is used to put LFR in the STANDBY mode.
629 629 *
630 630 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
631 631 *
632 632 * @return RTEMS directive status codes:
633 633 * - RTEMS_SUCCESSFUL - task restarted successfully
634 634 * - RTEMS_INVALID_ID - task id invalid
635 635 * - RTEMS_INCORRECT_STATE - task never started
636 636 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
637 637 *
638 638 * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
639 639 * is immediate.
640 640 *
641 641 */
642 642
643 643 int status;
644 644
645 645 status = stop_current_mode(); // STOP THE CURRENT MODE
646 646
647 647 #ifdef PRINT_TASK_STATISTICS
648 648 rtems_cpu_usage_report();
649 649 #endif
650 650
651 651 #ifdef PRINT_STACK_REPORT
652 652 PRINTF("stack report selected\n")
653 653 rtems_stack_checker_report_usage();
654 654 #endif
655 655
656 656 return status;
657 657 }
658 658
659 659 int enter_mode_normal( unsigned int transitionCoarseTime )
660 660 {
661 661 /** This function is used to start the NORMAL mode.
662 662 *
663 663 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
664 664 *
665 665 * @return RTEMS directive status codes:
666 666 * - RTEMS_SUCCESSFUL - task restarted successfully
667 667 * - RTEMS_INVALID_ID - task id invalid
668 668 * - RTEMS_INCORRECT_STATE - task never started
669 669 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
670 670 *
671 671 * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
672 672 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
673 673 *
674 674 */
675 675
676 676 int status;
677 677
678 678 #ifdef PRINT_TASK_STATISTICS
679 679 rtems_cpu_usage_reset();
680 680 #endif
681 681
682 682 status = RTEMS_UNSATISFIED;
683 683
684 684 switch( lfrCurrentMode )
685 685 {
686 686 case LFR_MODE_STANDBY:
687 687 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
688 688 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
689 689 {
690 690 launch_spectral_matrix( );
691 691 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
692 692 }
693 693 break;
694 694 case LFR_MODE_BURST:
695 695 status = stop_current_mode(); // stop the current mode
696 696 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
697 697 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
698 698 {
699 699 launch_spectral_matrix( );
700 700 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
701 701 }
702 702 break;
703 703 case LFR_MODE_SBM1:
704 704 status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
705 705 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
706 706 update_last_valid_transition_date( transitionCoarseTime );
707 707 break;
708 708 case LFR_MODE_SBM2:
709 709 status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
710 710 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
711 711 update_last_valid_transition_date( transitionCoarseTime );
712 712 break;
713 713 default:
714 714 break;
715 715 }
716 716
717 717 if (status != RTEMS_SUCCESSFUL)
718 718 {
719 719 PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
720 720 status = RTEMS_UNSATISFIED;
721 721 }
722 722
723 723 return status;
724 724 }
725 725
726 726 int enter_mode_burst( unsigned int transitionCoarseTime )
727 727 {
728 728 /** This function is used to start the BURST mode.
729 729 *
730 730 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
731 731 *
732 732 * @return RTEMS directive status codes:
733 733 * - RTEMS_SUCCESSFUL - task restarted successfully
734 734 * - RTEMS_INVALID_ID - task id invalid
735 735 * - RTEMS_INCORRECT_STATE - task never started
736 736 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
737 737 *
738 738 * The way the BURST mode is started does not depend on the LFR current mode.
739 739 *
740 740 */
741 741
742 742
743 743 int status;
744 744
745 745 #ifdef PRINT_TASK_STATISTICS
746 746 rtems_cpu_usage_reset();
747 747 #endif
748 748
749 749 status = stop_current_mode(); // stop the current mode
750 750 status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
751 751 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
752 752 {
753 753 launch_spectral_matrix( );
754 754 launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
755 755 }
756 756
757 757 if (status != RTEMS_SUCCESSFUL)
758 758 {
759 759 PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
760 760 status = RTEMS_UNSATISFIED;
761 761 }
762 762
763 763 return status;
764 764 }
765 765
766 766 int enter_mode_sbm1( unsigned int transitionCoarseTime )
767 767 {
768 768 /** This function is used to start the SBM1 mode.
769 769 *
770 770 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
771 771 *
772 772 * @return RTEMS directive status codes:
773 773 * - RTEMS_SUCCESSFUL - task restarted successfully
774 774 * - RTEMS_INVALID_ID - task id invalid
775 775 * - RTEMS_INCORRECT_STATE - task never started
776 776 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
777 777 *
778 778 * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
779 779 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
780 780 * cases, the acquisition is completely restarted.
781 781 *
782 782 */
783 783
784 784 int status;
785 785
786 786 #ifdef PRINT_TASK_STATISTICS
787 787 rtems_cpu_usage_reset();
788 788 #endif
789 789
790 790 status = RTEMS_UNSATISFIED;
791 791
792 792 switch( lfrCurrentMode )
793 793 {
794 794 case LFR_MODE_STANDBY:
795 795 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
796 796 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
797 797 {
798 798 launch_spectral_matrix( );
799 799 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
800 800 }
801 801 break;
802 802 case LFR_MODE_NORMAL: // lfrCurrentMode will be updated after the execution of close_action
803 803 status = restart_asm_activities( LFR_MODE_SBM1 );
804 804 status = LFR_SUCCESSFUL;
805 805 update_last_valid_transition_date( transitionCoarseTime );
806 806 break;
807 807 case LFR_MODE_BURST:
808 808 status = stop_current_mode(); // stop the current mode
809 809 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
810 810 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
811 811 {
812 812 launch_spectral_matrix( );
813 813 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
814 814 }
815 815 break;
816 816 case LFR_MODE_SBM2:
817 817 status = restart_asm_activities( LFR_MODE_SBM1 );
818 818 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
819 819 update_last_valid_transition_date( transitionCoarseTime );
820 820 break;
821 821 default:
822 822 break;
823 823 }
824 824
825 825 if (status != RTEMS_SUCCESSFUL)
826 826 {
827 827 PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
828 828 status = RTEMS_UNSATISFIED;
829 829 }
830 830
831 831 return status;
832 832 }
833 833
834 834 int enter_mode_sbm2( unsigned int transitionCoarseTime )
835 835 {
836 836 /** This function is used to start the SBM2 mode.
837 837 *
838 838 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
839 839 *
840 840 * @return RTEMS directive status codes:
841 841 * - RTEMS_SUCCESSFUL - task restarted successfully
842 842 * - RTEMS_INVALID_ID - task id invalid
843 843 * - RTEMS_INCORRECT_STATE - task never started
844 844 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
845 845 *
846 846 * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
847 847 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
848 848 * cases, the acquisition is completely restarted.
849 849 *
850 850 */
851 851
852 852 int status;
853 853
854 854 #ifdef PRINT_TASK_STATISTICS
855 855 rtems_cpu_usage_reset();
856 856 #endif
857 857
858 858 status = RTEMS_UNSATISFIED;
859 859
860 860 switch( lfrCurrentMode )
861 861 {
862 862 case LFR_MODE_STANDBY:
863 863 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
864 864 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
865 865 {
866 866 launch_spectral_matrix( );
867 867 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
868 868 }
869 869 break;
870 870 case LFR_MODE_NORMAL:
871 871 status = restart_asm_activities( LFR_MODE_SBM2 );
872 872 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
873 873 update_last_valid_transition_date( transitionCoarseTime );
874 874 break;
875 875 case LFR_MODE_BURST:
876 876 status = stop_current_mode(); // stop the current mode
877 877 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
878 878 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
879 879 {
880 880 launch_spectral_matrix( );
881 881 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
882 882 }
883 883 break;
884 884 case LFR_MODE_SBM1:
885 885 status = restart_asm_activities( LFR_MODE_SBM2 );
886 886 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
887 887 update_last_valid_transition_date( transitionCoarseTime );
888 888 break;
889 889 default:
890 890 break;
891 891 }
892 892
893 893 if (status != RTEMS_SUCCESSFUL)
894 894 {
895 895 PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
896 896 status = RTEMS_UNSATISFIED;
897 897 }
898 898
899 899 return status;
900 900 }
901 901
902 902 int restart_science_tasks( unsigned char lfrRequestedMode )
903 903 {
904 904 /** This function is used to restart all science tasks.
905 905 *
906 906 * @return RTEMS directive status codes:
907 907 * - RTEMS_SUCCESSFUL - task restarted successfully
908 908 * - RTEMS_INVALID_ID - task id invalid
909 909 * - RTEMS_INCORRECT_STATE - task never started
910 910 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
911 911 *
912 912 * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
913 913 *
914 914 */
915 915
916 916 rtems_status_code status[NB_SCIENCE_TASKS];
917 917 rtems_status_code ret;
918 918
919 919 ret = RTEMS_SUCCESSFUL;
920 920
921 921 status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
922 922 if (status[STATUS_0] != RTEMS_SUCCESSFUL)
923 923 {
924 924 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
925 925 }
926 926
927 927 status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
928 928 if (status[STATUS_1] != RTEMS_SUCCESSFUL)
929 929 {
930 930 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
931 931 }
932 932
933 933 status[STATUS_2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
934 934 if (status[STATUS_2] != RTEMS_SUCCESSFUL)
935 935 {
936 936 PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[STATUS_2])
937 937 }
938 938
939 939 status[STATUS_3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
940 940 if (status[STATUS_3] != RTEMS_SUCCESSFUL)
941 941 {
942 942 PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[STATUS_3])
943 943 }
944 944
945 945 status[STATUS_4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
946 946 if (status[STATUS_4] != RTEMS_SUCCESSFUL)
947 947 {
948 948 PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[STATUS_4])
949 949 }
950 950
951 951 status[STATUS_5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
952 952 if (status[STATUS_5] != RTEMS_SUCCESSFUL)
953 953 {
954 954 PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[STATUS_5])
955 955 }
956 956
957 957 status[STATUS_6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
958 958 if (status[STATUS_6] != RTEMS_SUCCESSFUL)
959 959 {
960 960 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_6])
961 961 }
962 962
963 963 status[STATUS_7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
964 964 if (status[STATUS_7] != RTEMS_SUCCESSFUL)
965 965 {
966 966 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_7])
967 967 }
968 968
969 969 status[STATUS_8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
970 970 if (status[STATUS_8] != RTEMS_SUCCESSFUL)
971 971 {
972 972 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_8])
973 973 }
974 974
975 975 status[STATUS_9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
976 976 if (status[STATUS_9] != RTEMS_SUCCESSFUL)
977 977 {
978 978 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_9])
979 979 }
980 980
981 981 if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
982 982 (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
983 983 (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) ||
984 984 (status[STATUS_6] != RTEMS_SUCCESSFUL) || (status[STATUS_7] != RTEMS_SUCCESSFUL) ||
985 985 (status[STATUS_8] != RTEMS_SUCCESSFUL) || (status[STATUS_9] != RTEMS_SUCCESSFUL) )
986 986 {
987 987 ret = RTEMS_UNSATISFIED;
988 988 }
989 989
990 990 return ret;
991 991 }
992 992
993 993 int restart_asm_tasks( unsigned char lfrRequestedMode )
994 994 {
995 995 /** This function is used to restart average spectral matrices tasks.
996 996 *
997 997 * @return RTEMS directive status codes:
998 998 * - RTEMS_SUCCESSFUL - task restarted successfully
999 999 * - RTEMS_INVALID_ID - task id invalid
1000 1000 * - RTEMS_INCORRECT_STATE - task never started
1001 1001 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1002 1002 *
1003 1003 * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1004 1004 *
1005 1005 */
1006 1006
1007 1007 rtems_status_code status[NB_ASM_TASKS];
1008 1008 rtems_status_code ret;
1009 1009
1010 1010 ret = RTEMS_SUCCESSFUL;
1011 1011
1012 1012 status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
1013 1013 if (status[STATUS_0] != RTEMS_SUCCESSFUL)
1014 1014 {
1015 1015 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
1016 1016 }
1017 1017
1018 1018 status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
1019 1019 if (status[STATUS_1] != RTEMS_SUCCESSFUL)
1020 1020 {
1021 1021 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
1022 1022 }
1023 1023
1024 1024 status[STATUS_2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
1025 1025 if (status[STATUS_2] != RTEMS_SUCCESSFUL)
1026 1026 {
1027 1027 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_2])
1028 1028 }
1029 1029
1030 1030 status[STATUS_3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1031 1031 if (status[STATUS_3] != RTEMS_SUCCESSFUL)
1032 1032 {
1033 1033 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_3])
1034 1034 }
1035 1035
1036 1036 status[STATUS_4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1037 1037 if (status[STATUS_4] != RTEMS_SUCCESSFUL)
1038 1038 {
1039 1039 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_4])
1040 1040 }
1041 1041
1042 1042 status[STATUS_5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1043 1043 if (status[STATUS_5] != RTEMS_SUCCESSFUL)
1044 1044 {
1045 1045 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_5])
1046 1046 }
1047 1047
1048 1048 if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1049 1049 (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1050 1050 (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) )
1051 1051 {
1052 1052 ret = RTEMS_UNSATISFIED;
1053 1053 }
1054 1054
1055 1055 return ret;
1056 1056 }
1057 1057
1058 1058 int suspend_science_tasks( void )
1059 1059 {
1060 1060 /** This function suspends the science tasks.
1061 1061 *
1062 1062 * @return RTEMS directive status codes:
1063 1063 * - RTEMS_SUCCESSFUL - task restarted successfully
1064 1064 * - RTEMS_INVALID_ID - task id invalid
1065 1065 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1066 1066 *
1067 1067 */
1068 1068
1069 1069 rtems_status_code status;
1070 1070
1071 1071 PRINTF("in suspend_science_tasks\n")
1072 1072
1073 1073 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1074 1074 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1075 1075 {
1076 1076 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1077 1077 }
1078 1078 else
1079 1079 {
1080 1080 status = RTEMS_SUCCESSFUL;
1081 1081 }
1082 1082 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1083 1083 {
1084 1084 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1085 1085 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1086 1086 {
1087 1087 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1088 1088 }
1089 1089 else
1090 1090 {
1091 1091 status = RTEMS_SUCCESSFUL;
1092 1092 }
1093 1093 }
1094 1094 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1095 1095 {
1096 1096 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1097 1097 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1098 1098 {
1099 1099 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1100 1100 }
1101 1101 else
1102 1102 {
1103 1103 status = RTEMS_SUCCESSFUL;
1104 1104 }
1105 1105 }
1106 1106 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1107 1107 {
1108 1108 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1109 1109 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1110 1110 {
1111 1111 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1112 1112 }
1113 1113 else
1114 1114 {
1115 1115 status = RTEMS_SUCCESSFUL;
1116 1116 }
1117 1117 }
1118 1118 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1119 1119 {
1120 1120 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1121 1121 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1122 1122 {
1123 1123 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1124 1124 }
1125 1125 else
1126 1126 {
1127 1127 status = RTEMS_SUCCESSFUL;
1128 1128 }
1129 1129 }
1130 1130 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1131 1131 {
1132 1132 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1133 1133 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1134 1134 {
1135 1135 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1136 1136 }
1137 1137 else
1138 1138 {
1139 1139 status = RTEMS_SUCCESSFUL;
1140 1140 }
1141 1141 }
1142 1142 if (status == RTEMS_SUCCESSFUL) // suspend WFRM
1143 1143 {
1144 1144 status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1145 1145 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1146 1146 {
1147 1147 PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1148 1148 }
1149 1149 else
1150 1150 {
1151 1151 status = RTEMS_SUCCESSFUL;
1152 1152 }
1153 1153 }
1154 1154 if (status == RTEMS_SUCCESSFUL) // suspend CWF3
1155 1155 {
1156 1156 status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1157 1157 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1158 1158 {
1159 1159 PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1160 1160 }
1161 1161 else
1162 1162 {
1163 1163 status = RTEMS_SUCCESSFUL;
1164 1164 }
1165 1165 }
1166 1166 if (status == RTEMS_SUCCESSFUL) // suspend CWF2
1167 1167 {
1168 1168 status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1169 1169 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1170 1170 {
1171 1171 PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1172 1172 }
1173 1173 else
1174 1174 {
1175 1175 status = RTEMS_SUCCESSFUL;
1176 1176 }
1177 1177 }
1178 1178 if (status == RTEMS_SUCCESSFUL) // suspend CWF1
1179 1179 {
1180 1180 status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1181 1181 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1182 1182 {
1183 1183 PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1184 1184 }
1185 1185 else
1186 1186 {
1187 1187 status = RTEMS_SUCCESSFUL;
1188 1188 }
1189 1189 }
1190 1190
1191 1191 return status;
1192 1192 }
1193 1193
1194 1194 int suspend_asm_tasks( void )
1195 1195 {
1196 1196 /** This function suspends the science tasks.
1197 1197 *
1198 1198 * @return RTEMS directive status codes:
1199 1199 * - RTEMS_SUCCESSFUL - task restarted successfully
1200 1200 * - RTEMS_INVALID_ID - task id invalid
1201 1201 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1202 1202 *
1203 1203 */
1204 1204
1205 1205 rtems_status_code status;
1206 1206
1207 1207 PRINTF("in suspend_science_tasks\n")
1208 1208
1209 1209 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1210 1210 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1211 1211 {
1212 1212 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1213 1213 }
1214 1214 else
1215 1215 {
1216 1216 status = RTEMS_SUCCESSFUL;
1217 1217 }
1218 1218
1219 1219 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1220 1220 {
1221 1221 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1222 1222 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1223 1223 {
1224 1224 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1225 1225 }
1226 1226 else
1227 1227 {
1228 1228 status = RTEMS_SUCCESSFUL;
1229 1229 }
1230 1230 }
1231 1231
1232 1232 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1233 1233 {
1234 1234 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1235 1235 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1236 1236 {
1237 1237 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1238 1238 }
1239 1239 else
1240 1240 {
1241 1241 status = RTEMS_SUCCESSFUL;
1242 1242 }
1243 1243 }
1244 1244
1245 1245 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1246 1246 {
1247 1247 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1248 1248 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1249 1249 {
1250 1250 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1251 1251 }
1252 1252 else
1253 1253 {
1254 1254 status = RTEMS_SUCCESSFUL;
1255 1255 }
1256 1256 }
1257 1257
1258 1258 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1259 1259 {
1260 1260 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1261 1261 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1262 1262 {
1263 1263 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1264 1264 }
1265 1265 else
1266 1266 {
1267 1267 status = RTEMS_SUCCESSFUL;
1268 1268 }
1269 1269 }
1270 1270
1271 1271 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1272 1272 {
1273 1273 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1274 1274 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1275 1275 {
1276 1276 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1277 1277 }
1278 1278 else
1279 1279 {
1280 1280 status = RTEMS_SUCCESSFUL;
1281 1281 }
1282 1282 }
1283 1283
1284 1284 return status;
1285 1285 }
1286 1286
1287 1287 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1288 1288 {
1289 1289
1290 1290 WFP_reset_current_ring_nodes();
1291 1291
1292 1292 reset_waveform_picker_regs();
1293 1293
1294 1294 set_wfp_burst_enable_register( mode );
1295 1295
1296 1296 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1297 1297 LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1298 1298
1299 1299 if (transitionCoarseTime == 0)
1300 1300 {
1301 1301 // instant transition means transition on the next valid date
1302 1302 // this is mandatory to have a good snapshot period and a good correction of the snapshot period
1303 1303 waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1304 1304 }
1305 1305 else
1306 1306 {
1307 1307 waveform_picker_regs->start_date = transitionCoarseTime;
1308 1308 }
1309 1309
1310 1310 update_last_valid_transition_date(waveform_picker_regs->start_date);
1311 1311
1312 1312 }
1313 1313
1314 1314 void launch_spectral_matrix( void )
1315 1315 {
1316 1316 SM_reset_current_ring_nodes();
1317 1317
1318 1318 reset_spectral_matrix_regs();
1319 1319
1320 1320 reset_nb_sm();
1321 1321
1322 1322 set_sm_irq_onNewMatrix( 1 );
1323 1323
1324 1324 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1325 1325 LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1326 1326
1327 1327 }
1328 1328
1329 1329 void set_sm_irq_onNewMatrix( unsigned char value )
1330 1330 {
1331 1331 if (value == 1)
1332 1332 {
1333 1333 spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1334 1334 }
1335 1335 else
1336 1336 {
1337 1337 spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX; // 1110
1338 1338 }
1339 1339 }
1340 1340
1341 1341 void set_sm_irq_onError( unsigned char value )
1342 1342 {
1343 1343 if (value == 1)
1344 1344 {
1345 1345 spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1346 1346 }
1347 1347 else
1348 1348 {
1349 1349 spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR; // 1101
1350 1350 }
1351 1351 }
1352 1352
1353 1353 //*****************************
1354 1354 // CONFIGURE CALIBRATION SIGNAL
1355 1355 void setCalibrationPrescaler( unsigned int prescaler )
1356 1356 {
1357 1357 // prescaling of the master clock (25 MHz)
1358 1358 // master clock is divided by 2^prescaler
1359 1359 time_management_regs->calPrescaler = prescaler;
1360 1360 }
1361 1361
1362 1362 void setCalibrationDivisor( unsigned int divisionFactor )
1363 1363 {
1364 1364 // division of the prescaled clock by the division factor
1365 1365 time_management_regs->calDivisor = divisionFactor;
1366 1366 }
1367 1367
1368 1368 void setCalibrationData( void )
1369 1369 {
1370 1370 /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1371 1371 *
1372 1372 * @param void
1373 1373 *
1374 1374 * @return void
1375 1375 *
1376 1376 */
1377 1377
1378 1378 unsigned int k;
1379 1379 unsigned short data;
1380 1380 float val;
1381 1381 float Ts;
1382 1382
1383 1383 time_management_regs->calDataPtr = INIT_CHAR;
1384 1384
1385 Ts = 1 / CAL_FS;
1386
1385 1387 // build the signal for the SCM calibration
1386 1388 for (k = 0; k < CAL_NB_PTS; k++)
1387 1389 {
1388 1390 val = sin( 2 * pi * CAL_F0 * k * Ts )
1389 1391 + sin( 2 * pi * CAL_F1 * k * Ts );
1390 1392 data = (unsigned short) ((val * CAL_SCALE_FACTOR) + CONST_2048);
1391 1393 time_management_regs->calData = data & CAL_DATA_MASK;
1392 1394 }
1393 1395 }
1394 1396
1395 1397 void setCalibrationDataInterleaved( void )
1396 1398 {
1397 1399 /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1398 1400 *
1399 1401 * @param void
1400 1402 *
1401 1403 * @return void
1402 1404 *
1403 1405 * In interleaved mode, one can store more values than in normal mode.
1404 1406 * The data are stored in bunch of 18 bits, 12 bits from one sample and 6 bits from another sample.
1405 1407 * T store 3 values, one need two write operations.
1406 1408 * s1 [ b11 b10 b9 b8 b7 b6 ] s0 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1407 1409 * s1 [ b5 b4 b3 b2 b1 b0 ] s2 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1408 1410 *
1409 1411 */
1410 1412
1411 1413 unsigned int k;
1412 1414 float val;
1413 1415 float Ts;
1414 1416 unsigned short data[CAL_NB_PTS_INTER];
1415 1417 unsigned char *dataPtr;
1416 1418
1417 Ts = 1. / CAL_FS_INTER;
1419 Ts = 1 / CAL_FS_INTER;
1418 1420
1419 1421 time_management_regs->calDataPtr = INIT_CHAR;
1420 1422
1421 1423 // build the signal for the SCM calibration
1422 1424 for (k=0; k<CAL_NB_PTS_INTER; k++)
1423 1425 {
1424 1426 val = sin( 2 * pi * CAL_F0 * k * Ts )
1425 1427 + sin( 2 * pi * CAL_F1 * k * Ts );
1426 1428 data[k] = (unsigned short) ((val * CONST_512) + CONST_2048);
1427 1429 }
1428 1430
1429 1431 // write the signal in interleaved mode
1430 1432 for (k=0; k < STEPS_FOR_STORAGE_INTER; k++)
1431 1433 {
1432 1434 dataPtr = (unsigned char*) &data[ (k * BYTES_FOR_2_SAMPLES) + 2 ];
1433 1435 time_management_regs->calData = ( data[ k * BYTES_FOR_2_SAMPLES ] & CAL_DATA_MASK )
1434 1436 + ( (dataPtr[0] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1435 1437 time_management_regs->calData = ( data[(k * BYTES_FOR_2_SAMPLES) + 1] & CAL_DATA_MASK )
1436 1438 + ( (dataPtr[1] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1437 1439 }
1438 1440 }
1439 1441
1440 1442 void setCalibrationReload( bool state)
1441 1443 {
1442 1444 if (state == true)
1443 1445 {
1444 1446 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_RELOAD; // [0001 0000]
1445 1447 }
1446 1448 else
1447 1449 {
1448 1450 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_RELOAD; // [1110 1111]
1449 1451 }
1450 1452 }
1451 1453
1452 1454 void setCalibrationEnable( bool state )
1453 1455 {
1454 1456 // this bit drives the multiplexer
1455 1457 if (state == true)
1456 1458 {
1457 1459 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_ENABLE; // [0100 0000]
1458 1460 }
1459 1461 else
1460 1462 {
1461 1463 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1462 1464 }
1463 1465 }
1464 1466
1465 1467 void setCalibrationInterleaved( bool state )
1466 1468 {
1467 1469 // this bit drives the multiplexer
1468 1470 if (state == true)
1469 1471 {
1470 1472 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_SET_INTERLEAVED; // [0010 0000]
1471 1473 }
1472 1474 else
1473 1475 {
1474 1476 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_SET_INTERLEAVED; // [1101 1111]
1475 1477 }
1476 1478 }
1477 1479
1478 1480 void setCalibration( bool state )
1479 1481 {
1480 1482 if (state == true)
1481 1483 {
1482 1484 setCalibrationEnable( true );
1483 1485 setCalibrationReload( false );
1484 1486 set_hk_lfr_calib_enable( true );
1485 1487 }
1486 1488 else
1487 1489 {
1488 1490 setCalibrationEnable( false );
1489 1491 setCalibrationReload( true );
1490 1492 set_hk_lfr_calib_enable( false );
1491 1493 }
1492 1494 }
1493 1495
1494 1496 void configureCalibration( bool interleaved )
1495 1497 {
1496 1498 setCalibration( false );
1497 1499 if ( interleaved == true )
1498 1500 {
1499 1501 setCalibrationInterleaved( true );
1500 1502 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1501 1503 setCalibrationDivisor( CAL_F_DIVISOR_INTER ); // => 240 384
1502 1504 setCalibrationDataInterleaved();
1503 1505 }
1504 1506 else
1505 1507 {
1506 1508 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1507 1509 setCalibrationDivisor( CAL_F_DIVISOR ); // => 160 256 (39 - 1)
1508 1510 setCalibrationData();
1509 1511 }
1510 1512 }
1511 1513
1512 1514 //****************
1513 1515 // CLOSING ACTIONS
1514 1516 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1515 1517 {
1516 1518 /** This function is used to update the HK packets statistics after a successful TC execution.
1517 1519 *
1518 1520 * @param TC points to the TC being processed
1519 1521 * @param time is the time used to date the TC execution
1520 1522 *
1521 1523 */
1522 1524
1523 1525 unsigned int val;
1524 1526
1525 1527 housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1526 1528 housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1527 1529 housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1528 1530 housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1529 1531 housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1530 1532 housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1531 1533 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1532 1534 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1533 1535 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1534 1536 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1535 1537 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1536 1538 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1537 1539
1538 1540 val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1539 1541 val++;
1540 1542 housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1541 1543 housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1542 1544 }
1543 1545
1544 1546 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1545 1547 {
1546 1548 /** This function is used to update the HK packets statistics after a TC rejection.
1547 1549 *
1548 1550 * @param TC points to the TC being processed
1549 1551 * @param time is the time used to date the TC rejection
1550 1552 *
1551 1553 */
1552 1554
1553 1555 unsigned int val;
1554 1556
1555 1557 housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1556 1558 housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1557 1559 housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1558 1560 housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1559 1561 housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1560 1562 housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1561 1563 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1562 1564 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1563 1565 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1564 1566 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1565 1567 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1566 1568 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1567 1569
1568 1570 val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1569 1571 val++;
1570 1572 housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1571 1573 housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1572 1574 }
1573 1575
1574 1576 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1575 1577 {
1576 1578 /** This function is the last step of the TC execution workflow.
1577 1579 *
1578 1580 * @param TC points to the TC being processed
1579 1581 * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1580 1582 * @param queue_id is the id of the RTEMS message queue used to send TM packets
1581 1583 * @param time is the time used to date the TC execution
1582 1584 *
1583 1585 */
1584 1586
1585 1587 unsigned char requestedMode;
1586 1588
1587 1589 if (result == LFR_SUCCESSFUL)
1588 1590 {
1589 1591 if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1590 1592 &
1591 1593 !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1592 1594 )
1593 1595 {
1594 1596 send_tm_lfr_tc_exe_success( TC, queue_id );
1595 1597 }
1596 1598 if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1597 1599 {
1598 1600 //**********************************
1599 1601 // UPDATE THE LFRMODE LOCAL VARIABLE
1600 1602 requestedMode = TC->dataAndCRC[1];
1601 1603 updateLFRCurrentMode( requestedMode );
1602 1604 }
1603 1605 }
1604 1606 else if (result == LFR_EXE_ERROR)
1605 1607 {
1606 1608 send_tm_lfr_tc_exe_error( TC, queue_id );
1607 1609 }
1608 1610 }
1609 1611
1610 1612 //***************************
1611 1613 // Interrupt Service Routines
1612 1614 rtems_isr commutation_isr1( rtems_vector_number vector )
1613 1615 {
1614 1616 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1615 1617 PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1616 1618 }
1617 1619 }
1618 1620
1619 1621 rtems_isr commutation_isr2( rtems_vector_number vector )
1620 1622 {
1621 1623 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1622 1624 PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1623 1625 }
1624 1626 }
1625 1627
1626 1628 //****************
1627 1629 // OTHER FUNCTIONS
1628 1630 void updateLFRCurrentMode( unsigned char requestedMode )
1629 1631 {
1630 1632 /** This function updates the value of the global variable lfrCurrentMode.
1631 1633 *
1632 1634 * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1633 1635 *
1634 1636 */
1635 1637
1636 1638 // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1637 1639 housekeeping_packet.lfr_status_word[0] = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1638 1640 + (unsigned char) ( requestedMode << STATUS_WORD_LFR_MODE_SHIFT );
1639 1641 lfrCurrentMode = requestedMode;
1640 1642 }
1641 1643
1642 1644 void set_lfr_soft_reset( unsigned char value )
1643 1645 {
1644 1646 if (value == 1)
1645 1647 {
1646 1648 time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1647 1649 }
1648 1650 else
1649 1651 {
1650 1652 time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1651 1653 }
1652 1654 }
1653 1655
1654 1656 void reset_lfr( void )
1655 1657 {
1656 1658 set_lfr_soft_reset( 1 );
1657 1659
1658 1660 set_lfr_soft_reset( 0 );
1659 1661
1660 1662 set_hk_lfr_sc_potential_flag( true );
1661 1663 }
General Comments 0
You need to be logged in to leave comments. Login now