##// END OF EJS Templates
ASM restart sequence updated at the interrupt service routine level...
paul -
r259:af93852650f9 R3a
parent child
Show More
@@ -1,2 +1,2
1 1 3081d1f9bb20b2b64a192585337a292a9804e0c5 LFR_basic-parameters
2 4ffa7549495b4d1e5ddbda520569468a5e3b8779 header/lfr_common_headers
2 ad7698268954c5d3d203a3b3ad09fcdf2d536472 header/lfr_common_headers
@@ -1,192 +1,221
1 1 #ifndef GSCMEMORY_HPP_
2 2 #define GSCMEMORY_HPP_
3 3
4 4 #ifndef LEON3
5 5 #define LEON3
6 6 #endif
7 7
8 8 #define REGS_ADDR_PLUGANDPLAY 0xFFFFF000
9 9 #define ASR16_REG_ADDRESS 0x90400040 // Ancillary State Register 16 = Register protection control register (FT only)
10 10
11 11 #define DEVICEID_LEON3 0x003
12 12 #define DEVICEID_LEON3FT 0x053
13 13 #define VENDORID_GAISLER 0x01
14 14
15 15 // CCR
16 #define POS_FT 19
17 //
16 18 #define POS_ITE 12
17 19 #define COUNTER_FIELD_ITE 0x00003000 // 0000 0000 0000 0000 0011 0000 0000 0000
18 20 #define COUNTER_MASK_ITE 0xffffcfff // 1111 1111 1111 1111 1100 1111 1111 1111
19 21 #define POS_IDE 10
20 22 #define COUNTER_FIELD_IDE 0x00000c00 // 0000 0000 0000 0000 0000 1100 0000 0000
21 23 #define COUNTER_MASK_IDE 0xfffff3ff // 1111 1111 1111 1111 1111 0011 1111 1111
22 24 //
23 25 #define POS_DTE 8
24 26 #define COUNTER_FIELD_DTE 0x00000300 // 0000 0000 0000 0000 0000 0011 0000 0000
25 27 #define COUNTER_MASK_DTE 0xfffffcff // 1111 1111 1111 1111 1111 1100 1111 1111
26 28 #define POS_DDE 6
27 29 #define COUNTER_FIELD_DDE 0x000000c0 // 0000 0000 0000 0000 0000 0000 1100 0000
28 30 #define COUNTER_MASK_DDE 0xffffff3f // 1111 1111 1111 1111 1111 1111 0011 1111
29 31
30 32 // ASR16
33 #define POS_FPFTID 30
31 34 #define POS_FPRF 27
35 #define POS_FDI 16 // FP RF protection enable/disable
36 #define POS_IUFTID 14
37 #define POS_IURF 11
38 #define POS_IDI 0 // IU RF protection enable/disable
39
32 40 #define COUNTER_FIELD_FPRF 0x38000000 // 0011 1000 0000 0000 0000 0000 0000 0000
33 41 #define COUNTER_MASK_FPRF 0xc7ffffff // 1100 0111 1111 1111 1111 1111 1111 1111
34 #define POS_IURF 11
42
35 43 #define COUNTER_FIELD_IURF 0x00003800 // 0000 0000 0000 0000 0011 1000 0000 0000
36 44 #define COUNTER_MASK_IURF 0xffffc7ff // 1111 1111 1111 1111 1100 0111 1111 1111
37 45
38 46 volatile unsigned int *asr16Ptr = (volatile unsigned int *) ASR16_REG_ADDRESS;
39 47
40 48 static inline void flushCache()
41 49 {
42 50 /**
43 51 * Flush the data cache and the instruction cache.
44 52 *
45 53 * @param void
46 54 *
47 55 * @return void
48 56 */
49 57
50 58 asm("flush");
51 59 }
52 60
53 61 //***************************
54 62 // CCR Cache control register
55 63
56 64 static unsigned int CCR_getValue()
57 65 {
58 66 unsigned int cacheControlRegister = 0;
59 67 __asm__ __volatile__("lda [%%g0] 2, %0" : "=r"(cacheControlRegister) : );
60 68 return cacheControlRegister;
61 69 }
62 70
63 71 static void CCR_setValue(unsigned int cacheControlRegister)
64 72 {
65 73 __asm__ __volatile__("sta %0, [%%g0] 2" : : "r"(cacheControlRegister));
66 74 }
67 75
68 76 static void CCR_resetCacheControlRegister()
69 77 {
70 78 unsigned int cacheControlRegister;
71 79 cacheControlRegister = 0x00;
72 80 CCR_setValue(cacheControlRegister);
73 81 }
74 82
75 83 static void CCR_enableInstructionCache()
76 84 {
77 85 // [1:0] Instruction Cache state (ICS)
78 86 // Indicates the current data cache state according to the following: X0 = disabled, 01 = frozen, 11 = enabled.
79 87 unsigned int cacheControlRegister;
80 88 cacheControlRegister = CCR_getValue();
81 89 cacheControlRegister = (cacheControlRegister | 0x3);
82 90 CCR_setValue(cacheControlRegister);
83 91 }
84 92
85 93 static void CCR_enableDataCache()
86 94 {
87 95 // [3:2] Data Cache state (DCS)
88 96 // Indicates the current data cache state according to the following: X0 = disabled, 01 = frozen, 11 = enabled.
89 97 unsigned int cacheControlRegister;
90 98 cacheControlRegister = CCR_getValue();
91 99 cacheControlRegister = (cacheControlRegister | 0xc);
92 100 CCR_setValue(cacheControlRegister);
93 101 }
94 102
95 static void CCR_faultTolerantScheme()
96 {
97 // [20:19] FT scheme (FT) - β€œ00” = no FT, β€œ01” = 4-bit checking implemented
98 unsigned int cacheControlRegister;
99 unsigned int *plugAndPlayRegister;
100 unsigned int vendorId;
101 unsigned int deviceId;
102
103 plugAndPlayRegister = (unsigned int*) REGS_ADDR_PLUGANDPLAY;
104 vendorId = ( (*plugAndPlayRegister) & 0xff000000 ) >> 24;
105 deviceId = ( (*plugAndPlayRegister) & 0x00fff000 ) >> 12;
106
107 if( (vendorId == VENDORID_GAISLER) & (deviceId ==DEVICEID_LEON3FT) )
108 {
109 PRINTF("in faultTolerantScheme *** Leon3FT detected, configure the CCR FT bits\n");
110 cacheControlRegister = CCR_getValue();
111 cacheControlRegister = (cacheControlRegister | 0xc);
112 CCR_setValue(cacheControlRegister);
113 }
114 else
115 {
116 PRINTF("in faultTolerantScheme *** not a Leon3FT, no need to configure the CCR FT bits\n");
117 PRINTF2(" *** vendorID = 0x%x, deviceId = 0x%x\n", vendorId, deviceId);
118 }
119 }
120
121 103 static void CCR_enableInstructionBurstFetch()
122 104 {
123 105 // [16] Instruction burst fetch (IB). This bit enables burst fill during instruction fetch.
124 106 unsigned int cacheControlRegister;
125 107 cacheControlRegister = CCR_getValue();
126 108 // set the bit IB to 1
127 109 cacheControlRegister = (cacheControlRegister | 0x10000);
128 110 CCR_setValue(cacheControlRegister);
129 111 }
130 112
131 static void CCR_getInstructionAndDataErrorCounters( unsigned int* instructionErrorCounter, unsigned int* dataErrorCounter )
113 void CCR_getInstructionAndDataErrorCounters( unsigned int* instructionErrorCounter, unsigned int* dataErrorCounter )
132 114 {
133 115 // [13:12] Instruction Tag Errors (ITE) - Number of detected parity errors in the instruction tag cache.
134 116 // Only available if fault-tolerance is enabled (FT field in this register is non-zero).
135 117 // [11:10] Instruction Data Errors (IDE) - Number of detected parity errors in the instruction data cache.
136 118 // Only available if fault-tolerance is enabled (FT field in this register is non-zero).
137 119
138 120 unsigned int cacheControlRegister;
139 121 unsigned int iTE;
140 122 unsigned int iDE;
141 123 unsigned int dTE;
142 124 unsigned int dDE;
143 125
144 126 cacheControlRegister = CCR_getValue();
145 127 iTE = (cacheControlRegister & COUNTER_FIELD_ITE) >> POS_ITE;
146 128 iDE = (cacheControlRegister & COUNTER_FIELD_IDE) >> POS_IDE;
147 129 dTE = (cacheControlRegister & COUNTER_FIELD_DTE) >> POS_DTE;
148 130 dDE = (cacheControlRegister & COUNTER_FIELD_DDE) >> POS_DDE;
149 131
150 132 *instructionErrorCounter = iTE + iDE;
151 133 *dataErrorCounter = dTE + dDE;
152 134
153 135 // reset counters
154 136 cacheControlRegister = cacheControlRegister
155 137 & COUNTER_FIELD_ITE
156 138 & COUNTER_FIELD_IDE
157 139 & COUNTER_FIELD_DTE
158 140 & COUNTER_FIELD_DDE;
159 141
160 142 CCR_setValue(cacheControlRegister);
161 143 }
162 144
163 145 //*******************************************
164 146 // ASR16 Register protection control register
165 147
166 static void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int* fprfErrorCounter, unsigned int* iurfErrorCounter)
148 static void ASR16_resetRegisterProtectionControlRegister()
149 {
150 *asr16Ptr = 0x00;
151 }
152
153 void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int* fprfErrorCounter, unsigned int* iurfErrorCounter)
167 154 {
168 155 /** This function is used to retrieve the integer unit register file error counter and the floating point unit
169 156 * register file error counter
170 157 *
171 158 * @return void
172 159 *
173 160 * [29:27] FP RF error counter - Number of detected parity errors in the FP register file.
174 161 * [13:11] IU RF error counter - Number of detected parity errors in the IU register file.
175 162 *
176 163 */
177 164
178 165 unsigned int asr16;
179 166
180 167 asr16 = *asr16Ptr;
181 168 *fprfErrorCounter = ( asr16 & COUNTER_FIELD_FPRF ) >> POS_FPRF;
182 169 *iurfErrorCounter = ( asr16 & COUNTER_FIELD_IURF ) >> POS_IURF;
183 170
184 171 // reset the counter to 0
185 172 asr16 = asr16
186 173 & COUNTER_MASK_FPRF
187 174 & COUNTER_FIELD_IURF;
188 175
189 176 *asr16Ptr = asr16;
190 177 }
191 178
179 static void faultTolerantScheme()
180 {
181 // [20:19] FT scheme (FT) - β€œ00” = no FT, β€œ01” = 4-bit checking implemented
182 unsigned int cacheControlRegister;
183 unsigned int *plugAndPlayRegister;
184 unsigned int vendorId;
185 unsigned int deviceId;
186
187 plugAndPlayRegister = (unsigned int*) REGS_ADDR_PLUGANDPLAY;
188 vendorId = ( (*plugAndPlayRegister) & 0xff000000 ) >> 24;
189 deviceId = ( (*plugAndPlayRegister) & 0x00fff000 ) >> 12;
190
191 cacheControlRegister = CCR_getValue();
192
193 if( (vendorId == VENDORID_GAISLER) & (deviceId ==DEVICEID_LEON3FT) )
194 {
195 PRINTF("in faultTolerantScheme *** Leon3FT detected\n");
196 PRINTF2(" *** vendorID = 0x%x, deviceId = 0x%x\n", vendorId, deviceId);
197 PRINTF1("ASR16 IU RF protection, bit 0 (IDI) is: 0x%x (0 => protection enabled)\n",
198 (*asr16Ptr >> POS_IDI) & 1);
199 PRINTF1("ASR16 FP RF protection, bit 16 (FDI) is: 0x%x (0 => protection enabled)\n",
200 (*asr16Ptr >> POS_FDI) & 1);
201 PRINTF1("ASR16 IU FT ID bits [15:14] is: 0x%x (2 => 8-bit parity without restart)\n",
202 (*asr16Ptr >> POS_IUFTID) & 0x3);
203 PRINTF1("ASR16 FP FT ID bits [31:30] is: 0x%x (1 => 4-bit parity with restart)\n",
204 (*asr16Ptr >> POS_FPFTID) & 0x03);
205 PRINTF1("CCR FT bits [20:19] are: 0x%x (1 => 4-bit parity with restart)\n",
206 (cacheControlRegister >> POS_FT) & 0x3 );
207
208 // CCR The FFT bits are just read, the FT scheme is set to β€œ01” = 4-bit checking implemented by default
209
210 // ASR16 Ancillary State Register configuration (Register protection control register)
211 // IU RF protection is set by default, bit 0 IDI = 0
212 // FP RF protection is set by default, bit 16 FDI = 0
213 }
214 else
215 {
216 PRINTF("in faultTolerantScheme *** not a Leon3FT not detected\n");
217 PRINTF2(" *** vendorID = 0x%x, deviceId = 0x%x\n", vendorId, deviceId);
218 }
219 }
220
192 221 #endif /* GSCMEMORY_HPP_ */
@@ -1,79 +1,82
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 14 enum lfr_reset_cause_t{
14 15 UNKNOWN_CAUSE,
15 16 POWER_ON,
16 17 TC_RESET,
17 18 WATCHDOG,
18 19 ERROR_RESET,
19 20 UNEXP_RESET
20 21 };
21 22
22 23 extern gptimer_regs_t *gptimer_regs;
24 extern void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int*, unsigned int* );
25 extern void CCR_getInstructionAndDataErrorCounters( unsigned int*, unsigned int* );
23 26
24 27 #define LFR_RESET_CAUSE_UNKNOWN_CAUSE 0
25 28
26 29 rtems_name name_hk_rate_monotonic; // name of the HK rate monotonic
27 30 rtems_id HK_id; // id of the HK rate monotonic period
28 31
29 32 void timer_configure( unsigned char timer, unsigned int clock_divider,
30 33 unsigned char interrupt_level, rtems_isr (*timer_isr)() );
31 34 void timer_start( unsigned char timer );
32 35 void timer_stop( unsigned char timer );
33 36 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider);
34 37
35 38 // WATCHDOG
36 39 rtems_isr watchdog_isr( rtems_vector_number vector );
37 40 void watchdog_configure(void);
38 41 void watchdog_stop(void);
39 42 void watchdog_start(void);
40 43
41 44 // SERIAL LINK
42 45 int send_console_outputs_on_apbuart_port( void );
43 46 int enable_apbuart_transmitter( void );
44 47 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value);
45 48
46 49 // RTEMS TASKS
47 50 rtems_task load_task( rtems_task_argument argument );
48 51 rtems_task hous_task( rtems_task_argument argument );
49 52 rtems_task dumb_task( rtems_task_argument unused );
50 53
51 54 void init_housekeeping_parameters( void );
52 55 void increment_seq_counter(unsigned short *packetSequenceControl);
53 56 void getTime( unsigned char *time);
54 57 unsigned long long int getTimeAsUnsignedLongLongInt( );
55 58 void send_dumb_hk( void );
56 59 void get_temperatures( unsigned char *temperatures );
57 60 void get_v_e1_e2_f3( unsigned char *spacecraft_potential );
58 61 void get_cpu_load( unsigned char *resource_statistics );
59 62 void set_hk_lfr_sc_potential_flag( bool state );
60 63 void set_hk_lfr_mag_fields_flag( bool state );
61 64 void set_hk_lfr_calib_enable( bool state );
62 65 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause );
63 66 void hk_lfr_le_me_he_update();
64 67 void set_hk_lfr_time_not_synchro();
65 68
66 69 extern int sched_yield( void );
67 70 extern void rtems_cpu_usage_reset();
68 71 extern ring_node *current_ring_node_f3;
69 72 extern ring_node *ring_node_to_send_cwf_f3;
70 73 extern ring_node waveform_ring_f3[];
71 74 extern unsigned short sequenceCounterHK;
72 75
73 76 extern unsigned char hk_lfr_q_sd_fifo_size_max;
74 77 extern unsigned char hk_lfr_q_rv_fifo_size_max;
75 78 extern unsigned char hk_lfr_q_p0_fifo_size_max;
76 79 extern unsigned char hk_lfr_q_p1_fifo_size_max;
77 80 extern unsigned char hk_lfr_q_p2_fifo_size_max;
78 81
79 82 #endif // FSW_MISC_H_INCLUDED
@@ -1,330 +1,332
1 1 #ifndef FSW_PROCESSING_H_INCLUDED
2 2 #define FSW_PROCESSING_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6 #include <math.h>
7 7 #include <stdlib.h> // abs() is in the stdlib
8 8 #include <stdio.h>
9 9 #include <math.h>
10 10 #include <grlib_regs.h>
11 11
12 12 #include "fsw_params.h"
13 13
14 14 typedef struct ring_node_asm
15 15 {
16 16 struct ring_node_asm *next;
17 17 float matrix[ TOTAL_SIZE_SM ];
18 18 unsigned int status;
19 19 } ring_node_asm;
20 20
21 21 typedef struct
22 22 {
23 23 unsigned char targetLogicalAddress;
24 24 unsigned char protocolIdentifier;
25 25 unsigned char reserved;
26 26 unsigned char userApplication;
27 27 unsigned char packetID[2];
28 28 unsigned char packetSequenceControl[2];
29 29 unsigned char packetLength[2];
30 30 // DATA FIELD HEADER
31 31 unsigned char spare1_pusVersion_spare2;
32 32 unsigned char serviceType;
33 33 unsigned char serviceSubType;
34 34 unsigned char destinationID;
35 35 unsigned char time[6];
36 36 // AUXILIARY HEADER
37 37 unsigned char sid;
38 38 unsigned char biaStatusInfo;
39 39 unsigned char sy_lfr_common_parameters_spare;
40 40 unsigned char sy_lfr_common_parameters;
41 41 unsigned char acquisitionTime[6];
42 42 unsigned char pa_lfr_bp_blk_nr[2];
43 43 // SOURCE DATA
44 44 unsigned char data[ 780 ]; // MAX size is 26 bins * 30 Bytes [TM_LFR_SCIENCE_BURST_BP2_F1]
45 45 } bp_packet;
46 46
47 47 typedef struct
48 48 {
49 49 unsigned char targetLogicalAddress;
50 50 unsigned char protocolIdentifier;
51 51 unsigned char reserved;
52 52 unsigned char userApplication;
53 53 unsigned char packetID[2];
54 54 unsigned char packetSequenceControl[2];
55 55 unsigned char packetLength[2];
56 56 // DATA FIELD HEADER
57 57 unsigned char spare1_pusVersion_spare2;
58 58 unsigned char serviceType;
59 59 unsigned char serviceSubType;
60 60 unsigned char destinationID;
61 61 unsigned char time[6];
62 62 // AUXILIARY HEADER
63 63 unsigned char sid;
64 64 unsigned char biaStatusInfo;
65 65 unsigned char sy_lfr_common_parameters_spare;
66 66 unsigned char sy_lfr_common_parameters;
67 67 unsigned char acquisitionTime[6];
68 68 unsigned char source_data_spare;
69 69 unsigned char pa_lfr_bp_blk_nr[2];
70 70 // SOURCE DATA
71 71 unsigned char data[ 143 ]; // 13 bins * 11 Bytes
72 72 } bp_packet_with_spare; // only for TM_LFR_SCIENCE_NORMAL_BP1_F0 and F1
73 73
74 74 typedef struct asm_msg
75 75 {
76 76 ring_node_asm *norm;
77 77 ring_node_asm *burst_sbm;
78 78 rtems_event_set event;
79 79 unsigned int coarseTimeNORM;
80 80 unsigned int fineTimeNORM;
81 81 unsigned int coarseTimeSBM;
82 82 unsigned int fineTimeSBM;
83 83 } asm_msg;
84 84
85 extern unsigned char thisIsAnASMRestart;
86
85 87 extern volatile int sm_f0[ ];
86 88 extern volatile int sm_f1[ ];
87 89 extern volatile int sm_f2[ ];
88 90
89 91 // parameters
90 92 extern struct param_local_str param_local;
91 93 extern Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet;
92 94
93 95 // registers
94 96 extern time_management_regs_t *time_management_regs;
95 97 extern volatile spectral_matrix_regs_t *spectral_matrix_regs;
96 98
97 99 extern rtems_name misc_name[5];
98 100 extern rtems_id Task_id[20]; /* array of task ids */
99 101
100 102 ring_node * getRingNodeForAveraging( unsigned char frequencyChannel);
101 103 // ISR
102 104 rtems_isr spectral_matrices_isr( rtems_vector_number vector );
103 105
104 106 //******************
105 107 // Spectral Matrices
106 108 void reset_nb_sm( void );
107 109 // SM
108 110 void SM_init_rings( void );
109 111 void SM_reset_current_ring_nodes( void );
110 112 // ASM
111 113 void ASM_generic_init_ring(ring_node_asm *ring, unsigned char nbNodes );
112 114
113 115 //*****************
114 116 // Basic Parameters
115 117
116 118 void BP_reset_current_ring_nodes( void );
117 119 void BP_init_header(bp_packet *packet,
118 120 unsigned int apid, unsigned char sid,
119 121 unsigned int packetLength , unsigned char blkNr);
120 122 void BP_init_header_with_spare(bp_packet_with_spare *packet,
121 123 unsigned int apid, unsigned char sid,
122 124 unsigned int packetLength, unsigned char blkNr );
123 125 void BP_send( char *data,
124 126 rtems_id queue_id,
125 127 unsigned int nbBytesToSend , unsigned int sid );
126 128 void BP_send_s1_s2(char *data,
127 129 rtems_id queue_id,
128 130 unsigned int nbBytesToSend, unsigned int sid );
129 131
130 132 //******************
131 133 // general functions
132 134 void reset_sm_status( void );
133 135 void reset_spectral_matrix_regs( void );
134 136 void set_time(unsigned char *time, unsigned char *timeInBuffer );
135 137 unsigned long long int get_acquisition_time( unsigned char *timePtr );
136 138 unsigned char getSID( rtems_event_set event );
137 139
138 140 extern rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id );
139 141 extern rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id );
140 142
141 143 //***************************************
142 144 // DEFINITIONS OF STATIC INLINE FUNCTIONS
143 145 static inline void SM_average(float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
144 146 ring_node *ring_node_tab[],
145 147 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
146 148 asm_msg *msgForMATR );
147 149
148 150 static inline void SM_average_debug(float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
149 151 ring_node *ring_node_tab[],
150 152 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
151 153 asm_msg *msgForMATR );
152 154
153 155 void ASM_patch( float *inputASM, float *outputASM );
154 156
155 157 void extractReImVectors(float *inputASM, float *outputASM, unsigned int asmComponent );
156 158
157 159 static inline void ASM_reorganize_and_divide(float *averaged_spec_mat, float *averaged_spec_mat_reorganized,
158 160 float divider );
159 161
160 162 static inline void ASM_compress_reorganize_and_divide(float *averaged_spec_mat, float *compressed_spec_mat,
161 163 float divider,
162 164 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage , unsigned char ASMIndexStart);
163 165
164 166 static inline void ASM_convert(volatile float *input_matrix, char *output_matrix);
165 167
166 168 void SM_average( float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
167 169 ring_node *ring_node_tab[],
168 170 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
169 171 asm_msg *msgForMATR )
170 172 {
171 173 float sum;
172 174 unsigned int i;
173 175
174 176 for(i=0; i<TOTAL_SIZE_SM; i++)
175 177 {
176 178 sum = ( (int *) (ring_node_tab[0]->buffer_address) ) [ i ]
177 179 + ( (int *) (ring_node_tab[1]->buffer_address) ) [ i ]
178 180 + ( (int *) (ring_node_tab[2]->buffer_address) ) [ i ]
179 181 + ( (int *) (ring_node_tab[3]->buffer_address) ) [ i ]
180 182 + ( (int *) (ring_node_tab[4]->buffer_address) ) [ i ]
181 183 + ( (int *) (ring_node_tab[5]->buffer_address) ) [ i ]
182 184 + ( (int *) (ring_node_tab[6]->buffer_address) ) [ i ]
183 185 + ( (int *) (ring_node_tab[7]->buffer_address) ) [ i ];
184 186
185 187 if ( (nbAverageNORM == 0) && (nbAverageSBM == 0) )
186 188 {
187 189 averaged_spec_mat_NORM[ i ] = sum;
188 190 averaged_spec_mat_SBM[ i ] = sum;
189 191 msgForMATR->coarseTimeNORM = ring_node_tab[0]->coarseTime;
190 192 msgForMATR->fineTimeNORM = ring_node_tab[0]->fineTime;
191 193 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
192 194 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
193 195 }
194 196 else if ( (nbAverageNORM != 0) && (nbAverageSBM != 0) )
195 197 {
196 198 averaged_spec_mat_NORM[ i ] = ( averaged_spec_mat_NORM[ i ] + sum );
197 199 averaged_spec_mat_SBM[ i ] = ( averaged_spec_mat_SBM[ i ] + sum );
198 200 }
199 201 else if ( (nbAverageNORM != 0) && (nbAverageSBM == 0) )
200 202 {
201 203 averaged_spec_mat_NORM[ i ] = ( averaged_spec_mat_NORM[ i ] + sum );
202 204 averaged_spec_mat_SBM[ i ] = sum;
203 205 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
204 206 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
205 207 }
206 208 else
207 209 {
208 210 averaged_spec_mat_NORM[ i ] = sum;
209 211 averaged_spec_mat_SBM[ i ] = ( averaged_spec_mat_SBM[ i ] + sum );
210 212 msgForMATR->coarseTimeNORM = ring_node_tab[0]->coarseTime;
211 213 msgForMATR->fineTimeNORM = ring_node_tab[0]->fineTime;
212 214 // PRINTF2("ERR *** in SM_average *** unexpected parameters %d %d\n", nbAverageNORM, nbAverageSBM)
213 215 }
214 216 }
215 217 }
216 218
217 219 void SM_average_debug( float *averaged_spec_mat_NORM, float *averaged_spec_mat_SBM,
218 220 ring_node *ring_node_tab[],
219 221 unsigned int nbAverageNORM, unsigned int nbAverageSBM,
220 222 asm_msg *msgForMATR )
221 223 {
222 224 float sum;
223 225 unsigned int i;
224 226
225 227 for(i=0; i<TOTAL_SIZE_SM; i++)
226 228 {
227 229 sum = ( (int *) (ring_node_tab[0]->buffer_address) ) [ i ];
228 230 averaged_spec_mat_NORM[ i ] = sum;
229 231 averaged_spec_mat_SBM[ i ] = sum;
230 232 msgForMATR->coarseTimeNORM = ring_node_tab[0]->coarseTime;
231 233 msgForMATR->fineTimeNORM = ring_node_tab[0]->fineTime;
232 234 msgForMATR->coarseTimeSBM = ring_node_tab[0]->coarseTime;
233 235 msgForMATR->fineTimeSBM = ring_node_tab[0]->fineTime;
234 236 }
235 237 }
236 238
237 239 void ASM_reorganize_and_divide( float *averaged_spec_mat, float *averaged_spec_mat_reorganized, float divider )
238 240 {
239 241 int frequencyBin;
240 242 int asmComponent;
241 243 unsigned int offsetASM;
242 244 unsigned int offsetASMReorganized;
243 245
244 246 // BUILD DATA
245 247 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
246 248 {
247 249 for( frequencyBin = 0; frequencyBin < NB_BINS_PER_SM; frequencyBin++ )
248 250 {
249 251 offsetASMReorganized =
250 252 frequencyBin * NB_VALUES_PER_SM
251 253 + asmComponent;
252 254 offsetASM =
253 255 asmComponent * NB_BINS_PER_SM
254 256 + frequencyBin;
255 257 averaged_spec_mat_reorganized[offsetASMReorganized ] =
256 258 averaged_spec_mat[ offsetASM ] / divider;
257 259 }
258 260 }
259 261 }
260 262
261 263 void ASM_compress_reorganize_and_divide(float *averaged_spec_mat, float *compressed_spec_mat , float divider,
262 264 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage, unsigned char ASMIndexStart )
263 265 {
264 266 int frequencyBin;
265 267 int asmComponent;
266 268 int offsetASM;
267 269 int offsetCompressed;
268 270 int k;
269 271
270 272 // BUILD DATA
271 273 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
272 274 {
273 275 for( frequencyBin = 0; frequencyBin < nbBinsCompressedMatrix; frequencyBin++ )
274 276 {
275 277 offsetCompressed = // NO TIME OFFSET
276 278 frequencyBin * NB_VALUES_PER_SM
277 279 + asmComponent;
278 280 offsetASM = // NO TIME OFFSET
279 281 asmComponent * NB_BINS_PER_SM
280 282 + ASMIndexStart
281 283 + frequencyBin * nbBinsToAverage;
282 284 compressed_spec_mat[ offsetCompressed ] = 0;
283 285 for ( k = 0; k < nbBinsToAverage; k++ )
284 286 {
285 287 compressed_spec_mat[offsetCompressed ] =
286 288 ( compressed_spec_mat[ offsetCompressed ]
287 289 + averaged_spec_mat[ offsetASM + k ] );
288 290 }
289 291 compressed_spec_mat[ offsetCompressed ] =
290 292 compressed_spec_mat[ offsetCompressed ] / (divider * nbBinsToAverage);
291 293 }
292 294 }
293 295 }
294 296
295 297 void ASM_convert( volatile float *input_matrix, char *output_matrix)
296 298 {
297 299 unsigned int frequencyBin;
298 300 unsigned int asmComponent;
299 301 char * pt_char_input;
300 302 char * pt_char_output;
301 303 unsigned int offsetInput;
302 304 unsigned int offsetOutput;
303 305
304 306 pt_char_input = (char*) &input_matrix;
305 307 pt_char_output = (char*) &output_matrix;
306 308
307 309 // convert all other data
308 310 for( frequencyBin=0; frequencyBin<NB_BINS_PER_SM; frequencyBin++)
309 311 {
310 312 for ( asmComponent=0; asmComponent<NB_VALUES_PER_SM; asmComponent++)
311 313 {
312 314 offsetInput = (frequencyBin*NB_VALUES_PER_SM) + asmComponent ;
313 315 offsetOutput = 2 * ( (frequencyBin*NB_VALUES_PER_SM) + asmComponent ) ;
314 316 pt_char_input = (char*) &input_matrix [ offsetInput ];
315 317 pt_char_output = (char*) &output_matrix[ offsetOutput ];
316 318 pt_char_output[0] = pt_char_input[0]; // bits 31 downto 24 of the float
317 319 pt_char_output[1] = pt_char_input[1]; // bits 23 downto 16 of the float
318 320 }
319 321 }
320 322 }
321 323
322 324 void ASM_compress_reorganize_and_divide_mask(float *averaged_spec_mat, float *compressed_spec_mat,
323 325 float divider,
324 326 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage , unsigned char ASMIndexStart, unsigned char channel);
325 327
326 328 int getFBinMask(int k, unsigned char channel);
327 329
328 330 void init_kcoeff_sbm_from_kcoeff_norm( float *input_kcoeff, float *output_kcoeff, unsigned char nb_bins_norm);
329 331
330 332 #endif // FSW_PROCESSING_H_INCLUDED
@@ -1,82 +1,83
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 // RTEMS GLOBAL VARIABLES
26 26 rtems_name misc_name[5];
27 27 rtems_name Task_name[20]; /* array of task names */
28 28 rtems_id Task_id[20]; /* array of task ids */
29 29 rtems_name timecode_timer_name;
30 30 rtems_id timecode_timer_id;
31 31 int fdSPW = 0;
32 32 int fdUART = 0;
33 33 unsigned char lfrCurrentMode;
34 34 unsigned char pa_bia_status_info;
35 unsigned char thisIsAnASMRestart = 0;
35 36
36 37 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
37 38 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
38 39 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
39 40 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
40 41 // F0 F1 F2 F3
41 42 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
42 43 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
43 44 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
44 45 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
45 46
46 47 //***********************************
47 48 // SPECTRAL MATRICES GLOBAL VARIABLES
48 49
49 50 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
50 51 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
51 52 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
52 53 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
53 54
54 55 // APB CONFIGURATION REGISTERS
55 56 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
56 57 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
57 58 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
58 59 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
59 60
60 61 // MODE PARAMETERS
61 62 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet;
62 63 struct param_local_str param_local;
63 64 unsigned int lastValidEnterModeTime;
64 65
65 66 // HK PACKETS
66 67 Packet_TM_LFR_HK_t housekeeping_packet;
67 68 // message queues occupancy
68 69 unsigned char hk_lfr_q_sd_fifo_size_max;
69 70 unsigned char hk_lfr_q_rv_fifo_size_max;
70 71 unsigned char hk_lfr_q_p0_fifo_size_max;
71 72 unsigned char hk_lfr_q_p1_fifo_size_max;
72 73 unsigned char hk_lfr_q_p2_fifo_size_max;
73 74 // sequence counters are incremented by APID (PID + CAT) and destination ID
74 75 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST;
75 76 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2;
76 77 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID];
77 78 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID];
78 79 unsigned short sequenceCounterHK;
79 80 spw_stats spacewire_stats;
80 81 spw_stats spacewire_stats_backup;
81 82
82 83
@@ -1,912 +1,916
1 1 /** This is the RTEMS initialization module.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * This module contains two very different information:
7 7 * - specific instructions to configure the compilation of the RTEMS executive
8 8 * - functions related to the fligth softwre initialization, especially the INIT RTEMS task
9 9 *
10 10 */
11 11
12 12 //*************************
13 13 // GPL reminder to be added
14 14 //*************************
15 15
16 16 #include <rtems.h>
17 17
18 18 /* configuration information */
19 19
20 20 #define CONFIGURE_INIT
21 21
22 22 #include <bsp.h> /* for device driver prototypes */
23 23
24 24 /* configuration information */
25 25
26 26 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
27 27 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
28 28
29 29 #define CONFIGURE_MAXIMUM_TASKS 20
30 30 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
31 31 #define CONFIGURE_EXTRA_TASK_STACKS (3 * RTEMS_MINIMUM_STACK_SIZE)
32 32 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
33 33 #define CONFIGURE_INIT_TASK_PRIORITY 1 // instead of 100
34 34 #define CONFIGURE_INIT_TASK_MODE (RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT)
35 35 #define CONFIGURE_INIT_TASK_ATTRIBUTES (RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT)
36 36 #define CONFIGURE_MAXIMUM_DRIVERS 16
37 37 #define CONFIGURE_MAXIMUM_PERIODS 5
38 38 #define CONFIGURE_MAXIMUM_TIMERS 5 // [spiq] [link] [spacewire_reset_link]
39 39 #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 5
40 40 #ifdef PRINT_STACK_REPORT
41 41 #define CONFIGURE_STACK_CHECKER_ENABLED
42 42 #endif
43 43
44 44 #include <rtems/confdefs.h>
45 45
46 46 /* If --drvmgr was enabled during the configuration of the RTEMS kernel */
47 47 #ifdef RTEMS_DRVMGR_STARTUP
48 48 #ifdef LEON3
49 49 /* Add Timer and UART Driver */
50 50 #ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
51 51 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER
52 52 #endif
53 53 #ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
54 54 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART
55 55 #endif
56 56 #endif
57 57 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW /* GRSPW Driver */
58 58 #include <drvmgr/drvmgr_confdefs.h>
59 59 #endif
60 60
61 61 #include "fsw_init.h"
62 62 #include "fsw_config.c"
63 63 #include "GscMemoryLPP.hpp"
64 64
65 65 void initCache()
66 66 {
67 67 // ASI 2 contains a few control registers that have not been assigned as ancillary state registers.
68 68 // These should only be read and written using 32-bit LDA/STA instructions.
69 69 // All cache registers are accessed through load/store operations to the alternate address space (LDA/STA), using ASI = 2.
70 70 // The table below shows the register addresses:
71 71 // 0x00 Cache control register
72 72 // 0x04 Reserved
73 73 // 0x08 Instruction cache configuration register
74 74 // 0x0C Data cache configuration register
75 75
76 76 // Cache Control Register Leon3 / Leon3FT
77 77 // 31..30 29 28 27..24 23 22 21 20..19 18 17 16
78 78 // RFT PS TB DS FD FI FT ST IB
79 79 // 15 14 13..12 11..10 9..8 7..6 5 4 3..2 1..0
80 80 // IP DP ITE IDE DTE DDE DF IF DCS ICS
81 81
82 82 unsigned int cacheControlRegister;
83 83
84 CCR_resetCacheControlRegister();
85 ASR16_resetRegisterProtectionControlRegister();
86
84 87 cacheControlRegister = CCR_getValue();
85 PRINTF1("(0) cacheControlRegister = %x\n", cacheControlRegister);
86
87 CCR_resetCacheControlRegister();
88 PRINTF1("(0) CCR - Cache Control Register = %x\n", cacheControlRegister);
89 PRINTF1("(0) ASR16 = %x\n", *asr16Ptr);
88 90
89 91 CCR_enableInstructionCache(); // ICS bits
90 92 CCR_enableDataCache(); // DCS bits
91 93 CCR_enableInstructionBurstFetch(); // IB bit
92 94
95 faultTolerantScheme();
96
93 97 cacheControlRegister = CCR_getValue();
94 PRINTF1("(1) cacheControlRegister = %x\n", cacheControlRegister);
95
96 CCR_faultTolerantScheme();
98 PRINTF1("(1) CCR - Cache Control Register = %x\n", cacheControlRegister);
99 PRINTF1("(1) ASR16 Register protection control register = %x\n", *asr16Ptr);
97 100
98 101 PRINTF("\n");
99 102 }
100 103
101 104 rtems_task Init( rtems_task_argument ignored )
102 105 {
103 106 /** This is the RTEMS INIT taks, it is the first task launched by the system.
104 107 *
105 108 * @param unused is the starting argument of the RTEMS task
106 109 *
107 110 * The INIT task create and run all other RTEMS tasks.
108 111 *
109 112 */
110 113
111 114 //***********
112 115 // INIT CACHE
113 116
114 117 unsigned char *vhdlVersion;
115 118
116 119 reset_lfr();
117 120
118 121 reset_local_time();
119 122
120 123 rtems_cpu_usage_reset();
121 124
122 125 rtems_status_code status;
123 126 rtems_status_code status_spw;
124 127 rtems_isr_entry old_isr_handler;
125 128
126 129 // UART settings
127 130 enable_apbuart_transmitter();
128 131 set_apbuart_scaler_reload_register(REGS_ADDR_APBUART, APBUART_SCALER_RELOAD_VALUE);
129 132
130 133 DEBUG_PRINTF("\n\n\n\n\nIn INIT *** Now the console is on port COM1\n")
131 134
132 135
133 136 PRINTF("\n\n\n\n\n")
134 137
135 138 initCache();
136 139
137 140 PRINTF("*************************\n")
138 141 PRINTF("** LFR Flight Software **\n")
139 142 PRINTF1("** %d.", SW_VERSION_N1)
140 143 PRINTF1("%d." , SW_VERSION_N2)
141 144 PRINTF1("%d." , SW_VERSION_N3)
142 145 PRINTF1("%d **\n", SW_VERSION_N4)
143 146
144 147 vhdlVersion = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
145 148 PRINTF("** VHDL **\n")
146 149 PRINTF1("** %d.", vhdlVersion[1])
147 150 PRINTF1("%d." , vhdlVersion[2])
148 151 PRINTF1("%d **\n", vhdlVersion[3])
149 152 PRINTF("*************************\n")
150 153 PRINTF("\n\n")
151 154
152 155 init_parameter_dump();
153 156 init_kcoefficients_dump();
154 157 init_local_mode_parameters();
155 158 init_housekeeping_parameters();
156 159 init_k_coefficients_prc0();
157 160 init_k_coefficients_prc1();
158 161 init_k_coefficients_prc2();
159 162 pa_bia_status_info = 0x00;
160 163 update_last_valid_transition_date( DEFAULT_LAST_VALID_TRANSITION_DATE );
161 164
162 165 // waveform picker initialization
163 166 WFP_init_rings(); LEON_Clear_interrupt( IRQ_SPARC_GPTIMER_WATCHDOG ); // initialize the waveform rings
164 167 WFP_reset_current_ring_nodes();
165 168 reset_waveform_picker_regs();
166 169
167 170 // spectral matrices initialization
168 171 SM_init_rings(); // initialize spectral matrices rings
169 172 SM_reset_current_ring_nodes();
170 173 reset_spectral_matrix_regs();
171 174
172 175 // configure calibration
173 176 configureCalibration( false ); // true means interleaved mode, false is for normal mode
174 177
175 178 updateLFRCurrentMode( LFR_MODE_STANDBY );
176 179
177 180 BOOT_PRINTF1("in INIT *** lfrCurrentMode is %d\n", lfrCurrentMode)
178 181
179 182 create_names(); // create all names
180 183
181 184 status = create_timecode_timer(); // create the timer used by timecode_irq_handler
182 185 if (status != RTEMS_SUCCESSFUL)
183 186 {
184 187 PRINTF1("in INIT *** ERR in create_timer_timecode, code %d", status)
185 188 }
186 189
187 190 status = create_message_queues(); // create message queues
188 191 if (status != RTEMS_SUCCESSFUL)
189 192 {
190 193 PRINTF1("in INIT *** ERR in create_message_queues, code %d", status)
191 194 }
192 195
193 196 status = create_all_tasks(); // create all tasks
194 197 if (status != RTEMS_SUCCESSFUL)
195 198 {
196 199 PRINTF1("in INIT *** ERR in create_all_tasks, code %d\n", status)
197 200 }
198 201
199 202 // **************************
200 203 // <SPACEWIRE INITIALIZATION>
201 grspw_timecode_callback = &timecode_irq_handler;
202
203 204 status_spw = spacewire_open_link(); // (1) open the link
204 205 if ( status_spw != RTEMS_SUCCESSFUL )
205 206 {
206 207 PRINTF1("in INIT *** ERR spacewire_open_link code %d\n", status_spw )
207 208 }
208 209
209 210 if ( status_spw == RTEMS_SUCCESSFUL ) // (2) configure the link
210 211 {
211 212 status_spw = spacewire_configure_link( fdSPW );
212 213 if ( status_spw != RTEMS_SUCCESSFUL )
213 214 {
214 215 PRINTF1("in INIT *** ERR spacewire_configure_link code %d\n", status_spw )
215 216 }
216 217 }
217 218
218 219 if ( status_spw == RTEMS_SUCCESSFUL) // (3) start the link
219 220 {
220 221 status_spw = spacewire_start_link( fdSPW );
221 222 if ( status_spw != RTEMS_SUCCESSFUL )
222 223 {
223 224 PRINTF1("in INIT *** ERR spacewire_start_link code %d\n", status_spw )
224 225 }
225 226 }
226 227 // </SPACEWIRE INITIALIZATION>
227 228 // ***************************
228 229
229 230 status = start_all_tasks(); // start all tasks
230 231 if (status != RTEMS_SUCCESSFUL)
231 232 {
232 233 PRINTF1("in INIT *** ERR in start_all_tasks, code %d", status)
233 234 }
234 235
235 236 // start RECV and SEND *AFTER* SpaceWire Initialization, due to the timeout of the start call during the initialization
236 237 status = start_recv_send_tasks();
237 238 if ( status != RTEMS_SUCCESSFUL )
238 239 {
239 240 PRINTF1("in INIT *** ERR start_recv_send_tasks code %d\n", status )
240 241 }
241 242
242 243 // suspend science tasks, they will be restarted later depending on the mode
243 244 status = suspend_science_tasks(); // suspend science tasks (not done in stop_current_mode if current mode = STANDBY)
244 245 if (status != RTEMS_SUCCESSFUL)
245 246 {
246 247 PRINTF1("in INIT *** in suspend_science_tasks *** ERR code: %d\n", status)
247 248 }
248 249
249 250 // configure IRQ handling for the waveform picker unit
250 251 status = rtems_interrupt_catch( waveforms_isr,
251 252 IRQ_SPARC_WAVEFORM_PICKER,
252 253 &old_isr_handler) ;
253 254 // configure IRQ handling for the spectral matrices unit
254 255 status = rtems_interrupt_catch( spectral_matrices_isr,
255 256 IRQ_SPARC_SPECTRAL_MATRIX,
256 257 &old_isr_handler) ;
257 258
258 259 // if the spacewire link is not up then send an event to the SPIQ task for link recovery
259 260 if ( status_spw != RTEMS_SUCCESSFUL )
260 261 {
261 262 status = rtems_event_send( Task_id[TASKID_SPIQ], SPW_LINKERR_EVENT );
262 263 if ( status != RTEMS_SUCCESSFUL ) {
263 264 PRINTF1("in INIT *** ERR rtems_event_send to SPIQ code %d\n", status )
264 265 }
265 266 }
266 267
267 268 BOOT_PRINTF("delete INIT\n")
268 269
269 270 set_hk_lfr_sc_potential_flag( true );
270 271
271 // start the timer used for the detection of missing parameters (started also by the timecode_irq_handler ISR)
272 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
272 // start the timer to detect a missing spacewire timecode
273 // the timeout is larger because the spw IP needs to receive several valid timecodes before generating a tickout
274 // if a tickout is generated, the timer is restarted
275 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT_INIT, timecode_timer_routine, NULL );
276 grspw_timecode_callback = &timecode_irq_handler;
273 277
274 278 status = rtems_task_delete(RTEMS_SELF);
275 279
276 280 }
277 281
278 282 void init_local_mode_parameters( void )
279 283 {
280 284 /** This function initialize the param_local global variable with default values.
281 285 *
282 286 */
283 287
284 288 unsigned int i;
285 289
286 290 // LOCAL PARAMETERS
287 291
288 292 BOOT_PRINTF1("local_sbm1_nb_cwf_max %d \n", param_local.local_sbm1_nb_cwf_max)
289 293 BOOT_PRINTF1("local_sbm2_nb_cwf_max %d \n", param_local.local_sbm2_nb_cwf_max)
290 294 BOOT_PRINTF1("nb_interrupt_f0_MAX = %d\n", param_local.local_nb_interrupt_f0_MAX)
291 295
292 296 // init sequence counters
293 297
294 298 for(i = 0; i<SEQ_CNT_NB_DEST_ID; i++)
295 299 {
296 300 sequenceCounters_TC_EXE[i] = 0x00;
297 301 sequenceCounters_TM_DUMP[i] = 0x00;
298 302 }
299 303 sequenceCounters_SCIENCE_NORMAL_BURST = 0x00;
300 304 sequenceCounters_SCIENCE_SBM1_SBM2 = 0x00;
301 305 sequenceCounterHK = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
302 306 }
303 307
304 308 void reset_local_time( void )
305 309 {
306 310 time_management_regs->ctrl = time_management_regs->ctrl | 0x02; // [0010] software reset, coarse time = 0x80000000
307 311 }
308 312
309 313 void create_names( void ) // create all names for tasks and queues
310 314 {
311 315 /** This function creates all RTEMS names used in the software for tasks and queues.
312 316 *
313 317 * @return RTEMS directive status codes:
314 318 * - RTEMS_SUCCESSFUL - successful completion
315 319 *
316 320 */
317 321
318 322 // task names
319 323 Task_name[TASKID_RECV] = rtems_build_name( 'R', 'E', 'C', 'V' );
320 324 Task_name[TASKID_ACTN] = rtems_build_name( 'A', 'C', 'T', 'N' );
321 325 Task_name[TASKID_SPIQ] = rtems_build_name( 'S', 'P', 'I', 'Q' );
322 326 Task_name[TASKID_LOAD] = rtems_build_name( 'L', 'O', 'A', 'D' );
323 327 Task_name[TASKID_AVF0] = rtems_build_name( 'A', 'V', 'F', '0' );
324 328 Task_name[TASKID_SWBD] = rtems_build_name( 'S', 'W', 'B', 'D' );
325 329 Task_name[TASKID_WFRM] = rtems_build_name( 'W', 'F', 'R', 'M' );
326 330 Task_name[TASKID_DUMB] = rtems_build_name( 'D', 'U', 'M', 'B' );
327 331 Task_name[TASKID_HOUS] = rtems_build_name( 'H', 'O', 'U', 'S' );
328 332 Task_name[TASKID_PRC0] = rtems_build_name( 'P', 'R', 'C', '0' );
329 333 Task_name[TASKID_CWF3] = rtems_build_name( 'C', 'W', 'F', '3' );
330 334 Task_name[TASKID_CWF2] = rtems_build_name( 'C', 'W', 'F', '2' );
331 335 Task_name[TASKID_CWF1] = rtems_build_name( 'C', 'W', 'F', '1' );
332 336 Task_name[TASKID_SEND] = rtems_build_name( 'S', 'E', 'N', 'D' );
333 337 Task_name[TASKID_LINK] = rtems_build_name( 'L', 'I', 'N', 'K' );
334 338 Task_name[TASKID_AVF1] = rtems_build_name( 'A', 'V', 'F', '1' );
335 339 Task_name[TASKID_PRC1] = rtems_build_name( 'P', 'R', 'C', '1' );
336 340 Task_name[TASKID_AVF2] = rtems_build_name( 'A', 'V', 'F', '2' );
337 341 Task_name[TASKID_PRC2] = rtems_build_name( 'P', 'R', 'C', '2' );
338 342
339 343 // rate monotonic period names
340 344 name_hk_rate_monotonic = rtems_build_name( 'H', 'O', 'U', 'S' );
341 345
342 346 misc_name[QUEUE_RECV] = rtems_build_name( 'Q', '_', 'R', 'V' );
343 347 misc_name[QUEUE_SEND] = rtems_build_name( 'Q', '_', 'S', 'D' );
344 348 misc_name[QUEUE_PRC0] = rtems_build_name( 'Q', '_', 'P', '0' );
345 349 misc_name[QUEUE_PRC1] = rtems_build_name( 'Q', '_', 'P', '1' );
346 350 misc_name[QUEUE_PRC2] = rtems_build_name( 'Q', '_', 'P', '2' );
347 351
348 352 timecode_timer_name = rtems_build_name( 'S', 'P', 'T', 'C' );
349 353 }
350 354
351 355 int create_all_tasks( void ) // create all tasks which run in the software
352 356 {
353 357 /** This function creates all RTEMS tasks used in the software.
354 358 *
355 359 * @return RTEMS directive status codes:
356 360 * - RTEMS_SUCCESSFUL - task created successfully
357 361 * - RTEMS_INVALID_ADDRESS - id is NULL
358 362 * - RTEMS_INVALID_NAME - invalid task name
359 363 * - RTEMS_INVALID_PRIORITY - invalid task priority
360 364 * - RTEMS_MP_NOT_CONFIGURED - multiprocessing not configured
361 365 * - RTEMS_TOO_MANY - too many tasks created
362 366 * - RTEMS_UNSATISFIED - not enough memory for stack/FP context
363 367 * - RTEMS_TOO_MANY - too many global objects
364 368 *
365 369 */
366 370
367 371 rtems_status_code status;
368 372
369 373 //**********
370 374 // SPACEWIRE
371 375 // RECV
372 376 status = rtems_task_create(
373 377 Task_name[TASKID_RECV], TASK_PRIORITY_RECV, RTEMS_MINIMUM_STACK_SIZE,
374 378 RTEMS_DEFAULT_MODES,
375 379 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_RECV]
376 380 );
377 381 if (status == RTEMS_SUCCESSFUL) // SEND
378 382 {
379 383 status = rtems_task_create(
380 384 Task_name[TASKID_SEND], TASK_PRIORITY_SEND, RTEMS_MINIMUM_STACK_SIZE * 2,
381 385 RTEMS_DEFAULT_MODES,
382 386 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SEND]
383 387 );
384 388 }
385 389 if (status == RTEMS_SUCCESSFUL) // LINK
386 390 {
387 391 status = rtems_task_create(
388 392 Task_name[TASKID_LINK], TASK_PRIORITY_LINK, RTEMS_MINIMUM_STACK_SIZE,
389 393 RTEMS_DEFAULT_MODES,
390 394 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_LINK]
391 395 );
392 396 }
393 397 if (status == RTEMS_SUCCESSFUL) // ACTN
394 398 {
395 399 status = rtems_task_create(
396 400 Task_name[TASKID_ACTN], TASK_PRIORITY_ACTN, RTEMS_MINIMUM_STACK_SIZE,
397 401 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
398 402 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_ACTN]
399 403 );
400 404 }
401 405 if (status == RTEMS_SUCCESSFUL) // SPIQ
402 406 {
403 407 status = rtems_task_create(
404 408 Task_name[TASKID_SPIQ], TASK_PRIORITY_SPIQ, RTEMS_MINIMUM_STACK_SIZE,
405 409 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
406 410 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SPIQ]
407 411 );
408 412 }
409 413
410 414 //******************
411 415 // SPECTRAL MATRICES
412 416 if (status == RTEMS_SUCCESSFUL) // AVF0
413 417 {
414 418 status = rtems_task_create(
415 419 Task_name[TASKID_AVF0], TASK_PRIORITY_AVF0, RTEMS_MINIMUM_STACK_SIZE,
416 420 RTEMS_DEFAULT_MODES,
417 421 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF0]
418 422 );
419 423 }
420 424 if (status == RTEMS_SUCCESSFUL) // PRC0
421 425 {
422 426 status = rtems_task_create(
423 427 Task_name[TASKID_PRC0], TASK_PRIORITY_PRC0, RTEMS_MINIMUM_STACK_SIZE * 2,
424 428 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
425 429 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC0]
426 430 );
427 431 }
428 432 if (status == RTEMS_SUCCESSFUL) // AVF1
429 433 {
430 434 status = rtems_task_create(
431 435 Task_name[TASKID_AVF1], TASK_PRIORITY_AVF1, RTEMS_MINIMUM_STACK_SIZE,
432 436 RTEMS_DEFAULT_MODES,
433 437 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF1]
434 438 );
435 439 }
436 440 if (status == RTEMS_SUCCESSFUL) // PRC1
437 441 {
438 442 status = rtems_task_create(
439 443 Task_name[TASKID_PRC1], TASK_PRIORITY_PRC1, RTEMS_MINIMUM_STACK_SIZE * 2,
440 444 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
441 445 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC1]
442 446 );
443 447 }
444 448 if (status == RTEMS_SUCCESSFUL) // AVF2
445 449 {
446 450 status = rtems_task_create(
447 451 Task_name[TASKID_AVF2], TASK_PRIORITY_AVF2, RTEMS_MINIMUM_STACK_SIZE,
448 452 RTEMS_DEFAULT_MODES,
449 453 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF2]
450 454 );
451 455 }
452 456 if (status == RTEMS_SUCCESSFUL) // PRC2
453 457 {
454 458 status = rtems_task_create(
455 459 Task_name[TASKID_PRC2], TASK_PRIORITY_PRC2, RTEMS_MINIMUM_STACK_SIZE * 2,
456 460 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
457 461 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC2]
458 462 );
459 463 }
460 464
461 465 //****************
462 466 // WAVEFORM PICKER
463 467 if (status == RTEMS_SUCCESSFUL) // WFRM
464 468 {
465 469 status = rtems_task_create(
466 470 Task_name[TASKID_WFRM], TASK_PRIORITY_WFRM, RTEMS_MINIMUM_STACK_SIZE,
467 471 RTEMS_DEFAULT_MODES,
468 472 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_WFRM]
469 473 );
470 474 }
471 475 if (status == RTEMS_SUCCESSFUL) // CWF3
472 476 {
473 477 status = rtems_task_create(
474 478 Task_name[TASKID_CWF3], TASK_PRIORITY_CWF3, RTEMS_MINIMUM_STACK_SIZE,
475 479 RTEMS_DEFAULT_MODES,
476 480 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF3]
477 481 );
478 482 }
479 483 if (status == RTEMS_SUCCESSFUL) // CWF2
480 484 {
481 485 status = rtems_task_create(
482 486 Task_name[TASKID_CWF2], TASK_PRIORITY_CWF2, RTEMS_MINIMUM_STACK_SIZE,
483 487 RTEMS_DEFAULT_MODES,
484 488 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF2]
485 489 );
486 490 }
487 491 if (status == RTEMS_SUCCESSFUL) // CWF1
488 492 {
489 493 status = rtems_task_create(
490 494 Task_name[TASKID_CWF1], TASK_PRIORITY_CWF1, RTEMS_MINIMUM_STACK_SIZE,
491 495 RTEMS_DEFAULT_MODES,
492 496 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF1]
493 497 );
494 498 }
495 499 if (status == RTEMS_SUCCESSFUL) // SWBD
496 500 {
497 501 status = rtems_task_create(
498 502 Task_name[TASKID_SWBD], TASK_PRIORITY_SWBD, RTEMS_MINIMUM_STACK_SIZE,
499 503 RTEMS_DEFAULT_MODES,
500 504 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SWBD]
501 505 );
502 506 }
503 507
504 508 //*****
505 509 // MISC
506 510 if (status == RTEMS_SUCCESSFUL) // LOAD
507 511 {
508 512 status = rtems_task_create(
509 513 Task_name[TASKID_LOAD], TASK_PRIORITY_LOAD, RTEMS_MINIMUM_STACK_SIZE,
510 514 RTEMS_DEFAULT_MODES,
511 515 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_LOAD]
512 516 );
513 517 }
514 518 if (status == RTEMS_SUCCESSFUL) // DUMB
515 519 {
516 520 status = rtems_task_create(
517 521 Task_name[TASKID_DUMB], TASK_PRIORITY_DUMB, RTEMS_MINIMUM_STACK_SIZE,
518 522 RTEMS_DEFAULT_MODES,
519 523 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_DUMB]
520 524 );
521 525 }
522 526 if (status == RTEMS_SUCCESSFUL) // HOUS
523 527 {
524 528 status = rtems_task_create(
525 529 Task_name[TASKID_HOUS], TASK_PRIORITY_HOUS, RTEMS_MINIMUM_STACK_SIZE,
526 530 RTEMS_DEFAULT_MODES,
527 531 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_HOUS]
528 532 );
529 533 }
530 534
531 535 return status;
532 536 }
533 537
534 538 int start_recv_send_tasks( void )
535 539 {
536 540 rtems_status_code status;
537 541
538 542 status = rtems_task_start( Task_id[TASKID_RECV], recv_task, 1 );
539 543 if (status!=RTEMS_SUCCESSFUL) {
540 544 BOOT_PRINTF("in INIT *** Error starting TASK_RECV\n")
541 545 }
542 546
543 547 if (status == RTEMS_SUCCESSFUL) // SEND
544 548 {
545 549 status = rtems_task_start( Task_id[TASKID_SEND], send_task, 1 );
546 550 if (status!=RTEMS_SUCCESSFUL) {
547 551 BOOT_PRINTF("in INIT *** Error starting TASK_SEND\n")
548 552 }
549 553 }
550 554
551 555 return status;
552 556 }
553 557
554 558 int start_all_tasks( void ) // start all tasks except SEND RECV and HOUS
555 559 {
556 560 /** This function starts all RTEMS tasks used in the software.
557 561 *
558 562 * @return RTEMS directive status codes:
559 563 * - RTEMS_SUCCESSFUL - ask started successfully
560 564 * - RTEMS_INVALID_ADDRESS - invalid task entry point
561 565 * - RTEMS_INVALID_ID - invalid task id
562 566 * - RTEMS_INCORRECT_STATE - task not in the dormant state
563 567 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task
564 568 *
565 569 */
566 570 // starts all the tasks fot eh flight software
567 571
568 572 rtems_status_code status;
569 573
570 574 //**********
571 575 // SPACEWIRE
572 576 status = rtems_task_start( Task_id[TASKID_SPIQ], spiq_task, 1 );
573 577 if (status!=RTEMS_SUCCESSFUL) {
574 578 BOOT_PRINTF("in INIT *** Error starting TASK_SPIQ\n")
575 579 }
576 580
577 581 if (status == RTEMS_SUCCESSFUL) // LINK
578 582 {
579 583 status = rtems_task_start( Task_id[TASKID_LINK], link_task, 1 );
580 584 if (status!=RTEMS_SUCCESSFUL) {
581 585 BOOT_PRINTF("in INIT *** Error starting TASK_LINK\n")
582 586 }
583 587 }
584 588
585 589 if (status == RTEMS_SUCCESSFUL) // ACTN
586 590 {
587 591 status = rtems_task_start( Task_id[TASKID_ACTN], actn_task, 1 );
588 592 if (status!=RTEMS_SUCCESSFUL) {
589 593 BOOT_PRINTF("in INIT *** Error starting TASK_ACTN\n")
590 594 }
591 595 }
592 596
593 597 //******************
594 598 // SPECTRAL MATRICES
595 599 if (status == RTEMS_SUCCESSFUL) // AVF0
596 600 {
597 601 status = rtems_task_start( Task_id[TASKID_AVF0], avf0_task, LFR_MODE_STANDBY );
598 602 if (status!=RTEMS_SUCCESSFUL) {
599 603 BOOT_PRINTF("in INIT *** Error starting TASK_AVF0\n")
600 604 }
601 605 }
602 606 if (status == RTEMS_SUCCESSFUL) // PRC0
603 607 {
604 608 status = rtems_task_start( Task_id[TASKID_PRC0], prc0_task, LFR_MODE_STANDBY );
605 609 if (status!=RTEMS_SUCCESSFUL) {
606 610 BOOT_PRINTF("in INIT *** Error starting TASK_PRC0\n")
607 611 }
608 612 }
609 613 if (status == RTEMS_SUCCESSFUL) // AVF1
610 614 {
611 615 status = rtems_task_start( Task_id[TASKID_AVF1], avf1_task, LFR_MODE_STANDBY );
612 616 if (status!=RTEMS_SUCCESSFUL) {
613 617 BOOT_PRINTF("in INIT *** Error starting TASK_AVF1\n")
614 618 }
615 619 }
616 620 if (status == RTEMS_SUCCESSFUL) // PRC1
617 621 {
618 622 status = rtems_task_start( Task_id[TASKID_PRC1], prc1_task, LFR_MODE_STANDBY );
619 623 if (status!=RTEMS_SUCCESSFUL) {
620 624 BOOT_PRINTF("in INIT *** Error starting TASK_PRC1\n")
621 625 }
622 626 }
623 627 if (status == RTEMS_SUCCESSFUL) // AVF2
624 628 {
625 629 status = rtems_task_start( Task_id[TASKID_AVF2], avf2_task, 1 );
626 630 if (status!=RTEMS_SUCCESSFUL) {
627 631 BOOT_PRINTF("in INIT *** Error starting TASK_AVF2\n")
628 632 }
629 633 }
630 634 if (status == RTEMS_SUCCESSFUL) // PRC2
631 635 {
632 636 status = rtems_task_start( Task_id[TASKID_PRC2], prc2_task, 1 );
633 637 if (status!=RTEMS_SUCCESSFUL) {
634 638 BOOT_PRINTF("in INIT *** Error starting TASK_PRC2\n")
635 639 }
636 640 }
637 641
638 642 //****************
639 643 // WAVEFORM PICKER
640 644 if (status == RTEMS_SUCCESSFUL) // WFRM
641 645 {
642 646 status = rtems_task_start( Task_id[TASKID_WFRM], wfrm_task, 1 );
643 647 if (status!=RTEMS_SUCCESSFUL) {
644 648 BOOT_PRINTF("in INIT *** Error starting TASK_WFRM\n")
645 649 }
646 650 }
647 651 if (status == RTEMS_SUCCESSFUL) // CWF3
648 652 {
649 653 status = rtems_task_start( Task_id[TASKID_CWF3], cwf3_task, 1 );
650 654 if (status!=RTEMS_SUCCESSFUL) {
651 655 BOOT_PRINTF("in INIT *** Error starting TASK_CWF3\n")
652 656 }
653 657 }
654 658 if (status == RTEMS_SUCCESSFUL) // CWF2
655 659 {
656 660 status = rtems_task_start( Task_id[TASKID_CWF2], cwf2_task, 1 );
657 661 if (status!=RTEMS_SUCCESSFUL) {
658 662 BOOT_PRINTF("in INIT *** Error starting TASK_CWF2\n")
659 663 }
660 664 }
661 665 if (status == RTEMS_SUCCESSFUL) // CWF1
662 666 {
663 667 status = rtems_task_start( Task_id[TASKID_CWF1], cwf1_task, 1 );
664 668 if (status!=RTEMS_SUCCESSFUL) {
665 669 BOOT_PRINTF("in INIT *** Error starting TASK_CWF1\n")
666 670 }
667 671 }
668 672 if (status == RTEMS_SUCCESSFUL) // SWBD
669 673 {
670 674 status = rtems_task_start( Task_id[TASKID_SWBD], swbd_task, 1 );
671 675 if (status!=RTEMS_SUCCESSFUL) {
672 676 BOOT_PRINTF("in INIT *** Error starting TASK_SWBD\n")
673 677 }
674 678 }
675 679
676 680 //*****
677 681 // MISC
678 682 if (status == RTEMS_SUCCESSFUL) // HOUS
679 683 {
680 684 status = rtems_task_start( Task_id[TASKID_HOUS], hous_task, 1 );
681 685 if (status!=RTEMS_SUCCESSFUL) {
682 686 BOOT_PRINTF("in INIT *** Error starting TASK_HOUS\n")
683 687 }
684 688 }
685 689 if (status == RTEMS_SUCCESSFUL) // DUMB
686 690 {
687 691 status = rtems_task_start( Task_id[TASKID_DUMB], dumb_task, 1 );
688 692 if (status!=RTEMS_SUCCESSFUL) {
689 693 BOOT_PRINTF("in INIT *** Error starting TASK_DUMB\n")
690 694 }
691 695 }
692 696 if (status == RTEMS_SUCCESSFUL) // LOAD
693 697 {
694 698 status = rtems_task_start( Task_id[TASKID_LOAD], load_task, 1 );
695 699 if (status!=RTEMS_SUCCESSFUL) {
696 700 BOOT_PRINTF("in INIT *** Error starting TASK_LOAD\n")
697 701 }
698 702 }
699 703
700 704 return status;
701 705 }
702 706
703 707 rtems_status_code create_message_queues( void ) // create the two message queues used in the software
704 708 {
705 709 rtems_status_code status_recv;
706 710 rtems_status_code status_send;
707 711 rtems_status_code status_q_p0;
708 712 rtems_status_code status_q_p1;
709 713 rtems_status_code status_q_p2;
710 714 rtems_status_code ret;
711 715 rtems_id queue_id;
712 716
713 717 //****************************************
714 718 // create the queue for handling valid TCs
715 719 status_recv = rtems_message_queue_create( misc_name[QUEUE_RECV],
716 720 MSG_QUEUE_COUNT_RECV, CCSDS_TC_PKT_MAX_SIZE,
717 721 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
718 722 if ( status_recv != RTEMS_SUCCESSFUL ) {
719 723 PRINTF1("in create_message_queues *** ERR creating QUEU queue, %d\n", status_recv)
720 724 }
721 725
722 726 //************************************************
723 727 // create the queue for handling TM packet sending
724 728 status_send = rtems_message_queue_create( misc_name[QUEUE_SEND],
725 729 MSG_QUEUE_COUNT_SEND, MSG_QUEUE_SIZE_SEND,
726 730 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
727 731 if ( status_send != RTEMS_SUCCESSFUL ) {
728 732 PRINTF1("in create_message_queues *** ERR creating PKTS queue, %d\n", status_send)
729 733 }
730 734
731 735 //*****************************************************************************
732 736 // create the queue for handling averaged spectral matrices for processing @ f0
733 737 status_q_p0 = rtems_message_queue_create( misc_name[QUEUE_PRC0],
734 738 MSG_QUEUE_COUNT_PRC0, MSG_QUEUE_SIZE_PRC0,
735 739 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
736 740 if ( status_q_p0 != RTEMS_SUCCESSFUL ) {
737 741 PRINTF1("in create_message_queues *** ERR creating Q_P0 queue, %d\n", status_q_p0)
738 742 }
739 743
740 744 //*****************************************************************************
741 745 // create the queue for handling averaged spectral matrices for processing @ f1
742 746 status_q_p1 = rtems_message_queue_create( misc_name[QUEUE_PRC1],
743 747 MSG_QUEUE_COUNT_PRC1, MSG_QUEUE_SIZE_PRC1,
744 748 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
745 749 if ( status_q_p1 != RTEMS_SUCCESSFUL ) {
746 750 PRINTF1("in create_message_queues *** ERR creating Q_P1 queue, %d\n", status_q_p1)
747 751 }
748 752
749 753 //*****************************************************************************
750 754 // create the queue for handling averaged spectral matrices for processing @ f2
751 755 status_q_p2 = rtems_message_queue_create( misc_name[QUEUE_PRC2],
752 756 MSG_QUEUE_COUNT_PRC2, MSG_QUEUE_SIZE_PRC2,
753 757 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
754 758 if ( status_q_p2 != RTEMS_SUCCESSFUL ) {
755 759 PRINTF1("in create_message_queues *** ERR creating Q_P2 queue, %d\n", status_q_p2)
756 760 }
757 761
758 762 if ( status_recv != RTEMS_SUCCESSFUL )
759 763 {
760 764 ret = status_recv;
761 765 }
762 766 else if( status_send != RTEMS_SUCCESSFUL )
763 767 {
764 768 ret = status_send;
765 769 }
766 770 else if( status_q_p0 != RTEMS_SUCCESSFUL )
767 771 {
768 772 ret = status_q_p0;
769 773 }
770 774 else if( status_q_p1 != RTEMS_SUCCESSFUL )
771 775 {
772 776 ret = status_q_p1;
773 777 }
774 778 else
775 779 {
776 780 ret = status_q_p2;
777 781 }
778 782
779 783 return ret;
780 784 }
781 785
782 786 rtems_status_code create_timecode_timer( void )
783 787 {
784 788 rtems_status_code status;
785 789
786 790 status = rtems_timer_create( timecode_timer_name, &timecode_timer_id );
787 791
788 792 if ( status != RTEMS_SUCCESSFUL )
789 793 {
790 794 PRINTF1("in create_timer_timecode *** ERR creating SPTC timer, %d\n", status)
791 795 }
792 796 else
793 797 {
794 798 PRINTF("in create_timer_timecode *** OK creating SPTC timer\n")
795 799 }
796 800
797 801 return status;
798 802 }
799 803
800 804 rtems_status_code get_message_queue_id_send( rtems_id *queue_id )
801 805 {
802 806 rtems_status_code status;
803 807 rtems_name queue_name;
804 808
805 809 queue_name = rtems_build_name( 'Q', '_', 'S', 'D' );
806 810
807 811 status = rtems_message_queue_ident( queue_name, 0, queue_id );
808 812
809 813 return status;
810 814 }
811 815
812 816 rtems_status_code get_message_queue_id_recv( rtems_id *queue_id )
813 817 {
814 818 rtems_status_code status;
815 819 rtems_name queue_name;
816 820
817 821 queue_name = rtems_build_name( 'Q', '_', 'R', 'V' );
818 822
819 823 status = rtems_message_queue_ident( queue_name, 0, queue_id );
820 824
821 825 return status;
822 826 }
823 827
824 828 rtems_status_code get_message_queue_id_prc0( rtems_id *queue_id )
825 829 {
826 830 rtems_status_code status;
827 831 rtems_name queue_name;
828 832
829 833 queue_name = rtems_build_name( 'Q', '_', 'P', '0' );
830 834
831 835 status = rtems_message_queue_ident( queue_name, 0, queue_id );
832 836
833 837 return status;
834 838 }
835 839
836 840 rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id )
837 841 {
838 842 rtems_status_code status;
839 843 rtems_name queue_name;
840 844
841 845 queue_name = rtems_build_name( 'Q', '_', 'P', '1' );
842 846
843 847 status = rtems_message_queue_ident( queue_name, 0, queue_id );
844 848
845 849 return status;
846 850 }
847 851
848 852 rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id )
849 853 {
850 854 rtems_status_code status;
851 855 rtems_name queue_name;
852 856
853 857 queue_name = rtems_build_name( 'Q', '_', 'P', '2' );
854 858
855 859 status = rtems_message_queue_ident( queue_name, 0, queue_id );
856 860
857 861 return status;
858 862 }
859 863
860 864 void update_queue_max_count( rtems_id queue_id, unsigned char*fifo_size_max )
861 865 {
862 866 u_int32_t count;
863 867 rtems_status_code status;
864 868
865 869 status = rtems_message_queue_get_number_pending( queue_id, &count );
866 870
867 871 count = count + 1;
868 872
869 873 if (status != RTEMS_SUCCESSFUL)
870 874 {
871 875 PRINTF1("in update_queue_max_count *** ERR = %d\n", status)
872 876 }
873 877 else
874 878 {
875 879 if (count > *fifo_size_max)
876 880 {
877 881 *fifo_size_max = count;
878 882 }
879 883 }
880 884 }
881 885
882 886 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize )
883 887 {
884 888 unsigned char i;
885 889
886 890 //***************
887 891 // BUFFER ADDRESS
888 892 for(i=0; i<nbNodes; i++)
889 893 {
890 894 ring[i].coarseTime = 0xffffffff;
891 895 ring[i].fineTime = 0xffffffff;
892 896 ring[i].sid = 0x00;
893 897 ring[i].status = 0x00;
894 898 ring[i].buffer_address = (int) &buffer[ i * bufferSize ];
895 899 }
896 900
897 901 //*****
898 902 // NEXT
899 903 ring[ nbNodes - 1 ].next = (ring_node*) &ring[ 0 ];
900 904 for(i=0; i<nbNodes-1; i++)
901 905 {
902 906 ring[i].next = (ring_node*) &ring[ i + 1 ];
903 907 }
904 908
905 909 //*********
906 910 // PREVIOUS
907 911 ring[ 0 ].previous = (ring_node*) &ring[ nbNodes - 1 ];
908 912 for(i=1; i<nbNodes; i++)
909 913 {
910 914 ring[i].previous = (ring_node*) &ring[ i - 1 ];
911 915 }
912 916 }
@@ -1,737 +1,783
1 1 /** General usage functions and RTEMS tasks.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 */
7 7
8 8 #include "fsw_misc.h"
9 9
10 10 void timer_configure(unsigned char timer, unsigned int clock_divider,
11 11 unsigned char interrupt_level, rtems_isr (*timer_isr)() )
12 12 {
13 13 /** This function configures a GPTIMER timer instantiated in the VHDL design.
14 14 *
15 15 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
16 16 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
17 17 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
18 18 * @param interrupt_level is the interrupt level that the timer drives.
19 19 * @param timer_isr is the interrupt subroutine that will be attached to the IRQ driven by the timer.
20 20 *
21 21 * Interrupt levels are described in the SPARC documentation sparcv8.pdf p.76
22 22 *
23 23 */
24 24
25 25 rtems_status_code status;
26 26 rtems_isr_entry old_isr_handler;
27 27
28 28 gptimer_regs->timer[timer].ctrl = 0x00; // reset the control register
29 29
30 30 status = rtems_interrupt_catch( timer_isr, interrupt_level, &old_isr_handler) ; // see sparcv8.pdf p.76 for interrupt levels
31 31 if (status!=RTEMS_SUCCESSFUL)
32 32 {
33 33 PRINTF("in configure_timer *** ERR rtems_interrupt_catch\n")
34 34 }
35 35
36 36 timer_set_clock_divider( timer, clock_divider);
37 37 }
38 38
39 39 void timer_start(unsigned char timer)
40 40 {
41 41 /** This function starts a GPTIMER timer.
42 42 *
43 43 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
44 44 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
45 45 *
46 46 */
47 47
48 48 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
49 49 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000004; // LD load value from the reload register
50 50 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000001; // EN enable the timer
51 51 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000002; // RS restart
52 52 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000008; // IE interrupt enable
53 53 }
54 54
55 55 void timer_stop(unsigned char timer)
56 56 {
57 57 /** This function stops a GPTIMER timer.
58 58 *
59 59 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
60 60 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
61 61 *
62 62 */
63 63
64 64 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xfffffffe; // EN enable the timer
65 65 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xffffffef; // IE interrupt enable
66 66 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
67 67 }
68 68
69 69 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider)
70 70 {
71 71 /** This function sets the clock divider of a GPTIMER timer.
72 72 *
73 73 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
74 74 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
75 75 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
76 76 *
77 77 */
78 78
79 79 gptimer_regs->timer[timer].reload = clock_divider; // base clock frequency is 1 MHz
80 80 }
81 81
82 82 // WATCHDOG
83 83
84 84 rtems_isr watchdog_isr( rtems_vector_number vector )
85 85 {
86 86 rtems_status_code status_code;
87 87
88 88 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_12 );
89 89 }
90 90
91 91 void watchdog_configure(void)
92 92 {
93 93 /** This function configure the watchdog.
94 94 *
95 95 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
96 96 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
97 97 *
98 98 * The watchdog is a timer provided by the GPTIMER IP core of the GRLIB.
99 99 *
100 100 */
101 101
102 102 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt during configuration
103 103
104 104 timer_configure( TIMER_WATCHDOG, CLKDIV_WATCHDOG, IRQ_SPARC_GPTIMER_WATCHDOG, watchdog_isr );
105 105
106 106 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
107 107 }
108 108
109 109 void watchdog_stop(void)
110 110 {
111 111 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt line
112 112 timer_stop( TIMER_WATCHDOG );
113 113 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
114 114 }
115 115
116 116 void watchdog_reload(void)
117 117 {
118 118 /** This function reloads the watchdog timer counter with the timer reload value.
119 119 *
120 120 * @param void
121 121 *
122 122 * @return void
123 123 *
124 124 */
125 125
126 126 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
127 127 }
128 128
129 129 void watchdog_start(void)
130 130 {
131 131 /** This function starts the watchdog timer.
132 132 *
133 133 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
134 134 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
135 135 *
136 136 */
137 137
138 138 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
139 139
140 140 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000010; // clear pending IRQ if any
141 141 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
142 142 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000001; // EN enable the timer
143 143 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000008; // IE interrupt enable
144 144
145 145 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
146 146
147 147 }
148 148
149 149 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
150 150 {
151 151 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
152 152
153 153 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
154 154
155 155 return 0;
156 156 }
157 157
158 158 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
159 159 {
160 160 /** This function sets the scaler reload register of the apbuart module
161 161 *
162 162 * @param regs is the address of the apbuart registers in memory
163 163 * @param value is the value that will be stored in the scaler register
164 164 *
165 165 * The value shall be set by the software to get data on the serial interface.
166 166 *
167 167 */
168 168
169 169 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
170 170
171 171 apbuart_regs->scaler = value;
172 172
173 173 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
174 174 }
175 175
176 176 //************
177 177 // RTEMS TASKS
178 178
179 179 rtems_task load_task(rtems_task_argument argument)
180 180 {
181 181 BOOT_PRINTF("in LOAD *** \n")
182 182
183 183 rtems_status_code status;
184 184 unsigned int i;
185 185 unsigned int j;
186 186 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
187 187 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
188 188
189 189 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
190 190
191 191 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
192 192 if( status != RTEMS_SUCCESSFUL ) {
193 193 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
194 194 }
195 195
196 196 i = 0;
197 197 j = 0;
198 198
199 199 watchdog_configure();
200 200
201 201 watchdog_start();
202 202
203 203 while(1){
204 204 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
205 205 watchdog_reload();
206 206 i = i + 1;
207 207 if ( i == 10 )
208 208 {
209 209 i = 0;
210 210 j = j + 1;
211 211 PRINTF1("%d\n", j)
212 212 }
213 213 #ifdef DEBUG_WATCHDOG
214 214 if (j == 3 )
215 215 {
216 216 status = rtems_task_delete(RTEMS_SELF);
217 217 }
218 218 #endif
219 219 }
220 220 }
221 221
222 222 rtems_task hous_task(rtems_task_argument argument)
223 223 {
224 224 rtems_status_code status;
225 225 rtems_status_code spare_status;
226 226 rtems_id queue_id;
227 227 rtems_rate_monotonic_period_status period_status;
228 228
229 229 status = get_message_queue_id_send( &queue_id );
230 230 if (status != RTEMS_SUCCESSFUL)
231 231 {
232 232 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
233 233 }
234 234
235 BOOT_PRINTF("in HOUS ***\n")
235 BOOT_PRINTF("in HOUS ***\n");
236 236
237 237 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
238 238 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
239 239 if( status != RTEMS_SUCCESSFUL ) {
240 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status )
240 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status );
241 241 }
242 242 }
243 243
244 244 status = rtems_rate_monotonic_cancel(HK_id);
245 245 if( status != RTEMS_SUCCESSFUL ) {
246 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status )
246 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status );
247 247 }
248 248 else {
249 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n")
249 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n");
250 250 }
251 251
252 252 // startup phase
253 253 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
254 254 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
255 255 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
256 256 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
257 257 {
258 258 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
259 259 {
260 260 break; // break if LFR is synchronized
261 261 }
262 262 else
263 263 {
264 264 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
265 265 // sched_yield();
266 266 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
267 267 }
268 268 }
269 269 status = rtems_rate_monotonic_cancel(HK_id);
270 270 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
271 271
272 272 set_hk_lfr_reset_cause( POWER_ON );
273 273
274 274 while(1){ // launch the rate monotonic task
275 275 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
276 276 if ( status != RTEMS_SUCCESSFUL ) {
277 277 PRINTF1( "in HOUS *** ERR period: %d\n", status);
278 278 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
279 279 }
280 280 else {
281 281 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
282 282 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
283 283 increment_seq_counter( &sequenceCounterHK );
284 284
285 285 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
286 286 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
287 287 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
288 288 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
289 289 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
290 290 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
291 291
292 292 spacewire_update_statistics();
293 293
294 294 hk_lfr_le_me_he_update();
295 295
296 296 set_hk_lfr_time_not_synchro();
297 297
298 298 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
299 299 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
300 300 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
301 301 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
302 302 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
303 303
304 304 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
305 305 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
306 306 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
307 307 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
308 308 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
309 309
310 310 // SEND PACKET
311 311 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
312 312 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
313 313 if (status != RTEMS_SUCCESSFUL) {
314 314 PRINTF1("in HOUS *** ERR send: %d\n", status)
315 315 }
316 316 }
317 317 }
318 318
319 319 PRINTF("in HOUS *** deleting task\n")
320 320
321 321 status = rtems_task_delete( RTEMS_SELF ); // should not return
322 322
323 323 return;
324 324 }
325 325
326 326 rtems_task dumb_task( rtems_task_argument unused )
327 327 {
328 328 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
329 329 *
330 330 * @param unused is the starting argument of the RTEMS task
331 331 *
332 332 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
333 333 *
334 334 */
335 335
336 336 unsigned int i;
337 337 unsigned int intEventOut;
338 338 unsigned int coarse_time = 0;
339 339 unsigned int fine_time = 0;
340 340 rtems_event_set event_out;
341 341
342 char *DumbMessages[14] = {"in DUMB *** default", // RTEMS_EVENT_0
342 char *DumbMessages[15] = {"in DUMB *** default", // RTEMS_EVENT_0
343 343 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
344 344 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
345 345 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
346 346 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
347 347 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
348 348 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
349 349 "ready for dump", // RTEMS_EVENT_7
350 350 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
351 351 "tick", // RTEMS_EVENT_9
352 352 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
353 353 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11
354 354 "WATCHDOG timer", // RTEMS_EVENT_12
355 "TIMECODE timer" // RTEMS_EVENT_13
355 "TIMECODE timer", // RTEMS_EVENT_13
356 "TIMECODE ISR" // RTEMS_EVENT_14
356 357 };
357 358
358 359 BOOT_PRINTF("in DUMB *** \n")
359 360
360 361 while(1){
361 362 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
362 363 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
363 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13,
364 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13
365 | RTEMS_EVENT_14,
364 366 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
365 367 intEventOut = (unsigned int) event_out;
366 368 for ( i=0; i<32; i++)
367 369 {
368 370 if ( ((intEventOut >> i) & 0x0001) != 0)
369 371 {
370 372 coarse_time = time_management_regs->coarse_time;
371 373 fine_time = time_management_regs->fine_time;
372 374 if (i==12)
373 375 {
374 376 PRINTF1("%s\n", DumbMessages[12])
375 377 }
376 378 if (i==13)
377 379 {
378 380 PRINTF1("%s\n", DumbMessages[13])
379 381 }
382 if (i==14)
383 {
384 PRINTF1("%s\n", DumbMessages[1])
385 }
380 386 }
381 387 }
382 388 }
383 389 }
384 390
385 391 //*****************************
386 392 // init housekeeping parameters
387 393
388 394 void init_housekeeping_parameters( void )
389 395 {
390 396 /** This function initialize the housekeeping_packet global variable with default values.
391 397 *
392 398 */
393 399
394 400 unsigned int i = 0;
395 401 unsigned char *parameters;
396 402 unsigned char sizeOfHK;
397 403
398 404 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
399 405
400 406 parameters = (unsigned char*) &housekeeping_packet;
401 407
402 408 for(i = 0; i< sizeOfHK; i++)
403 409 {
404 410 parameters[i] = 0x00;
405 411 }
406 412
407 413 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
408 414 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
409 415 housekeeping_packet.reserved = DEFAULT_RESERVED;
410 416 housekeeping_packet.userApplication = CCSDS_USER_APP;
411 417 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
412 418 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
413 419 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
414 420 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
415 421 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
416 422 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
417 423 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
418 424 housekeeping_packet.serviceType = TM_TYPE_HK;
419 425 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
420 426 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
421 427 housekeeping_packet.sid = SID_HK;
422 428
423 429 // init status word
424 430 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
425 431 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
426 432 // init software version
427 433 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
428 434 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
429 435 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
430 436 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
431 437 // init fpga version
432 438 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
433 439 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
434 440 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
435 441 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
436 442
437 443 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
438 444 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
439 445 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
440 446 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
441 447 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
442 448 }
443 449
444 450 void increment_seq_counter( unsigned short *packetSequenceControl )
445 451 {
446 452 /** This function increment the sequence counter passes in argument.
447 453 *
448 454 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
449 455 *
450 456 */
451 457
452 458 unsigned short segmentation_grouping_flag;
453 459 unsigned short sequence_cnt;
454 460
455 461 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
456 462 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
457 463
458 464 if ( sequence_cnt < SEQ_CNT_MAX)
459 465 {
460 466 sequence_cnt = sequence_cnt + 1;
461 467 }
462 468 else
463 469 {
464 470 sequence_cnt = 0;
465 471 }
466 472
467 473 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
468 474 }
469 475
470 476 void getTime( unsigned char *time)
471 477 {
472 478 /** This function write the current local time in the time buffer passed in argument.
473 479 *
474 480 */
475 481
476 482 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
477 483 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
478 484 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
479 485 time[3] = (unsigned char) (time_management_regs->coarse_time);
480 486 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
481 487 time[5] = (unsigned char) (time_management_regs->fine_time);
482 488 }
483 489
484 490 unsigned long long int getTimeAsUnsignedLongLongInt( )
485 491 {
486 492 /** This function write the current local time in the time buffer passed in argument.
487 493 *
488 494 */
489 495 unsigned long long int time;
490 496
491 497 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
492 498 + time_management_regs->fine_time;
493 499
494 500 return time;
495 501 }
496 502
497 503 void send_dumb_hk( void )
498 504 {
499 505 Packet_TM_LFR_HK_t dummy_hk_packet;
500 506 unsigned char *parameters;
501 507 unsigned int i;
502 508 rtems_id queue_id;
503 509
504 510 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
505 511 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
506 512 dummy_hk_packet.reserved = DEFAULT_RESERVED;
507 513 dummy_hk_packet.userApplication = CCSDS_USER_APP;
508 514 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
509 515 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
510 516 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
511 517 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
512 518 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
513 519 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
514 520 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
515 521 dummy_hk_packet.serviceType = TM_TYPE_HK;
516 522 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
517 523 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
518 524 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
519 525 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
520 526 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
521 527 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
522 528 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
523 529 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
524 530 dummy_hk_packet.sid = SID_HK;
525 531
526 532 // init status word
527 533 dummy_hk_packet.lfr_status_word[0] = 0xff;
528 534 dummy_hk_packet.lfr_status_word[1] = 0xff;
529 535 // init software version
530 536 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
531 537 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
532 538 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
533 539 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
534 540 // init fpga version
535 541 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
536 542 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
537 543 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
538 544 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
539 545
540 546 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
541 547
542 548 for (i=0; i<100; i++)
543 549 {
544 550 parameters[i] = 0xff;
545 551 }
546 552
547 553 get_message_queue_id_send( &queue_id );
548 554
549 555 rtems_message_queue_send( queue_id, &dummy_hk_packet,
550 556 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
551 557 }
552 558
553 559 void get_temperatures( unsigned char *temperatures )
554 560 {
555 561 unsigned char* temp_scm_ptr;
556 562 unsigned char* temp_pcb_ptr;
557 563 unsigned char* temp_fpga_ptr;
558 564
559 565 // SEL1 SEL0
560 566 // 0 0 => PCB
561 567 // 0 1 => FPGA
562 568 // 1 0 => SCM
563 569
564 570 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
565 571 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
566 572 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
567 573
568 574 temperatures[0] = temp_scm_ptr[2];
569 575 temperatures[1] = temp_scm_ptr[3];
570 576 temperatures[2] = temp_pcb_ptr[2];
571 577 temperatures[3] = temp_pcb_ptr[3];
572 578 temperatures[4] = temp_fpga_ptr[2];
573 579 temperatures[5] = temp_fpga_ptr[3];
574 580 }
575 581
576 582 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
577 583 {
578 584 unsigned char* v_ptr;
579 585 unsigned char* e1_ptr;
580 586 unsigned char* e2_ptr;
581 587
582 588 v_ptr = (unsigned char *) &waveform_picker_regs->v;
583 589 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
584 590 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
585 591
586 592 spacecraft_potential[0] = v_ptr[2];
587 593 spacecraft_potential[1] = v_ptr[3];
588 594 spacecraft_potential[2] = e1_ptr[2];
589 595 spacecraft_potential[3] = e1_ptr[3];
590 596 spacecraft_potential[4] = e2_ptr[2];
591 597 spacecraft_potential[5] = e2_ptr[3];
592 598 }
593 599
594 600 void get_cpu_load( unsigned char *resource_statistics )
595 601 {
596 602 unsigned char cpu_load;
597 603
598 604 cpu_load = lfr_rtems_cpu_usage_report();
599 605
600 606 // HK_LFR_CPU_LOAD
601 607 resource_statistics[0] = cpu_load;
602 608
603 609 // HK_LFR_CPU_LOAD_MAX
604 610 if (cpu_load > resource_statistics[1])
605 611 {
606 612 resource_statistics[1] = cpu_load;
607 613 }
608 614
609 615 // CPU_LOAD_AVE
610 616 resource_statistics[2] = 0;
611 617
612 618 #ifndef PRINT_TASK_STATISTICS
613 619 rtems_cpu_usage_reset();
614 620 #endif
615 621
616 622 }
617 623
618 624 void set_hk_lfr_sc_potential_flag( bool state )
619 625 {
620 626 if (state == true)
621 627 {
622 628 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x40; // [0100 0000]
623 629 }
624 630 else
625 631 {
626 632 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xbf; // [1011 1111]
627 633 }
628 634 }
629 635
630 636 void set_hk_lfr_mag_fields_flag( bool state )
631 637 {
632 638 if (state == true)
633 639 {
634 640 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x20; // [0010 0000]
635 641 }
636 642 else
637 643 {
638 644 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xd7; // [1101 1111]
639 645 }
640 646 }
641 647
642 648 void set_hk_lfr_calib_enable( bool state )
643 649 {
644 650 if (state == true)
645 651 {
646 652 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x08; // [0000 1000]
647 653 }
648 654 else
649 655 {
650 656 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xf7; // [1111 0111]
651 657 }
652 658 }
653 659
654 660 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
655 661 {
656 662 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
657 663 | (lfr_reset_cause & 0x07 ); // [0000 0111]
658 664 }
659 665
660 666 void hk_lfr_le_me_he_update()
661 667 {
662 668 unsigned int hk_lfr_le_cnt;
663 669 unsigned int hk_lfr_me_cnt;
664 670 unsigned int hk_lfr_he_cnt;
665 671
666 672 hk_lfr_le_cnt = 0;
667 673 hk_lfr_me_cnt = 0;
668 674 hk_lfr_he_cnt = 0;
669 675
670 676 //update the low severity error counter
671 677 hk_lfr_le_cnt =
672 678 housekeeping_packet.hk_lfr_dpu_spw_parity
673 679 + housekeeping_packet.hk_lfr_dpu_spw_disconnect
674 680 + housekeeping_packet.hk_lfr_dpu_spw_escape
675 681 + housekeeping_packet.hk_lfr_dpu_spw_credit
676 682 + housekeeping_packet.hk_lfr_dpu_spw_write_sync
677 683 + housekeeping_packet.hk_lfr_dpu_spw_rx_ahb
678 684 + housekeeping_packet.hk_lfr_dpu_spw_tx_ahb
679 685 + housekeeping_packet.hk_lfr_timecode_erroneous
680 686 + housekeeping_packet.hk_lfr_timecode_missing
681 687 + housekeeping_packet.hk_lfr_timecode_invalid
682 688 + housekeeping_packet.hk_lfr_time_timecode_it
683 689 + housekeeping_packet.hk_lfr_time_not_synchro
684 690 + housekeeping_packet.hk_lfr_time_timecode_ctr;
685 691
686 692 //update the medium severity error counter
687 693 hk_lfr_me_cnt =
688 694 housekeeping_packet.hk_lfr_dpu_spw_early_eop
689 695 + housekeeping_packet.hk_lfr_dpu_spw_invalid_addr
690 696 + housekeeping_packet.hk_lfr_dpu_spw_eep
691 697 + housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
692 698
693 699 //update the high severity error counter
694 700 hk_lfr_he_cnt = 0;
695 701
696 702 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
697 703 // LE
698 704 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((hk_lfr_le_cnt & 0xff00) >> 8);
699 705 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (hk_lfr_le_cnt & 0x00ff);
700 706 // ME
701 707 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((hk_lfr_me_cnt & 0xff00) >> 8);
702 708 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (hk_lfr_me_cnt & 0x00ff);
703 709 // HE
704 710 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & 0xff00) >> 8);
705 711 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & 0x00ff);
706 712
707 713 }
708 714
709 715 void set_hk_lfr_time_not_synchro()
710 716 {
711 717 static unsigned char synchroLost = 1;
712 718 int synchronizationBit;
713 719
714 720 // get the synchronization bit
715 721 synchronizationBit = (time_management_regs->coarse_time & 0x80000000) >> 31; // 1000 0000 0000 0000
716 722
717 723 switch (synchronizationBit)
718 724 {
719 725 case 0:
720 726 if (synchroLost == 1)
721 727 {
722 728 synchroLost = 0;
723 729 }
724 730 break;
725 731 case 1:
726 732 if (synchroLost == 0 )
727 733 {
728 734 synchroLost = 1;
729 735 increase_unsigned_char_counter(&housekeeping_packet.hk_lfr_time_not_synchro);
730 736 }
731 737 break;
732 738 default:
733 739 PRINTF1("in hk_lfr_time_not_synchro *** unexpected value for synchronizationBit = %d\n", synchronizationBit);
734 740 break;
735 741 }
736 742
737 743 }
744
745 void set_hk_lfr_ahb_correctable()
746 {
747 /** This function builds the error counter hk_lfr_ahb_correctable using the statistics provided
748 * by the Cache Control Register (ASI 2, offset 0) and in the Register Protection Control Register (ASR16) on the
749 * detected errors in the cache, in the integer unit and in the floating point unit.
750 *
751 * @param void
752 *
753 * @return void
754 *
755 * All errors are summed to set the value of the hk_lfr_ahb_correctable counter.
756 *
757 */
758
759 unsigned int ahb_correctable;
760 unsigned int instructionErrorCounter;
761 unsigned int dataErrorCounter;
762 unsigned int fprfErrorCounter;
763 unsigned int iurfErrorCounter;
764
765 CCR_getInstructionAndDataErrorCounters( &instructionErrorCounter, &dataErrorCounter);
766 ASR16_get_FPRF_IURF_ErrorCounters( &fprfErrorCounter, &iurfErrorCounter);
767
768 ahb_correctable = instructionErrorCounter
769 + dataErrorCounter
770 + fprfErrorCounter
771 + iurfErrorCounter
772 + housekeeping_packet.hk_lfr_ahb_correctable;
773
774 if (ahb_correctable > 255)
775 {
776 housekeeping_packet.hk_lfr_ahb_correctable = 255;
777 }
778 else
779 {
780 housekeeping_packet.hk_lfr_ahb_correctable = ahb_correctable;
781 }
782
783 }
@@ -1,1426 +1,1441
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;
17 17 rtems_id semq_id;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF;
22 22 Header_TM_LFR_SCIENCE_SWF_t headerSWF;
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM;
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 BOOT_PRINTF("in SPIQ *** \n")
43 43
44 44 while(true){
45 45 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
46 46 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
47 47
48 48 // [0] SUSPEND RECV AND SEND TASKS
49 49 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
50 50 if ( status != RTEMS_SUCCESSFUL ) {
51 51 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
52 52 }
53 53 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
54 54 if ( status != RTEMS_SUCCESSFUL ) {
55 55 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
56 56 }
57 57
58 58 // [1] CHECK THE LINK
59 59 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
60 60 if ( linkStatus != 5) {
61 61 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
62 62 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
63 63 }
64 64
65 65 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
66 66 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
67 67 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
68 68 {
69 69 spacewire_compute_stats_offsets();
70 70 status = spacewire_several_connect_attemps( );
71 71 }
72 72 else // [2.b] in run state, start the link
73 73 {
74 74 status = spacewire_stop_and_start_link( fdSPW ); // start the link
75 75 if ( status != RTEMS_SUCCESSFUL)
76 76 {
77 77 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
78 78 }
79 79 }
80 80
81 81 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
82 82 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
83 83 {
84 84 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
85 85 if ( status != RTEMS_SUCCESSFUL ) {
86 86 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
87 87 }
88 88 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
89 89 if ( status != RTEMS_SUCCESSFUL ) {
90 90 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
91 91 }
92 92 }
93 93 else // [3.b] the link is not in run state, go in STANDBY mode
94 94 {
95 95 status = enter_mode_standby();
96 96 if ( status != RTEMS_SUCCESSFUL )
97 97 {
98 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
99 99 }
100 100 {
101 101 updateLFRCurrentMode( LFR_MODE_STANDBY );
102 102 }
103 103 // wake the LINK task up to wait for the link recovery
104 104 status = rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
105 105 status = rtems_task_suspend( RTEMS_SELF );
106 106 }
107 107 }
108 108 }
109 109
110 110 rtems_task recv_task( rtems_task_argument unused )
111 111 {
112 112 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
113 113 *
114 114 * @param unused is the starting argument of the RTEMS task
115 115 *
116 116 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
117 117 * 1. It reads the incoming data.
118 118 * 2. Launches the acceptance procedure.
119 119 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
120 120 *
121 121 */
122 122
123 123 int len;
124 124 ccsdsTelecommandPacket_t currentTC;
125 125 unsigned char computed_CRC[ 2 ];
126 126 unsigned char currentTC_LEN_RCV[ 2 ];
127 127 unsigned char destinationID;
128 128 unsigned int estimatedPacketLength;
129 129 unsigned int parserCode;
130 130 rtems_status_code status;
131 131 rtems_id queue_recv_id;
132 132 rtems_id queue_send_id;
133 133
134 134 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
135 135
136 136 status = get_message_queue_id_recv( &queue_recv_id );
137 137 if (status != RTEMS_SUCCESSFUL)
138 138 {
139 139 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
140 140 }
141 141
142 142 status = get_message_queue_id_send( &queue_send_id );
143 143 if (status != RTEMS_SUCCESSFUL)
144 144 {
145 145 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
146 146 }
147 147
148 148 BOOT_PRINTF("in RECV *** \n")
149 149
150 150 while(1)
151 151 {
152 152 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
153 153 if (len == -1){ // error during the read call
154 154 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
155 155 }
156 156 else {
157 157 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
158 158 PRINTF("in RECV *** packet lenght too short\n")
159 159 }
160 160 else {
161 161 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
162 162 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
163 163 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
164 164 // CHECK THE TC
165 165 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
166 166 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
167 167 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
168 168 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
169 169 || (parserCode == WRONG_SRC_ID) )
170 170 { // send TM_LFR_TC_EXE_CORRUPTED
171 171 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
172 172 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
173 173 &&
174 174 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
175 175 )
176 176 {
177 177 if ( parserCode == WRONG_SRC_ID )
178 178 {
179 179 destinationID = SID_TC_GROUND;
180 180 }
181 181 else
182 182 {
183 183 destinationID = currentTC.sourceID;
184 184 }
185 185 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
186 186 computed_CRC, currentTC_LEN_RCV,
187 187 destinationID );
188 188 }
189 189 }
190 190 else
191 191 { // send valid TC to the action launcher
192 192 status = rtems_message_queue_send( queue_recv_id, &currentTC,
193 193 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
194 194 }
195 195 }
196 196 }
197 197
198 198 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
199 199
200 200 }
201 201 }
202 202
203 203 rtems_task send_task( rtems_task_argument argument)
204 204 {
205 205 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
206 206 *
207 207 * @param unused is the starting argument of the RTEMS task
208 208 *
209 209 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
210 210 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
211 211 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
212 212 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
213 213 * data it contains.
214 214 *
215 215 */
216 216
217 217 rtems_status_code status; // RTEMS status code
218 218 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
219 219 ring_node *incomingRingNodePtr;
220 220 int ring_node_address;
221 221 char *charPtr;
222 222 spw_ioctl_pkt_send *spw_ioctl_send;
223 223 size_t size; // size of the incoming TC packet
224 224 rtems_id queue_send_id;
225 225 unsigned int sid;
226 226 unsigned char sidAsUnsignedChar;
227 227 unsigned char type;
228 228
229 229 incomingRingNodePtr = NULL;
230 230 ring_node_address = 0;
231 231 charPtr = (char *) &ring_node_address;
232 232 sid = 0;
233 233 sidAsUnsignedChar = 0;
234 234
235 235 init_header_cwf( &headerCWF );
236 236 init_header_swf( &headerSWF );
237 237 init_header_asm( &headerASM );
238 238
239 239 status = get_message_queue_id_send( &queue_send_id );
240 240 if (status != RTEMS_SUCCESSFUL)
241 241 {
242 242 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
243 243 }
244 244
245 245 BOOT_PRINTF("in SEND *** \n")
246 246
247 247 while(1)
248 248 {
249 249 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
250 250 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
251 251
252 252 if (status!=RTEMS_SUCCESSFUL)
253 253 {
254 254 PRINTF1("in SEND *** (1) ERR = %d\n", status)
255 255 }
256 256 else
257 257 {
258 258 if ( size == sizeof(ring_node*) )
259 259 {
260 260 charPtr[0] = incomingData[0];
261 261 charPtr[1] = incomingData[1];
262 262 charPtr[2] = incomingData[2];
263 263 charPtr[3] = incomingData[3];
264 264 incomingRingNodePtr = (ring_node*) ring_node_address;
265 265 sid = incomingRingNodePtr->sid;
266 266 if ( (sid==SID_NORM_CWF_LONG_F3)
267 267 || (sid==SID_BURST_CWF_F2 )
268 268 || (sid==SID_SBM1_CWF_F1 )
269 269 || (sid==SID_SBM2_CWF_F2 ))
270 270 {
271 271 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
272 272 }
273 273 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
274 274 {
275 275 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
276 276 }
277 277 else if ( (sid==SID_NORM_CWF_F3) )
278 278 {
279 279 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
280 280 }
281 281 else if (sid==SID_NORM_ASM_F0)
282 282 {
283 283 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
284 284 }
285 285 else if (sid==SID_NORM_ASM_F1)
286 286 {
287 287 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
288 288 }
289 289 else if (sid==SID_NORM_ASM_F2)
290 290 {
291 291 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
292 292 }
293 293 else if ( sid==TM_CODE_K_DUMP )
294 294 {
295 295 spw_send_k_dump( incomingRingNodePtr );
296 296 }
297 297 else
298 298 {
299 299 PRINTF1("unexpected sid = %d\n", sid);
300 300 }
301 301 }
302 302 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
303 303 {
304 304 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
305 305 sid = sidAsUnsignedChar;
306 306 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
307 307 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
308 308 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
309 309 {
310 310 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
311 311 }
312 312
313 313 status = write( fdSPW, incomingData, size );
314 314 if (status == -1){
315 315 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
316 316 }
317 317 }
318 318 else // the incoming message is a spw_ioctl_pkt_send structure
319 319 {
320 320 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
321 321 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
322 322 if (status == -1){
323 323 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
324 324 }
325 325 }
326 326 }
327 327
328 328 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
329 329
330 330 }
331 331 }
332 332
333 333 rtems_task link_task( rtems_task_argument argument )
334 334 {
335 335 rtems_event_set event_out;
336 336 rtems_status_code status;
337 337 int linkStatus;
338 338
339 339 BOOT_PRINTF("in LINK ***\n")
340 340
341 341 while(1)
342 342 {
343 343 // wait for an RTEMS_EVENT
344 344 rtems_event_receive( RTEMS_EVENT_0,
345 345 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
346 346 PRINTF("in LINK *** wait for the link\n")
347 347 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
348 348 while( linkStatus != 5) // wait for the link
349 349 {
350 350 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
351 351 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
352 352 }
353 353
354 354 status = spacewire_stop_and_start_link( fdSPW );
355 355
356 356 if (status != RTEMS_SUCCESSFUL)
357 357 {
358 358 PRINTF1("in LINK *** ERR link not started %d\n", status)
359 359 }
360 360 else
361 361 {
362 362 PRINTF("in LINK *** OK link started\n")
363 363 }
364 364
365 365 // restart the SPIQ task
366 366 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
367 367 if ( status != RTEMS_SUCCESSFUL ) {
368 368 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
369 369 }
370 370
371 371 // restart RECV and SEND
372 372 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
373 373 if ( status != RTEMS_SUCCESSFUL ) {
374 374 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
375 375 }
376 376 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
377 377 if ( status != RTEMS_SUCCESSFUL ) {
378 378 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
379 379 }
380 380 }
381 381 }
382 382
383 383 //****************
384 384 // OTHER FUNCTIONS
385 385 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
386 386 {
387 387 /** This function opens the SpaceWire link.
388 388 *
389 389 * @return a valid file descriptor in case of success, -1 in case of a failure
390 390 *
391 391 */
392 392 rtems_status_code status;
393 393
394 394 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
395 395 if ( fdSPW < 0 ) {
396 396 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
397 397 }
398 398 else
399 399 {
400 400 status = RTEMS_SUCCESSFUL;
401 401 }
402 402
403 403 return status;
404 404 }
405 405
406 406 int spacewire_start_link( int fd )
407 407 {
408 408 rtems_status_code status;
409 409
410 410 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
411 411 // -1 default hardcoded driver timeout
412 412
413 413 return status;
414 414 }
415 415
416 416 int spacewire_stop_and_start_link( int fd )
417 417 {
418 418 rtems_status_code status;
419 419
420 420 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
421 421 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
422 422 // -1 default hardcoded driver timeout
423 423
424 424 return status;
425 425 }
426 426
427 427 int spacewire_configure_link( int fd )
428 428 {
429 429 /** This function configures the SpaceWire link.
430 430 *
431 431 * @return GR-RTEMS-DRIVER directive status codes:
432 432 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
433 433 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
434 434 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
435 435 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
436 436 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
437 437 * - 5 EIO - Error when writing to grswp hardware registers.
438 438 * - 2 ENOENT - No such file or directory
439 439 */
440 440
441 441 rtems_status_code status;
442 442
443 443 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
444 444 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
445 445
446 446 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
447 447 if (status!=RTEMS_SUCCESSFUL) {
448 448 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
449 449 }
450 450 //
451 451 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
452 452 if (status!=RTEMS_SUCCESSFUL) {
453 453 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
454 454 }
455 455 //
456 456 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
457 457 if (status!=RTEMS_SUCCESSFUL) {
458 458 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
459 459 }
460 460 //
461 461 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
462 462 if (status!=RTEMS_SUCCESSFUL) {
463 463 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
464 464 }
465 465 //
466 466 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
467 467 if (status!=RTEMS_SUCCESSFUL) {
468 468 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
469 469 }
470 470 //
471 471 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
472 472 if (status!=RTEMS_SUCCESSFUL) {
473 473 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
474 474 }
475 475 //
476 476 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
477 477 if (status!=RTEMS_SUCCESSFUL) {
478 478 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
479 479 }
480 480
481 481 return status;
482 482 }
483 483
484 484 int spacewire_several_connect_attemps( void )
485 485 {
486 486 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
487 487 *
488 488 * @return RTEMS directive status code:
489 489 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
490 490 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
491 491 *
492 492 */
493 493
494 494 rtems_status_code status_spw;
495 495 rtems_status_code status;
496 496 int i;
497 497
498 498 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
499 499 {
500 500 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
501 501
502 502 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
503 503
504 504 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
505 505
506 506 status_spw = spacewire_stop_and_start_link( fdSPW );
507 507 if ( status_spw != RTEMS_SUCCESSFUL )
508 508 {
509 509 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
510 510 }
511 511
512 512 if ( status_spw == RTEMS_SUCCESSFUL)
513 513 {
514 514 break;
515 515 }
516 516 }
517 517
518 518 return status_spw;
519 519 }
520 520
521 521 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
522 522 {
523 523 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
524 524 *
525 525 * @param val is the value, 0 or 1, used to set the value of the NP bit.
526 526 * @param regAddr is the address of the GRSPW control register.
527 527 *
528 528 * NP is the bit 20 of the GRSPW control register.
529 529 *
530 530 */
531 531
532 532 unsigned int *spwptr = (unsigned int*) regAddr;
533 533
534 534 if (val == 1) {
535 535 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
536 536 }
537 537 if (val== 0) {
538 538 *spwptr = *spwptr & 0xffdfffff;
539 539 }
540 540 }
541 541
542 542 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
543 543 {
544 544 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
545 545 *
546 546 * @param val is the value, 0 or 1, used to set the value of the RE bit.
547 547 * @param regAddr is the address of the GRSPW control register.
548 548 *
549 549 * RE is the bit 16 of the GRSPW control register.
550 550 *
551 551 */
552 552
553 553 unsigned int *spwptr = (unsigned int*) regAddr;
554 554
555 555 if (val == 1)
556 556 {
557 557 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
558 558 }
559 559 if (val== 0)
560 560 {
561 561 *spwptr = *spwptr & 0xfffdffff;
562 562 }
563 563 }
564 564
565 565 void spacewire_compute_stats_offsets( void )
566 566 {
567 567 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
568 568 *
569 569 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
570 570 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
571 571 * during the open systel call).
572 572 *
573 573 */
574 574
575 575 spw_stats spacewire_stats_grspw;
576 576 rtems_status_code status;
577 577
578 578 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
579 579
580 580 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
581 581 + spacewire_stats.packets_received;
582 582 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
583 583 + spacewire_stats.packets_sent;
584 584 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
585 585 + spacewire_stats.parity_err;
586 586 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
587 587 + spacewire_stats.disconnect_err;
588 588 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
589 589 + spacewire_stats.escape_err;
590 590 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
591 591 + spacewire_stats.credit_err;
592 592 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
593 593 + spacewire_stats.write_sync_err;
594 594 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
595 595 + spacewire_stats.rx_rmap_header_crc_err;
596 596 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
597 597 + spacewire_stats.rx_rmap_data_crc_err;
598 598 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
599 599 + spacewire_stats.early_ep;
600 600 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
601 601 + spacewire_stats.invalid_address;
602 602 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
603 603 + spacewire_stats.rx_eep_err;
604 604 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
605 605 + spacewire_stats.rx_truncated;
606 606 }
607 607
608 608 void spacewire_update_statistics( void )
609 609 {
610 610 rtems_status_code status;
611 611 spw_stats spacewire_stats_grspw;
612 612
613 613 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
614 614
615 615 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
616 616 + spacewire_stats_grspw.packets_received;
617 617 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
618 618 + spacewire_stats_grspw.packets_sent;
619 619 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
620 620 + spacewire_stats_grspw.parity_err;
621 621 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
622 622 + spacewire_stats_grspw.disconnect_err;
623 623 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
624 624 + spacewire_stats_grspw.escape_err;
625 625 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
626 626 + spacewire_stats_grspw.credit_err;
627 627 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
628 628 + spacewire_stats_grspw.write_sync_err;
629 629 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
630 630 + spacewire_stats_grspw.rx_rmap_header_crc_err;
631 631 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
632 632 + spacewire_stats_grspw.rx_rmap_data_crc_err;
633 633 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
634 634 + spacewire_stats_grspw.early_ep;
635 635 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
636 636 + spacewire_stats_grspw.invalid_address;
637 637 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
638 638 + spacewire_stats_grspw.rx_eep_err;
639 639 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
640 640 + spacewire_stats_grspw.rx_truncated;
641 641 //spacewire_stats.tx_link_err;
642 642
643 643 //****************************
644 644 // DPU_SPACEWIRE_IF_STATISTICS
645 645 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
646 646 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
647 647 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
648 648 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
649 649 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
650 650 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
651 651
652 652 //******************************************
653 653 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
654 654 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
655 655 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
656 656 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
657 657 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
658 658 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
659 659
660 660 //*********************************************
661 661 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
662 662 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
663 663 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
664 664 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
665 665 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
666 666 }
667 667
668 668 void increase_unsigned_char_counter( unsigned char *counter )
669 669 {
670 670 // update the number of valid timecodes that have been received
671 671 if (*counter == 255)
672 672 {
673 673 *counter = 0;
674 674 }
675 675 else
676 676 {
677 677 *counter = *counter + 1;
678 678 }
679 679 }
680 680
681 681 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
682 682 {
683 static unsigned char initStep = 1;
683 684
684 685 unsigned char currentTimecodeCtr;
685 686
686 687 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
687 688
688 if (currentTimecodeCtr == previousTimecodeCtr)
689 if (initStep == 1)
689 690 {
690 //************************
691 // HK_LFR_TIMECODE_MISSING
692 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
693 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
694 }
695 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
696 {
697 // the timecode value has changed and the value is valid, this is unexpected because
698 // the timer should not have fired, the timecode_irq_handler should have been raised
691 if (currentTimecodeCtr == previousTimecodeCtr)
692 {
693 //************************
694 // HK_LFR_TIMECODE_MISSING
695 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
696 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
697 }
698 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
699 {
700 // the timecode value has changed and the value is valid, this is unexpected because
701 // the timer should not have fired, the timecode_irq_handler should have been raised
702 }
703 else
704 {
705 //************************
706 // HK_LFR_TIMECODE_INVALID
707 // the timecode value has changed and the value is not valid, no tickout has been generated
708 // this is why the timer has fired
709 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
710 }
699 711 }
700 712 else
701 713 {
714 initStep = 1;
702 715 //************************
703 // HK_LFR_TIMECODE_INVALID
704 // the timecode value has changed and the value is not valid, no tickout has been generated
705 // this is why the timer has fired
706 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
716 // HK_LFR_TIMECODE_MISSING
717 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
707 718 }
708 719
709 720 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
710 721 }
711 722
712 723 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
713 724 {
714 725 /** This function checks the coherency between the incoming timecode and the last valid timecode.
715 726 *
716 727 * @param currentTimecodeCtr is the incoming timecode
717 728 *
718 729 * @return returned codes::
719 730 * - LFR_DEFAULT
720 731 * - LFR_SUCCESSFUL
721 732 *
722 733 */
723 734
724 735 static unsigned char firstTickout = 1;
725 736 unsigned char ret;
726 737
727 738 ret = LFR_DEFAULT;
728 739
729 740 if (firstTickout == 0)
730 741 {
731 742 if (currentTimecodeCtr == 0)
732 743 {
733 744 if (previousTimecodeCtr == 63)
734 745 {
735 746 ret = LFR_SUCCESSFUL;
736 747 }
737 748 else
738 749 {
739 750 ret = LFR_DEFAULT;
740 751 }
741 752 }
742 753 else
743 754 {
744 755 if (currentTimecodeCtr == (previousTimecodeCtr +1))
745 756 {
746 757 ret = LFR_SUCCESSFUL;
747 758 }
748 759 else
749 760 {
750 761 ret = LFR_DEFAULT;
751 762 }
752 763 }
753 764 }
754 765 else
755 766 {
756 767 firstTickout = 0;
757 768 ret = LFR_SUCCESSFUL;
758 769 }
759 770
760 771 return ret;
761 772 }
762 773
763 774 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
764 775 {
765 776 unsigned int ret;
766 777
767 778 ret = LFR_DEFAULT;
768 779
769 780 if (timecode == internalTime)
770 781 {
771 782 ret = LFR_SUCCESSFUL;
772 783 }
773 784 else
774 785 {
775 786 ret = LFR_DEFAULT;
776 787 }
777 788
778 789 return ret;
779 790 }
780 791
781 792 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
782 793 {
783 794 // a tickout has been emitted, perform actions on the incoming timecode
784 795
785 796 unsigned char incomingTimecode;
786 797 unsigned char updateTime;
787 798 unsigned char internalTime;
788 799 rtems_status_code status;
789 800
790 801 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
791 802 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
792 803 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
793 804
794 805 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
795 806
796 807 // update the number of tickout that have been generated
797 808 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
798 809
799 810 //**************************
800 811 // HK_LFR_TIMECODE_ERRONEOUS
801 812 // MISSING and INVALID are handled by the timecode_timer_routine service routine
802 813 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
803 814 {
804 815 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
805 816 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
806 817 }
807 818
808 819 //************************
809 820 // HK_LFR_TIME_TIMECODE_IT
810 821 // check the coherency between the SpaceWire timecode and the Internal Time
811 822 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
812 823 {
813 824 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
814 825 }
815 826
816 827 //********************
817 828 // HK_LFR_TIMECODE_CTR
818 829 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
819 830 if (incomingTimecode != updateTime)
820 831 {
821 832 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
822 833 }
823 834
824 835 // launch the timecode timer to detect missing or invalid timecodes
825 836 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
826 837 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
838 if (status != RTEMS_SUCCESSFUL)
839 {
840 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
841 }
827 842 }
828 843
829 844 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
830 845 {
831 846 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
832 847 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
833 848 header->reserved = DEFAULT_RESERVED;
834 849 header->userApplication = CCSDS_USER_APP;
835 850 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
836 851 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
837 852 header->packetLength[0] = 0x00;
838 853 header->packetLength[1] = 0x00;
839 854 // DATA FIELD HEADER
840 855 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
841 856 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
842 857 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
843 858 header->destinationID = TM_DESTINATION_ID_GROUND;
844 859 header->time[0] = 0x00;
845 860 header->time[0] = 0x00;
846 861 header->time[0] = 0x00;
847 862 header->time[0] = 0x00;
848 863 header->time[0] = 0x00;
849 864 header->time[0] = 0x00;
850 865 // AUXILIARY DATA HEADER
851 866 header->sid = 0x00;
852 867 header->hkBIA = DEFAULT_HKBIA;
853 868 header->blkNr[0] = 0x00;
854 869 header->blkNr[1] = 0x00;
855 870 }
856 871
857 872 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
858 873 {
859 874 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
860 875 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
861 876 header->reserved = DEFAULT_RESERVED;
862 877 header->userApplication = CCSDS_USER_APP;
863 878 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
864 879 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
865 880 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
866 881 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
867 882 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
868 883 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
869 884 // DATA FIELD HEADER
870 885 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
871 886 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
872 887 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
873 888 header->destinationID = TM_DESTINATION_ID_GROUND;
874 889 header->time[0] = 0x00;
875 890 header->time[0] = 0x00;
876 891 header->time[0] = 0x00;
877 892 header->time[0] = 0x00;
878 893 header->time[0] = 0x00;
879 894 header->time[0] = 0x00;
880 895 // AUXILIARY DATA HEADER
881 896 header->sid = 0x00;
882 897 header->hkBIA = DEFAULT_HKBIA;
883 898 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
884 899 header->pktNr = 0x00;
885 900 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
886 901 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
887 902 }
888 903
889 904 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
890 905 {
891 906 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
892 907 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
893 908 header->reserved = DEFAULT_RESERVED;
894 909 header->userApplication = CCSDS_USER_APP;
895 910 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
896 911 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
897 912 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
898 913 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
899 914 header->packetLength[0] = 0x00;
900 915 header->packetLength[1] = 0x00;
901 916 // DATA FIELD HEADER
902 917 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
903 918 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
904 919 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
905 920 header->destinationID = TM_DESTINATION_ID_GROUND;
906 921 header->time[0] = 0x00;
907 922 header->time[0] = 0x00;
908 923 header->time[0] = 0x00;
909 924 header->time[0] = 0x00;
910 925 header->time[0] = 0x00;
911 926 header->time[0] = 0x00;
912 927 // AUXILIARY DATA HEADER
913 928 header->sid = 0x00;
914 929 header->biaStatusInfo = 0x00;
915 930 header->pa_lfr_pkt_cnt_asm = 0x00;
916 931 header->pa_lfr_pkt_nr_asm = 0x00;
917 932 header->pa_lfr_asm_blk_nr[0] = 0x00;
918 933 header->pa_lfr_asm_blk_nr[1] = 0x00;
919 934 }
920 935
921 936 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
922 937 Header_TM_LFR_SCIENCE_CWF_t *header )
923 938 {
924 939 /** This function sends CWF CCSDS packets (F2, F1 or F0).
925 940 *
926 941 * @param waveform points to the buffer containing the data that will be send.
927 942 * @param sid is the source identifier of the data that will be sent.
928 943 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
929 944 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
930 945 * contain information to setup the transmission of the data packets.
931 946 *
932 947 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
933 948 *
934 949 */
935 950
936 951 unsigned int i;
937 952 int ret;
938 953 unsigned int coarseTime;
939 954 unsigned int fineTime;
940 955 rtems_status_code status;
941 956 spw_ioctl_pkt_send spw_ioctl_send_CWF;
942 957 int *dataPtr;
943 958 unsigned char sid;
944 959
945 960 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
946 961 spw_ioctl_send_CWF.options = 0;
947 962
948 963 ret = LFR_DEFAULT;
949 964 sid = (unsigned char) ring_node_to_send->sid;
950 965
951 966 coarseTime = ring_node_to_send->coarseTime;
952 967 fineTime = ring_node_to_send->fineTime;
953 968 dataPtr = (int*) ring_node_to_send->buffer_address;
954 969
955 970 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
956 971 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
957 972 header->hkBIA = pa_bia_status_info;
958 973 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
959 974 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
960 975 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
961 976
962 977 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
963 978 {
964 979 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
965 980 spw_ioctl_send_CWF.hdr = (char*) header;
966 981 // BUILD THE DATA
967 982 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
968 983
969 984 // SET PACKET SEQUENCE CONTROL
970 985 increment_seq_counter_source_id( header->packetSequenceControl, sid );
971 986
972 987 // SET SID
973 988 header->sid = sid;
974 989
975 990 // SET PACKET TIME
976 991 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
977 992 //
978 993 header->time[0] = header->acquisitionTime[0];
979 994 header->time[1] = header->acquisitionTime[1];
980 995 header->time[2] = header->acquisitionTime[2];
981 996 header->time[3] = header->acquisitionTime[3];
982 997 header->time[4] = header->acquisitionTime[4];
983 998 header->time[5] = header->acquisitionTime[5];
984 999
985 1000 // SET PACKET ID
986 1001 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
987 1002 {
988 1003 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
989 1004 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
990 1005 }
991 1006 else
992 1007 {
993 1008 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
994 1009 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
995 1010 }
996 1011
997 1012 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
998 1013 if (status != RTEMS_SUCCESSFUL) {
999 1014 ret = LFR_DEFAULT;
1000 1015 }
1001 1016 }
1002 1017
1003 1018 return ret;
1004 1019 }
1005 1020
1006 1021 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1007 1022 Header_TM_LFR_SCIENCE_SWF_t *header )
1008 1023 {
1009 1024 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1010 1025 *
1011 1026 * @param waveform points to the buffer containing the data that will be send.
1012 1027 * @param sid is the source identifier of the data that will be sent.
1013 1028 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1014 1029 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1015 1030 * contain information to setup the transmission of the data packets.
1016 1031 *
1017 1032 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1018 1033 *
1019 1034 */
1020 1035
1021 1036 unsigned int i;
1022 1037 int ret;
1023 1038 unsigned int coarseTime;
1024 1039 unsigned int fineTime;
1025 1040 rtems_status_code status;
1026 1041 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1027 1042 int *dataPtr;
1028 1043 unsigned char sid;
1029 1044
1030 1045 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1031 1046 spw_ioctl_send_SWF.options = 0;
1032 1047
1033 1048 ret = LFR_DEFAULT;
1034 1049
1035 1050 coarseTime = ring_node_to_send->coarseTime;
1036 1051 fineTime = ring_node_to_send->fineTime;
1037 1052 dataPtr = (int*) ring_node_to_send->buffer_address;
1038 1053 sid = ring_node_to_send->sid;
1039 1054
1040 1055 header->hkBIA = pa_bia_status_info;
1041 1056 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1042 1057
1043 1058 for (i=0; i<7; i++) // send waveform
1044 1059 {
1045 1060 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1046 1061 spw_ioctl_send_SWF.hdr = (char*) header;
1047 1062
1048 1063 // SET PACKET SEQUENCE CONTROL
1049 1064 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1050 1065
1051 1066 // SET PACKET LENGTH AND BLKNR
1052 1067 if (i == 6)
1053 1068 {
1054 1069 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1055 1070 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
1056 1071 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1057 1072 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
1058 1073 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1059 1074 }
1060 1075 else
1061 1076 {
1062 1077 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1063 1078 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
1064 1079 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1065 1080 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
1066 1081 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1067 1082 }
1068 1083
1069 1084 // SET PACKET TIME
1070 1085 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1071 1086 //
1072 1087 header->time[0] = header->acquisitionTime[0];
1073 1088 header->time[1] = header->acquisitionTime[1];
1074 1089 header->time[2] = header->acquisitionTime[2];
1075 1090 header->time[3] = header->acquisitionTime[3];
1076 1091 header->time[4] = header->acquisitionTime[4];
1077 1092 header->time[5] = header->acquisitionTime[5];
1078 1093
1079 1094 // SET SID
1080 1095 header->sid = sid;
1081 1096
1082 1097 // SET PKTNR
1083 1098 header->pktNr = i+1; // PKT_NR
1084 1099
1085 1100 // SEND PACKET
1086 1101 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1087 1102 if (status != RTEMS_SUCCESSFUL) {
1088 1103 ret = LFR_DEFAULT;
1089 1104 }
1090 1105 }
1091 1106
1092 1107 return ret;
1093 1108 }
1094 1109
1095 1110 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1096 1111 Header_TM_LFR_SCIENCE_CWF_t *header )
1097 1112 {
1098 1113 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1099 1114 *
1100 1115 * @param waveform points to the buffer containing the data that will be send.
1101 1116 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1102 1117 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1103 1118 * contain information to setup the transmission of the data packets.
1104 1119 *
1105 1120 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1106 1121 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1107 1122 *
1108 1123 */
1109 1124
1110 1125 unsigned int i;
1111 1126 int ret;
1112 1127 unsigned int coarseTime;
1113 1128 unsigned int fineTime;
1114 1129 rtems_status_code status;
1115 1130 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1116 1131 char *dataPtr;
1117 1132 unsigned char sid;
1118 1133
1119 1134 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1120 1135 spw_ioctl_send_CWF.options = 0;
1121 1136
1122 1137 ret = LFR_DEFAULT;
1123 1138 sid = ring_node_to_send->sid;
1124 1139
1125 1140 coarseTime = ring_node_to_send->coarseTime;
1126 1141 fineTime = ring_node_to_send->fineTime;
1127 1142 dataPtr = (char*) ring_node_to_send->buffer_address;
1128 1143
1129 1144 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
1130 1145 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1131 1146 header->hkBIA = pa_bia_status_info;
1132 1147 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1133 1148 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1134 1149 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1135 1150
1136 1151 //*********************
1137 1152 // SEND CWF3_light DATA
1138 1153 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1139 1154 {
1140 1155 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1141 1156 spw_ioctl_send_CWF.hdr = (char*) header;
1142 1157 // BUILD THE DATA
1143 1158 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1144 1159
1145 1160 // SET PACKET SEQUENCE COUNTER
1146 1161 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1147 1162
1148 1163 // SET SID
1149 1164 header->sid = sid;
1150 1165
1151 1166 // SET PACKET TIME
1152 1167 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1153 1168 //
1154 1169 header->time[0] = header->acquisitionTime[0];
1155 1170 header->time[1] = header->acquisitionTime[1];
1156 1171 header->time[2] = header->acquisitionTime[2];
1157 1172 header->time[3] = header->acquisitionTime[3];
1158 1173 header->time[4] = header->acquisitionTime[4];
1159 1174 header->time[5] = header->acquisitionTime[5];
1160 1175
1161 1176 // SET PACKET ID
1162 1177 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1163 1178 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1164 1179
1165 1180 // SEND PACKET
1166 1181 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1167 1182 if (status != RTEMS_SUCCESSFUL) {
1168 1183 ret = LFR_DEFAULT;
1169 1184 }
1170 1185 }
1171 1186
1172 1187 return ret;
1173 1188 }
1174 1189
1175 1190 void spw_send_asm_f0( ring_node *ring_node_to_send,
1176 1191 Header_TM_LFR_SCIENCE_ASM_t *header )
1177 1192 {
1178 1193 unsigned int i;
1179 1194 unsigned int length = 0;
1180 1195 rtems_status_code status;
1181 1196 unsigned int sid;
1182 1197 float *spectral_matrix;
1183 1198 int coarseTime;
1184 1199 int fineTime;
1185 1200 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1186 1201
1187 1202 sid = ring_node_to_send->sid;
1188 1203 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1189 1204 coarseTime = ring_node_to_send->coarseTime;
1190 1205 fineTime = ring_node_to_send->fineTime;
1191 1206
1192 1207 header->biaStatusInfo = pa_bia_status_info;
1193 1208 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1194 1209
1195 1210 for (i=0; i<3; i++)
1196 1211 {
1197 1212 if ((i==0) || (i==1))
1198 1213 {
1199 1214 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1200 1215 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1201 1216 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1202 1217 ];
1203 1218 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1204 1219 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1205 1220 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1206 1221 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1207 1222 }
1208 1223 else
1209 1224 {
1210 1225 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1211 1226 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1212 1227 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1213 1228 ];
1214 1229 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1215 1230 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1216 1231 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1217 1232 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1218 1233 }
1219 1234
1220 1235 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1221 1236 spw_ioctl_send_ASM.hdr = (char *) header;
1222 1237 spw_ioctl_send_ASM.options = 0;
1223 1238
1224 1239 // (2) BUILD THE HEADER
1225 1240 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1226 1241 header->packetLength[0] = (unsigned char) (length>>8);
1227 1242 header->packetLength[1] = (unsigned char) (length);
1228 1243 header->sid = (unsigned char) sid; // SID
1229 1244 header->pa_lfr_pkt_cnt_asm = 3;
1230 1245 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1231 1246
1232 1247 // (3) SET PACKET TIME
1233 1248 header->time[0] = (unsigned char) (coarseTime>>24);
1234 1249 header->time[1] = (unsigned char) (coarseTime>>16);
1235 1250 header->time[2] = (unsigned char) (coarseTime>>8);
1236 1251 header->time[3] = (unsigned char) (coarseTime);
1237 1252 header->time[4] = (unsigned char) (fineTime>>8);
1238 1253 header->time[5] = (unsigned char) (fineTime);
1239 1254 //
1240 1255 header->acquisitionTime[0] = header->time[0];
1241 1256 header->acquisitionTime[1] = header->time[1];
1242 1257 header->acquisitionTime[2] = header->time[2];
1243 1258 header->acquisitionTime[3] = header->time[3];
1244 1259 header->acquisitionTime[4] = header->time[4];
1245 1260 header->acquisitionTime[5] = header->time[5];
1246 1261
1247 1262 // (4) SEND PACKET
1248 1263 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1249 1264 if (status != RTEMS_SUCCESSFUL) {
1250 1265 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1251 1266 }
1252 1267 }
1253 1268 }
1254 1269
1255 1270 void spw_send_asm_f1( ring_node *ring_node_to_send,
1256 1271 Header_TM_LFR_SCIENCE_ASM_t *header )
1257 1272 {
1258 1273 unsigned int i;
1259 1274 unsigned int length = 0;
1260 1275 rtems_status_code status;
1261 1276 unsigned int sid;
1262 1277 float *spectral_matrix;
1263 1278 int coarseTime;
1264 1279 int fineTime;
1265 1280 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1266 1281
1267 1282 sid = ring_node_to_send->sid;
1268 1283 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1269 1284 coarseTime = ring_node_to_send->coarseTime;
1270 1285 fineTime = ring_node_to_send->fineTime;
1271 1286
1272 1287 header->biaStatusInfo = pa_bia_status_info;
1273 1288 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1274 1289
1275 1290 for (i=0; i<3; i++)
1276 1291 {
1277 1292 if ((i==0) || (i==1))
1278 1293 {
1279 1294 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1280 1295 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1281 1296 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1282 1297 ];
1283 1298 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1284 1299 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1285 1300 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1286 1301 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1287 1302 }
1288 1303 else
1289 1304 {
1290 1305 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1291 1306 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1292 1307 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1293 1308 ];
1294 1309 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1295 1310 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1296 1311 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1297 1312 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1298 1313 }
1299 1314
1300 1315 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1301 1316 spw_ioctl_send_ASM.hdr = (char *) header;
1302 1317 spw_ioctl_send_ASM.options = 0;
1303 1318
1304 1319 // (2) BUILD THE HEADER
1305 1320 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1306 1321 header->packetLength[0] = (unsigned char) (length>>8);
1307 1322 header->packetLength[1] = (unsigned char) (length);
1308 1323 header->sid = (unsigned char) sid; // SID
1309 1324 header->pa_lfr_pkt_cnt_asm = 3;
1310 1325 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1311 1326
1312 1327 // (3) SET PACKET TIME
1313 1328 header->time[0] = (unsigned char) (coarseTime>>24);
1314 1329 header->time[1] = (unsigned char) (coarseTime>>16);
1315 1330 header->time[2] = (unsigned char) (coarseTime>>8);
1316 1331 header->time[3] = (unsigned char) (coarseTime);
1317 1332 header->time[4] = (unsigned char) (fineTime>>8);
1318 1333 header->time[5] = (unsigned char) (fineTime);
1319 1334 //
1320 1335 header->acquisitionTime[0] = header->time[0];
1321 1336 header->acquisitionTime[1] = header->time[1];
1322 1337 header->acquisitionTime[2] = header->time[2];
1323 1338 header->acquisitionTime[3] = header->time[3];
1324 1339 header->acquisitionTime[4] = header->time[4];
1325 1340 header->acquisitionTime[5] = header->time[5];
1326 1341
1327 1342 // (4) SEND PACKET
1328 1343 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1329 1344 if (status != RTEMS_SUCCESSFUL) {
1330 1345 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1331 1346 }
1332 1347 }
1333 1348 }
1334 1349
1335 1350 void spw_send_asm_f2( ring_node *ring_node_to_send,
1336 1351 Header_TM_LFR_SCIENCE_ASM_t *header )
1337 1352 {
1338 1353 unsigned int i;
1339 1354 unsigned int length = 0;
1340 1355 rtems_status_code status;
1341 1356 unsigned int sid;
1342 1357 float *spectral_matrix;
1343 1358 int coarseTime;
1344 1359 int fineTime;
1345 1360 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1346 1361
1347 1362 sid = ring_node_to_send->sid;
1348 1363 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1349 1364 coarseTime = ring_node_to_send->coarseTime;
1350 1365 fineTime = ring_node_to_send->fineTime;
1351 1366
1352 1367 header->biaStatusInfo = pa_bia_status_info;
1353 1368 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1354 1369
1355 1370 for (i=0; i<3; i++)
1356 1371 {
1357 1372
1358 1373 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1359 1374 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1360 1375 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1361 1376 ];
1362 1377 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1363 1378 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1364 1379 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1365 1380 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1366 1381
1367 1382 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1368 1383 spw_ioctl_send_ASM.hdr = (char *) header;
1369 1384 spw_ioctl_send_ASM.options = 0;
1370 1385
1371 1386 // (2) BUILD THE HEADER
1372 1387 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1373 1388 header->packetLength[0] = (unsigned char) (length>>8);
1374 1389 header->packetLength[1] = (unsigned char) (length);
1375 1390 header->sid = (unsigned char) sid; // SID
1376 1391 header->pa_lfr_pkt_cnt_asm = 3;
1377 1392 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1378 1393
1379 1394 // (3) SET PACKET TIME
1380 1395 header->time[0] = (unsigned char) (coarseTime>>24);
1381 1396 header->time[1] = (unsigned char) (coarseTime>>16);
1382 1397 header->time[2] = (unsigned char) (coarseTime>>8);
1383 1398 header->time[3] = (unsigned char) (coarseTime);
1384 1399 header->time[4] = (unsigned char) (fineTime>>8);
1385 1400 header->time[5] = (unsigned char) (fineTime);
1386 1401 //
1387 1402 header->acquisitionTime[0] = header->time[0];
1388 1403 header->acquisitionTime[1] = header->time[1];
1389 1404 header->acquisitionTime[2] = header->time[2];
1390 1405 header->acquisitionTime[3] = header->time[3];
1391 1406 header->acquisitionTime[4] = header->time[4];
1392 1407 header->acquisitionTime[5] = header->time[5];
1393 1408
1394 1409 // (4) SEND PACKET
1395 1410 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1396 1411 if (status != RTEMS_SUCCESSFUL) {
1397 1412 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1398 1413 }
1399 1414 }
1400 1415 }
1401 1416
1402 1417 void spw_send_k_dump( ring_node *ring_node_to_send )
1403 1418 {
1404 1419 rtems_status_code status;
1405 1420 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1406 1421 unsigned int packetLength;
1407 1422 unsigned int size;
1408 1423
1409 1424 PRINTF("spw_send_k_dump\n")
1410 1425
1411 1426 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1412 1427
1413 1428 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1414 1429
1415 1430 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1416 1431
1417 1432 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1418 1433
1419 1434 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1420 1435
1421 1436 if (status == -1){
1422 1437 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1423 1438 }
1424 1439
1425 1440 ring_node_to_send->status = 0x00;
1426 1441 }
@@ -1,408 +1,408
1 1 /** Functions related to data processing.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * These function are related to data processing, i.e. spectral matrices averaging and basic parameters computation.
7 7 *
8 8 */
9 9
10 10 #include "avf0_prc0.h"
11 11 #include "fsw_processing.h"
12 12
13 13 nb_sm_before_bp_asm_f0 nb_sm_before_f0;
14 14
15 15 //***
16 16 // F0
17 17 ring_node_asm asm_ring_norm_f0 [ NB_RING_NODES_ASM_NORM_F0 ];
18 18 ring_node_asm asm_ring_burst_sbm_f0 [ NB_RING_NODES_ASM_BURST_SBM_F0 ];
19 19
20 20 ring_node ring_to_send_asm_f0 [ NB_RING_NODES_ASM_F0 ];
21 21 int buffer_asm_f0 [ NB_RING_NODES_ASM_F0 * TOTAL_SIZE_SM ];
22 22
23 23 float asm_f0_patched_norm [ TOTAL_SIZE_SM ];
24 24 float asm_f0_patched_burst_sbm [ TOTAL_SIZE_SM ];
25 25 float asm_f0_reorganized [ TOTAL_SIZE_SM ];
26 26
27 27 char asm_f0_char [ TIME_OFFSET_IN_BYTES + (TOTAL_SIZE_SM * 2) ];
28 28 float compressed_sm_norm_f0[ TOTAL_SIZE_COMPRESSED_ASM_NORM_F0];
29 29 float compressed_sm_sbm_f0 [ TOTAL_SIZE_COMPRESSED_ASM_SBM_F0 ];
30 30
31 31 float k_coeff_intercalib_f0_norm[ NB_BINS_COMPRESSED_SM_F0 * NB_K_COEFF_PER_BIN ]; // 11 * 32 = 352
32 32 float k_coeff_intercalib_f0_sbm[ NB_BINS_COMPRESSED_SM_SBM_F0 * NB_K_COEFF_PER_BIN ]; // 22 * 32 = 704
33 33
34 34 //************
35 35 // RTEMS TASKS
36 36
37 37 rtems_task avf0_task( rtems_task_argument lfrRequestedMode )
38 38 {
39 39 int i;
40 40
41 41 rtems_event_set event_out;
42 42 rtems_status_code status;
43 43 rtems_id queue_id_prc0;
44 asm_msg msgForMATR;
44 asm_msg msgForPRC;
45 45 ring_node *nodeForAveraging;
46 46 ring_node *ring_node_tab[8];
47 47 ring_node_asm *current_ring_node_asm_burst_sbm_f0;
48 48 ring_node_asm *current_ring_node_asm_norm_f0;
49 49
50 50 unsigned int nb_norm_bp1;
51 51 unsigned int nb_norm_bp2;
52 52 unsigned int nb_norm_asm;
53 53 unsigned int nb_sbm_bp1;
54 54 unsigned int nb_sbm_bp2;
55 55
56 56 nb_norm_bp1 = 0;
57 57 nb_norm_bp2 = 0;
58 58 nb_norm_asm = 0;
59 59 nb_sbm_bp1 = 0;
60 60 nb_sbm_bp2 = 0;
61 61
62 62 reset_nb_sm_f0( lfrRequestedMode ); // reset the sm counters that drive the BP and ASM computations / transmissions
63 63 ASM_generic_init_ring( asm_ring_norm_f0, NB_RING_NODES_ASM_NORM_F0 );
64 64 ASM_generic_init_ring( asm_ring_burst_sbm_f0, NB_RING_NODES_ASM_BURST_SBM_F0 );
65 65 current_ring_node_asm_norm_f0 = asm_ring_norm_f0;
66 66 current_ring_node_asm_burst_sbm_f0 = asm_ring_burst_sbm_f0;
67 67
68 68 BOOT_PRINTF1("in AVFO *** lfrRequestedMode = %d\n", (int) lfrRequestedMode)
69 69
70 70 status = get_message_queue_id_prc0( &queue_id_prc0 );
71 71 if (status != RTEMS_SUCCESSFUL)
72 72 {
73 73 PRINTF1("in MATR *** ERR get_message_queue_id_prc0 %d\n", status)
74 74 }
75 75
76 76 while(1){
77 77 rtems_event_receive(RTEMS_EVENT_0, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT0
78 78
79 79 //****************************************
80 80 // initialize the mesage for the MATR task
81 msgForMATR.norm = current_ring_node_asm_norm_f0;
82 msgForMATR.burst_sbm = current_ring_node_asm_burst_sbm_f0;
83 msgForMATR.event = 0x00; // this composite event will be sent to the PRC0 task
81 msgForPRC.norm = current_ring_node_asm_norm_f0;
82 msgForPRC.burst_sbm = current_ring_node_asm_burst_sbm_f0;
83 msgForPRC.event = 0x00; // this composite event will be sent to the PRC0 task
84 84 //
85 85 //****************************************
86 86
87 87 nodeForAveraging = getRingNodeForAveraging( 0 );
88 88
89 89 ring_node_tab[NB_SM_BEFORE_AVF0-1] = nodeForAveraging;
90 90 for ( i = 2; i < (NB_SM_BEFORE_AVF0+1); i++ )
91 91 {
92 92 nodeForAveraging = nodeForAveraging->previous;
93 93 ring_node_tab[NB_SM_BEFORE_AVF0-i] = nodeForAveraging;
94 94 }
95 95
96 96 // compute the average and store it in the averaged_sm_f1 buffer
97 97 SM_average( current_ring_node_asm_norm_f0->matrix,
98 98 current_ring_node_asm_burst_sbm_f0->matrix,
99 99 ring_node_tab,
100 100 nb_norm_bp1, nb_sbm_bp1,
101 &msgForMATR );
101 &msgForPRC );
102 102
103 103 // update nb_average
104 104 nb_norm_bp1 = nb_norm_bp1 + NB_SM_BEFORE_AVF0;
105 105 nb_norm_bp2 = nb_norm_bp2 + NB_SM_BEFORE_AVF0;
106 106 nb_norm_asm = nb_norm_asm + NB_SM_BEFORE_AVF0;
107 107 nb_sbm_bp1 = nb_sbm_bp1 + NB_SM_BEFORE_AVF0;
108 108 nb_sbm_bp2 = nb_sbm_bp2 + NB_SM_BEFORE_AVF0;
109 109
110 110 if (nb_sbm_bp1 == nb_sm_before_f0.burst_sbm_bp1)
111 111 {
112 112 nb_sbm_bp1 = 0;
113 113 // set another ring for the ASM storage
114 114 current_ring_node_asm_burst_sbm_f0 = current_ring_node_asm_burst_sbm_f0->next;
115 115 if ( lfrCurrentMode == LFR_MODE_BURST )
116 116 {
117 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_BURST_BP1_F0;
117 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_BURST_BP1_F0;
118 118 }
119 119 else if ( (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
120 120 {
121 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_SBM_BP1_F0;
121 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_SBM_BP1_F0;
122 122 }
123 123 }
124 124
125 125 if (nb_sbm_bp2 == nb_sm_before_f0.burst_sbm_bp2)
126 126 {
127 127 nb_sbm_bp2 = 0;
128 128 if ( lfrCurrentMode == LFR_MODE_BURST )
129 129 {
130 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_BURST_BP2_F0;
130 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_BURST_BP2_F0;
131 131 }
132 132 else if ( (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
133 133 {
134 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_SBM_BP2_F0;
134 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_SBM_BP2_F0;
135 135 }
136 136 }
137 137
138 138 if (nb_norm_bp1 == nb_sm_before_f0.norm_bp1)
139 139 {
140 140 nb_norm_bp1 = 0;
141 141 // set another ring for the ASM storage
142 142 current_ring_node_asm_norm_f0 = current_ring_node_asm_norm_f0->next;
143 143 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
144 144 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
145 145 {
146 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP1_F0;
146 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP1_F0;
147 147 }
148 148 }
149 149
150 150 if (nb_norm_bp2 == nb_sm_before_f0.norm_bp2)
151 151 {
152 152 nb_norm_bp2 = 0;
153 153 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
154 154 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
155 155 {
156 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP2_F0;
156 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP2_F0;
157 157 }
158 158 }
159 159
160 160 if (nb_norm_asm == nb_sm_before_f0.norm_asm)
161 161 {
162 162 nb_norm_asm = 0;
163 163 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
164 164 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
165 165 {
166 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_ASM_F0;
166 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_ASM_F0;
167 167 }
168 168 }
169 169
170 170 //*************************
171 // send the message to MATR
172 if (msgForMATR.event != 0x00)
171 // send the message to PRC
172 if (msgForPRC.event != 0x00)
173 173 {
174 status = rtems_message_queue_send( queue_id_prc0, (char *) &msgForMATR, MSG_QUEUE_SIZE_PRC0);
174 status = rtems_message_queue_send( queue_id_prc0, (char *) &msgForPRC, MSG_QUEUE_SIZE_PRC0);
175 175 }
176 176
177 177 if (status != RTEMS_SUCCESSFUL) {
178 PRINTF1("in AVF0 *** Error sending message to MATR, code %d\n", status)
178 PRINTF1("in AVF0 *** Error sending message to PRC, code %d\n", status)
179 179 }
180 180 }
181 181 }
182 182
183 183 rtems_task prc0_task( rtems_task_argument lfrRequestedMode )
184 184 {
185 185 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
186 186 size_t size; // size of the incoming TC packet
187 187 asm_msg *incomingMsg;
188 188 //
189 189 unsigned char sid;
190 190 rtems_status_code status;
191 191 rtems_id queue_id;
192 192 rtems_id queue_id_q_p0;
193 193 bp_packet_with_spare packet_norm_bp1;
194 194 bp_packet packet_norm_bp2;
195 195 bp_packet packet_sbm_bp1;
196 196 bp_packet packet_sbm_bp2;
197 197 ring_node *current_ring_node_to_send_asm_f0;
198 198
199 199 // init the ring of the averaged spectral matrices which will be transmitted to the DPU
200 200 init_ring( ring_to_send_asm_f0, NB_RING_NODES_ASM_F0, (volatile int*) buffer_asm_f0, TOTAL_SIZE_SM );
201 201 current_ring_node_to_send_asm_f0 = ring_to_send_asm_f0;
202 202
203 203 //*************
204 204 // NORM headers
205 205 BP_init_header_with_spare( &packet_norm_bp1,
206 206 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP1_F0,
207 207 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F0, NB_BINS_COMPRESSED_SM_F0 );
208 208 BP_init_header( &packet_norm_bp2,
209 209 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP2_F0,
210 210 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F0, NB_BINS_COMPRESSED_SM_F0);
211 211
212 212 //****************************
213 213 // BURST SBM1 and SBM2 headers
214 214 if ( lfrRequestedMode == LFR_MODE_BURST )
215 215 {
216 216 BP_init_header( &packet_sbm_bp1,
217 217 APID_TM_SCIENCE_NORMAL_BURST, SID_BURST_BP1_F0,
218 218 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
219 219 BP_init_header( &packet_sbm_bp2,
220 220 APID_TM_SCIENCE_NORMAL_BURST, SID_BURST_BP2_F0,
221 221 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
222 222 }
223 223 else if ( lfrRequestedMode == LFR_MODE_SBM1 )
224 224 {
225 225 BP_init_header( &packet_sbm_bp1,
226 226 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM1_BP1_F0,
227 227 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
228 228 BP_init_header( &packet_sbm_bp2,
229 229 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM1_BP2_F0,
230 230 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
231 231 }
232 232 else if ( lfrRequestedMode == LFR_MODE_SBM2 )
233 233 {
234 234 BP_init_header( &packet_sbm_bp1,
235 235 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM2_BP1_F0,
236 236 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
237 237 BP_init_header( &packet_sbm_bp2,
238 238 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM2_BP2_F0,
239 239 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F0, NB_BINS_COMPRESSED_SM_SBM_F0);
240 240 }
241 241 else
242 242 {
243 243 PRINTF1("in PRC0 *** lfrRequestedMode is %d, several headers not initialized\n", (unsigned int) lfrRequestedMode)
244 244 }
245 245
246 246 status = get_message_queue_id_send( &queue_id );
247 247 if (status != RTEMS_SUCCESSFUL)
248 248 {
249 249 PRINTF1("in PRC0 *** ERR get_message_queue_id_send %d\n", status)
250 250 }
251 251 status = get_message_queue_id_prc0( &queue_id_q_p0);
252 252 if (status != RTEMS_SUCCESSFUL)
253 253 {
254 254 PRINTF1("in PRC0 *** ERR get_message_queue_id_prc0 %d\n", status)
255 255 }
256 256
257 257 BOOT_PRINTF1("in PRC0 *** lfrRequestedMode = %d\n", (int) lfrRequestedMode)
258 258
259 259 while(1){
260 260 status = rtems_message_queue_receive( queue_id_q_p0, incomingData, &size, //************************************
261 261 RTEMS_WAIT, RTEMS_NO_TIMEOUT ); // wait for a message coming from AVF0
262 262
263 263 incomingMsg = (asm_msg*) incomingData;
264 264
265 265 ASM_patch( incomingMsg->norm->matrix, asm_f0_patched_norm );
266 266 ASM_patch( incomingMsg->burst_sbm->matrix, asm_f0_patched_burst_sbm );
267 267
268 268 //****************
269 269 //****************
270 270 // BURST SBM1 SBM2
271 271 //****************
272 272 //****************
273 273 if ( (incomingMsg->event & RTEMS_EVENT_BURST_BP1_F0 ) || (incomingMsg->event & RTEMS_EVENT_SBM_BP1_F0 ) )
274 274 {
275 275 sid = getSID( incomingMsg->event );
276 276 // 1) compress the matrix for Basic Parameters calculation
277 277 ASM_compress_reorganize_and_divide_mask( asm_f0_patched_burst_sbm, compressed_sm_sbm_f0,
278 278 nb_sm_before_f0.burst_sbm_bp1,
279 279 NB_BINS_COMPRESSED_SM_SBM_F0, NB_BINS_TO_AVERAGE_ASM_SBM_F0,
280 280 ASM_F0_INDICE_START, CHANNELF0);
281 281 // 2) compute the BP1 set
282 282 BP1_set( compressed_sm_sbm_f0, k_coeff_intercalib_f0_sbm, NB_BINS_COMPRESSED_SM_SBM_F0, packet_sbm_bp1.data );
283 283 // 3) send the BP1 set
284 284 set_time( packet_sbm_bp1.time, (unsigned char *) &incomingMsg->coarseTimeSBM );
285 285 set_time( packet_sbm_bp1.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeSBM );
286 286 packet_sbm_bp1.biaStatusInfo = pa_bia_status_info;
287 287 packet_sbm_bp1.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
288 288 BP_send_s1_s2( (char *) &packet_sbm_bp1, queue_id,
289 289 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F0 + PACKET_LENGTH_DELTA,
290 290 sid);
291 291 // 4) compute the BP2 set if needed
292 292 if ( (incomingMsg->event & RTEMS_EVENT_BURST_BP2_F0) || (incomingMsg->event & RTEMS_EVENT_SBM_BP2_F0) )
293 293 {
294 294 // 1) compute the BP2 set
295 295 BP2_set( compressed_sm_sbm_f0, NB_BINS_COMPRESSED_SM_SBM_F0, packet_sbm_bp2.data );
296 296 // 2) send the BP2 set
297 297 set_time( packet_sbm_bp2.time, (unsigned char *) &incomingMsg->coarseTimeSBM );
298 298 set_time( packet_sbm_bp2.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeSBM );
299 299 packet_sbm_bp2.biaStatusInfo = pa_bia_status_info;
300 300 packet_sbm_bp2.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
301 301 BP_send_s1_s2( (char *) &packet_sbm_bp2, queue_id,
302 302 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F0 + PACKET_LENGTH_DELTA,
303 303 sid);
304 304 }
305 305 }
306 306
307 307 //*****
308 308 //*****
309 309 // NORM
310 310 //*****
311 311 //*****
312 312 if (incomingMsg->event & RTEMS_EVENT_NORM_BP1_F0)
313 313 {
314 314 // 1) compress the matrix for Basic Parameters calculation
315 315 ASM_compress_reorganize_and_divide_mask( asm_f0_patched_norm, compressed_sm_norm_f0,
316 316 nb_sm_before_f0.norm_bp1,
317 317 NB_BINS_COMPRESSED_SM_F0, NB_BINS_TO_AVERAGE_ASM_F0,
318 318 ASM_F0_INDICE_START, CHANNELF0 );
319 319 // 2) compute the BP1 set
320 320 BP1_set( compressed_sm_norm_f0, k_coeff_intercalib_f0_norm, NB_BINS_COMPRESSED_SM_F0, packet_norm_bp1.data );
321 321 // 3) send the BP1 set
322 322 set_time( packet_norm_bp1.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
323 323 set_time( packet_norm_bp1.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
324 324 packet_norm_bp1.biaStatusInfo = pa_bia_status_info;
325 325 packet_norm_bp1.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
326 326 BP_send( (char *) &packet_norm_bp1, queue_id,
327 327 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F0 + PACKET_LENGTH_DELTA,
328 328 SID_NORM_BP1_F0 );
329 329 if (incomingMsg->event & RTEMS_EVENT_NORM_BP2_F0)
330 330 {
331 331 // 1) compute the BP2 set using the same ASM as the one used for BP1
332 332 BP2_set( compressed_sm_norm_f0, NB_BINS_COMPRESSED_SM_F0, packet_norm_bp2.data );
333 333 // 2) send the BP2 set
334 334 set_time( packet_norm_bp2.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
335 335 set_time( packet_norm_bp2.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
336 336 packet_norm_bp2.biaStatusInfo = pa_bia_status_info;
337 337 packet_norm_bp2.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
338 338 BP_send( (char *) &packet_norm_bp2, queue_id,
339 339 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F0 + PACKET_LENGTH_DELTA,
340 340 SID_NORM_BP2_F0);
341 341 }
342 342 }
343 343
344 344 if (incomingMsg->event & RTEMS_EVENT_NORM_ASM_F0)
345 345 {
346 346 // 1) reorganize the ASM and divide
347 347 ASM_reorganize_and_divide( asm_f0_patched_norm,
348 348 (float*) current_ring_node_to_send_asm_f0->buffer_address,
349 349 nb_sm_before_f0.norm_bp1 );
350 350 current_ring_node_to_send_asm_f0->coarseTime = incomingMsg->coarseTimeNORM;
351 351 current_ring_node_to_send_asm_f0->fineTime = incomingMsg->fineTimeNORM;
352 352 current_ring_node_to_send_asm_f0->sid = SID_NORM_ASM_F0;
353 353
354 354 // 3) send the spectral matrix packets
355 355 status = rtems_message_queue_send( queue_id, &current_ring_node_to_send_asm_f0, sizeof( ring_node* ) );
356 356 // change asm ring node
357 357 current_ring_node_to_send_asm_f0 = current_ring_node_to_send_asm_f0->next;
358 358 }
359 359
360 360 update_queue_max_count( queue_id_q_p0, &hk_lfr_q_p0_fifo_size_max );
361 361
362 362 }
363 363 }
364 364
365 365 //**********
366 366 // FUNCTIONS
367 367
368 368 void reset_nb_sm_f0( unsigned char lfrMode )
369 369 {
370 370 nb_sm_before_f0.norm_bp1 = parameter_dump_packet.sy_lfr_n_bp_p0 * 96;
371 371 nb_sm_before_f0.norm_bp2 = parameter_dump_packet.sy_lfr_n_bp_p1 * 96;
372 372 nb_sm_before_f0.norm_asm = (parameter_dump_packet.sy_lfr_n_asm_p[0] * 256 + parameter_dump_packet.sy_lfr_n_asm_p[1]) * 96;
373 373 nb_sm_before_f0.sbm1_bp1 = parameter_dump_packet.sy_lfr_s1_bp_p0 * 24; // 0.25 s per digit
374 374 nb_sm_before_f0.sbm1_bp2 = parameter_dump_packet.sy_lfr_s1_bp_p1 * 96;
375 375 nb_sm_before_f0.sbm2_bp1 = parameter_dump_packet.sy_lfr_s2_bp_p0 * 96;
376 376 nb_sm_before_f0.sbm2_bp2 = parameter_dump_packet.sy_lfr_s2_bp_p1 * 96;
377 377 nb_sm_before_f0.burst_bp1 = parameter_dump_packet.sy_lfr_b_bp_p0 * 96;
378 378 nb_sm_before_f0.burst_bp2 = parameter_dump_packet.sy_lfr_b_bp_p1 * 96;
379 379
380 380 if (lfrMode == LFR_MODE_SBM1)
381 381 {
382 382 nb_sm_before_f0.burst_sbm_bp1 = nb_sm_before_f0.sbm1_bp1;
383 383 nb_sm_before_f0.burst_sbm_bp2 = nb_sm_before_f0.sbm1_bp2;
384 384 }
385 385 else if (lfrMode == LFR_MODE_SBM2)
386 386 {
387 387 nb_sm_before_f0.burst_sbm_bp1 = nb_sm_before_f0.sbm2_bp1;
388 388 nb_sm_before_f0.burst_sbm_bp2 = nb_sm_before_f0.sbm2_bp2;
389 389 }
390 390 else if (lfrMode == LFR_MODE_BURST)
391 391 {
392 392 nb_sm_before_f0.burst_sbm_bp1 = nb_sm_before_f0.burst_bp1;
393 393 nb_sm_before_f0.burst_sbm_bp2 = nb_sm_before_f0.burst_bp2;
394 394 }
395 395 else
396 396 {
397 397 nb_sm_before_f0.burst_sbm_bp1 = nb_sm_before_f0.burst_bp1;
398 398 nb_sm_before_f0.burst_sbm_bp2 = nb_sm_before_f0.burst_bp2;
399 399 }
400 400 }
401 401
402 402 void init_k_coefficients_prc0( void )
403 403 {
404 404 init_k_coefficients( k_coeff_intercalib_f0_norm, NB_BINS_COMPRESSED_SM_F0 );
405 405
406 406 init_kcoeff_sbm_from_kcoeff_norm( k_coeff_intercalib_f0_norm, k_coeff_intercalib_f0_sbm, NB_BINS_COMPRESSED_SM_F0);
407 407 }
408 408
@@ -1,394 +1,394
1 1 /** Functions related to data processing.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * These function are related to data processing, i.e. spectral matrices averaging and basic parameters computation.
7 7 *
8 8 */
9 9
10 10 #include "avf1_prc1.h"
11 11
12 12 nb_sm_before_bp_asm_f1 nb_sm_before_f1;
13 13
14 14 extern ring_node sm_ring_f1[ ];
15 15
16 16 //***
17 17 // F1
18 18 ring_node_asm asm_ring_norm_f1 [ NB_RING_NODES_ASM_NORM_F1 ];
19 19 ring_node_asm asm_ring_burst_sbm_f1 [ NB_RING_NODES_ASM_BURST_SBM_F1 ];
20 20
21 21 ring_node ring_to_send_asm_f1 [ NB_RING_NODES_ASM_F1 ];
22 22 int buffer_asm_f1 [ NB_RING_NODES_ASM_F1 * TOTAL_SIZE_SM ];
23 23
24 24 float asm_f1_patched_norm [ TOTAL_SIZE_SM ];
25 25 float asm_f1_patched_burst_sbm [ TOTAL_SIZE_SM ];
26 26 float asm_f1_reorganized [ TOTAL_SIZE_SM ];
27 27
28 28 char asm_f1_char [ TOTAL_SIZE_SM * 2 ];
29 29 float compressed_sm_norm_f1[ TOTAL_SIZE_COMPRESSED_ASM_NORM_F1];
30 30 float compressed_sm_sbm_f1 [ TOTAL_SIZE_COMPRESSED_ASM_SBM_F1 ];
31 31
32 32 float k_coeff_intercalib_f1_norm[ NB_BINS_COMPRESSED_SM_F1 * NB_K_COEFF_PER_BIN ]; // 13 * 32 = 416
33 33 float k_coeff_intercalib_f1_sbm[ NB_BINS_COMPRESSED_SM_SBM_F1 * NB_K_COEFF_PER_BIN ]; // 26 * 32 = 832
34 34
35 35 //************
36 36 // RTEMS TASKS
37 37
38 38 rtems_task avf1_task( rtems_task_argument lfrRequestedMode )
39 39 {
40 40 int i;
41 41
42 42 rtems_event_set event_out;
43 43 rtems_status_code status;
44 44 rtems_id queue_id_prc1;
45 asm_msg msgForMATR;
45 asm_msg msgForPRC;
46 46 ring_node *nodeForAveraging;
47 47 ring_node *ring_node_tab[NB_SM_BEFORE_AVF0];
48 48 ring_node_asm *current_ring_node_asm_burst_sbm_f1;
49 49 ring_node_asm *current_ring_node_asm_norm_f1;
50 50
51 51 unsigned int nb_norm_bp1;
52 52 unsigned int nb_norm_bp2;
53 53 unsigned int nb_norm_asm;
54 54 unsigned int nb_sbm_bp1;
55 55 unsigned int nb_sbm_bp2;
56 56
57 57 nb_norm_bp1 = 0;
58 58 nb_norm_bp2 = 0;
59 59 nb_norm_asm = 0;
60 60 nb_sbm_bp1 = 0;
61 61 nb_sbm_bp2 = 0;
62 62
63 63 reset_nb_sm_f1( lfrRequestedMode ); // reset the sm counters that drive the BP and ASM computations / transmissions
64 64 ASM_generic_init_ring( asm_ring_norm_f1, NB_RING_NODES_ASM_NORM_F1 );
65 65 ASM_generic_init_ring( asm_ring_burst_sbm_f1, NB_RING_NODES_ASM_BURST_SBM_F1 );
66 66 current_ring_node_asm_norm_f1 = asm_ring_norm_f1;
67 67 current_ring_node_asm_burst_sbm_f1 = asm_ring_burst_sbm_f1;
68 68
69 69 BOOT_PRINTF1("in AVF1 *** lfrRequestedMode = %d\n", (int) lfrRequestedMode)
70 70
71 71 status = get_message_queue_id_prc1( &queue_id_prc1 );
72 72 if (status != RTEMS_SUCCESSFUL)
73 73 {
74 74 PRINTF1("in AVF1 *** ERR get_message_queue_id_prc1 %d\n", status)
75 75 }
76 76
77 77 while(1){
78 78 rtems_event_receive(RTEMS_EVENT_0, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT0
79 79
80 80 //****************************************
81 81 // initialize the mesage for the MATR task
82 msgForMATR.norm = current_ring_node_asm_norm_f1;
83 msgForMATR.burst_sbm = current_ring_node_asm_burst_sbm_f1;
84 msgForMATR.event = 0x00; // this composite event will be sent to the PRC1 task
82 msgForPRC.norm = current_ring_node_asm_norm_f1;
83 msgForPRC.burst_sbm = current_ring_node_asm_burst_sbm_f1;
84 msgForPRC.event = 0x00; // this composite event will be sent to the PRC1 task
85 85 //
86 86 //****************************************
87 87
88 88 nodeForAveraging = getRingNodeForAveraging( 1 );
89 89
90 90 ring_node_tab[NB_SM_BEFORE_AVF1-1] = nodeForAveraging;
91 91 for ( i = 2; i < (NB_SM_BEFORE_AVF1+1); i++ )
92 92 {
93 93 nodeForAveraging = nodeForAveraging->previous;
94 94 ring_node_tab[NB_SM_BEFORE_AVF1-i] = nodeForAveraging;
95 95 }
96 96
97 97 // compute the average and store it in the averaged_sm_f1 buffer
98 98 SM_average( current_ring_node_asm_norm_f1->matrix,
99 99 current_ring_node_asm_burst_sbm_f1->matrix,
100 100 ring_node_tab,
101 101 nb_norm_bp1, nb_sbm_bp1,
102 &msgForMATR );
102 &msgForPRC );
103 103
104 104 // update nb_average
105 105 nb_norm_bp1 = nb_norm_bp1 + NB_SM_BEFORE_AVF1;
106 106 nb_norm_bp2 = nb_norm_bp2 + NB_SM_BEFORE_AVF1;
107 107 nb_norm_asm = nb_norm_asm + NB_SM_BEFORE_AVF1;
108 108 nb_sbm_bp1 = nb_sbm_bp1 + NB_SM_BEFORE_AVF1;
109 109 nb_sbm_bp2 = nb_sbm_bp2 + NB_SM_BEFORE_AVF1;
110 110
111 111 if (nb_sbm_bp1 == nb_sm_before_f1.burst_sbm_bp1)
112 112 {
113 113 nb_sbm_bp1 = 0;
114 114 // set another ring for the ASM storage
115 115 current_ring_node_asm_burst_sbm_f1 = current_ring_node_asm_burst_sbm_f1->next;
116 116 if ( lfrCurrentMode == LFR_MODE_BURST )
117 117 {
118 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_BURST_BP1_F1;
118 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_BURST_BP1_F1;
119 119 }
120 120 else if ( lfrCurrentMode == LFR_MODE_SBM2 )
121 121 {
122 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_SBM_BP1_F1;
122 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_SBM_BP1_F1;
123 123 }
124 124 }
125 125
126 126 if (nb_sbm_bp2 == nb_sm_before_f1.burst_sbm_bp2)
127 127 {
128 128 nb_sbm_bp2 = 0;
129 129 if ( lfrCurrentMode == LFR_MODE_BURST )
130 130 {
131 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_BURST_BP2_F1;
131 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_BURST_BP2_F1;
132 132 }
133 133 else if ( lfrCurrentMode == LFR_MODE_SBM2 )
134 134 {
135 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_SBM_BP2_F1;
135 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_SBM_BP2_F1;
136 136 }
137 137 }
138 138
139 139 if (nb_norm_bp1 == nb_sm_before_f1.norm_bp1)
140 140 {
141 141 nb_norm_bp1 = 0;
142 142 // set another ring for the ASM storage
143 143 current_ring_node_asm_norm_f1 = current_ring_node_asm_norm_f1->next;
144 144 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
145 145 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
146 146 {
147 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP1_F1;
147 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP1_F1;
148 148 }
149 149 }
150 150
151 151 if (nb_norm_bp2 == nb_sm_before_f1.norm_bp2)
152 152 {
153 153 nb_norm_bp2 = 0;
154 154 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
155 155 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
156 156 {
157 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP2_F1;
157 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP2_F1;
158 158 }
159 159 }
160 160
161 161 if (nb_norm_asm == nb_sm_before_f1.norm_asm)
162 162 {
163 163 nb_norm_asm = 0;
164 164 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
165 165 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
166 166 {
167 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_ASM_F1;
167 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_ASM_F1;
168 168 }
169 169 }
170 170
171 171 //*************************
172 // send the message to MATR
173 if (msgForMATR.event != 0x00)
172 // send the message to PRC
173 if (msgForPRC.event != 0x00)
174 174 {
175 status = rtems_message_queue_send( queue_id_prc1, (char *) &msgForMATR, MSG_QUEUE_SIZE_PRC1);
175 status = rtems_message_queue_send( queue_id_prc1, (char *) &msgForPRC, MSG_QUEUE_SIZE_PRC1);
176 176 }
177 177
178 178 if (status != RTEMS_SUCCESSFUL) {
179 179 PRINTF1("in AVF1 *** Error sending message to PRC1, code %d\n", status)
180 180 }
181 181 }
182 182 }
183 183
184 184 rtems_task prc1_task( rtems_task_argument lfrRequestedMode )
185 185 {
186 186 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
187 187 size_t size; // size of the incoming TC packet
188 188 asm_msg *incomingMsg;
189 189 //
190 190 unsigned char sid;
191 191 rtems_status_code status;
192 192 rtems_id queue_id_send;
193 193 rtems_id queue_id_q_p1;
194 194 bp_packet_with_spare packet_norm_bp1;
195 195 bp_packet packet_norm_bp2;
196 196 bp_packet packet_sbm_bp1;
197 197 bp_packet packet_sbm_bp2;
198 198 ring_node *current_ring_node_to_send_asm_f1;
199 199
200 200 unsigned long long int localTime;
201 201
202 202 // init the ring of the averaged spectral matrices which will be transmitted to the DPU
203 203 init_ring( ring_to_send_asm_f1, NB_RING_NODES_ASM_F1, (volatile int*) buffer_asm_f1, TOTAL_SIZE_SM );
204 204 current_ring_node_to_send_asm_f1 = ring_to_send_asm_f1;
205 205
206 206 //*************
207 207 // NORM headers
208 208 BP_init_header_with_spare( &packet_norm_bp1,
209 209 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP1_F1,
210 210 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F1, NB_BINS_COMPRESSED_SM_F1 );
211 211 BP_init_header( &packet_norm_bp2,
212 212 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP2_F1,
213 213 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F1, NB_BINS_COMPRESSED_SM_F1);
214 214
215 215 //***********************
216 216 // BURST and SBM2 headers
217 217 if ( lfrRequestedMode == LFR_MODE_BURST )
218 218 {
219 219 BP_init_header( &packet_sbm_bp1,
220 220 APID_TM_SCIENCE_NORMAL_BURST, SID_BURST_BP1_F1,
221 221 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F1, NB_BINS_COMPRESSED_SM_SBM_F1);
222 222 BP_init_header( &packet_sbm_bp2,
223 223 APID_TM_SCIENCE_NORMAL_BURST, SID_BURST_BP2_F1,
224 224 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F1, NB_BINS_COMPRESSED_SM_SBM_F1);
225 225 }
226 226 else if ( lfrRequestedMode == LFR_MODE_SBM2 )
227 227 {
228 228 BP_init_header( &packet_sbm_bp1,
229 229 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM2_BP1_F1,
230 230 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F1, NB_BINS_COMPRESSED_SM_SBM_F1);
231 231 BP_init_header( &packet_sbm_bp2,
232 232 APID_TM_SCIENCE_SBM1_SBM2, SID_SBM2_BP2_F1,
233 233 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F1, NB_BINS_COMPRESSED_SM_SBM_F1);
234 234 }
235 235 else
236 236 {
237 237 PRINTF1("in PRC1 *** lfrRequestedMode is %d, several headers not initialized\n", (unsigned int) lfrRequestedMode)
238 238 }
239 239
240 240 status = get_message_queue_id_send( &queue_id_send );
241 241 if (status != RTEMS_SUCCESSFUL)
242 242 {
243 243 PRINTF1("in PRC1 *** ERR get_message_queue_id_send %d\n", status)
244 244 }
245 245 status = get_message_queue_id_prc1( &queue_id_q_p1);
246 246 if (status != RTEMS_SUCCESSFUL)
247 247 {
248 248 PRINTF1("in PRC1 *** ERR get_message_queue_id_prc1 %d\n", status)
249 249 }
250 250
251 251 BOOT_PRINTF1("in PRC1 *** lfrRequestedMode = %d\n", (int) lfrRequestedMode)
252 252
253 253 while(1){
254 254 status = rtems_message_queue_receive( queue_id_q_p1, incomingData, &size, //************************************
255 255 RTEMS_WAIT, RTEMS_NO_TIMEOUT ); // wait for a message coming from AVF0
256 256
257 257 incomingMsg = (asm_msg*) incomingData;
258 258
259 259 ASM_patch( incomingMsg->norm->matrix, asm_f1_patched_norm );
260 260 ASM_patch( incomingMsg->burst_sbm->matrix, asm_f1_patched_burst_sbm );
261 261
262 262 localTime = getTimeAsUnsignedLongLongInt( );
263 263 //***********
264 264 //***********
265 265 // BURST SBM2
266 266 //***********
267 267 //***********
268 268 if ( (incomingMsg->event & RTEMS_EVENT_BURST_BP1_F1) || (incomingMsg->event & RTEMS_EVENT_SBM_BP1_F1) )
269 269 {
270 270 sid = getSID( incomingMsg->event );
271 271 // 1) compress the matrix for Basic Parameters calculation
272 272 ASM_compress_reorganize_and_divide_mask( asm_f1_patched_burst_sbm, compressed_sm_sbm_f1,
273 273 nb_sm_before_f1.burst_sbm_bp1,
274 274 NB_BINS_COMPRESSED_SM_SBM_F1, NB_BINS_TO_AVERAGE_ASM_SBM_F1,
275 275 ASM_F1_INDICE_START, CHANNELF1);
276 276 // 2) compute the BP1 set
277 277 BP1_set( compressed_sm_sbm_f1, k_coeff_intercalib_f1_sbm, NB_BINS_COMPRESSED_SM_SBM_F1, packet_sbm_bp1.data );
278 278 // 3) send the BP1 set
279 279 set_time( packet_sbm_bp1.time, (unsigned char *) &incomingMsg->coarseTimeSBM );
280 280 set_time( packet_sbm_bp1.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeSBM );
281 281 packet_sbm_bp1.biaStatusInfo = pa_bia_status_info;
282 282 packet_sbm_bp1.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
283 283 BP_send_s1_s2( (char *) &packet_sbm_bp1, queue_id_send,
284 284 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP1_F1 + PACKET_LENGTH_DELTA,
285 285 sid );
286 286 // 4) compute the BP2 set if needed
287 287 if ( (incomingMsg->event & RTEMS_EVENT_BURST_BP2_F1) || (incomingMsg->event & RTEMS_EVENT_SBM_BP2_F1) )
288 288 {
289 289 // 1) compute the BP2 set
290 290 BP2_set( compressed_sm_sbm_f1, NB_BINS_COMPRESSED_SM_SBM_F1, packet_sbm_bp2.data );
291 291 // 2) send the BP2 set
292 292 set_time( packet_sbm_bp2.time, (unsigned char *) &incomingMsg->coarseTimeSBM );
293 293 set_time( packet_sbm_bp2.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeSBM );
294 294 packet_sbm_bp2.biaStatusInfo = pa_bia_status_info;
295 295 packet_sbm_bp2.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
296 296 BP_send_s1_s2( (char *) &packet_sbm_bp2, queue_id_send,
297 297 PACKET_LENGTH_TM_LFR_SCIENCE_SBM_BP2_F1 + PACKET_LENGTH_DELTA,
298 298 sid );
299 299 }
300 300 }
301 301
302 302 //*****
303 303 //*****
304 304 // NORM
305 305 //*****
306 306 //*****
307 307 if (incomingMsg->event & RTEMS_EVENT_NORM_BP1_F1)
308 308 {
309 309 // 1) compress the matrix for Basic Parameters calculation
310 310 ASM_compress_reorganize_and_divide_mask( asm_f1_patched_norm, compressed_sm_norm_f1,
311 311 nb_sm_before_f1.norm_bp1,
312 312 NB_BINS_COMPRESSED_SM_F1, NB_BINS_TO_AVERAGE_ASM_F1,
313 313 ASM_F1_INDICE_START, CHANNELF1 );
314 314 // 2) compute the BP1 set
315 315 BP1_set( compressed_sm_norm_f1, k_coeff_intercalib_f1_norm, NB_BINS_COMPRESSED_SM_F1, packet_norm_bp1.data );
316 316 // 3) send the BP1 set
317 317 set_time( packet_norm_bp1.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
318 318 set_time( packet_norm_bp1.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
319 319 packet_norm_bp1.biaStatusInfo = pa_bia_status_info;
320 320 packet_norm_bp1.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
321 321 BP_send( (char *) &packet_norm_bp1, queue_id_send,
322 322 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F1 + PACKET_LENGTH_DELTA,
323 323 SID_NORM_BP1_F1 );
324 324 if (incomingMsg->event & RTEMS_EVENT_NORM_BP2_F1)
325 325 {
326 326 // 1) compute the BP2 set
327 327 BP2_set( compressed_sm_norm_f1, NB_BINS_COMPRESSED_SM_F1, packet_norm_bp2.data );
328 328 // 2) send the BP2 set
329 329 set_time( packet_norm_bp2.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
330 330 set_time( packet_norm_bp2.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
331 331 packet_norm_bp2.biaStatusInfo = pa_bia_status_info;
332 332 packet_norm_bp2.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
333 333 BP_send( (char *) &packet_norm_bp2, queue_id_send,
334 334 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F1 + PACKET_LENGTH_DELTA,
335 335 SID_NORM_BP2_F1 );
336 336 }
337 337 }
338 338
339 339 if (incomingMsg->event & RTEMS_EVENT_NORM_ASM_F1)
340 340 {
341 341 // 1) reorganize the ASM and divide
342 342 ASM_reorganize_and_divide( asm_f1_patched_norm,
343 343 (float*) current_ring_node_to_send_asm_f1->buffer_address,
344 344 nb_sm_before_f1.norm_bp1 );
345 345 current_ring_node_to_send_asm_f1->coarseTime = incomingMsg->coarseTimeNORM;
346 346 current_ring_node_to_send_asm_f1->fineTime = incomingMsg->fineTimeNORM;
347 347 current_ring_node_to_send_asm_f1->sid = SID_NORM_ASM_F1;
348 348 // 3) send the spectral matrix packets
349 349 status = rtems_message_queue_send( queue_id_send, &current_ring_node_to_send_asm_f1, sizeof( ring_node* ) );
350 350 // change asm ring node
351 351 current_ring_node_to_send_asm_f1 = current_ring_node_to_send_asm_f1->next;
352 352 }
353 353
354 354 update_queue_max_count( queue_id_q_p1, &hk_lfr_q_p1_fifo_size_max );
355 355
356 356 }
357 357 }
358 358
359 359 //**********
360 360 // FUNCTIONS
361 361
362 362 void reset_nb_sm_f1( unsigned char lfrMode )
363 363 {
364 364 nb_sm_before_f1.norm_bp1 = parameter_dump_packet.sy_lfr_n_bp_p0 * 16;
365 365 nb_sm_before_f1.norm_bp2 = parameter_dump_packet.sy_lfr_n_bp_p1 * 16;
366 366 nb_sm_before_f1.norm_asm = (parameter_dump_packet.sy_lfr_n_asm_p[0] * 256 + parameter_dump_packet.sy_lfr_n_asm_p[1]) * 16;
367 367 nb_sm_before_f1.sbm2_bp1 = parameter_dump_packet.sy_lfr_s2_bp_p0 * 16;
368 368 nb_sm_before_f1.sbm2_bp2 = parameter_dump_packet.sy_lfr_s2_bp_p1 * 16;
369 369 nb_sm_before_f1.burst_bp1 = parameter_dump_packet.sy_lfr_b_bp_p0 * 16;
370 370 nb_sm_before_f1.burst_bp2 = parameter_dump_packet.sy_lfr_b_bp_p1 * 16;
371 371
372 372 if (lfrMode == LFR_MODE_SBM2)
373 373 {
374 374 nb_sm_before_f1.burst_sbm_bp1 = nb_sm_before_f1.sbm2_bp1;
375 375 nb_sm_before_f1.burst_sbm_bp2 = nb_sm_before_f1.sbm2_bp2;
376 376 }
377 377 else if (lfrMode == LFR_MODE_BURST)
378 378 {
379 379 nb_sm_before_f1.burst_sbm_bp1 = nb_sm_before_f1.burst_bp1;
380 380 nb_sm_before_f1.burst_sbm_bp2 = nb_sm_before_f1.burst_bp2;
381 381 }
382 382 else
383 383 {
384 384 nb_sm_before_f1.burst_sbm_bp1 = nb_sm_before_f1.burst_bp1;
385 385 nb_sm_before_f1.burst_sbm_bp2 = nb_sm_before_f1.burst_bp2;
386 386 }
387 387 }
388 388
389 389 void init_k_coefficients_prc1( void )
390 390 {
391 391 init_k_coefficients( k_coeff_intercalib_f1_norm, NB_BINS_COMPRESSED_SM_F1 );
392 392
393 393 init_kcoeff_sbm_from_kcoeff_norm( k_coeff_intercalib_f1_norm, k_coeff_intercalib_f1_sbm, NB_BINS_COMPRESSED_SM_F1);
394 394 }
@@ -1,281 +1,281
1 1 /** Functions related to data processing.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * These function are related to data processing, i.e. spectral matrices averaging and basic parameters computation.
7 7 *
8 8 */
9 9
10 10 #include "avf2_prc2.h"
11 11
12 12 nb_sm_before_bp_asm_f2 nb_sm_before_f2;
13 13
14 14 extern ring_node sm_ring_f2[ ];
15 15
16 16 //***
17 17 // F2
18 18 ring_node_asm asm_ring_norm_f2 [ NB_RING_NODES_ASM_NORM_F2 ];
19 19
20 20 ring_node ring_to_send_asm_f2 [ NB_RING_NODES_ASM_F2 ];
21 21 int buffer_asm_f2 [ NB_RING_NODES_ASM_F2 * TOTAL_SIZE_SM ];
22 22
23 23 float asm_f2_patched_norm [ TOTAL_SIZE_SM ];
24 24 float asm_f2_reorganized [ TOTAL_SIZE_SM ];
25 25
26 26 char asm_f2_char [ TOTAL_SIZE_SM * 2 ];
27 27 float compressed_sm_norm_f2[ TOTAL_SIZE_COMPRESSED_ASM_NORM_F2];
28 28
29 29 float k_coeff_intercalib_f2[ NB_BINS_COMPRESSED_SM_F2 * NB_K_COEFF_PER_BIN ]; // 12 * 32 = 384
30 30
31 31 //************
32 32 // RTEMS TASKS
33 33
34 34 //***
35 35 // F2
36 36 rtems_task avf2_task( rtems_task_argument argument )
37 37 {
38 38 rtems_event_set event_out;
39 39 rtems_status_code status;
40 40 rtems_id queue_id_prc2;
41 asm_msg msgForMATR;
41 asm_msg msgForPRC;
42 42 ring_node *nodeForAveraging;
43 43 ring_node_asm *current_ring_node_asm_norm_f2;
44 44
45 45 unsigned int nb_norm_bp1;
46 46 unsigned int nb_norm_bp2;
47 47 unsigned int nb_norm_asm;
48 48
49 49 nb_norm_bp1 = 0;
50 50 nb_norm_bp2 = 0;
51 51 nb_norm_asm = 0;
52 52
53 53 reset_nb_sm_f2( ); // reset the sm counters that drive the BP and ASM computations / transmissions
54 54 ASM_generic_init_ring( asm_ring_norm_f2, NB_RING_NODES_ASM_NORM_F2 );
55 55 current_ring_node_asm_norm_f2 = asm_ring_norm_f2;
56 56
57 57 BOOT_PRINTF("in AVF2 ***\n")
58 58
59 59 status = get_message_queue_id_prc2( &queue_id_prc2 );
60 60 if (status != RTEMS_SUCCESSFUL)
61 61 {
62 62 PRINTF1("in AVF2 *** ERR get_message_queue_id_prc2 %d\n", status)
63 63 }
64 64
65 65 while(1){
66 66 rtems_event_receive(RTEMS_EVENT_0, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT0
67 67
68 68 //****************************************
69 69 // initialize the mesage for the MATR task
70 msgForMATR.norm = current_ring_node_asm_norm_f2;
71 msgForMATR.burst_sbm = NULL;
72 msgForMATR.event = 0x00; // this composite event will be sent to the PRC2 task
70 msgForPRC.norm = current_ring_node_asm_norm_f2;
71 msgForPRC.burst_sbm = NULL;
72 msgForPRC.event = 0x00; // this composite event will be sent to the PRC2 task
73 73 //
74 74 //****************************************
75 75
76 76 nodeForAveraging = getRingNodeForAveraging( 2 );
77 77
78 78 // compute the average and store it in the averaged_sm_f2 buffer
79 79 SM_average_f2( current_ring_node_asm_norm_f2->matrix,
80 80 nodeForAveraging,
81 81 nb_norm_bp1,
82 &msgForMATR );
82 &msgForPRC );
83 83
84 84 // update nb_average
85 85 nb_norm_bp1 = nb_norm_bp1 + NB_SM_BEFORE_AVF2;
86 86 nb_norm_bp2 = nb_norm_bp2 + NB_SM_BEFORE_AVF2;
87 87 nb_norm_asm = nb_norm_asm + NB_SM_BEFORE_AVF2;
88 88
89 89 if (nb_norm_bp1 == nb_sm_before_f2.norm_bp1)
90 90 {
91 91 nb_norm_bp1 = 0;
92 92 // set another ring for the ASM storage
93 93 current_ring_node_asm_norm_f2 = current_ring_node_asm_norm_f2->next;
94 94 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_SBM1)
95 95 || (lfrCurrentMode == LFR_MODE_SBM2) )
96 96 {
97 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP1_F2;
97 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP1_F2;
98 98 }
99 99 }
100 100
101 101 if (nb_norm_bp2 == nb_sm_before_f2.norm_bp2)
102 102 {
103 103 nb_norm_bp2 = 0;
104 104 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_SBM1)
105 105 || (lfrCurrentMode == LFR_MODE_SBM2) )
106 106 {
107 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_BP2_F2;
107 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_BP2_F2;
108 108 }
109 109 }
110 110
111 111 if (nb_norm_asm == nb_sm_before_f2.norm_asm)
112 112 {
113 113 nb_norm_asm = 0;
114 114 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_SBM1)
115 115 || (lfrCurrentMode == LFR_MODE_SBM2) )
116 116 {
117 msgForMATR.event = msgForMATR.event | RTEMS_EVENT_NORM_ASM_F2;
117 msgForPRC.event = msgForPRC.event | RTEMS_EVENT_NORM_ASM_F2;
118 118 }
119 119 }
120 120
121 121 //*************************
122 // send the message to MATR
123 if (msgForMATR.event != 0x00)
122 // send the message to PRC2
123 if (msgForPRC.event != 0x00)
124 124 {
125 status = rtems_message_queue_send( queue_id_prc2, (char *) &msgForMATR, MSG_QUEUE_SIZE_PRC2);
125 status = rtems_message_queue_send( queue_id_prc2, (char *) &msgForPRC, MSG_QUEUE_SIZE_PRC2);
126 126 }
127 127
128 128 if (status != RTEMS_SUCCESSFUL) {
129 PRINTF1("in AVF2 *** Error sending message to MATR, code %d\n", status)
129 PRINTF1("in AVF2 *** Error sending message to PRC2, code %d\n", status)
130 130 }
131 131 }
132 132 }
133 133
134 134 rtems_task prc2_task( rtems_task_argument argument )
135 135 {
136 136 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
137 137 size_t size; // size of the incoming TC packet
138 138 asm_msg *incomingMsg;
139 139 //
140 140 rtems_status_code status;
141 141 rtems_id queue_id_send;
142 142 rtems_id queue_id_q_p2;
143 143 bp_packet packet_norm_bp1;
144 144 bp_packet packet_norm_bp2;
145 145 ring_node *current_ring_node_to_send_asm_f2;
146 146
147 147 unsigned long long int localTime;
148 148
149 149 // init the ring of the averaged spectral matrices which will be transmitted to the DPU
150 150 init_ring( ring_to_send_asm_f2, NB_RING_NODES_ASM_F2, (volatile int*) buffer_asm_f2, TOTAL_SIZE_SM );
151 151 current_ring_node_to_send_asm_f2 = ring_to_send_asm_f2;
152 152
153 153 //*************
154 154 // NORM headers
155 155 BP_init_header( &packet_norm_bp1,
156 156 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP1_F2,
157 157 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F2, NB_BINS_COMPRESSED_SM_F2 );
158 158 BP_init_header( &packet_norm_bp2,
159 159 APID_TM_SCIENCE_NORMAL_BURST, SID_NORM_BP2_F2,
160 160 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F2, NB_BINS_COMPRESSED_SM_F2 );
161 161
162 162 status = get_message_queue_id_send( &queue_id_send );
163 163 if (status != RTEMS_SUCCESSFUL)
164 164 {
165 165 PRINTF1("in PRC2 *** ERR get_message_queue_id_send %d\n", status)
166 166 }
167 167 status = get_message_queue_id_prc2( &queue_id_q_p2);
168 168 if (status != RTEMS_SUCCESSFUL)
169 169 {
170 170 PRINTF1("in PRC2 *** ERR get_message_queue_id_prc2 %d\n", status)
171 171 }
172 172
173 173 BOOT_PRINTF("in PRC2 ***\n")
174 174
175 175 while(1){
176 176 status = rtems_message_queue_receive( queue_id_q_p2, incomingData, &size, //************************************
177 177 RTEMS_WAIT, RTEMS_NO_TIMEOUT ); // wait for a message coming from AVF2
178 178
179 179 incomingMsg = (asm_msg*) incomingData;
180 180
181 181 ASM_patch( incomingMsg->norm->matrix, asm_f2_patched_norm );
182 182
183 183 localTime = getTimeAsUnsignedLongLongInt( );
184 184
185 185 //*****
186 186 //*****
187 187 // NORM
188 188 //*****
189 189 //*****
190 190 // 1) compress the matrix for Basic Parameters calculation
191 191 ASM_compress_reorganize_and_divide_mask( asm_f2_patched_norm, compressed_sm_norm_f2,
192 192 nb_sm_before_f2.norm_bp1,
193 193 NB_BINS_COMPRESSED_SM_F2, NB_BINS_TO_AVERAGE_ASM_F2,
194 194 ASM_F2_INDICE_START, CHANNELF2 );
195 195 // BP1_F2
196 196 if (incomingMsg->event & RTEMS_EVENT_NORM_BP1_F2)
197 197 {
198 198 // 1) compute the BP1 set
199 199 BP1_set( compressed_sm_norm_f2, k_coeff_intercalib_f2, NB_BINS_COMPRESSED_SM_F2, packet_norm_bp1.data );
200 200 // 2) send the BP1 set
201 201 set_time( packet_norm_bp1.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
202 202 set_time( packet_norm_bp1.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
203 203 packet_norm_bp1.biaStatusInfo = pa_bia_status_info;
204 204 packet_norm_bp1.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
205 205 BP_send( (char *) &packet_norm_bp1, queue_id_send,
206 206 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP1_F2 + PACKET_LENGTH_DELTA,
207 207 SID_NORM_BP1_F2 );
208 208 }
209 209 // BP2_F2
210 210 if (incomingMsg->event & RTEMS_EVENT_NORM_BP2_F2)
211 211 {
212 212 // 1) compute the BP2 set
213 213 BP2_set( compressed_sm_norm_f2, NB_BINS_COMPRESSED_SM_F2, packet_norm_bp2.data );
214 214 // 2) send the BP2 set
215 215 set_time( packet_norm_bp2.time, (unsigned char *) &incomingMsg->coarseTimeNORM );
216 216 set_time( packet_norm_bp2.acquisitionTime, (unsigned char *) &incomingMsg->coarseTimeNORM );
217 217 packet_norm_bp2.biaStatusInfo = pa_bia_status_info;
218 218 packet_norm_bp2.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
219 219 BP_send( (char *) &packet_norm_bp2, queue_id_send,
220 220 PACKET_LENGTH_TM_LFR_SCIENCE_NORM_BP2_F2 + PACKET_LENGTH_DELTA,
221 221 SID_NORM_BP2_F2 );
222 222 }
223 223
224 224 if (incomingMsg->event & RTEMS_EVENT_NORM_ASM_F2)
225 225 {
226 226 // 1) reorganize the ASM and divide
227 227 ASM_reorganize_and_divide( asm_f2_patched_norm,
228 228 (float*) current_ring_node_to_send_asm_f2->buffer_address,
229 229 nb_sm_before_f2.norm_bp1 );
230 230 current_ring_node_to_send_asm_f2->coarseTime = incomingMsg->coarseTimeNORM;
231 231 current_ring_node_to_send_asm_f2->fineTime = incomingMsg->fineTimeNORM;
232 232 current_ring_node_to_send_asm_f2->sid = SID_NORM_ASM_F2;
233 233 // 3) send the spectral matrix packets
234 234 status = rtems_message_queue_send( queue_id_send, &current_ring_node_to_send_asm_f2, sizeof( ring_node* ) );
235 235 // change asm ring node
236 236 current_ring_node_to_send_asm_f2 = current_ring_node_to_send_asm_f2->next;
237 237 }
238 238
239 239 update_queue_max_count( queue_id_q_p2, &hk_lfr_q_p2_fifo_size_max );
240 240
241 241 }
242 242 }
243 243
244 244 //**********
245 245 // FUNCTIONS
246 246
247 247 void reset_nb_sm_f2( void )
248 248 {
249 249 nb_sm_before_f2.norm_bp1 = parameter_dump_packet.sy_lfr_n_bp_p0;
250 250 nb_sm_before_f2.norm_bp2 = parameter_dump_packet.sy_lfr_n_bp_p1;
251 251 nb_sm_before_f2.norm_asm = parameter_dump_packet.sy_lfr_n_asm_p[0] * 256 + parameter_dump_packet.sy_lfr_n_asm_p[1];
252 252 }
253 253
254 254 void SM_average_f2( float *averaged_spec_mat_f2,
255 255 ring_node *ring_node,
256 256 unsigned int nbAverageNormF2,
257 257 asm_msg *msgForMATR )
258 258 {
259 259 float sum;
260 260 unsigned int i;
261 261
262 262 for(i=0; i<TOTAL_SIZE_SM; i++)
263 263 {
264 264 sum = ( (int *) (ring_node->buffer_address) ) [ i ];
265 265 if ( (nbAverageNormF2 == 0) )
266 266 {
267 267 averaged_spec_mat_f2[ i ] = sum;
268 268 msgForMATR->coarseTimeNORM = ring_node->coarseTime;
269 269 msgForMATR->fineTimeNORM = ring_node->fineTime;
270 270 }
271 271 else
272 272 {
273 273 averaged_spec_mat_f2[ i ] = ( averaged_spec_mat_f2[ i ] + sum );
274 274 }
275 275 }
276 276 }
277 277
278 278 void init_k_coefficients_prc2( void )
279 279 {
280 280 init_k_coefficients( k_coeff_intercalib_f2, NB_BINS_COMPRESSED_SM_F2);
281 281 }
@@ -1,668 +1,708
1 1 /** Functions related to data processing.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * These function are related to data processing, i.e. spectral matrices averaging and basic parameters computation.
7 7 *
8 8 */
9 9
10 10 #include "fsw_processing.h"
11 11 #include "fsw_processing_globals.c"
12 12 #include "fsw_init.h"
13 13
14 14 unsigned int nb_sm_f0;
15 15 unsigned int nb_sm_f0_aux_f1;
16 16 unsigned int nb_sm_f1;
17 17 unsigned int nb_sm_f0_aux_f2;
18 18
19 typedef enum restartState_t
20 {
21 WAIT_FOR_F2,
22 WAIT_FOR_F1,
23 WAIT_FOR_F0
24 } restartState;
25
19 26 //************************
20 27 // spectral matrices rings
21 28 ring_node sm_ring_f0[ NB_RING_NODES_SM_F0 ];
22 29 ring_node sm_ring_f1[ NB_RING_NODES_SM_F1 ];
23 30 ring_node sm_ring_f2[ NB_RING_NODES_SM_F2 ];
24 31 ring_node *current_ring_node_sm_f0;
25 32 ring_node *current_ring_node_sm_f1;
26 33 ring_node *current_ring_node_sm_f2;
27 34 ring_node *ring_node_for_averaging_sm_f0;
28 35 ring_node *ring_node_for_averaging_sm_f1;
29 36 ring_node *ring_node_for_averaging_sm_f2;
30 37
31 38 //
32 39 ring_node * getRingNodeForAveraging( unsigned char frequencyChannel)
33 40 {
34 41 ring_node *node;
35 42
36 43 node = NULL;
37 44 switch ( frequencyChannel ) {
38 45 case 0:
39 46 node = ring_node_for_averaging_sm_f0;
40 47 break;
41 48 case 1:
42 49 node = ring_node_for_averaging_sm_f1;
43 50 break;
44 51 case 2:
45 52 node = ring_node_for_averaging_sm_f2;
46 53 break;
47 54 default:
48 55 break;
49 56 }
50 57
51 58 return node;
52 59 }
53 60
54 61 //***********************************************************
55 62 // Interrupt Service Routine for spectral matrices processing
56 63
57 64 void spectral_matrices_isr_f0( unsigned char statusReg )
58 65 {
59 66 unsigned char status;
60 67 rtems_status_code status_code;
61 68 ring_node *full_ring_node;
62 69
63 70 status = statusReg & 0x03; // [0011] get the status_ready_matrix_f0_x bits
64 71
65 72 switch(status)
66 73 {
67 74 case 0:
68 75 break;
69 76 case 3:
70 77 // UNEXPECTED VALUE
71 78 spectral_matrix_regs->status = 0x03; // [0011]
72 79 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
73 80 break;
74 81 case 1:
75 82 full_ring_node = current_ring_node_sm_f0->previous;
76 83 full_ring_node->coarseTime = spectral_matrix_regs->f0_0_coarse_time;
77 84 full_ring_node->fineTime = spectral_matrix_regs->f0_0_fine_time;
78 85 current_ring_node_sm_f0 = current_ring_node_sm_f0->next;
79 86 spectral_matrix_regs->f0_0_address = current_ring_node_sm_f0->buffer_address;
80 87 // if there are enough ring nodes ready, wake up an AVFx task
81 88 nb_sm_f0 = nb_sm_f0 + 1;
82 89 if (nb_sm_f0 == NB_SM_BEFORE_AVF0)
83 90 {
84 91 ring_node_for_averaging_sm_f0 = full_ring_node;
85 92 if (rtems_event_send( Task_id[TASKID_AVF0], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
86 93 {
87 94 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
88 95 }
89 96 nb_sm_f0 = 0;
90 97 }
91 98 spectral_matrix_regs->status = 0x01; // [0000 0001]
92 99 break;
93 100 case 2:
94 101 full_ring_node = current_ring_node_sm_f0->previous;
95 102 full_ring_node->coarseTime = spectral_matrix_regs->f0_1_coarse_time;
96 103 full_ring_node->fineTime = spectral_matrix_regs->f0_1_fine_time;
97 104 current_ring_node_sm_f0 = current_ring_node_sm_f0->next;
98 105 spectral_matrix_regs->f0_1_address = current_ring_node_sm_f0->buffer_address;
99 106 // if there are enough ring nodes ready, wake up an AVFx task
100 107 nb_sm_f0 = nb_sm_f0 + 1;
101 108 if (nb_sm_f0 == NB_SM_BEFORE_AVF0)
102 109 {
103 110 ring_node_for_averaging_sm_f0 = full_ring_node;
104 111 if (rtems_event_send( Task_id[TASKID_AVF0], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
105 112 {
106 113 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
107 114 }
108 115 nb_sm_f0 = 0;
109 116 }
110 117 spectral_matrix_regs->status = 0x02; // [0000 0010]
111 118 break;
112 119 }
113 120 }
114 121
115 122 void spectral_matrices_isr_f1( unsigned char statusReg )
116 123 {
117 124 rtems_status_code status_code;
118 125 unsigned char status;
119 126 ring_node *full_ring_node;
120 127
121 status = (statusReg & 0x0c) >> 2; // [1100] get the status_ready_matrix_f0_x bits
128 status = (statusReg & 0x0c) >> 2; // [1100] get the status_ready_matrix_f1_x bits
122 129
123 130 switch(status)
124 131 {
125 132 case 0:
126 133 break;
127 134 case 3:
128 135 // UNEXPECTED VALUE
129 136 spectral_matrix_regs->status = 0xc0; // [1100]
130 137 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
131 138 break;
132 139 case 1:
133 140 full_ring_node = current_ring_node_sm_f1->previous;
134 141 full_ring_node->coarseTime = spectral_matrix_regs->f1_0_coarse_time;
135 142 full_ring_node->fineTime = spectral_matrix_regs->f1_0_fine_time;
136 143 current_ring_node_sm_f1 = current_ring_node_sm_f1->next;
137 144 spectral_matrix_regs->f1_0_address = current_ring_node_sm_f1->buffer_address;
138 145 // if there are enough ring nodes ready, wake up an AVFx task
139 146 nb_sm_f1 = nb_sm_f1 + 1;
140 147 if (nb_sm_f1 == NB_SM_BEFORE_AVF1)
141 148 {
142 149 ring_node_for_averaging_sm_f1 = full_ring_node;
143 150 if (rtems_event_send( Task_id[TASKID_AVF1], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
144 151 {
145 152 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
146 153 }
147 154 nb_sm_f1 = 0;
148 155 }
149 156 spectral_matrix_regs->status = 0x04; // [0000 0100]
150 157 break;
151 158 case 2:
152 159 full_ring_node = current_ring_node_sm_f1->previous;
153 160 full_ring_node->coarseTime = spectral_matrix_regs->f1_1_coarse_time;
154 161 full_ring_node->fineTime = spectral_matrix_regs->f1_1_fine_time;
155 162 current_ring_node_sm_f1 = current_ring_node_sm_f1->next;
156 163 spectral_matrix_regs->f1_1_address = current_ring_node_sm_f1->buffer_address;
157 164 // if there are enough ring nodes ready, wake up an AVFx task
158 165 nb_sm_f1 = nb_sm_f1 + 1;
159 166 if (nb_sm_f1 == NB_SM_BEFORE_AVF1)
160 167 {
161 168 ring_node_for_averaging_sm_f1 = full_ring_node;
162 169 if (rtems_event_send( Task_id[TASKID_AVF1], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
163 170 {
164 171 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
165 172 }
166 173 nb_sm_f1 = 0;
167 174 }
168 175 spectral_matrix_regs->status = 0x08; // [1000 0000]
169 176 break;
170 177 }
171 178 }
172 179
173 180 void spectral_matrices_isr_f2( unsigned char statusReg )
174 181 {
175 182 unsigned char status;
176 183 rtems_status_code status_code;
177 184
178 status = (statusReg & 0x30) >> 4; // [0011 0000] get the status_ready_matrix_f0_x bits
185 status = (statusReg & 0x30) >> 4; // [0011 0000] get the status_ready_matrix_f2_x bits
179 186
180 187 switch(status)
181 188 {
182 189 case 0:
183 190 break;
184 191 case 3:
185 192 // UNEXPECTED VALUE
186 193 spectral_matrix_regs->status = 0x30; // [0011 0000]
187 194 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_11 );
188 195 break;
189 196 case 1:
190 197 ring_node_for_averaging_sm_f2 = current_ring_node_sm_f2->previous;
191 198 current_ring_node_sm_f2 = current_ring_node_sm_f2->next;
192 199 ring_node_for_averaging_sm_f2->coarseTime = spectral_matrix_regs->f2_0_coarse_time;
193 200 ring_node_for_averaging_sm_f2->fineTime = spectral_matrix_regs->f2_0_fine_time;
194 201 spectral_matrix_regs->f2_0_address = current_ring_node_sm_f2->buffer_address;
195 202 spectral_matrix_regs->status = 0x10; // [0001 0000]
196 203 if (rtems_event_send( Task_id[TASKID_AVF2], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
197 204 {
198 205 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
199 206 }
200 207 break;
201 208 case 2:
202 209 ring_node_for_averaging_sm_f2 = current_ring_node_sm_f2->previous;
203 210 current_ring_node_sm_f2 = current_ring_node_sm_f2->next;
204 211 ring_node_for_averaging_sm_f2->coarseTime = spectral_matrix_regs->f2_1_coarse_time;
205 212 ring_node_for_averaging_sm_f2->fineTime = spectral_matrix_regs->f2_1_fine_time;
206 213 spectral_matrix_regs->f2_1_address = current_ring_node_sm_f2->buffer_address;
207 214 spectral_matrix_regs->status = 0x20; // [0010 0000]
208 215 if (rtems_event_send( Task_id[TASKID_AVF2], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL)
209 216 {
210 217 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_3 );
211 218 }
212 219 break;
213 220 }
214 221 }
215 222
216 223 void spectral_matrix_isr_error_handler( unsigned char statusReg )
217 224 {
218 225 rtems_status_code status_code;
219 226
220 227 if (statusReg & 0x7c0) // [0111 1100 0000]
221 228 {
222 229 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_8 );
223 230 }
224 231
225 232 spectral_matrix_regs->status = spectral_matrix_regs->status & 0x7c0;
226 233 }
227 234
228 235 rtems_isr spectral_matrices_isr( rtems_vector_number vector )
229 236 {
230 237 // STATUS REGISTER
231 238 // input_fifo_write(2) *** input_fifo_write(1) *** input_fifo_write(0)
232 239 // 10 9 8
233 240 // buffer_full ** bad_component_err ** f2_1 ** f2_0 ** f1_1 ** f1_0 ** f0_1 ** f0_0
234 241 // 7 6 5 4 3 2 1 0
235 242
236 243 unsigned char statusReg;
237 244
245 static restartState state = WAIT_FOR_F2;
246
238 247 statusReg = spectral_matrix_regs->status;
239 248
240 spectral_matrices_isr_f0( statusReg );
249 if (thisIsAnASMRestart == 0)
250 { // this is not a restart sequence, process incoming matrices normally
251 spectral_matrices_isr_f0( statusReg );
252
253 spectral_matrices_isr_f1( statusReg );
241 254
242 spectral_matrices_isr_f1( statusReg );
243
244 spectral_matrices_isr_f2( statusReg );
255 spectral_matrices_isr_f2( statusReg );
256 }
257 else
258 { // a restart sequence has to be launched
259 switch (state) {
260 case WAIT_FOR_F2:
261 if ((statusReg & 0x30) != 0x00) // [0011 0000] check the status_ready_matrix_f2_x bits
262 {
263 state = WAIT_FOR_F1;
264 }
265 break;
266 case WAIT_FOR_F1:
267 if ((statusReg & 0x0c) != 0x00) // [0000 1100] check the status_ready_matrix_f1_x bits
268 {
269 state = WAIT_FOR_F0;
270 }
271 break;
272 case WAIT_FOR_F0:
273 if ((statusReg & 0x03) != 0x00) // [0000 0011] check the status_ready_matrix_f0_x bits
274 {
275 state = WAIT_FOR_F2;
276 thisIsAnASMRestart = 0;
277 }
278 break;
279 default:
280 break;
281 }
282 reset_sm_status();
283 }
245 284
246 285 spectral_matrix_isr_error_handler( statusReg );
286
247 287 }
248 288
249 289 //******************
250 290 // Spectral Matrices
251 291
252 292 void reset_nb_sm( void )
253 293 {
254 294 nb_sm_f0 = 0;
255 295 nb_sm_f0_aux_f1 = 0;
256 296 nb_sm_f0_aux_f2 = 0;
257 297
258 298 nb_sm_f1 = 0;
259 299 }
260 300
261 301 void SM_init_rings( void )
262 302 {
263 303 init_ring( sm_ring_f0, NB_RING_NODES_SM_F0, sm_f0, TOTAL_SIZE_SM );
264 304 init_ring( sm_ring_f1, NB_RING_NODES_SM_F1, sm_f1, TOTAL_SIZE_SM );
265 305 init_ring( sm_ring_f2, NB_RING_NODES_SM_F2, sm_f2, TOTAL_SIZE_SM );
266 306
267 307 DEBUG_PRINTF1("sm_ring_f0 @%x\n", (unsigned int) sm_ring_f0)
268 308 DEBUG_PRINTF1("sm_ring_f1 @%x\n", (unsigned int) sm_ring_f1)
269 309 DEBUG_PRINTF1("sm_ring_f2 @%x\n", (unsigned int) sm_ring_f2)
270 310 DEBUG_PRINTF1("sm_f0 @%x\n", (unsigned int) sm_f0)
271 311 DEBUG_PRINTF1("sm_f1 @%x\n", (unsigned int) sm_f1)
272 312 DEBUG_PRINTF1("sm_f2 @%x\n", (unsigned int) sm_f2)
273 313 }
274 314
275 315 void ASM_generic_init_ring( ring_node_asm *ring, unsigned char nbNodes )
276 316 {
277 317 unsigned char i;
278 318
279 319 ring[ nbNodes - 1 ].next
280 320 = (ring_node_asm*) &ring[ 0 ];
281 321
282 322 for(i=0; i<nbNodes-1; i++)
283 323 {
284 324 ring[ i ].next = (ring_node_asm*) &ring[ i + 1 ];
285 325 }
286 326 }
287 327
288 328 void SM_reset_current_ring_nodes( void )
289 329 {
290 330 current_ring_node_sm_f0 = sm_ring_f0[0].next;
291 331 current_ring_node_sm_f1 = sm_ring_f1[0].next;
292 332 current_ring_node_sm_f2 = sm_ring_f2[0].next;
293 333
294 334 ring_node_for_averaging_sm_f0 = NULL;
295 335 ring_node_for_averaging_sm_f1 = NULL;
296 336 ring_node_for_averaging_sm_f2 = NULL;
297 337 }
298 338
299 339 //*****************
300 340 // Basic Parameters
301 341
302 342 void BP_init_header( bp_packet *packet,
303 343 unsigned int apid, unsigned char sid,
304 344 unsigned int packetLength, unsigned char blkNr )
305 345 {
306 346 packet->targetLogicalAddress = CCSDS_DESTINATION_ID;
307 347 packet->protocolIdentifier = CCSDS_PROTOCOLE_ID;
308 348 packet->reserved = 0x00;
309 349 packet->userApplication = CCSDS_USER_APP;
310 350 packet->packetID[0] = (unsigned char) (apid >> 8);
311 351 packet->packetID[1] = (unsigned char) (apid);
312 352 packet->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
313 353 packet->packetSequenceControl[1] = 0x00;
314 354 packet->packetLength[0] = (unsigned char) (packetLength >> 8);
315 355 packet->packetLength[1] = (unsigned char) (packetLength);
316 356 // DATA FIELD HEADER
317 357 packet->spare1_pusVersion_spare2 = 0x10;
318 358 packet->serviceType = TM_TYPE_LFR_SCIENCE; // service type
319 359 packet->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
320 360 packet->destinationID = TM_DESTINATION_ID_GROUND;
321 361 packet->time[0] = 0x00;
322 362 packet->time[1] = 0x00;
323 363 packet->time[2] = 0x00;
324 364 packet->time[3] = 0x00;
325 365 packet->time[4] = 0x00;
326 366 packet->time[5] = 0x00;
327 367 // AUXILIARY DATA HEADER
328 368 packet->sid = sid;
329 369 packet->biaStatusInfo = 0x00;
330 370 packet->sy_lfr_common_parameters_spare = 0x00;
331 371 packet->sy_lfr_common_parameters = 0x00;
332 372 packet->acquisitionTime[0] = 0x00;
333 373 packet->acquisitionTime[1] = 0x00;
334 374 packet->acquisitionTime[2] = 0x00;
335 375 packet->acquisitionTime[3] = 0x00;
336 376 packet->acquisitionTime[4] = 0x00;
337 377 packet->acquisitionTime[5] = 0x00;
338 378 packet->pa_lfr_bp_blk_nr[0] = 0x00; // BLK_NR MSB
339 379 packet->pa_lfr_bp_blk_nr[1] = blkNr; // BLK_NR LSB
340 380 }
341 381
342 382 void BP_init_header_with_spare( bp_packet_with_spare *packet,
343 383 unsigned int apid, unsigned char sid,
344 384 unsigned int packetLength , unsigned char blkNr)
345 385 {
346 386 packet->targetLogicalAddress = CCSDS_DESTINATION_ID;
347 387 packet->protocolIdentifier = CCSDS_PROTOCOLE_ID;
348 388 packet->reserved = 0x00;
349 389 packet->userApplication = CCSDS_USER_APP;
350 390 packet->packetID[0] = (unsigned char) (apid >> 8);
351 391 packet->packetID[1] = (unsigned char) (apid);
352 392 packet->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
353 393 packet->packetSequenceControl[1] = 0x00;
354 394 packet->packetLength[0] = (unsigned char) (packetLength >> 8);
355 395 packet->packetLength[1] = (unsigned char) (packetLength);
356 396 // DATA FIELD HEADER
357 397 packet->spare1_pusVersion_spare2 = 0x10;
358 398 packet->serviceType = TM_TYPE_LFR_SCIENCE; // service type
359 399 packet->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
360 400 packet->destinationID = TM_DESTINATION_ID_GROUND;
361 401 // AUXILIARY DATA HEADER
362 402 packet->sid = sid;
363 403 packet->biaStatusInfo = 0x00;
364 404 packet->sy_lfr_common_parameters_spare = 0x00;
365 405 packet->sy_lfr_common_parameters = 0x00;
366 406 packet->time[0] = 0x00;
367 407 packet->time[0] = 0x00;
368 408 packet->time[0] = 0x00;
369 409 packet->time[0] = 0x00;
370 410 packet->time[0] = 0x00;
371 411 packet->time[0] = 0x00;
372 412 packet->source_data_spare = 0x00;
373 413 packet->pa_lfr_bp_blk_nr[0] = 0x00; // BLK_NR MSB
374 414 packet->pa_lfr_bp_blk_nr[1] = blkNr; // BLK_NR LSB
375 415 }
376 416
377 417 void BP_send(char *data, rtems_id queue_id, unsigned int nbBytesToSend, unsigned int sid )
378 418 {
379 419 rtems_status_code status;
380 420
381 421 // SEND PACKET
382 422 status = rtems_message_queue_send( queue_id, data, nbBytesToSend);
383 423 if (status != RTEMS_SUCCESSFUL)
384 424 {
385 425 PRINTF1("ERR *** in BP_send *** ERR %d\n", (int) status)
386 426 }
387 427 }
388 428
389 429 void BP_send_s1_s2(char *data, rtems_id queue_id, unsigned int nbBytesToSend, unsigned int sid )
390 430 {
391 431 /** This function is used to send the BP paquets when needed.
392 432 *
393 433 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
394 434 *
395 435 * @return void
396 436 *
397 437 * SBM1 and SBM2 paquets are sent depending on the type of the LFR mode transition.
398 438 * BURST paquets are sent everytime.
399 439 *
400 440 */
401 441
402 442 rtems_status_code status;
403 443
404 444 // SEND PACKET
405 445 // before lastValidTransitionDate, the data are drops even if they are ready
406 // this guarantees that no SBM packets will be received before the requestion enter mode time
446 // this guarantees that no SBM packets will be received before the requested enter mode time
407 447 if ( time_management_regs->coarse_time >= lastValidEnterModeTime)
408 448 {
409 449 status = rtems_message_queue_send( queue_id, data, nbBytesToSend);
410 450 if (status != RTEMS_SUCCESSFUL)
411 451 {
412 452 PRINTF1("ERR *** in BP_send *** ERR %d\n", (int) status)
413 453 }
414 454 }
415 455 }
416 456
417 457 //******************
418 458 // general functions
419 459
420 460 void reset_sm_status( void )
421 461 {
422 462 // error
423 463 // 10 --------------- 9 ---------------- 8 ---------------- 7 ---------
424 464 // input_fif0_write_2 input_fifo_write_1 input_fifo_write_0 buffer_full
425 465 // ---------- 5 -- 4 -- 3 -- 2 -- 1 -- 0 --
426 466 // ready bits f2_1 f2_0 f1_1 f1_1 f0_1 f0_0
427 467
428 468 spectral_matrix_regs->status = 0x7ff; // [0111 1111 1111]
429 469 }
430 470
431 471 void reset_spectral_matrix_regs( void )
432 472 {
433 473 /** This function resets the spectral matrices module registers.
434 474 *
435 475 * The registers affected by this function are located at the following offset addresses:
436 476 *
437 477 * - 0x00 config
438 478 * - 0x04 status
439 479 * - 0x08 matrixF0_Address0
440 480 * - 0x10 matrixFO_Address1
441 481 * - 0x14 matrixF1_Address
442 482 * - 0x18 matrixF2_Address
443 483 *
444 484 */
445 485
446 486 set_sm_irq_onError( 0 );
447 487
448 488 set_sm_irq_onNewMatrix( 0 );
449 489
450 490 reset_sm_status();
451 491
452 492 // F1
453 493 spectral_matrix_regs->f0_0_address = current_ring_node_sm_f0->previous->buffer_address;
454 494 spectral_matrix_regs->f0_1_address = current_ring_node_sm_f0->buffer_address;
455 495 // F2
456 496 spectral_matrix_regs->f1_0_address = current_ring_node_sm_f1->previous->buffer_address;
457 497 spectral_matrix_regs->f1_1_address = current_ring_node_sm_f1->buffer_address;
458 498 // F3
459 499 spectral_matrix_regs->f2_0_address = current_ring_node_sm_f2->previous->buffer_address;
460 500 spectral_matrix_regs->f2_1_address = current_ring_node_sm_f2->buffer_address;
461 501
462 502 spectral_matrix_regs->matrix_length = 0xc8; // 25 * 128 / 16 = 200 = 0xc8
463 503 }
464 504
465 505 void set_time( unsigned char *time, unsigned char * timeInBuffer )
466 506 {
467 507 time[0] = timeInBuffer[0];
468 508 time[1] = timeInBuffer[1];
469 509 time[2] = timeInBuffer[2];
470 510 time[3] = timeInBuffer[3];
471 511 time[4] = timeInBuffer[6];
472 512 time[5] = timeInBuffer[7];
473 513 }
474 514
475 515 unsigned long long int get_acquisition_time( unsigned char *timePtr )
476 516 {
477 517 unsigned long long int acquisitionTimeAslong;
478 518 acquisitionTimeAslong = 0x00;
479 519 acquisitionTimeAslong = ( (unsigned long long int) (timePtr[0] & 0x7f) << 40 ) // [0111 1111] mask the synchronization bit
480 520 + ( (unsigned long long int) timePtr[1] << 32 )
481 521 + ( (unsigned long long int) timePtr[2] << 24 )
482 522 + ( (unsigned long long int) timePtr[3] << 16 )
483 523 + ( (unsigned long long int) timePtr[6] << 8 )
484 524 + ( (unsigned long long int) timePtr[7] );
485 525 return acquisitionTimeAslong;
486 526 }
487 527
488 528 unsigned char getSID( rtems_event_set event )
489 529 {
490 530 unsigned char sid;
491 531
492 532 rtems_event_set eventSetBURST;
493 533 rtems_event_set eventSetSBM;
494 534
495 535 //******
496 536 // BURST
497 537 eventSetBURST = RTEMS_EVENT_BURST_BP1_F0
498 538 | RTEMS_EVENT_BURST_BP1_F1
499 539 | RTEMS_EVENT_BURST_BP2_F0
500 540 | RTEMS_EVENT_BURST_BP2_F1;
501 541
502 542 //****
503 543 // SBM
504 544 eventSetSBM = RTEMS_EVENT_SBM_BP1_F0
505 545 | RTEMS_EVENT_SBM_BP1_F1
506 546 | RTEMS_EVENT_SBM_BP2_F0
507 547 | RTEMS_EVENT_SBM_BP2_F1;
508 548
509 549 if (event & eventSetBURST)
510 550 {
511 551 sid = SID_BURST_BP1_F0;
512 552 }
513 553 else if (event & eventSetSBM)
514 554 {
515 555 sid = SID_SBM1_BP1_F0;
516 556 }
517 557 else
518 558 {
519 559 sid = 0;
520 560 }
521 561
522 562 return sid;
523 563 }
524 564
525 565 void extractReImVectors( float *inputASM, float *outputASM, unsigned int asmComponent )
526 566 {
527 567 unsigned int i;
528 568 float re;
529 569 float im;
530 570
531 571 for (i=0; i<NB_BINS_PER_SM; i++){
532 572 re = inputASM[ (asmComponent*NB_BINS_PER_SM) + i * 2 ];
533 573 im = inputASM[ (asmComponent*NB_BINS_PER_SM) + i * 2 + 1];
534 574 outputASM[ (asmComponent *NB_BINS_PER_SM) + i] = re;
535 575 outputASM[ (asmComponent+1)*NB_BINS_PER_SM + i] = im;
536 576 }
537 577 }
538 578
539 579 void copyReVectors( float *inputASM, float *outputASM, unsigned int asmComponent )
540 580 {
541 581 unsigned int i;
542 582 float re;
543 583
544 584 for (i=0; i<NB_BINS_PER_SM; i++){
545 585 re = inputASM[ (asmComponent*NB_BINS_PER_SM) + i];
546 586 outputASM[ (asmComponent*NB_BINS_PER_SM) + i] = re;
547 587 }
548 588 }
549 589
550 590 void ASM_patch( float *inputASM, float *outputASM )
551 591 {
552 592 extractReImVectors( inputASM, outputASM, 1); // b1b2
553 593 extractReImVectors( inputASM, outputASM, 3 ); // b1b3
554 594 extractReImVectors( inputASM, outputASM, 5 ); // b1e1
555 595 extractReImVectors( inputASM, outputASM, 7 ); // b1e2
556 596 extractReImVectors( inputASM, outputASM, 10 ); // b2b3
557 597 extractReImVectors( inputASM, outputASM, 12 ); // b2e1
558 598 extractReImVectors( inputASM, outputASM, 14 ); // b2e2
559 599 extractReImVectors( inputASM, outputASM, 17 ); // b3e1
560 600 extractReImVectors( inputASM, outputASM, 19 ); // b3e2
561 601 extractReImVectors( inputASM, outputASM, 22 ); // e1e2
562 602
563 603 copyReVectors(inputASM, outputASM, 0 ); // b1b1
564 604 copyReVectors(inputASM, outputASM, 9 ); // b2b2
565 605 copyReVectors(inputASM, outputASM, 16); // b3b3
566 606 copyReVectors(inputASM, outputASM, 21); // e1e1
567 607 copyReVectors(inputASM, outputASM, 24); // e2e2
568 608 }
569 609
570 610 void ASM_compress_reorganize_and_divide_mask(float *averaged_spec_mat, float *compressed_spec_mat , float divider,
571 611 unsigned char nbBinsCompressedMatrix, unsigned char nbBinsToAverage,
572 612 unsigned char ASMIndexStart,
573 613 unsigned char channel )
574 614 {
575 615 //*************
576 616 // input format
577 617 // component0[0 .. 127] component1[0 .. 127] .. component24[0 .. 127]
578 618 //**************
579 619 // output format
580 620 // matr0[0 .. 24] matr1[0 .. 24] .. matr127[0 .. 24]
581 621 //************
582 622 // compression
583 623 // matr0[0 .. 24] matr1[0 .. 24] .. matr11[0 .. 24] => f0 NORM
584 624 // matr0[0 .. 24] matr1[0 .. 24] .. matr22[0 .. 24] => f0 BURST, SBM
585 625
586 626 int frequencyBin;
587 627 int asmComponent;
588 628 int offsetASM;
589 629 int offsetCompressed;
590 630 int offsetFBin;
591 631 int fBinMask;
592 632 int k;
593 633
594 634 // BUILD DATA
595 635 for (asmComponent = 0; asmComponent < NB_VALUES_PER_SM; asmComponent++)
596 636 {
597 637 for( frequencyBin = 0; frequencyBin < nbBinsCompressedMatrix; frequencyBin++ )
598 638 {
599 639 offsetCompressed = // NO TIME OFFSET
600 640 frequencyBin * NB_VALUES_PER_SM
601 641 + asmComponent;
602 642 offsetASM = // NO TIME OFFSET
603 643 asmComponent * NB_BINS_PER_SM
604 644 + ASMIndexStart
605 645 + frequencyBin * nbBinsToAverage;
606 646 offsetFBin = ASMIndexStart
607 647 + frequencyBin * nbBinsToAverage;
608 648 compressed_spec_mat[ offsetCompressed ] = 0;
609 649 for ( k = 0; k < nbBinsToAverage; k++ )
610 650 {
611 651 fBinMask = getFBinMask( offsetFBin + k, channel );
612 652 compressed_spec_mat[offsetCompressed ] =
613 653 ( compressed_spec_mat[ offsetCompressed ]
614 654 + averaged_spec_mat[ offsetASM + k ] * fBinMask );
615 655 }
616 656 compressed_spec_mat[ offsetCompressed ] =
617 657 compressed_spec_mat[ offsetCompressed ] / (divider * nbBinsToAverage);
618 658 }
619 659 }
620 660
621 661 }
622 662
623 663 int getFBinMask( int index, unsigned char channel )
624 664 {
625 665 unsigned int indexInChar;
626 666 unsigned int indexInTheChar;
627 667 int fbin;
628 668 unsigned char *sy_lfr_fbins_fx_word1;
629 669
630 670 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f0_word1;
631 671
632 672 switch(channel)
633 673 {
634 674 case 0:
635 675 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f0_word1;
636 676 break;
637 677 case 1:
638 678 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f1_word1;
639 679 break;
640 680 case 2:
641 681 sy_lfr_fbins_fx_word1 = parameter_dump_packet.sy_lfr_fbins_f2_word1;
642 682 break;
643 683 default:
644 684 PRINTF("ERR *** in getFBinMask, wrong frequency channel")
645 685 }
646 686
647 687 indexInChar = index >> 3;
648 688 indexInTheChar = index - indexInChar * 8;
649 689
650 690 fbin = (int) ((sy_lfr_fbins_fx_word1[ NB_BYTES_PER_FREQ_MASK - 1 - indexInChar] >> indexInTheChar) & 0x1);
651 691
652 692 return fbin;
653 693 }
654 694
655 695 void init_kcoeff_sbm_from_kcoeff_norm(float *input_kcoeff, float *output_kcoeff, unsigned char nb_bins_norm)
656 696 {
657 697 unsigned char bin;
658 698 unsigned char kcoeff;
659 699
660 700 for (bin=0; bin<nb_bins_norm; bin++)
661 701 {
662 702 for (kcoeff=0; kcoeff<NB_K_COEFF_PER_BIN; kcoeff++)
663 703 {
664 704 output_kcoeff[ (bin*NB_K_COEFF_PER_BIN + kcoeff)*2 ] = input_kcoeff[ bin*NB_K_COEFF_PER_BIN + kcoeff ];
665 705 output_kcoeff[ (bin*NB_K_COEFF_PER_BIN + kcoeff)*2 + 1 ] = input_kcoeff[ bin*NB_K_COEFF_PER_BIN + kcoeff ];
666 706 }
667 707 }
668 708 }
@@ -1,1624 +1,1626
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[6];
36 36 rtems_id queue_rcv_id;
37 37 rtems_id queue_snd_id;
38 38
39 39 status = get_message_queue_id_recv( &queue_rcv_id );
40 40 if (status != RTEMS_SUCCESSFUL)
41 41 {
42 42 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
43 43 }
44 44
45 45 status = get_message_queue_id_send( &queue_snd_id );
46 46 if (status != RTEMS_SUCCESSFUL)
47 47 {
48 48 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
49 49 }
50 50
51 51 result = LFR_SUCCESSFUL;
52 52 subtype = 0; // subtype of the current TC packet
53 53
54 54 BOOT_PRINTF("in ACTN *** \n")
55 55
56 56 while(1)
57 57 {
58 58 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
59 59 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
60 60 getTime( time ); // set time to the current time
61 61 if (status!=RTEMS_SUCCESSFUL)
62 62 {
63 63 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
64 64 }
65 65 else
66 66 {
67 67 subtype = TC.serviceSubType;
68 68 switch(subtype)
69 69 {
70 70 case TC_SUBTYPE_RESET:
71 71 result = action_reset( &TC, queue_snd_id, time );
72 72 close_action( &TC, result, queue_snd_id );
73 73 break;
74 74 case TC_SUBTYPE_LOAD_COMM:
75 75 result = action_load_common_par( &TC );
76 76 close_action( &TC, result, queue_snd_id );
77 77 break;
78 78 case TC_SUBTYPE_LOAD_NORM:
79 79 result = action_load_normal_par( &TC, queue_snd_id, time );
80 80 close_action( &TC, result, queue_snd_id );
81 81 break;
82 82 case TC_SUBTYPE_LOAD_BURST:
83 83 result = action_load_burst_par( &TC, queue_snd_id, time );
84 84 close_action( &TC, result, queue_snd_id );
85 85 break;
86 86 case TC_SUBTYPE_LOAD_SBM1:
87 87 result = action_load_sbm1_par( &TC, queue_snd_id, time );
88 88 close_action( &TC, result, queue_snd_id );
89 89 break;
90 90 case TC_SUBTYPE_LOAD_SBM2:
91 91 result = action_load_sbm2_par( &TC, queue_snd_id, time );
92 92 close_action( &TC, result, queue_snd_id );
93 93 break;
94 94 case TC_SUBTYPE_DUMP:
95 95 result = action_dump_par( &TC, queue_snd_id );
96 96 close_action( &TC, result, queue_snd_id );
97 97 break;
98 98 case TC_SUBTYPE_ENTER:
99 99 result = action_enter_mode( &TC, queue_snd_id );
100 100 close_action( &TC, result, queue_snd_id );
101 101 break;
102 102 case TC_SUBTYPE_UPDT_INFO:
103 103 result = action_update_info( &TC, queue_snd_id );
104 104 close_action( &TC, result, queue_snd_id );
105 105 break;
106 106 case TC_SUBTYPE_EN_CAL:
107 107 result = action_enable_calibration( &TC, queue_snd_id, time );
108 108 close_action( &TC, result, queue_snd_id );
109 109 break;
110 110 case TC_SUBTYPE_DIS_CAL:
111 111 result = action_disable_calibration( &TC, queue_snd_id, time );
112 112 close_action( &TC, result, queue_snd_id );
113 113 break;
114 114 case TC_SUBTYPE_LOAD_K:
115 115 result = action_load_kcoefficients( &TC, queue_snd_id, time );
116 116 close_action( &TC, result, queue_snd_id );
117 117 break;
118 118 case TC_SUBTYPE_DUMP_K:
119 119 result = action_dump_kcoefficients( &TC, queue_snd_id, time );
120 120 close_action( &TC, result, queue_snd_id );
121 121 break;
122 122 case TC_SUBTYPE_LOAD_FBINS:
123 123 result = action_load_fbins_mask( &TC, queue_snd_id, time );
124 124 close_action( &TC, result, queue_snd_id );
125 125 break;
126 126 case TC_SUBTYPE_UPDT_TIME:
127 127 result = action_update_time( &TC );
128 128 close_action( &TC, result, queue_snd_id );
129 129 break;
130 130 default:
131 131 break;
132 132 }
133 133 }
134 134 }
135 135 }
136 136
137 137 //***********
138 138 // TC ACTIONS
139 139
140 140 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
141 141 {
142 142 /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
143 143 *
144 144 * @param TC points to the TeleCommand packet that is being processed
145 145 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
146 146 *
147 147 */
148 148
149 149 PRINTF("this is the end!!!\n");
150 150 exit(0);
151 151
152 152 send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
153 153
154 154 return LFR_DEFAULT;
155 155 }
156 156
157 157 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
158 158 {
159 159 /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
160 160 *
161 161 * @param TC points to the TeleCommand packet that is being processed
162 162 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
163 163 *
164 164 */
165 165
166 166 rtems_status_code status;
167 167 unsigned char requestedMode;
168 168 unsigned int *transitionCoarseTime_ptr;
169 169 unsigned int transitionCoarseTime;
170 170 unsigned char * bytePosPtr;
171 171
172 172 bytePosPtr = (unsigned char *) &TC->packetID;
173 173
174 174 requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
175 175 transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
176 176 transitionCoarseTime = (*transitionCoarseTime_ptr) & 0x7fffffff;
177 177
178 178 status = check_mode_value( requestedMode );
179 179
180 180 if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent
181 181 {
182 182 send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
183 183 }
184 184
185 185 else // the mode value is valid, check the transition
186 186 {
187 187 status = check_mode_transition(requestedMode);
188 188 if (status != LFR_SUCCESSFUL)
189 189 {
190 190 PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
191 191 send_tm_lfr_tc_exe_not_executable( TC, queue_id );
192 192 }
193 193 }
194 194
195 195 if ( status == LFR_SUCCESSFUL ) // the transition is valid, check the date
196 196 {
197 197 status = check_transition_date( transitionCoarseTime );
198 198 if (status != LFR_SUCCESSFUL)
199 199 {
200 200 PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
201 201 send_tm_lfr_tc_exe_not_executable(TC, queue_id );
202 202 }
203 203 }
204 204
205 205 if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode
206 206 {
207 207 PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
208 208
209 209 update_last_valid_transition_date( transitionCoarseTime );
210 210
211 211 switch(requestedMode)
212 212 {
213 213 case LFR_MODE_STANDBY:
214 214 status = enter_mode_standby();
215 215 break;
216 216 case LFR_MODE_NORMAL:
217 217 status = enter_mode_normal( transitionCoarseTime );
218 218 break;
219 219 case LFR_MODE_BURST:
220 220 status = enter_mode_burst( transitionCoarseTime );
221 221 break;
222 222 case LFR_MODE_SBM1:
223 223 status = enter_mode_sbm1( transitionCoarseTime );
224 224 break;
225 225 case LFR_MODE_SBM2:
226 226 status = enter_mode_sbm2( transitionCoarseTime );
227 227 break;
228 228 default:
229 229 break;
230 230 }
231 }
232 231
233 if (status != RTEMS_SUCCESSFUL)
234 {
235 status = LFR_EXE_ERROR;
232 if (status != RTEMS_SUCCESSFUL)
233 {
234 status = LFR_EXE_ERROR;
235 }
236 236 }
237 237
238 238 return status;
239 239 }
240 240
241 241 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
242 242 {
243 243 /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
244 244 *
245 245 * @param TC points to the TeleCommand packet that is being processed
246 246 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
247 247 *
248 248 * @return LFR directive status code:
249 249 * - LFR_DEFAULT
250 250 * - LFR_SUCCESSFUL
251 251 *
252 252 */
253 253
254 254 unsigned int val;
255 255 int result;
256 256 unsigned int status;
257 257 unsigned char mode;
258 258 unsigned char * bytePosPtr;
259 259
260 260 bytePosPtr = (unsigned char *) &TC->packetID;
261 261
262 262 // check LFR mode
263 263 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & 0x1e) >> 1;
264 264 status = check_update_info_hk_lfr_mode( mode );
265 265 if (status == LFR_SUCCESSFUL) // check TDS mode
266 266 {
267 267 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0xf0) >> 4;
268 268 status = check_update_info_hk_tds_mode( mode );
269 269 }
270 270 if (status == LFR_SUCCESSFUL) // check THR mode
271 271 {
272 272 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0x0f);
273 273 status = check_update_info_hk_thr_mode( mode );
274 274 }
275 275 if (status == LFR_SUCCESSFUL) // if the parameter check is successful
276 276 {
277 277 val = housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * 256
278 278 + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
279 279 val++;
280 280 housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> 8);
281 281 housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
282 282 }
283 283
284 284 // pa_bia_status_info
285 285 // => pa_bia_mode_mux_set 3 bits
286 286 // => pa_bia_mode_hv_enabled 1 bit
287 287 // => pa_bia_mode_bias1_enabled 1 bit
288 288 // => pa_bia_mode_bias2_enabled 1 bit
289 289 // => pa_bia_mode_bias3_enabled 1 bit
290 290 // => pa_bia_on_off (cp_dpu_bias_on_off)
291 291 pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & 0xfe; // [1111 1110]
292 292 pa_bia_status_info = pa_bia_status_info
293 293 | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 0x1);
294 294
295 295 result = status;
296 296
297 297 return result;
298 298 }
299 299
300 300 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
301 301 {
302 302 /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
303 303 *
304 304 * @param TC points to the TeleCommand packet that is being processed
305 305 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
306 306 *
307 307 */
308 308
309 309 int result;
310 310
311 311 result = LFR_DEFAULT;
312 312
313 313 setCalibration( true );
314 314
315 315 result = LFR_SUCCESSFUL;
316 316
317 317 return result;
318 318 }
319 319
320 320 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
321 321 {
322 322 /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
323 323 *
324 324 * @param TC points to the TeleCommand packet that is being processed
325 325 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
326 326 *
327 327 */
328 328
329 329 int result;
330 330
331 331 result = LFR_DEFAULT;
332 332
333 333 setCalibration( false );
334 334
335 335 result = LFR_SUCCESSFUL;
336 336
337 337 return result;
338 338 }
339 339
340 340 int action_update_time(ccsdsTelecommandPacket_t *TC)
341 341 {
342 342 /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
343 343 *
344 344 * @param TC points to the TeleCommand packet that is being processed
345 345 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
346 346 *
347 347 * @return LFR_SUCCESSFUL
348 348 *
349 349 */
350 350
351 351 unsigned int val;
352 352
353 353 time_management_regs->coarse_time_load = (TC->dataAndCRC[0] << 24)
354 354 + (TC->dataAndCRC[1] << 16)
355 355 + (TC->dataAndCRC[2] << 8)
356 356 + TC->dataAndCRC[3];
357 357
358 358 val = housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * 256
359 359 + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
360 360 val++;
361 361 housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> 8);
362 362 housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
363 363
364 364 return LFR_SUCCESSFUL;
365 365 }
366 366
367 367 //*******************
368 368 // ENTERING THE MODES
369 369 int check_mode_value( unsigned char requestedMode )
370 370 {
371 371 int status;
372 372
373 373 if ( (requestedMode != LFR_MODE_STANDBY)
374 374 && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
375 375 && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
376 376 {
377 377 status = LFR_DEFAULT;
378 378 }
379 379 else
380 380 {
381 381 status = LFR_SUCCESSFUL;
382 382 }
383 383
384 384 return status;
385 385 }
386 386
387 387 int check_mode_transition( unsigned char requestedMode )
388 388 {
389 389 /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
390 390 *
391 391 * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
392 392 *
393 393 * @return LFR directive status codes:
394 394 * - LFR_SUCCESSFUL - the transition is authorized
395 395 * - LFR_DEFAULT - the transition is not authorized
396 396 *
397 397 */
398 398
399 399 int status;
400 400
401 401 switch (requestedMode)
402 402 {
403 403 case LFR_MODE_STANDBY:
404 404 if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
405 405 status = LFR_DEFAULT;
406 406 }
407 407 else
408 408 {
409 409 status = LFR_SUCCESSFUL;
410 410 }
411 411 break;
412 412 case LFR_MODE_NORMAL:
413 413 if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
414 414 status = LFR_DEFAULT;
415 415 }
416 416 else {
417 417 status = LFR_SUCCESSFUL;
418 418 }
419 419 break;
420 420 case LFR_MODE_BURST:
421 421 if ( lfrCurrentMode == LFR_MODE_BURST ) {
422 422 status = LFR_DEFAULT;
423 423 }
424 424 else {
425 425 status = LFR_SUCCESSFUL;
426 426 }
427 427 break;
428 428 case LFR_MODE_SBM1:
429 429 if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
430 430 status = LFR_DEFAULT;
431 431 }
432 432 else {
433 433 status = LFR_SUCCESSFUL;
434 434 }
435 435 break;
436 436 case LFR_MODE_SBM2:
437 437 if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
438 438 status = LFR_DEFAULT;
439 439 }
440 440 else {
441 441 status = LFR_SUCCESSFUL;
442 442 }
443 443 break;
444 444 default:
445 445 status = LFR_DEFAULT;
446 446 break;
447 447 }
448 448
449 449 return status;
450 450 }
451 451
452 452 void update_last_valid_transition_date( unsigned int transitionCoarseTime )
453 453 {
454 454 if (transitionCoarseTime == 0)
455 455 {
456 456 lastValidEnterModeTime = time_management_regs->coarse_time + 1;
457 457 PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", transitionCoarseTime);
458 458 }
459 459 else
460 460 {
461 461 lastValidEnterModeTime = transitionCoarseTime;
462 462 PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
463 463 }
464 464 }
465 465
466 466 int check_transition_date( unsigned int transitionCoarseTime )
467 467 {
468 468 int status;
469 469 unsigned int localCoarseTime;
470 470 unsigned int deltaCoarseTime;
471 471
472 472 status = LFR_SUCCESSFUL;
473 473
474 474 if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
475 475 {
476 476 status = LFR_SUCCESSFUL;
477 477 }
478 478 else
479 479 {
480 480 localCoarseTime = time_management_regs->coarse_time & 0x7fffffff;
481 481
482 482 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
483 483
484 484 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
485 485 {
486 486 status = LFR_DEFAULT;
487 487 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
488 488 }
489 489
490 490 if (status == LFR_SUCCESSFUL)
491 491 {
492 492 deltaCoarseTime = transitionCoarseTime - localCoarseTime;
493 493 if ( deltaCoarseTime > 3 ) // SSS-CP-EQS-323
494 494 {
495 495 status = LFR_DEFAULT;
496 496 PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
497 497 }
498 498 }
499 499 }
500 500
501 501 return status;
502 502 }
503 503
504 504 int restart_asm_activities( unsigned char lfrRequestedMode )
505 505 {
506 506 rtems_status_code status;
507 507
508 508 status = stop_spectral_matrices();
509 509
510 thisIsAnASMRestart = 1;
511
510 512 status = restart_asm_tasks( lfrRequestedMode );
511 513
512 514 launch_spectral_matrix();
513 515
514 516 return status;
515 517 }
516 518
517 519 int stop_spectral_matrices( void )
518 520 {
519 521 /** This function stops and restarts the current mode average spectral matrices activities.
520 522 *
521 523 * @return RTEMS directive status codes:
522 524 * - RTEMS_SUCCESSFUL - task restarted successfully
523 525 * - RTEMS_INVALID_ID - task id invalid
524 526 * - RTEMS_ALREADY_SUSPENDED - task already suspended
525 527 *
526 528 */
527 529
528 530 rtems_status_code status;
529 531
530 532 status = RTEMS_SUCCESSFUL;
531 533
532 534 // (1) mask interruptions
533 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
535 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // mask spectral matrix interrupt
534 536
535 537 // (2) reset spectral matrices registers
536 538 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
537 539 reset_sm_status();
538 540
539 541 // (3) clear interruptions
540 542 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
541 543
542 544 // suspend several tasks
543 545 if (lfrCurrentMode != LFR_MODE_STANDBY) {
544 546 status = suspend_asm_tasks();
545 547 }
546 548
547 549 if (status != RTEMS_SUCCESSFUL)
548 550 {
549 551 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
550 552 }
551 553
552 554 return status;
553 555 }
554 556
555 557 int stop_current_mode( void )
556 558 {
557 559 /** This function stops the current mode by masking interrupt lines and suspending science tasks.
558 560 *
559 561 * @return RTEMS directive status codes:
560 562 * - RTEMS_SUCCESSFUL - task restarted successfully
561 563 * - RTEMS_INVALID_ID - task id invalid
562 564 * - RTEMS_ALREADY_SUSPENDED - task already suspended
563 565 *
564 566 */
565 567
566 568 rtems_status_code status;
567 569
568 570 status = RTEMS_SUCCESSFUL;
569 571
570 572 // (1) mask interruptions
571 573 LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt
572 574 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
573 575
574 576 // (2) reset waveform picker registers
575 577 reset_wfp_burst_enable(); // reset burst and enable bits
576 578 reset_wfp_status(); // reset all the status bits
577 579
578 580 // (3) reset spectral matrices registers
579 581 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
580 582 reset_sm_status();
581 583
582 584 // reset lfr VHDL module
583 585 reset_lfr();
584 586
585 587 reset_extractSWF(); // reset the extractSWF flag to false
586 588
587 589 // (4) clear interruptions
588 590 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt
589 591 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
590 592
591 593 // suspend several tasks
592 594 if (lfrCurrentMode != LFR_MODE_STANDBY) {
593 595 status = suspend_science_tasks();
594 596 }
595 597
596 598 if (status != RTEMS_SUCCESSFUL)
597 599 {
598 600 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
599 601 }
600 602
601 603 return status;
602 604 }
603 605
604 606 int enter_mode_standby( void )
605 607 {
606 608 /** This function is used to put LFR in the STANDBY mode.
607 609 *
608 610 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
609 611 *
610 612 * @return RTEMS directive status codes:
611 613 * - RTEMS_SUCCESSFUL - task restarted successfully
612 614 * - RTEMS_INVALID_ID - task id invalid
613 615 * - RTEMS_INCORRECT_STATE - task never started
614 616 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
615 617 *
616 618 * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
617 619 * is immediate.
618 620 *
619 621 */
620 622
621 623 int status;
622 624
623 625 status = stop_current_mode(); // STOP THE CURRENT MODE
624 626
625 627 #ifdef PRINT_TASK_STATISTICS
626 628 rtems_cpu_usage_report();
627 629 #endif
628 630
629 631 #ifdef PRINT_STACK_REPORT
630 632 PRINTF("stack report selected\n")
631 633 rtems_stack_checker_report_usage();
632 634 #endif
633 635
634 636 return status;
635 637 }
636 638
637 639 int enter_mode_normal( unsigned int transitionCoarseTime )
638 640 {
639 641 /** This function is used to start the NORMAL mode.
640 642 *
641 643 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
642 644 *
643 645 * @return RTEMS directive status codes:
644 646 * - RTEMS_SUCCESSFUL - task restarted successfully
645 647 * - RTEMS_INVALID_ID - task id invalid
646 648 * - RTEMS_INCORRECT_STATE - task never started
647 649 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
648 650 *
649 651 * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
650 652 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
651 653 *
652 654 */
653 655
654 656 int status;
655 657
656 658 #ifdef PRINT_TASK_STATISTICS
657 659 rtems_cpu_usage_reset();
658 660 #endif
659 661
660 662 status = RTEMS_UNSATISFIED;
661 663
662 664 switch( lfrCurrentMode )
663 665 {
664 666 case LFR_MODE_STANDBY:
665 667 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
666 668 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
667 669 {
668 670 launch_spectral_matrix( );
669 671 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
670 672 }
671 673 break;
672 674 case LFR_MODE_BURST:
673 675 status = stop_current_mode(); // stop the current mode
674 676 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
675 677 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
676 678 {
677 679 launch_spectral_matrix( );
678 680 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
679 681 }
680 682 break;
681 683 case LFR_MODE_SBM1:
682 684 restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
683 685 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
684 686 break;
685 687 case LFR_MODE_SBM2:
686 688 restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
687 689 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
688 690 break;
689 691 default:
690 692 break;
691 693 }
692 694
693 695 if (status != RTEMS_SUCCESSFUL)
694 696 {
695 697 PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
696 698 status = RTEMS_UNSATISFIED;
697 699 }
698 700
699 701 return status;
700 702 }
701 703
702 704 int enter_mode_burst( unsigned int transitionCoarseTime )
703 705 {
704 706 /** This function is used to start the BURST mode.
705 707 *
706 708 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
707 709 *
708 710 * @return RTEMS directive status codes:
709 711 * - RTEMS_SUCCESSFUL - task restarted successfully
710 712 * - RTEMS_INVALID_ID - task id invalid
711 713 * - RTEMS_INCORRECT_STATE - task never started
712 714 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
713 715 *
714 716 * The way the BURST mode is started does not depend on the LFR current mode.
715 717 *
716 718 */
717 719
718 720
719 721 int status;
720 722
721 723 #ifdef PRINT_TASK_STATISTICS
722 724 rtems_cpu_usage_reset();
723 725 #endif
724 726
725 727 status = stop_current_mode(); // stop the current mode
726 728 status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
727 729 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
728 730 {
729 731 launch_spectral_matrix( );
730 732 launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
731 733 }
732 734
733 735 if (status != RTEMS_SUCCESSFUL)
734 736 {
735 737 PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
736 738 status = RTEMS_UNSATISFIED;
737 739 }
738 740
739 741 return status;
740 742 }
741 743
742 744 int enter_mode_sbm1( unsigned int transitionCoarseTime )
743 745 {
744 746 /** This function is used to start the SBM1 mode.
745 747 *
746 748 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
747 749 *
748 750 * @return RTEMS directive status codes:
749 751 * - RTEMS_SUCCESSFUL - task restarted successfully
750 752 * - RTEMS_INVALID_ID - task id invalid
751 753 * - RTEMS_INCORRECT_STATE - task never started
752 754 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
753 755 *
754 756 * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
755 757 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
756 758 * cases, the acquisition is completely restarted.
757 759 *
758 760 */
759 761
760 762 int status;
761 763
762 764 #ifdef PRINT_TASK_STATISTICS
763 765 rtems_cpu_usage_reset();
764 766 #endif
765 767
766 768 status = RTEMS_UNSATISFIED;
767 769
768 770 switch( lfrCurrentMode )
769 771 {
770 772 case LFR_MODE_STANDBY:
771 773 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
772 774 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
773 775 {
774 776 launch_spectral_matrix( );
775 777 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
776 778 }
777 779 break;
778 780 case LFR_MODE_NORMAL: // lfrCurrentMode will be updated after the execution of close_action
779 781 restart_asm_activities( LFR_MODE_SBM1 );
780 782 status = LFR_SUCCESSFUL;
781 783 break;
782 784 case LFR_MODE_BURST:
783 785 status = stop_current_mode(); // stop the current mode
784 786 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
785 787 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
786 788 {
787 789 launch_spectral_matrix( );
788 790 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
789 791 }
790 792 break;
791 793 case LFR_MODE_SBM2:
792 794 restart_asm_activities( LFR_MODE_SBM1 );
793 795 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
794 796 break;
795 797 default:
796 798 break;
797 799 }
798 800
799 801 if (status != RTEMS_SUCCESSFUL)
800 802 {
801 803 PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
802 804 status = RTEMS_UNSATISFIED;
803 805 }
804 806
805 807 return status;
806 808 }
807 809
808 810 int enter_mode_sbm2( unsigned int transitionCoarseTime )
809 811 {
810 812 /** This function is used to start the SBM2 mode.
811 813 *
812 814 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
813 815 *
814 816 * @return RTEMS directive status codes:
815 817 * - RTEMS_SUCCESSFUL - task restarted successfully
816 818 * - RTEMS_INVALID_ID - task id invalid
817 819 * - RTEMS_INCORRECT_STATE - task never started
818 820 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
819 821 *
820 822 * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
821 823 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
822 824 * cases, the acquisition is completely restarted.
823 825 *
824 826 */
825 827
826 828 int status;
827 829
828 830 #ifdef PRINT_TASK_STATISTICS
829 831 rtems_cpu_usage_reset();
830 832 #endif
831 833
832 834 status = RTEMS_UNSATISFIED;
833 835
834 836 switch( lfrCurrentMode )
835 837 {
836 838 case LFR_MODE_STANDBY:
837 839 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
838 840 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
839 841 {
840 842 launch_spectral_matrix( );
841 843 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
842 844 }
843 845 break;
844 846 case LFR_MODE_NORMAL:
845 847 restart_asm_activities( LFR_MODE_SBM2 );
846 848 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
847 849 break;
848 850 case LFR_MODE_BURST:
849 851 status = stop_current_mode(); // stop the current mode
850 852 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
851 853 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
852 854 {
853 855 launch_spectral_matrix( );
854 856 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
855 857 }
856 858 break;
857 859 case LFR_MODE_SBM1:
858 860 restart_asm_activities( LFR_MODE_SBM2 );
859 861 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
860 862 break;
861 863 default:
862 864 break;
863 865 }
864 866
865 867 if (status != RTEMS_SUCCESSFUL)
866 868 {
867 869 PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
868 870 status = RTEMS_UNSATISFIED;
869 871 }
870 872
871 873 return status;
872 874 }
873 875
874 876 int restart_science_tasks( unsigned char lfrRequestedMode )
875 877 {
876 878 /** This function is used to restart all science tasks.
877 879 *
878 880 * @return RTEMS directive status codes:
879 881 * - RTEMS_SUCCESSFUL - task restarted successfully
880 882 * - RTEMS_INVALID_ID - task id invalid
881 883 * - RTEMS_INCORRECT_STATE - task never started
882 884 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
883 885 *
884 886 * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
885 887 *
886 888 */
887 889
888 890 rtems_status_code status[10];
889 891 rtems_status_code ret;
890 892
891 893 ret = RTEMS_SUCCESSFUL;
892 894
893 895 status[0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
894 896 if (status[0] != RTEMS_SUCCESSFUL)
895 897 {
896 898 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[0])
897 899 }
898 900
899 901 status[1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
900 902 if (status[1] != RTEMS_SUCCESSFUL)
901 903 {
902 904 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[1])
903 905 }
904 906
905 907 status[2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
906 908 if (status[2] != RTEMS_SUCCESSFUL)
907 909 {
908 910 PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[2])
909 911 }
910 912
911 913 status[3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
912 914 if (status[3] != RTEMS_SUCCESSFUL)
913 915 {
914 916 PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[3])
915 917 }
916 918
917 919 status[4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
918 920 if (status[4] != RTEMS_SUCCESSFUL)
919 921 {
920 922 PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[4])
921 923 }
922 924
923 925 status[5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
924 926 if (status[5] != RTEMS_SUCCESSFUL)
925 927 {
926 928 PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[5])
927 929 }
928 930
929 931 status[6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
930 932 if (status[6] != RTEMS_SUCCESSFUL)
931 933 {
932 934 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[6])
933 935 }
934 936
935 937 status[7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
936 938 if (status[7] != RTEMS_SUCCESSFUL)
937 939 {
938 940 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[7])
939 941 }
940 942
941 943 status[8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
942 944 if (status[8] != RTEMS_SUCCESSFUL)
943 945 {
944 946 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[8])
945 947 }
946 948
947 949 status[9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
948 950 if (status[9] != RTEMS_SUCCESSFUL)
949 951 {
950 952 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[9])
951 953 }
952 954
953 955 if ( (status[0] != RTEMS_SUCCESSFUL) || (status[1] != RTEMS_SUCCESSFUL) ||
954 956 (status[2] != RTEMS_SUCCESSFUL) || (status[3] != RTEMS_SUCCESSFUL) ||
955 957 (status[4] != RTEMS_SUCCESSFUL) || (status[5] != RTEMS_SUCCESSFUL) ||
956 958 (status[6] != RTEMS_SUCCESSFUL) || (status[7] != RTEMS_SUCCESSFUL) ||
957 959 (status[8] != RTEMS_SUCCESSFUL) || (status[9] != RTEMS_SUCCESSFUL) )
958 960 {
959 961 ret = RTEMS_UNSATISFIED;
960 962 }
961 963
962 964 return ret;
963 965 }
964 966
965 967 int restart_asm_tasks( unsigned char lfrRequestedMode )
966 968 {
967 969 /** This function is used to restart average spectral matrices tasks.
968 970 *
969 971 * @return RTEMS directive status codes:
970 972 * - RTEMS_SUCCESSFUL - task restarted successfully
971 973 * - RTEMS_INVALID_ID - task id invalid
972 974 * - RTEMS_INCORRECT_STATE - task never started
973 975 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
974 976 *
975 977 * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
976 978 *
977 979 */
978 980
979 981 rtems_status_code status[6];
980 982 rtems_status_code ret;
981 983
982 984 ret = RTEMS_SUCCESSFUL;
983 985
984 986 status[0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
985 987 if (status[0] != RTEMS_SUCCESSFUL)
986 988 {
987 989 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[0])
988 990 }
989 991
990 992 status[1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
991 993 if (status[1] != RTEMS_SUCCESSFUL)
992 994 {
993 995 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[1])
994 996 }
995 997
996 998 status[2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
997 999 if (status[2] != RTEMS_SUCCESSFUL)
998 1000 {
999 1001 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[2])
1000 1002 }
1001 1003
1002 1004 status[3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1003 1005 if (status[3] != RTEMS_SUCCESSFUL)
1004 1006 {
1005 1007 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[3])
1006 1008 }
1007 1009
1008 1010 status[4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1009 1011 if (status[4] != RTEMS_SUCCESSFUL)
1010 1012 {
1011 1013 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[4])
1012 1014 }
1013 1015
1014 1016 status[5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1015 1017 if (status[5] != RTEMS_SUCCESSFUL)
1016 1018 {
1017 1019 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[5])
1018 1020 }
1019 1021
1020 1022 if ( (status[0] != RTEMS_SUCCESSFUL) || (status[1] != RTEMS_SUCCESSFUL) ||
1021 1023 (status[2] != RTEMS_SUCCESSFUL) || (status[3] != RTEMS_SUCCESSFUL) ||
1022 1024 (status[4] != RTEMS_SUCCESSFUL) || (status[5] != RTEMS_SUCCESSFUL) )
1023 1025 {
1024 1026 ret = RTEMS_UNSATISFIED;
1025 1027 }
1026 1028
1027 1029 return ret;
1028 1030 }
1029 1031
1030 1032 int suspend_science_tasks( void )
1031 1033 {
1032 1034 /** This function suspends the science tasks.
1033 1035 *
1034 1036 * @return RTEMS directive status codes:
1035 1037 * - RTEMS_SUCCESSFUL - task restarted successfully
1036 1038 * - RTEMS_INVALID_ID - task id invalid
1037 1039 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1038 1040 *
1039 1041 */
1040 1042
1041 1043 rtems_status_code status;
1042 1044
1043 1045 PRINTF("in suspend_science_tasks\n")
1044 1046
1045 1047 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1046 1048 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1047 1049 {
1048 1050 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1049 1051 }
1050 1052 else
1051 1053 {
1052 1054 status = RTEMS_SUCCESSFUL;
1053 1055 }
1054 1056 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1055 1057 {
1056 1058 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1057 1059 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1058 1060 {
1059 1061 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1060 1062 }
1061 1063 else
1062 1064 {
1063 1065 status = RTEMS_SUCCESSFUL;
1064 1066 }
1065 1067 }
1066 1068 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1067 1069 {
1068 1070 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1069 1071 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1070 1072 {
1071 1073 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1072 1074 }
1073 1075 else
1074 1076 {
1075 1077 status = RTEMS_SUCCESSFUL;
1076 1078 }
1077 1079 }
1078 1080 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1079 1081 {
1080 1082 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1081 1083 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1082 1084 {
1083 1085 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1084 1086 }
1085 1087 else
1086 1088 {
1087 1089 status = RTEMS_SUCCESSFUL;
1088 1090 }
1089 1091 }
1090 1092 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1091 1093 {
1092 1094 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1093 1095 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1094 1096 {
1095 1097 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1096 1098 }
1097 1099 else
1098 1100 {
1099 1101 status = RTEMS_SUCCESSFUL;
1100 1102 }
1101 1103 }
1102 1104 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1103 1105 {
1104 1106 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1105 1107 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1106 1108 {
1107 1109 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1108 1110 }
1109 1111 else
1110 1112 {
1111 1113 status = RTEMS_SUCCESSFUL;
1112 1114 }
1113 1115 }
1114 1116 if (status == RTEMS_SUCCESSFUL) // suspend WFRM
1115 1117 {
1116 1118 status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1117 1119 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1118 1120 {
1119 1121 PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1120 1122 }
1121 1123 else
1122 1124 {
1123 1125 status = RTEMS_SUCCESSFUL;
1124 1126 }
1125 1127 }
1126 1128 if (status == RTEMS_SUCCESSFUL) // suspend CWF3
1127 1129 {
1128 1130 status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1129 1131 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1130 1132 {
1131 1133 PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1132 1134 }
1133 1135 else
1134 1136 {
1135 1137 status = RTEMS_SUCCESSFUL;
1136 1138 }
1137 1139 }
1138 1140 if (status == RTEMS_SUCCESSFUL) // suspend CWF2
1139 1141 {
1140 1142 status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1141 1143 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1142 1144 {
1143 1145 PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1144 1146 }
1145 1147 else
1146 1148 {
1147 1149 status = RTEMS_SUCCESSFUL;
1148 1150 }
1149 1151 }
1150 1152 if (status == RTEMS_SUCCESSFUL) // suspend CWF1
1151 1153 {
1152 1154 status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1153 1155 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1154 1156 {
1155 1157 PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1156 1158 }
1157 1159 else
1158 1160 {
1159 1161 status = RTEMS_SUCCESSFUL;
1160 1162 }
1161 1163 }
1162 1164
1163 1165 return status;
1164 1166 }
1165 1167
1166 1168 int suspend_asm_tasks( void )
1167 1169 {
1168 1170 /** This function suspends the science tasks.
1169 1171 *
1170 1172 * @return RTEMS directive status codes:
1171 1173 * - RTEMS_SUCCESSFUL - task restarted successfully
1172 1174 * - RTEMS_INVALID_ID - task id invalid
1173 1175 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1174 1176 *
1175 1177 */
1176 1178
1177 1179 rtems_status_code status;
1178 1180
1179 1181 PRINTF("in suspend_science_tasks\n")
1180 1182
1181 1183 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1182 1184 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1183 1185 {
1184 1186 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1185 1187 }
1186 1188 else
1187 1189 {
1188 1190 status = RTEMS_SUCCESSFUL;
1189 1191 }
1190 1192
1191 1193 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1192 1194 {
1193 1195 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1194 1196 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1195 1197 {
1196 1198 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1197 1199 }
1198 1200 else
1199 1201 {
1200 1202 status = RTEMS_SUCCESSFUL;
1201 1203 }
1202 1204 }
1203 1205
1204 1206 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1205 1207 {
1206 1208 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1207 1209 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1208 1210 {
1209 1211 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1210 1212 }
1211 1213 else
1212 1214 {
1213 1215 status = RTEMS_SUCCESSFUL;
1214 1216 }
1215 1217 }
1216 1218
1217 1219 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1218 1220 {
1219 1221 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1220 1222 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1221 1223 {
1222 1224 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1223 1225 }
1224 1226 else
1225 1227 {
1226 1228 status = RTEMS_SUCCESSFUL;
1227 1229 }
1228 1230 }
1229 1231
1230 1232 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1231 1233 {
1232 1234 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1233 1235 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1234 1236 {
1235 1237 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1236 1238 }
1237 1239 else
1238 1240 {
1239 1241 status = RTEMS_SUCCESSFUL;
1240 1242 }
1241 1243 }
1242 1244
1243 1245 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1244 1246 {
1245 1247 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1246 1248 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1247 1249 {
1248 1250 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1249 1251 }
1250 1252 else
1251 1253 {
1252 1254 status = RTEMS_SUCCESSFUL;
1253 1255 }
1254 1256 }
1255 1257
1256 1258 return status;
1257 1259 }
1258 1260
1259 1261 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1260 1262 {
1261 1263
1262 1264 WFP_reset_current_ring_nodes();
1263 1265
1264 1266 reset_waveform_picker_regs();
1265 1267
1266 1268 set_wfp_burst_enable_register( mode );
1267 1269
1268 1270 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1269 1271 LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1270 1272
1271 1273 if (transitionCoarseTime == 0)
1272 1274 {
1273 1275 // instant transition means transition on the next valid date
1274 1276 // this is mandatory to have a good snapshot period a a good correction of the snapshot period
1275 1277 waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1276 1278 }
1277 1279 else
1278 1280 {
1279 1281 waveform_picker_regs->start_date = transitionCoarseTime;
1280 1282 }
1281 1283
1282 1284 update_last_valid_transition_date(waveform_picker_regs->start_date);
1283 1285
1284 1286 }
1285 1287
1286 1288 void launch_spectral_matrix( void )
1287 1289 {
1288 1290 SM_reset_current_ring_nodes();
1289 1291
1290 1292 reset_spectral_matrix_regs();
1291 1293
1292 1294 reset_nb_sm();
1293 1295
1294 1296 set_sm_irq_onNewMatrix( 1 );
1295 1297
1296 1298 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1297 1299 LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1298 1300
1299 1301 }
1300 1302
1301 1303 void set_sm_irq_onNewMatrix( unsigned char value )
1302 1304 {
1303 1305 if (value == 1)
1304 1306 {
1305 1307 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x01;
1306 1308 }
1307 1309 else
1308 1310 {
1309 1311 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffe; // 1110
1310 1312 }
1311 1313 }
1312 1314
1313 1315 void set_sm_irq_onError( unsigned char value )
1314 1316 {
1315 1317 if (value == 1)
1316 1318 {
1317 1319 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x02;
1318 1320 }
1319 1321 else
1320 1322 {
1321 1323 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffd; // 1101
1322 1324 }
1323 1325 }
1324 1326
1325 1327 //*****************************
1326 1328 // CONFIGURE CALIBRATION SIGNAL
1327 1329 void setCalibrationPrescaler( unsigned int prescaler )
1328 1330 {
1329 1331 // prescaling of the master clock (25 MHz)
1330 1332 // master clock is divided by 2^prescaler
1331 1333 time_management_regs->calPrescaler = prescaler;
1332 1334 }
1333 1335
1334 1336 void setCalibrationDivisor( unsigned int divisionFactor )
1335 1337 {
1336 1338 // division of the prescaled clock by the division factor
1337 1339 time_management_regs->calDivisor = divisionFactor;
1338 1340 }
1339 1341
1340 1342 void setCalibrationData( void ){
1341 1343 unsigned int k;
1342 1344 unsigned short data;
1343 1345 float val;
1344 1346 float f0;
1345 1347 float f1;
1346 1348 float fs;
1347 1349 float Ts;
1348 1350 float scaleFactor;
1349 1351
1350 1352 f0 = 625;
1351 1353 f1 = 10000;
1352 1354 fs = 160256.410;
1353 1355 Ts = 1. / fs;
1354 1356 scaleFactor = 0.250 / 0.000654; // 191, 500 mVpp, 2 sinus waves => 500 mVpp each, amplitude = 250 mV
1355 1357
1356 1358 time_management_regs->calDataPtr = 0x00;
1357 1359
1358 1360 // build the signal for the SCM calibration
1359 1361 for (k=0; k<256; k++)
1360 1362 {
1361 1363 val = sin( 2 * pi * f0 * k * Ts )
1362 1364 + sin( 2 * pi * f1 * k * Ts );
1363 1365 data = (unsigned short) ((val * scaleFactor) + 2048);
1364 1366 time_management_regs->calData = data & 0xfff;
1365 1367 }
1366 1368 }
1367 1369
1368 1370 void setCalibrationDataInterleaved( void ){
1369 1371 unsigned int k;
1370 1372 float val;
1371 1373 float f0;
1372 1374 float f1;
1373 1375 float fs;
1374 1376 float Ts;
1375 1377 unsigned short data[384];
1376 1378 unsigned char *dataPtr;
1377 1379
1378 1380 f0 = 625;
1379 1381 f1 = 10000;
1380 1382 fs = 240384.615;
1381 1383 Ts = 1. / fs;
1382 1384
1383 1385 time_management_regs->calDataPtr = 0x00;
1384 1386
1385 1387 // build the signal for the SCM calibration
1386 1388 for (k=0; k<384; k++)
1387 1389 {
1388 1390 val = sin( 2 * pi * f0 * k * Ts )
1389 1391 + sin( 2 * pi * f1 * k * Ts );
1390 1392 data[k] = (unsigned short) (val * 512 + 2048);
1391 1393 }
1392 1394
1393 1395 // write the signal in interleaved mode
1394 1396 for (k=0; k<128; k++)
1395 1397 {
1396 1398 dataPtr = (unsigned char*) &data[k*3 + 2];
1397 1399 time_management_regs->calData = (data[k*3] & 0xfff)
1398 1400 + ( (dataPtr[0] & 0x3f) << 12);
1399 1401 time_management_regs->calData = (data[k*3 + 1] & 0xfff)
1400 1402 + ( (dataPtr[1] & 0x3f) << 12);
1401 1403 }
1402 1404 }
1403 1405
1404 1406 void setCalibrationReload( bool state)
1405 1407 {
1406 1408 if (state == true)
1407 1409 {
1408 1410 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000010; // [0001 0000]
1409 1411 }
1410 1412 else
1411 1413 {
1412 1414 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffef; // [1110 1111]
1413 1415 }
1414 1416 }
1415 1417
1416 1418 void setCalibrationEnable( bool state )
1417 1419 {
1418 1420 // this bit drives the multiplexer
1419 1421 if (state == true)
1420 1422 {
1421 1423 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000040; // [0100 0000]
1422 1424 }
1423 1425 else
1424 1426 {
1425 1427 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffbf; // [1011 1111]
1426 1428 }
1427 1429 }
1428 1430
1429 1431 void setCalibrationInterleaved( bool state )
1430 1432 {
1431 1433 // this bit drives the multiplexer
1432 1434 if (state == true)
1433 1435 {
1434 1436 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000020; // [0010 0000]
1435 1437 }
1436 1438 else
1437 1439 {
1438 1440 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffdf; // [1101 1111]
1439 1441 }
1440 1442 }
1441 1443
1442 1444 void setCalibration( bool state )
1443 1445 {
1444 1446 if (state == true)
1445 1447 {
1446 1448 setCalibrationEnable( true );
1447 1449 setCalibrationReload( false );
1448 1450 set_hk_lfr_calib_enable( true );
1449 1451 }
1450 1452 else
1451 1453 {
1452 1454 setCalibrationEnable( false );
1453 1455 setCalibrationReload( true );
1454 1456 set_hk_lfr_calib_enable( false );
1455 1457 }
1456 1458 }
1457 1459
1458 1460 void configureCalibration( bool interleaved )
1459 1461 {
1460 1462 setCalibration( false );
1461 1463 if ( interleaved == true )
1462 1464 {
1463 1465 setCalibrationInterleaved( true );
1464 1466 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1465 1467 setCalibrationDivisor( 26 ); // => 240 384
1466 1468 setCalibrationDataInterleaved();
1467 1469 }
1468 1470 else
1469 1471 {
1470 1472 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1471 1473 setCalibrationDivisor( 38 ); // => 160 256 (39 - 1)
1472 1474 setCalibrationData();
1473 1475 }
1474 1476 }
1475 1477
1476 1478 //****************
1477 1479 // CLOSING ACTIONS
1478 1480 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1479 1481 {
1480 1482 /** This function is used to update the HK packets statistics after a successful TC execution.
1481 1483 *
1482 1484 * @param TC points to the TC being processed
1483 1485 * @param time is the time used to date the TC execution
1484 1486 *
1485 1487 */
1486 1488
1487 1489 unsigned int val;
1488 1490
1489 1491 housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1490 1492 housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1491 1493 housekeeping_packet.hk_lfr_last_exe_tc_type[0] = 0x00;
1492 1494 housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1493 1495 housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = 0x00;
1494 1496 housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1495 1497 housekeeping_packet.hk_lfr_last_exe_tc_time[0] = time[0];
1496 1498 housekeeping_packet.hk_lfr_last_exe_tc_time[1] = time[1];
1497 1499 housekeeping_packet.hk_lfr_last_exe_tc_time[2] = time[2];
1498 1500 housekeeping_packet.hk_lfr_last_exe_tc_time[3] = time[3];
1499 1501 housekeeping_packet.hk_lfr_last_exe_tc_time[4] = time[4];
1500 1502 housekeeping_packet.hk_lfr_last_exe_tc_time[5] = time[5];
1501 1503
1502 1504 val = housekeeping_packet.hk_lfr_exe_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1503 1505 val++;
1504 1506 housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> 8);
1505 1507 housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1506 1508 }
1507 1509
1508 1510 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1509 1511 {
1510 1512 /** This function is used to update the HK packets statistics after a TC rejection.
1511 1513 *
1512 1514 * @param TC points to the TC being processed
1513 1515 * @param time is the time used to date the TC rejection
1514 1516 *
1515 1517 */
1516 1518
1517 1519 unsigned int val;
1518 1520
1519 1521 housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1520 1522 housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1521 1523 housekeeping_packet.hk_lfr_last_rej_tc_type[0] = 0x00;
1522 1524 housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1523 1525 housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = 0x00;
1524 1526 housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1525 1527 housekeeping_packet.hk_lfr_last_rej_tc_time[0] = time[0];
1526 1528 housekeeping_packet.hk_lfr_last_rej_tc_time[1] = time[1];
1527 1529 housekeeping_packet.hk_lfr_last_rej_tc_time[2] = time[2];
1528 1530 housekeeping_packet.hk_lfr_last_rej_tc_time[3] = time[3];
1529 1531 housekeeping_packet.hk_lfr_last_rej_tc_time[4] = time[4];
1530 1532 housekeeping_packet.hk_lfr_last_rej_tc_time[5] = time[5];
1531 1533
1532 1534 val = housekeeping_packet.hk_lfr_rej_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1533 1535 val++;
1534 1536 housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> 8);
1535 1537 housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1536 1538 }
1537 1539
1538 1540 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1539 1541 {
1540 1542 /** This function is the last step of the TC execution workflow.
1541 1543 *
1542 1544 * @param TC points to the TC being processed
1543 1545 * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1544 1546 * @param queue_id is the id of the RTEMS message queue used to send TM packets
1545 1547 * @param time is the time used to date the TC execution
1546 1548 *
1547 1549 */
1548 1550
1549 1551 unsigned char requestedMode;
1550 1552
1551 1553 if (result == LFR_SUCCESSFUL)
1552 1554 {
1553 1555 if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1554 1556 &
1555 1557 !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1556 1558 )
1557 1559 {
1558 1560 send_tm_lfr_tc_exe_success( TC, queue_id );
1559 1561 }
1560 1562 if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1561 1563 {
1562 1564 //**********************************
1563 1565 // UPDATE THE LFRMODE LOCAL VARIABLE
1564 1566 requestedMode = TC->dataAndCRC[1];
1565 1567 updateLFRCurrentMode( requestedMode );
1566 1568 }
1567 1569 }
1568 1570 else if (result == LFR_EXE_ERROR)
1569 1571 {
1570 1572 send_tm_lfr_tc_exe_error( TC, queue_id );
1571 1573 }
1572 1574 }
1573 1575
1574 1576 //***************************
1575 1577 // Interrupt Service Routines
1576 1578 rtems_isr commutation_isr1( rtems_vector_number vector )
1577 1579 {
1578 1580 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1579 1581 PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1580 1582 }
1581 1583 }
1582 1584
1583 1585 rtems_isr commutation_isr2( rtems_vector_number vector )
1584 1586 {
1585 1587 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1586 1588 PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1587 1589 }
1588 1590 }
1589 1591
1590 1592 //****************
1591 1593 // OTHER FUNCTIONS
1592 1594 void updateLFRCurrentMode( unsigned char requestedMode )
1593 1595 {
1594 1596 /** This function updates the value of the global variable lfrCurrentMode.
1595 1597 *
1596 1598 * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1597 1599 *
1598 1600 */
1599 1601
1600 1602 // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1601 1603 housekeeping_packet.lfr_status_word[0] = (unsigned char) ((requestedMode << 4) + 0x0d);
1602 1604 lfrCurrentMode = requestedMode;
1603 1605 }
1604 1606
1605 1607 void set_lfr_soft_reset( unsigned char value )
1606 1608 {
1607 1609 if (value == 1)
1608 1610 {
1609 1611 time_management_regs->ctrl = time_management_regs->ctrl | 0x00000004; // [0100]
1610 1612 }
1611 1613 else
1612 1614 {
1613 1615 time_management_regs->ctrl = time_management_regs->ctrl & 0xfffffffb; // [1011]
1614 1616 }
1615 1617 }
1616 1618
1617 1619 void reset_lfr( void )
1618 1620 {
1619 1621 set_lfr_soft_reset( 1 );
1620 1622
1621 1623 set_lfr_soft_reset( 0 );
1622 1624
1623 1625 set_hk_lfr_sc_potential_flag( true );
1624 1626 }
General Comments 0
You need to be logged in to leave comments. Login now