##// END OF EJS Templates
spacewire statistics management modified...
paul -
r264:2120c4473911 R3a
parent child
Show More
@@ -1,59 +1,57
1 1 #ifndef FSW_SPACEWIRE_H_INCLUDED
2 2 #define FSW_SPACEWIRE_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6
7 7 #include <fcntl.h> // for O_RDWR
8 8 #include <unistd.h> // for the read call
9 9 #include <sys/ioctl.h> // for the ioctl call
10 10 #include <errno.h>
11 11
12 12 #include "fsw_params.h"
13 13 #include "tc_handler.h"
14 14 #include "fsw_init.h"
15 15
16 16 extern spw_stats grspw_stats;
17 17 extern spw_stats spw_backup;
18 18 extern rtems_name timecode_timer_name;
19 19 extern rtems_id timecode_timer_id;
20 20
21 21 // RTEMS TASK
22 22 rtems_task spiq_task( rtems_task_argument argument );
23 23 rtems_task recv_task( rtems_task_argument unused );
24 24 rtems_task send_task( rtems_task_argument argument );
25 25 rtems_task link_task( rtems_task_argument argument );
26 26
27 27 int spacewire_open_link( void );
28 28 int spacewire_start_link( int fd );
29 29 int spacewire_stop_and_start_link( int fd );
30 30 int spacewire_configure_link(int fd );
31 31 int spacewire_several_connect_attemps( void );
32 32 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
33 33 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
34 void spacewire_save_stats( void );
35 void spacewire_restore_stats( void );
36 void spacewire_update_statistics( void );
34 void spacewire_read_statistics( void );
37 35 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code);
38 void update_hk_with_grspw_stats( spw_stats stats );
36 void update_hk_with_grspw_stats(void );
39 37 void increase_unsigned_char_counter( unsigned char *counter );
40 38
41 39 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
42 40 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
43 41 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
44 42 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
45 43 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
46 44 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
47 45 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
48 46 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
49 47 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
50 48 void spw_send_k_dump( ring_node *ring_node_to_send );
51 49
52 50 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
53 51 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
54 52 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
55 53 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
56 54
57 55 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
58 56
59 57 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,804 +1,804
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 PRINTF("watchdog_isr *** this is the end, exit(0)\n");
91 91
92 92 exit(0);
93 93 }
94 94
95 95 void watchdog_configure(void)
96 96 {
97 97 /** This function configure the watchdog.
98 98 *
99 99 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
100 100 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
101 101 *
102 102 * The watchdog is a timer provided by the GPTIMER IP core of the GRLIB.
103 103 *
104 104 */
105 105
106 106 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt during configuration
107 107
108 108 timer_configure( TIMER_WATCHDOG, CLKDIV_WATCHDOG, IRQ_SPARC_GPTIMER_WATCHDOG, watchdog_isr );
109 109
110 110 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
111 111 }
112 112
113 113 void watchdog_stop(void)
114 114 {
115 115 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt line
116 116 timer_stop( TIMER_WATCHDOG );
117 117 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
118 118 }
119 119
120 120 void watchdog_reload(void)
121 121 {
122 122 /** This function reloads the watchdog timer counter with the timer reload value.
123 123 *
124 124 * @param void
125 125 *
126 126 * @return void
127 127 *
128 128 */
129 129
130 130 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
131 131 }
132 132
133 133 void watchdog_start(void)
134 134 {
135 135 /** This function starts the watchdog timer.
136 136 *
137 137 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
138 138 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
139 139 *
140 140 */
141 141
142 142 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
143 143
144 144 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000010; // clear pending IRQ if any
145 145 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
146 146 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000001; // EN enable the timer
147 147 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000008; // IE interrupt enable
148 148
149 149 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
150 150
151 151 }
152 152
153 153 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
154 154 {
155 155 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
156 156
157 157 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
158 158
159 159 return 0;
160 160 }
161 161
162 162 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
163 163 {
164 164 /** This function sets the scaler reload register of the apbuart module
165 165 *
166 166 * @param regs is the address of the apbuart registers in memory
167 167 * @param value is the value that will be stored in the scaler register
168 168 *
169 169 * The value shall be set by the software to get data on the serial interface.
170 170 *
171 171 */
172 172
173 173 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
174 174
175 175 apbuart_regs->scaler = value;
176 176
177 177 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
178 178 }
179 179
180 180 //************
181 181 // RTEMS TASKS
182 182
183 183 rtems_task load_task(rtems_task_argument argument)
184 184 {
185 185 BOOT_PRINTF("in LOAD *** \n")
186 186
187 187 rtems_status_code status;
188 188 unsigned int i;
189 189 unsigned int j;
190 190 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
191 191 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
192 192
193 193 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
194 194
195 195 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
196 196 if( status != RTEMS_SUCCESSFUL ) {
197 197 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
198 198 }
199 199
200 200 i = 0;
201 201 j = 0;
202 202
203 203 watchdog_configure();
204 204
205 205 watchdog_start();
206 206
207 207 set_sy_lfr_watchdog_enabled( true );
208 208
209 209 while(1){
210 210 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
211 211 watchdog_reload();
212 212 i = i + 1;
213 213 if ( i == 10 )
214 214 {
215 215 i = 0;
216 216 j = j + 1;
217 217 PRINTF1("%d\n", j)
218 218 }
219 219 #ifdef DEBUG_WATCHDOG
220 220 if (j == 3 )
221 221 {
222 222 status = rtems_task_delete(RTEMS_SELF);
223 223 }
224 224 #endif
225 225 }
226 226 }
227 227
228 228 rtems_task hous_task(rtems_task_argument argument)
229 229 {
230 230 rtems_status_code status;
231 231 rtems_status_code spare_status;
232 232 rtems_id queue_id;
233 233 rtems_rate_monotonic_period_status period_status;
234 234
235 235 status = get_message_queue_id_send( &queue_id );
236 236 if (status != RTEMS_SUCCESSFUL)
237 237 {
238 238 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
239 239 }
240 240
241 241 BOOT_PRINTF("in HOUS ***\n");
242 242
243 243 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
244 244 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
245 245 if( status != RTEMS_SUCCESSFUL ) {
246 246 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status );
247 247 }
248 248 }
249 249
250 250 status = rtems_rate_monotonic_cancel(HK_id);
251 251 if( status != RTEMS_SUCCESSFUL ) {
252 252 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status );
253 253 }
254 254 else {
255 255 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n");
256 256 }
257 257
258 258 // startup phase
259 259 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
260 260 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
261 261 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
262 262 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
263 263 {
264 264 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
265 265 {
266 266 break; // break if LFR is synchronized
267 267 }
268 268 else
269 269 {
270 270 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
271 271 // sched_yield();
272 272 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
273 273 }
274 274 }
275 275 status = rtems_rate_monotonic_cancel(HK_id);
276 276 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
277 277
278 278 set_hk_lfr_reset_cause( POWER_ON );
279 279
280 280 while(1){ // launch the rate monotonic task
281 281 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
282 282 if ( status != RTEMS_SUCCESSFUL ) {
283 283 PRINTF1( "in HOUS *** ERR period: %d\n", status);
284 284 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
285 285 }
286 286 else {
287 287 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
288 288 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
289 289 increment_seq_counter( &sequenceCounterHK );
290 290
291 291 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
292 292 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
293 293 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
294 294 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
295 295 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
296 296 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
297 297
298 spacewire_update_statistics();
298 spacewire_read_statistics();
299 299
300 update_hk_with_grspw_stats( grspw_stats );
300 update_hk_with_grspw_stats();
301 301
302 302 set_hk_lfr_time_not_synchro();
303 303
304 304 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
305 305 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
306 306 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
307 307 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
308 308 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
309 309
310 310 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
311 311 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
312 312 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
313 313 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
314 314 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
315 315
316 316 hk_lfr_le_me_he_update();
317 317
318 318 // SEND PACKET
319 319 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
320 320 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
321 321 if (status != RTEMS_SUCCESSFUL) {
322 322 PRINTF1("in HOUS *** ERR send: %d\n", status)
323 323 }
324 324 }
325 325 }
326 326
327 327 PRINTF("in HOUS *** deleting task\n")
328 328
329 329 status = rtems_task_delete( RTEMS_SELF ); // should not return
330 330
331 331 return;
332 332 }
333 333
334 334 rtems_task dumb_task( rtems_task_argument unused )
335 335 {
336 336 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
337 337 *
338 338 * @param unused is the starting argument of the RTEMS task
339 339 *
340 340 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
341 341 *
342 342 */
343 343
344 344 unsigned int i;
345 345 unsigned int intEventOut;
346 346 unsigned int coarse_time = 0;
347 347 unsigned int fine_time = 0;
348 348 rtems_event_set event_out;
349 349
350 350 char *DumbMessages[15] = {"in DUMB *** default", // RTEMS_EVENT_0
351 351 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
352 352 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
353 353 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
354 354 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
355 355 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
356 356 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
357 357 "ready for dump", // RTEMS_EVENT_7
358 358 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
359 359 "tick", // RTEMS_EVENT_9
360 360 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
361 361 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11
362 362 "WATCHDOG timer", // RTEMS_EVENT_12
363 363 "TIMECODE timer", // RTEMS_EVENT_13
364 364 "TIMECODE ISR" // RTEMS_EVENT_14
365 365 };
366 366
367 367 BOOT_PRINTF("in DUMB *** \n")
368 368
369 369 while(1){
370 370 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
371 371 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
372 372 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13
373 373 | RTEMS_EVENT_14,
374 374 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
375 375 intEventOut = (unsigned int) event_out;
376 376 for ( i=0; i<32; i++)
377 377 {
378 378 if ( ((intEventOut >> i) & 0x0001) != 0)
379 379 {
380 380 coarse_time = time_management_regs->coarse_time;
381 381 fine_time = time_management_regs->fine_time;
382 382 if (i==12)
383 383 {
384 384 PRINTF1("%s\n", DumbMessages[12])
385 385 }
386 386 if (i==13)
387 387 {
388 388 PRINTF1("%s\n", DumbMessages[13])
389 389 }
390 390 if (i==14)
391 391 {
392 392 PRINTF1("%s\n", DumbMessages[1])
393 393 }
394 394 }
395 395 }
396 396 }
397 397 }
398 398
399 399 //*****************************
400 400 // init housekeeping parameters
401 401
402 402 void init_housekeeping_parameters( void )
403 403 {
404 404 /** This function initialize the housekeeping_packet global variable with default values.
405 405 *
406 406 */
407 407
408 408 unsigned int i = 0;
409 409 unsigned char *parameters;
410 410 unsigned char sizeOfHK;
411 411
412 412 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
413 413
414 414 parameters = (unsigned char*) &housekeeping_packet;
415 415
416 416 for(i = 0; i< sizeOfHK; i++)
417 417 {
418 418 parameters[i] = 0x00;
419 419 }
420 420
421 421 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
422 422 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
423 423 housekeeping_packet.reserved = DEFAULT_RESERVED;
424 424 housekeeping_packet.userApplication = CCSDS_USER_APP;
425 425 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
426 426 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
427 427 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
428 428 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
429 429 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
430 430 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
431 431 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
432 432 housekeeping_packet.serviceType = TM_TYPE_HK;
433 433 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
434 434 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
435 435 housekeeping_packet.sid = SID_HK;
436 436
437 437 // init status word
438 438 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
439 439 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
440 440 // init software version
441 441 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
442 442 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
443 443 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
444 444 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
445 445 // init fpga version
446 446 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
447 447 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
448 448 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
449 449 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
450 450
451 451 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
452 452 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
453 453 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
454 454 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
455 455 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
456 456 }
457 457
458 458 void increment_seq_counter( unsigned short *packetSequenceControl )
459 459 {
460 460 /** This function increment the sequence counter passes in argument.
461 461 *
462 462 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
463 463 *
464 464 */
465 465
466 466 unsigned short segmentation_grouping_flag;
467 467 unsigned short sequence_cnt;
468 468
469 469 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
470 470 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
471 471
472 472 if ( sequence_cnt < SEQ_CNT_MAX)
473 473 {
474 474 sequence_cnt = sequence_cnt + 1;
475 475 }
476 476 else
477 477 {
478 478 sequence_cnt = 0;
479 479 }
480 480
481 481 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
482 482 }
483 483
484 484 void getTime( unsigned char *time)
485 485 {
486 486 /** This function write the current local time in the time buffer passed in argument.
487 487 *
488 488 */
489 489
490 490 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
491 491 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
492 492 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
493 493 time[3] = (unsigned char) (time_management_regs->coarse_time);
494 494 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
495 495 time[5] = (unsigned char) (time_management_regs->fine_time);
496 496 }
497 497
498 498 unsigned long long int getTimeAsUnsignedLongLongInt( )
499 499 {
500 500 /** This function write the current local time in the time buffer passed in argument.
501 501 *
502 502 */
503 503 unsigned long long int time;
504 504
505 505 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
506 506 + time_management_regs->fine_time;
507 507
508 508 return time;
509 509 }
510 510
511 511 void send_dumb_hk( void )
512 512 {
513 513 Packet_TM_LFR_HK_t dummy_hk_packet;
514 514 unsigned char *parameters;
515 515 unsigned int i;
516 516 rtems_id queue_id;
517 517
518 518 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
519 519 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
520 520 dummy_hk_packet.reserved = DEFAULT_RESERVED;
521 521 dummy_hk_packet.userApplication = CCSDS_USER_APP;
522 522 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
523 523 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
524 524 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
525 525 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
526 526 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
527 527 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
528 528 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
529 529 dummy_hk_packet.serviceType = TM_TYPE_HK;
530 530 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
531 531 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
532 532 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
533 533 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
534 534 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
535 535 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
536 536 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
537 537 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
538 538 dummy_hk_packet.sid = SID_HK;
539 539
540 540 // init status word
541 541 dummy_hk_packet.lfr_status_word[0] = 0xff;
542 542 dummy_hk_packet.lfr_status_word[1] = 0xff;
543 543 // init software version
544 544 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
545 545 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
546 546 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
547 547 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
548 548 // init fpga version
549 549 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
550 550 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
551 551 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
552 552 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
553 553
554 554 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
555 555
556 556 for (i=0; i<100; i++)
557 557 {
558 558 parameters[i] = 0xff;
559 559 }
560 560
561 561 get_message_queue_id_send( &queue_id );
562 562
563 563 rtems_message_queue_send( queue_id, &dummy_hk_packet,
564 564 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
565 565 }
566 566
567 567 void get_temperatures( unsigned char *temperatures )
568 568 {
569 569 unsigned char* temp_scm_ptr;
570 570 unsigned char* temp_pcb_ptr;
571 571 unsigned char* temp_fpga_ptr;
572 572
573 573 // SEL1 SEL0
574 574 // 0 0 => PCB
575 575 // 0 1 => FPGA
576 576 // 1 0 => SCM
577 577
578 578 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
579 579 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
580 580 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
581 581
582 582 temperatures[0] = temp_scm_ptr[2];
583 583 temperatures[1] = temp_scm_ptr[3];
584 584 temperatures[2] = temp_pcb_ptr[2];
585 585 temperatures[3] = temp_pcb_ptr[3];
586 586 temperatures[4] = temp_fpga_ptr[2];
587 587 temperatures[5] = temp_fpga_ptr[3];
588 588 }
589 589
590 590 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
591 591 {
592 592 unsigned char* v_ptr;
593 593 unsigned char* e1_ptr;
594 594 unsigned char* e2_ptr;
595 595
596 596 v_ptr = (unsigned char *) &waveform_picker_regs->v;
597 597 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
598 598 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
599 599
600 600 spacecraft_potential[0] = v_ptr[2];
601 601 spacecraft_potential[1] = v_ptr[3];
602 602 spacecraft_potential[2] = e1_ptr[2];
603 603 spacecraft_potential[3] = e1_ptr[3];
604 604 spacecraft_potential[4] = e2_ptr[2];
605 605 spacecraft_potential[5] = e2_ptr[3];
606 606 }
607 607
608 608 void get_cpu_load( unsigned char *resource_statistics )
609 609 {
610 610 unsigned char cpu_load;
611 611
612 612 cpu_load = lfr_rtems_cpu_usage_report();
613 613
614 614 // HK_LFR_CPU_LOAD
615 615 resource_statistics[0] = cpu_load;
616 616
617 617 // HK_LFR_CPU_LOAD_MAX
618 618 if (cpu_load > resource_statistics[1])
619 619 {
620 620 resource_statistics[1] = cpu_load;
621 621 }
622 622
623 623 // CPU_LOAD_AVE
624 624 resource_statistics[2] = 0;
625 625
626 626 #ifndef PRINT_TASK_STATISTICS
627 627 rtems_cpu_usage_reset();
628 628 #endif
629 629
630 630 }
631 631
632 632 void set_hk_lfr_sc_potential_flag( bool state )
633 633 {
634 634 if (state == true)
635 635 {
636 636 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x40; // [0100 0000]
637 637 }
638 638 else
639 639 {
640 640 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xbf; // [1011 1111]
641 641 }
642 642 }
643 643
644 644 void set_hk_lfr_mag_fields_flag( bool state )
645 645 {
646 646 if (state == true)
647 647 {
648 648 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x20; // [0010 0000]
649 649 }
650 650 else
651 651 {
652 652 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xd7; // [1101 1111]
653 653 }
654 654 }
655 655
656 656 void set_sy_lfr_watchdog_enabled( bool state )
657 657 {
658 658 if (state == true)
659 659 {
660 660 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x10; // [0001 0000]
661 661 }
662 662 else
663 663 {
664 664 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xef; // [1110 1111]
665 665 }
666 666 }
667 667
668 668 void set_hk_lfr_calib_enable( bool state )
669 669 {
670 670 if (state == true)
671 671 {
672 672 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x08; // [0000 1000]
673 673 }
674 674 else
675 675 {
676 676 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xf7; // [1111 0111]
677 677 }
678 678 }
679 679
680 680 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
681 681 {
682 682 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
683 683 | (lfr_reset_cause & 0x07 ); // [0000 0111]
684 684 }
685 685
686 686 void hk_lfr_le_me_he_update()
687 687 {
688 688 unsigned int hk_lfr_le_cnt;
689 689 unsigned int hk_lfr_me_cnt;
690 690 unsigned int hk_lfr_he_cnt;
691 691
692 692 hk_lfr_le_cnt = 0;
693 693 hk_lfr_me_cnt = 0;
694 694 hk_lfr_he_cnt = 0;
695 695
696 696 //update the low severity error counter
697 697 hk_lfr_le_cnt =
698 698 housekeeping_packet.hk_lfr_dpu_spw_parity
699 699 + housekeeping_packet.hk_lfr_dpu_spw_disconnect
700 700 + housekeeping_packet.hk_lfr_dpu_spw_escape
701 701 + housekeeping_packet.hk_lfr_dpu_spw_credit
702 702 + housekeeping_packet.hk_lfr_dpu_spw_write_sync
703 703 + housekeeping_packet.hk_lfr_timecode_erroneous
704 704 + housekeeping_packet.hk_lfr_timecode_missing
705 705 + housekeeping_packet.hk_lfr_timecode_invalid
706 706 + housekeeping_packet.hk_lfr_time_timecode_it
707 707 + housekeeping_packet.hk_lfr_time_not_synchro
708 708 + housekeeping_packet.hk_lfr_time_timecode_ctr;
709 709 // housekeeping_packet.hk_lfr_dpu_spw_rx_ahb => not handled by the grspw driver
710 710 // housekeeping_packet.hk_lfr_dpu_spw_tx_ahb => not handled by the grspw driver
711 711
712 712 //update the medium severity error counter
713 713 hk_lfr_me_cnt =
714 714 housekeeping_packet.hk_lfr_dpu_spw_early_eop
715 715 + housekeeping_packet.hk_lfr_dpu_spw_invalid_addr
716 716 + housekeeping_packet.hk_lfr_dpu_spw_eep
717 717 + housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
718 718
719 719 //update the high severity error counter
720 720 hk_lfr_he_cnt = 0;
721 721
722 722 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
723 723 // LE
724 724 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((hk_lfr_le_cnt & 0xff00) >> 8);
725 725 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (hk_lfr_le_cnt & 0x00ff);
726 726 // ME
727 727 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((hk_lfr_me_cnt & 0xff00) >> 8);
728 728 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (hk_lfr_me_cnt & 0x00ff);
729 729 // HE
730 730 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & 0xff00) >> 8);
731 731 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & 0x00ff);
732 732
733 733 }
734 734
735 735 void set_hk_lfr_time_not_synchro()
736 736 {
737 737 static unsigned char synchroLost = 1;
738 738 int synchronizationBit;
739 739
740 740 // get the synchronization bit
741 741 synchronizationBit = (time_management_regs->coarse_time & 0x80000000) >> 31; // 1000 0000 0000 0000
742 742
743 743 switch (synchronizationBit)
744 744 {
745 745 case 0:
746 746 if (synchroLost == 1)
747 747 {
748 748 synchroLost = 0;
749 749 }
750 750 break;
751 751 case 1:
752 752 if (synchroLost == 0 )
753 753 {
754 754 synchroLost = 1;
755 755 increase_unsigned_char_counter(&housekeeping_packet.hk_lfr_time_not_synchro);
756 756 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_NOT_SYNCHRO );
757 757 }
758 758 break;
759 759 default:
760 760 PRINTF1("in hk_lfr_time_not_synchro *** unexpected value for synchronizationBit = %d\n", synchronizationBit);
761 761 break;
762 762 }
763 763
764 764 }
765 765
766 766 void set_hk_lfr_ahb_correctable()
767 767 {
768 768 /** This function builds the error counter hk_lfr_ahb_correctable using the statistics provided
769 769 * by the Cache Control Register (ASI 2, offset 0) and in the Register Protection Control Register (ASR16) on the
770 770 * detected errors in the cache, in the integer unit and in the floating point unit.
771 771 *
772 772 * @param void
773 773 *
774 774 * @return void
775 775 *
776 776 * All errors are summed to set the value of the hk_lfr_ahb_correctable counter.
777 777 *
778 778 */
779 779
780 780 unsigned int ahb_correctable;
781 781 unsigned int instructionErrorCounter;
782 782 unsigned int dataErrorCounter;
783 783 unsigned int fprfErrorCounter;
784 784 unsigned int iurfErrorCounter;
785 785
786 786 CCR_getInstructionAndDataErrorCounters( &instructionErrorCounter, &dataErrorCounter);
787 787 ASR16_get_FPRF_IURF_ErrorCounters( &fprfErrorCounter, &iurfErrorCounter);
788 788
789 789 ahb_correctable = instructionErrorCounter
790 790 + dataErrorCounter
791 791 + fprfErrorCounter
792 792 + iurfErrorCounter
793 793 + housekeeping_packet.hk_lfr_ahb_correctable;
794 794
795 795 if (ahb_correctable > 255)
796 796 {
797 797 housekeeping_packet.hk_lfr_ahb_correctable = 255;
798 798 }
799 799 else
800 800 {
801 801 housekeeping_packet.hk_lfr_ahb_correctable = ahb_correctable;
802 802 }
803 803
804 804 }
@@ -1,1659 +1,1569
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 spacewire_save_stats();
69 spacewire_read_statistics();
70 70 status = spacewire_several_connect_attemps( );
71 spacewire_restore_stats();
72 71 }
73 72 else // [2.b] in run state, start the link
74 73 {
75 74 status = spacewire_stop_and_start_link( fdSPW ); // start the link
76 75 if ( status != RTEMS_SUCCESSFUL)
77 76 {
78 77 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
79 78 }
80 79 }
81 80
82 81 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
83 82 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
84 83 {
85 84 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
86 85 if ( status != RTEMS_SUCCESSFUL ) {
87 86 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
88 87 }
89 88 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
90 89 if ( status != RTEMS_SUCCESSFUL ) {
91 90 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
92 91 }
93 92 }
94 93 else // [3.b] the link is not in run state, go in STANDBY mode
95 94 {
96 95 status = enter_mode_standby();
97 96 if ( status != RTEMS_SUCCESSFUL )
98 97 {
99 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
100 99 }
101 100 {
102 101 updateLFRCurrentMode( LFR_MODE_STANDBY );
103 102 }
104 103 // wake the LINK task up to wait for the link recovery
105 104 status = rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
106 105 status = rtems_task_suspend( RTEMS_SELF );
107 106 }
108 107 }
109 108 }
110 109
111 110 rtems_task recv_task( rtems_task_argument unused )
112 111 {
113 112 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
114 113 *
115 114 * @param unused is the starting argument of the RTEMS task
116 115 *
117 116 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
118 117 * 1. It reads the incoming data.
119 118 * 2. Launches the acceptance procedure.
120 119 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
121 120 *
122 121 */
123 122
124 123 int len;
125 124 ccsdsTelecommandPacket_t currentTC;
126 125 unsigned char computed_CRC[ 2 ];
127 126 unsigned char currentTC_LEN_RCV[ 2 ];
128 127 unsigned char destinationID;
129 128 unsigned int estimatedPacketLength;
130 129 unsigned int parserCode;
131 130 rtems_status_code status;
132 131 rtems_id queue_recv_id;
133 132 rtems_id queue_send_id;
134 133
135 134 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
136 135
137 136 status = get_message_queue_id_recv( &queue_recv_id );
138 137 if (status != RTEMS_SUCCESSFUL)
139 138 {
140 139 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
141 140 }
142 141
143 142 status = get_message_queue_id_send( &queue_send_id );
144 143 if (status != RTEMS_SUCCESSFUL)
145 144 {
146 145 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
147 146 }
148 147
149 148 BOOT_PRINTF("in RECV *** \n")
150 149
151 150 while(1)
152 151 {
153 152 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
154 153 if (len == -1){ // error during the read call
155 154 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
156 155 }
157 156 else {
158 157 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
159 158 PRINTF("in RECV *** packet lenght too short\n")
160 159 }
161 160 else {
162 161 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
163 162 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
164 163 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
165 164 // CHECK THE TC
166 165 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
167 166 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
168 167 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
169 168 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
170 169 || (parserCode == WRONG_SRC_ID) )
171 170 { // send TM_LFR_TC_EXE_CORRUPTED
172 171 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
173 172 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
174 173 &&
175 174 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
176 175 )
177 176 {
178 177 if ( parserCode == WRONG_SRC_ID )
179 178 {
180 179 destinationID = SID_TC_GROUND;
181 180 }
182 181 else
183 182 {
184 183 destinationID = currentTC.sourceID;
185 184 }
186 185 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
187 186 computed_CRC, currentTC_LEN_RCV,
188 187 destinationID );
189 188 }
190 189 }
191 190 else
192 191 { // send valid TC to the action launcher
193 192 status = rtems_message_queue_send( queue_recv_id, &currentTC,
194 193 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
195 194 }
196 195 }
197 196 }
198 197
199 198 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
200 199
201 200 }
202 201 }
203 202
204 203 rtems_task send_task( rtems_task_argument argument)
205 204 {
206 205 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
207 206 *
208 207 * @param unused is the starting argument of the RTEMS task
209 208 *
210 209 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
211 210 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
212 211 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
213 212 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
214 213 * data it contains.
215 214 *
216 215 */
217 216
218 217 rtems_status_code status; // RTEMS status code
219 218 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
220 219 ring_node *incomingRingNodePtr;
221 220 int ring_node_address;
222 221 char *charPtr;
223 222 spw_ioctl_pkt_send *spw_ioctl_send;
224 223 size_t size; // size of the incoming TC packet
225 224 rtems_id queue_send_id;
226 225 unsigned int sid;
227 226 unsigned char sidAsUnsignedChar;
228 227 unsigned char type;
229 228
230 229 incomingRingNodePtr = NULL;
231 230 ring_node_address = 0;
232 231 charPtr = (char *) &ring_node_address;
233 232 sid = 0;
234 233 sidAsUnsignedChar = 0;
235 234
236 235 init_header_cwf( &headerCWF );
237 236 init_header_swf( &headerSWF );
238 237 init_header_asm( &headerASM );
239 238
240 239 status = get_message_queue_id_send( &queue_send_id );
241 240 if (status != RTEMS_SUCCESSFUL)
242 241 {
243 242 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
244 243 }
245 244
246 245 BOOT_PRINTF("in SEND *** \n")
247 246
248 247 while(1)
249 248 {
250 249 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
251 250 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
252 251
253 252 if (status!=RTEMS_SUCCESSFUL)
254 253 {
255 254 PRINTF1("in SEND *** (1) ERR = %d\n", status)
256 255 }
257 256 else
258 257 {
259 258 if ( size == sizeof(ring_node*) )
260 259 {
261 260 charPtr[0] = incomingData[0];
262 261 charPtr[1] = incomingData[1];
263 262 charPtr[2] = incomingData[2];
264 263 charPtr[3] = incomingData[3];
265 264 incomingRingNodePtr = (ring_node*) ring_node_address;
266 265 sid = incomingRingNodePtr->sid;
267 266 if ( (sid==SID_NORM_CWF_LONG_F3)
268 267 || (sid==SID_BURST_CWF_F2 )
269 268 || (sid==SID_SBM1_CWF_F1 )
270 269 || (sid==SID_SBM2_CWF_F2 ))
271 270 {
272 271 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
273 272 }
274 273 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
275 274 {
276 275 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
277 276 }
278 277 else if ( (sid==SID_NORM_CWF_F3) )
279 278 {
280 279 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
281 280 }
282 281 else if (sid==SID_NORM_ASM_F0)
283 282 {
284 283 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
285 284 }
286 285 else if (sid==SID_NORM_ASM_F1)
287 286 {
288 287 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
289 288 }
290 289 else if (sid==SID_NORM_ASM_F2)
291 290 {
292 291 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
293 292 }
294 293 else if ( sid==TM_CODE_K_DUMP )
295 294 {
296 295 spw_send_k_dump( incomingRingNodePtr );
297 296 }
298 297 else
299 298 {
300 299 PRINTF1("unexpected sid = %d\n", sid);
301 300 }
302 301 }
303 302 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
304 303 {
305 304 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
306 305 sid = sidAsUnsignedChar;
307 306 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
308 307 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
309 308 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
310 309 {
311 310 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
312 311 }
313 312
314 313 status = write( fdSPW, incomingData, size );
315 314 if (status == -1){
316 315 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
317 316 }
318 317 }
319 318 else // the incoming message is a spw_ioctl_pkt_send structure
320 319 {
321 320 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
322 321 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
323 322 if (status == -1){
324 323 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
325 324 }
326 325 }
327 326 }
328 327
329 328 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
330 329
331 330 }
332 331 }
333 332
334 333 rtems_task link_task( rtems_task_argument argument )
335 334 {
336 335 rtems_event_set event_out;
337 336 rtems_status_code status;
338 337 int linkStatus;
339 338
340 339 BOOT_PRINTF("in LINK ***\n")
341 340
342 341 while(1)
343 342 {
344 343 // wait for an RTEMS_EVENT
345 344 rtems_event_receive( RTEMS_EVENT_0,
346 345 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
347 346 PRINTF("in LINK *** wait for the link\n")
348 347 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
349 348 while( linkStatus != 5) // wait for the link
350 349 {
351 350 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
352 351 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
353 352 watchdog_reload();
354 353 }
355 354
356 spacewire_save_stats();
355 spacewire_read_statistics();
357 356 status = spacewire_stop_and_start_link( fdSPW );
358 spacewire_restore_stats();
359 357
360 358 if (status != RTEMS_SUCCESSFUL)
361 359 {
362 360 PRINTF1("in LINK *** ERR link not started %d\n", status)
363 361 }
364 362 else
365 363 {
366 364 PRINTF("in LINK *** OK link started\n")
367 365 }
368 366
369 367 // restart the SPIQ task
370 368 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
371 369 if ( status != RTEMS_SUCCESSFUL ) {
372 370 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
373 371 }
374 372
375 373 // restart RECV and SEND
376 374 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
377 375 if ( status != RTEMS_SUCCESSFUL ) {
378 376 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
379 377 }
380 378 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
381 379 if ( status != RTEMS_SUCCESSFUL ) {
382 380 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
383 381 }
384 382 }
385 383 }
386 384
387 385 //****************
388 386 // OTHER FUNCTIONS
389 387 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
390 388 {
391 389 /** This function opens the SpaceWire link.
392 390 *
393 391 * @return a valid file descriptor in case of success, -1 in case of a failure
394 392 *
395 393 */
396 394 rtems_status_code status;
397 395
398 396 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
399 397 if ( fdSPW < 0 ) {
400 398 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
401 399 }
402 400 else
403 401 {
404 402 status = RTEMS_SUCCESSFUL;
405 403 }
406 404
407 405 return status;
408 406 }
409 407
410 408 int spacewire_start_link( int fd )
411 409 {
412 410 rtems_status_code status;
413 411
414 412 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
415 413 // -1 default hardcoded driver timeout
416 414
417 415 return status;
418 416 }
419 417
420 418 int spacewire_stop_and_start_link( int fd )
421 419 {
422 420 rtems_status_code status;
423 421
424 422 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
425 423 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
426 424 // -1 default hardcoded driver timeout
427 425
428 426 return status;
429 427 }
430 428
431 429 int spacewire_configure_link( int fd )
432 430 {
433 431 /** This function configures the SpaceWire link.
434 432 *
435 433 * @return GR-RTEMS-DRIVER directive status codes:
436 434 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
437 435 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
438 436 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
439 437 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
440 438 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
441 439 * - 5 EIO - Error when writing to grswp hardware registers.
442 440 * - 2 ENOENT - No such file or directory
443 441 */
444 442
445 443 rtems_status_code status;
446 444
447 445 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
448 446 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
449 447
450 448 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
451 449 if (status!=RTEMS_SUCCESSFUL) {
452 450 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
453 451 }
454 452 //
455 453 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
456 454 if (status!=RTEMS_SUCCESSFUL) {
457 455 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
458 456 }
459 457 //
460 458 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
461 459 if (status!=RTEMS_SUCCESSFUL) {
462 460 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
463 461 }
464 462 //
465 463 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
466 464 if (status!=RTEMS_SUCCESSFUL) {
467 465 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
468 466 }
469 467 //
470 468 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
471 469 if (status!=RTEMS_SUCCESSFUL) {
472 470 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
473 471 }
474 472 //
475 473 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
476 474 if (status!=RTEMS_SUCCESSFUL) {
477 475 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
478 476 }
479 477 //
480 478 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
481 479 if (status!=RTEMS_SUCCESSFUL) {
482 480 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
483 481 }
484 482
485 483 return status;
486 484 }
487 485
488 486 int spacewire_several_connect_attemps( void )
489 487 {
490 488 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
491 489 *
492 490 * @return RTEMS directive status code:
493 491 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
494 492 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
495 493 *
496 494 */
497 495
498 496 rtems_status_code status_spw;
499 497 rtems_status_code status;
500 498 int i;
501 499
502 500 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
503 501 {
504 502 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
505 503
506 504 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
507 505
508 506 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
509 507
510 508 status_spw = spacewire_stop_and_start_link( fdSPW );
511 509
512 510 if ( status_spw != RTEMS_SUCCESSFUL )
513 511 {
514 512 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
515 513 }
516 514
517 515 if ( status_spw == RTEMS_SUCCESSFUL)
518 516 {
519 517 break;
520 518 }
521 519 }
522 520
523 521 return status_spw;
524 522 }
525 523
526 524 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
527 525 {
528 526 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
529 527 *
530 528 * @param val is the value, 0 or 1, used to set the value of the NP bit.
531 529 * @param regAddr is the address of the GRSPW control register.
532 530 *
533 531 * NP is the bit 20 of the GRSPW control register.
534 532 *
535 533 */
536 534
537 535 unsigned int *spwptr = (unsigned int*) regAddr;
538 536
539 537 if (val == 1) {
540 538 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
541 539 }
542 540 if (val== 0) {
543 541 *spwptr = *spwptr & 0xffdfffff;
544 542 }
545 543 }
546 544
547 545 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
548 546 {
549 547 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
550 548 *
551 549 * @param val is the value, 0 or 1, used to set the value of the RE bit.
552 550 * @param regAddr is the address of the GRSPW control register.
553 551 *
554 552 * RE is the bit 16 of the GRSPW control register.
555 553 *
556 554 */
557 555
558 556 unsigned int *spwptr = (unsigned int*) regAddr;
559 557
560 558 if (val == 1)
561 559 {
562 560 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
563 561 }
564 562 if (val== 0)
565 563 {
566 564 *spwptr = *spwptr & 0xfffdffff;
567 565 }
568 566 }
569 567
570 void spacewire_save_stats( void )
571 {
572 /** This function save the SpaceWire statistics.
573 *
574 * @param void
575 *
576 * @return void
577 *
578 */
579
580 spw_stats spw_current;
581 rtems_status_code status;
582
583 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spw_current );
584
585 // typedef struct {
586 // unsigned int tx_link_err; // NOT IN HK
587 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
588 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
589 // unsigned int rx_eep_err;
590 // unsigned int rx_truncated;
591 // unsigned int parity_err;
592 // unsigned int escape_err;
593 // unsigned int credit_err;
594 // unsigned int write_sync_err;
595 // unsigned int disconnect_err;
596 // unsigned int early_ep;
597 // unsigned int invalid_address;
598 // unsigned int packets_sent;
599 // unsigned int packets_received;
600 // } spw_stats;
601
602 // rx_eep_err
603 spw_backup.rx_eep_err = grspw_stats.rx_eep_err + spw_current.rx_eep_err;
604 // rx_truncated
605 spw_backup.rx_truncated = grspw_stats.rx_truncated + spw_current.rx_truncated;
606 // parity_err
607 spw_backup.parity_err = grspw_stats.parity_err + spw_current.parity_err;
608 // escape_err
609 spw_backup.escape_err = grspw_stats.escape_err + spw_current.escape_err;
610 // credit_err
611 spw_backup.credit_err = grspw_stats.credit_err + spw_current.credit_err;
612 // write_sync_err
613 spw_backup.write_sync_err = grspw_stats.write_sync_err + spw_current.write_sync_err;
614 // disconnect_err
615 spw_backup.disconnect_err = grspw_stats.disconnect_err + spw_current.disconnect_err;
616 // early_ep
617 spw_backup.early_ep = grspw_stats.early_ep + spw_current.early_ep;
618 // invalid_address
619 spw_backup.invalid_address = grspw_stats.invalid_address + spw_current.invalid_address;
620 // packets_sent
621 spw_backup.packets_sent = grspw_stats.packets_sent + spw_current.packets_sent;
622 // packets_received
623 spw_backup.packets_received = grspw_stats.packets_received + spw_current.packets_received;
624
625 }
626
627 void spacewire_restore_stats( void )
628 {
629 /** This function restore the SpaceWire statistics values recorded before a link restart which reset the counters.
630 *
631 * @param void
632 *
633 * @return void
634 *
635 */
636
637 // rx_eep_err
638 grspw_stats.rx_eep_err = spw_backup.rx_eep_err ;
639 // rx_truncated
640 grspw_stats.rx_truncated = spw_backup.rx_truncated;
641 // parity_err
642 grspw_stats.parity_err = spw_backup.parity_err;
643 // escape_err
644 grspw_stats.escape_err = spw_backup.escape_err;
645 // credit_err
646 grspw_stats.credit_err = spw_backup.credit_err;
647 // write_sync_err
648 grspw_stats.write_sync_err = spw_backup.write_sync_err;
649 // disconnect_err
650 grspw_stats.disconnect_err = spw_backup.disconnect_err;
651 // early_ep
652 grspw_stats.early_ep = spw_backup.early_ep;
653 // invalid_address
654 grspw_stats.invalid_address = spw_backup.invalid_address;
655 // packets_sent
656 grspw_stats.packets_sent = spw_backup.packets_sent;
657 // packets_received
658 grspw_stats.packets_received= spw_backup.packets_received;
659
660 }
661
662 void spacewire_update_statistics( void )
568 void spacewire_read_statistics( void )
663 569 {
664 570 rtems_status_code status;
665 spw_stats spw_current;
571 spw_stats current;
666 572
667 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spw_current );
573 // read the current statistics
574 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
575
576 // clear the counters
577 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
668 578
669 579 // typedef struct {
670 580 // unsigned int tx_link_err; // NOT IN HK
671 581 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
672 582 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
673 583 // unsigned int rx_eep_err;
674 584 // unsigned int rx_truncated;
675 585 // unsigned int parity_err;
676 586 // unsigned int escape_err;
677 587 // unsigned int credit_err;
678 588 // unsigned int write_sync_err;
679 589 // unsigned int disconnect_err;
680 590 // unsigned int early_ep;
681 591 // unsigned int invalid_address;
682 592 // unsigned int packets_sent;
683 593 // unsigned int packets_received;
684 594 // } spw_stats;
685 595
686 596 // rx_eep_err
687 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + spw_current.rx_eep_err;
597 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
688 598 // rx_truncated
689 grspw_stats.rx_truncated = grspw_stats.rx_truncated + spw_current.rx_truncated;
599 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
690 600 // parity_err
691 grspw_stats.parity_err = grspw_stats.parity_err + spw_current.parity_err;
601 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
692 602 // escape_err
693 grspw_stats.escape_err = grspw_stats.escape_err + spw_current.escape_err;
603 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
694 604 // credit_err
695 grspw_stats.credit_err = grspw_stats.credit_err + spw_current.credit_err;
605 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
696 606 // write_sync_err
697 grspw_stats.write_sync_err = grspw_stats.write_sync_err + spw_current.write_sync_err;
607 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
698 608 // disconnect_err
699 grspw_stats.disconnect_err = grspw_stats.disconnect_err + spw_current.disconnect_err;
609 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
700 610 // early_ep
701 grspw_stats.early_ep = grspw_stats.early_ep + spw_current.early_ep;
611 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
702 612 // invalid_address
703 grspw_stats.invalid_address = grspw_stats.invalid_address + spw_current.invalid_address;
613 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
704 614 // packets_sent
705 grspw_stats.packets_sent = grspw_stats.packets_sent + spw_current.packets_sent;
615 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
706 616 // packets_received
707 grspw_stats.packets_received= grspw_stats.packets_received + spw_current.packets_received;
617 grspw_stats.packets_received= grspw_stats.packets_received + current.packets_received;
708 618
709 619 }
710 620
711 621 void spacewire_get_last_error( void )
712 622 {
713 623 static spw_stats previous;
714 624 spw_stats current;
715 625 rtems_status_code status;
716 626
717 627 unsigned int hk_lfr_last_er_rid;
718 628 unsigned char hk_lfr_last_er_code;
719 629 int coarseTime;
720 630 int fineTime;
721 631 unsigned char update_hk_lfr_last_er;
722 632
723 633 update_hk_lfr_last_er = 0;
724 634
725 635 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
726 636
727 637 // get current time
728 638 coarseTime = time_management_regs->coarse_time;
729 639 fineTime = time_management_regs->fine_time;
730 640
731 641 // typedef struct {
732 642 // unsigned int tx_link_err; // NOT IN HK
733 643 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
734 644 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
735 645 // unsigned int rx_eep_err;
736 646 // unsigned int rx_truncated;
737 647 // unsigned int parity_err;
738 648 // unsigned int escape_err;
739 649 // unsigned int credit_err;
740 650 // unsigned int write_sync_err;
741 651 // unsigned int disconnect_err;
742 652 // unsigned int early_ep;
743 653 // unsigned int invalid_address;
744 654 // unsigned int packets_sent;
745 655 // unsigned int packets_received;
746 656 // } spw_stats;
747 657
748 658 // tx_link_err *** no code associated to this field
749 659 // rx_rmap_header_crc_err *** LE *** in HK
750 660 if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
751 661 {
752 662 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
753 663 hk_lfr_last_er_code = CODE_HEADER_CRC;
754 664 update_hk_lfr_last_er = 1;
755 665 }
756 666 // rx_rmap_data_crc_err *** LE *** NOT IN HK
757 667 if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
758 668 {
759 669 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
760 670 hk_lfr_last_er_code = CODE_DATA_CRC;
761 671 update_hk_lfr_last_er = 1;
762 672 }
763 673 // rx_eep_err
764 674 if (previous.rx_eep_err != current.rx_eep_err)
765 675 {
766 676 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
767 677 hk_lfr_last_er_code = CODE_EEP;
768 678 update_hk_lfr_last_er = 1;
769 679 }
770 680 // rx_truncated
771 681 if (previous.rx_truncated != current.rx_truncated)
772 682 {
773 683 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
774 684 hk_lfr_last_er_code = CODE_RX_TOO_BIG;
775 685 update_hk_lfr_last_er = 1;
776 686 }
777 687 // parity_err
778 688 if (previous.parity_err != current.parity_err)
779 689 {
780 690 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
781 691 hk_lfr_last_er_code = CODE_PARITY;
782 692 update_hk_lfr_last_er = 1;
783 693 }
784 694 // escape_err
785 695 if (previous.parity_err != current.parity_err)
786 696 {
787 697 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
788 698 hk_lfr_last_er_code = CODE_ESCAPE;
789 699 update_hk_lfr_last_er = 1;
790 700 }
791 701 // credit_err
792 702 if (previous.credit_err != current.credit_err)
793 703 {
794 704 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
795 705 hk_lfr_last_er_code = CODE_CREDIT;
796 706 update_hk_lfr_last_er = 1;
797 707 }
798 708 // write_sync_err
799 709 if (previous.write_sync_err != current.write_sync_err)
800 710 {
801 711 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
802 712 hk_lfr_last_er_code = CODE_WRITE_SYNC;
803 713 update_hk_lfr_last_er = 1;
804 714 }
805 715 // disconnect_err
806 716 if (previous.disconnect_err != current.disconnect_err)
807 717 {
808 718 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
809 719 hk_lfr_last_er_code = CODE_DISCONNECT;
810 720 update_hk_lfr_last_er = 1;
811 721 }
812 722 // early_ep
813 723 if (previous.early_ep != current.early_ep)
814 724 {
815 725 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
816 726 hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
817 727 update_hk_lfr_last_er = 1;
818 728 }
819 729 // invalid_address
820 730 if (previous.invalid_address != current.invalid_address)
821 731 {
822 732 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
823 733 hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
824 734 update_hk_lfr_last_er = 1;
825 735 }
826 736
827 737 // if a field has changed, update the hk_last_er fields
828 738 if (update_hk_lfr_last_er == 1)
829 739 {
830 740 update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
831 741 }
832 742
833 743 previous = current;
834 744 }
835 745
836 746 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
837 747 {
838 748 unsigned char *coarseTimePtr;
839 749 unsigned char *fineTimePtr;
840 750
841 751 coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
842 752 fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
843 753
844 754 housekeeping_packet.hk_lfr_last_er_rid[0] = (unsigned char) ((rid & 0xff00) >> 8 );
845 755 housekeeping_packet.hk_lfr_last_er_rid[1] = (unsigned char) (rid & 0x00ff);
846 756 housekeeping_packet.hk_lfr_last_er_code = code;
847 757 housekeeping_packet.hk_lfr_last_er_time[0] = coarseTimePtr[0];
848 758 housekeeping_packet.hk_lfr_last_er_time[1] = coarseTimePtr[1];
849 759 housekeeping_packet.hk_lfr_last_er_time[2] = coarseTimePtr[2];
850 760 housekeeping_packet.hk_lfr_last_er_time[3] = coarseTimePtr[3];
851 761 housekeeping_packet.hk_lfr_last_er_time[4] = fineTimePtr[2];
852 762 housekeeping_packet.hk_lfr_last_er_time[5] = fineTimePtr[3];
853 763 }
854 764
855 void update_hk_with_grspw_stats( spw_stats stats )
765 void update_hk_with_grspw_stats( void )
856 766 {
857 767 //****************************
858 768 // DPU_SPACEWIRE_IF_STATISTICS
859 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (stats.packets_received >> 8);
860 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (stats.packets_received);
861 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (stats.packets_sent >> 8);
862 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (stats.packets_sent);
769 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (grspw_stats.packets_received >> 8);
770 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (grspw_stats.packets_received);
771 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (grspw_stats.packets_sent >> 8);
772 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (grspw_stats.packets_sent);
863 773
864 774 //******************************************
865 775 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
866 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) stats.parity_err;
867 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) stats.disconnect_err;
868 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) stats.escape_err;
869 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) stats.credit_err;
870 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) stats.write_sync_err;
776 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) grspw_stats.parity_err;
777 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) grspw_stats.disconnect_err;
778 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) grspw_stats.escape_err;
779 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) grspw_stats.credit_err;
780 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) grspw_stats.write_sync_err;
871 781
872 782 //*********************************************
873 783 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
874 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) stats.early_ep;
875 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) stats.invalid_address;
876 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) stats.rx_eep_err;
877 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) stats.rx_truncated;
784 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) grspw_stats.early_ep;
785 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) grspw_stats.invalid_address;
786 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) grspw_stats.rx_eep_err;
787 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) grspw_stats.rx_truncated;
878 788 }
879 789
880 790 void increase_unsigned_char_counter( unsigned char *counter )
881 791 {
882 792 // update the number of valid timecodes that have been received
883 793 if (*counter == 255)
884 794 {
885 795 *counter = 0;
886 796 }
887 797 else
888 798 {
889 799 *counter = *counter + 1;
890 800 }
891 801 }
892 802
893 803 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
894 804 {
895 805 static unsigned char initStep = 1;
896 806
897 807 unsigned char currentTimecodeCtr;
898 808
899 809 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
900 810
901 811 if (initStep == 1)
902 812 {
903 813 if (currentTimecodeCtr == previousTimecodeCtr)
904 814 {
905 815 //************************
906 816 // HK_LFR_TIMECODE_MISSING
907 817 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
908 818 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
909 819 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
910 820 }
911 821 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
912 822 {
913 823 // the timecode value has changed and the value is valid, this is unexpected because
914 824 // the timer should not have fired, the timecode_irq_handler should have been raised
915 825 }
916 826 else
917 827 {
918 828 //************************
919 829 // HK_LFR_TIMECODE_INVALID
920 830 // the timecode value has changed and the value is not valid, no tickout has been generated
921 831 // this is why the timer has fired
922 832 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
923 833 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_INVALID );
924 834 }
925 835 }
926 836 else
927 837 {
928 838 initStep = 1;
929 839 //************************
930 840 // HK_LFR_TIMECODE_MISSING
931 841 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
932 842 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
933 843 }
934 844
935 845 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
936 846 }
937 847
938 848 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
939 849 {
940 850 /** This function checks the coherency between the incoming timecode and the last valid timecode.
941 851 *
942 852 * @param currentTimecodeCtr is the incoming timecode
943 853 *
944 854 * @return returned codes::
945 855 * - LFR_DEFAULT
946 856 * - LFR_SUCCESSFUL
947 857 *
948 858 */
949 859
950 860 static unsigned char firstTickout = 1;
951 861 unsigned char ret;
952 862
953 863 ret = LFR_DEFAULT;
954 864
955 865 if (firstTickout == 0)
956 866 {
957 867 if (currentTimecodeCtr == 0)
958 868 {
959 869 if (previousTimecodeCtr == 63)
960 870 {
961 871 ret = LFR_SUCCESSFUL;
962 872 }
963 873 else
964 874 {
965 875 ret = LFR_DEFAULT;
966 876 }
967 877 }
968 878 else
969 879 {
970 880 if (currentTimecodeCtr == (previousTimecodeCtr +1))
971 881 {
972 882 ret = LFR_SUCCESSFUL;
973 883 }
974 884 else
975 885 {
976 886 ret = LFR_DEFAULT;
977 887 }
978 888 }
979 889 }
980 890 else
981 891 {
982 892 firstTickout = 0;
983 893 ret = LFR_SUCCESSFUL;
984 894 }
985 895
986 896 return ret;
987 897 }
988 898
989 899 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
990 900 {
991 901 unsigned int ret;
992 902
993 903 ret = LFR_DEFAULT;
994 904
995 905 if (timecode == internalTime)
996 906 {
997 907 ret = LFR_SUCCESSFUL;
998 908 }
999 909 else
1000 910 {
1001 911 ret = LFR_DEFAULT;
1002 912 }
1003 913
1004 914 return ret;
1005 915 }
1006 916
1007 917 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
1008 918 {
1009 919 // a tickout has been emitted, perform actions on the incoming timecode
1010 920
1011 921 unsigned char incomingTimecode;
1012 922 unsigned char updateTime;
1013 923 unsigned char internalTime;
1014 924 rtems_status_code status;
1015 925
1016 926 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
1017 927 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
1018 928 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
1019 929
1020 930 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
1021 931
1022 932 // update the number of tickout that have been generated
1023 933 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
1024 934
1025 935 //**************************
1026 936 // HK_LFR_TIMECODE_ERRONEOUS
1027 937 // MISSING and INVALID are handled by the timecode_timer_routine service routine
1028 938 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
1029 939 {
1030 940 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
1031 941 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
1032 942 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_ERRONEOUS );
1033 943 }
1034 944
1035 945 //************************
1036 946 // HK_LFR_TIME_TIMECODE_IT
1037 947 // check the coherency between the SpaceWire timecode and the Internal Time
1038 948 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
1039 949 {
1040 950 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
1041 951 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_IT );
1042 952 }
1043 953
1044 954 //********************
1045 955 // HK_LFR_TIMECODE_CTR
1046 956 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
1047 957 if (incomingTimecode != updateTime)
1048 958 {
1049 959 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
1050 960 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_CTR );
1051 961 }
1052 962
1053 963 // launch the timecode timer to detect missing or invalid timecodes
1054 964 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
1055 965 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
1056 966 if (status != RTEMS_SUCCESSFUL)
1057 967 {
1058 968 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
1059 969 }
1060 970 }
1061 971
1062 972 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
1063 973 {
1064 974 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1065 975 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1066 976 header->reserved = DEFAULT_RESERVED;
1067 977 header->userApplication = CCSDS_USER_APP;
1068 978 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
1069 979 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
1070 980 header->packetLength[0] = 0x00;
1071 981 header->packetLength[1] = 0x00;
1072 982 // DATA FIELD HEADER
1073 983 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1074 984 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1075 985 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1076 986 header->destinationID = TM_DESTINATION_ID_GROUND;
1077 987 header->time[0] = 0x00;
1078 988 header->time[0] = 0x00;
1079 989 header->time[0] = 0x00;
1080 990 header->time[0] = 0x00;
1081 991 header->time[0] = 0x00;
1082 992 header->time[0] = 0x00;
1083 993 // AUXILIARY DATA HEADER
1084 994 header->sid = 0x00;
1085 995 header->hkBIA = DEFAULT_HKBIA;
1086 996 header->blkNr[0] = 0x00;
1087 997 header->blkNr[1] = 0x00;
1088 998 }
1089 999
1090 1000 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
1091 1001 {
1092 1002 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1093 1003 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1094 1004 header->reserved = DEFAULT_RESERVED;
1095 1005 header->userApplication = CCSDS_USER_APP;
1096 1006 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1097 1007 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1098 1008 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1099 1009 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1100 1010 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1101 1011 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1102 1012 // DATA FIELD HEADER
1103 1013 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1104 1014 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1105 1015 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1106 1016 header->destinationID = TM_DESTINATION_ID_GROUND;
1107 1017 header->time[0] = 0x00;
1108 1018 header->time[0] = 0x00;
1109 1019 header->time[0] = 0x00;
1110 1020 header->time[0] = 0x00;
1111 1021 header->time[0] = 0x00;
1112 1022 header->time[0] = 0x00;
1113 1023 // AUXILIARY DATA HEADER
1114 1024 header->sid = 0x00;
1115 1025 header->hkBIA = DEFAULT_HKBIA;
1116 1026 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
1117 1027 header->pktNr = 0x00;
1118 1028 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1119 1029 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1120 1030 }
1121 1031
1122 1032 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
1123 1033 {
1124 1034 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1125 1035 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1126 1036 header->reserved = DEFAULT_RESERVED;
1127 1037 header->userApplication = CCSDS_USER_APP;
1128 1038 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1129 1039 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1130 1040 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1131 1041 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1132 1042 header->packetLength[0] = 0x00;
1133 1043 header->packetLength[1] = 0x00;
1134 1044 // DATA FIELD HEADER
1135 1045 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1136 1046 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1137 1047 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
1138 1048 header->destinationID = TM_DESTINATION_ID_GROUND;
1139 1049 header->time[0] = 0x00;
1140 1050 header->time[0] = 0x00;
1141 1051 header->time[0] = 0x00;
1142 1052 header->time[0] = 0x00;
1143 1053 header->time[0] = 0x00;
1144 1054 header->time[0] = 0x00;
1145 1055 // AUXILIARY DATA HEADER
1146 1056 header->sid = 0x00;
1147 1057 header->biaStatusInfo = 0x00;
1148 1058 header->pa_lfr_pkt_cnt_asm = 0x00;
1149 1059 header->pa_lfr_pkt_nr_asm = 0x00;
1150 1060 header->pa_lfr_asm_blk_nr[0] = 0x00;
1151 1061 header->pa_lfr_asm_blk_nr[1] = 0x00;
1152 1062 }
1153 1063
1154 1064 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
1155 1065 Header_TM_LFR_SCIENCE_CWF_t *header )
1156 1066 {
1157 1067 /** This function sends CWF CCSDS packets (F2, F1 or F0).
1158 1068 *
1159 1069 * @param waveform points to the buffer containing the data that will be send.
1160 1070 * @param sid is the source identifier of the data that will be sent.
1161 1071 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1162 1072 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1163 1073 * contain information to setup the transmission of the data packets.
1164 1074 *
1165 1075 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1166 1076 *
1167 1077 */
1168 1078
1169 1079 unsigned int i;
1170 1080 int ret;
1171 1081 unsigned int coarseTime;
1172 1082 unsigned int fineTime;
1173 1083 rtems_status_code status;
1174 1084 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1175 1085 int *dataPtr;
1176 1086 unsigned char sid;
1177 1087
1178 1088 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1179 1089 spw_ioctl_send_CWF.options = 0;
1180 1090
1181 1091 ret = LFR_DEFAULT;
1182 1092 sid = (unsigned char) ring_node_to_send->sid;
1183 1093
1184 1094 coarseTime = ring_node_to_send->coarseTime;
1185 1095 fineTime = ring_node_to_send->fineTime;
1186 1096 dataPtr = (int*) ring_node_to_send->buffer_address;
1187 1097
1188 1098 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1189 1099 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1190 1100 header->hkBIA = pa_bia_status_info;
1191 1101 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1192 1102 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1193 1103 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1194 1104
1195 1105 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
1196 1106 {
1197 1107 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
1198 1108 spw_ioctl_send_CWF.hdr = (char*) header;
1199 1109 // BUILD THE DATA
1200 1110 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
1201 1111
1202 1112 // SET PACKET SEQUENCE CONTROL
1203 1113 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1204 1114
1205 1115 // SET SID
1206 1116 header->sid = sid;
1207 1117
1208 1118 // SET PACKET TIME
1209 1119 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
1210 1120 //
1211 1121 header->time[0] = header->acquisitionTime[0];
1212 1122 header->time[1] = header->acquisitionTime[1];
1213 1123 header->time[2] = header->acquisitionTime[2];
1214 1124 header->time[3] = header->acquisitionTime[3];
1215 1125 header->time[4] = header->acquisitionTime[4];
1216 1126 header->time[5] = header->acquisitionTime[5];
1217 1127
1218 1128 // SET PACKET ID
1219 1129 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
1220 1130 {
1221 1131 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
1222 1132 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
1223 1133 }
1224 1134 else
1225 1135 {
1226 1136 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1227 1137 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1228 1138 }
1229 1139
1230 1140 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1231 1141 if (status != RTEMS_SUCCESSFUL) {
1232 1142 ret = LFR_DEFAULT;
1233 1143 }
1234 1144 }
1235 1145
1236 1146 return ret;
1237 1147 }
1238 1148
1239 1149 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1240 1150 Header_TM_LFR_SCIENCE_SWF_t *header )
1241 1151 {
1242 1152 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1243 1153 *
1244 1154 * @param waveform points to the buffer containing the data that will be send.
1245 1155 * @param sid is the source identifier of the data that will be sent.
1246 1156 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1247 1157 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1248 1158 * contain information to setup the transmission of the data packets.
1249 1159 *
1250 1160 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1251 1161 *
1252 1162 */
1253 1163
1254 1164 unsigned int i;
1255 1165 int ret;
1256 1166 unsigned int coarseTime;
1257 1167 unsigned int fineTime;
1258 1168 rtems_status_code status;
1259 1169 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1260 1170 int *dataPtr;
1261 1171 unsigned char sid;
1262 1172
1263 1173 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1264 1174 spw_ioctl_send_SWF.options = 0;
1265 1175
1266 1176 ret = LFR_DEFAULT;
1267 1177
1268 1178 coarseTime = ring_node_to_send->coarseTime;
1269 1179 fineTime = ring_node_to_send->fineTime;
1270 1180 dataPtr = (int*) ring_node_to_send->buffer_address;
1271 1181 sid = ring_node_to_send->sid;
1272 1182
1273 1183 header->hkBIA = pa_bia_status_info;
1274 1184 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1275 1185
1276 1186 for (i=0; i<7; i++) // send waveform
1277 1187 {
1278 1188 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1279 1189 spw_ioctl_send_SWF.hdr = (char*) header;
1280 1190
1281 1191 // SET PACKET SEQUENCE CONTROL
1282 1192 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1283 1193
1284 1194 // SET PACKET LENGTH AND BLKNR
1285 1195 if (i == 6)
1286 1196 {
1287 1197 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1288 1198 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
1289 1199 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1290 1200 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
1291 1201 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1292 1202 }
1293 1203 else
1294 1204 {
1295 1205 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1296 1206 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
1297 1207 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1298 1208 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
1299 1209 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1300 1210 }
1301 1211
1302 1212 // SET PACKET TIME
1303 1213 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1304 1214 //
1305 1215 header->time[0] = header->acquisitionTime[0];
1306 1216 header->time[1] = header->acquisitionTime[1];
1307 1217 header->time[2] = header->acquisitionTime[2];
1308 1218 header->time[3] = header->acquisitionTime[3];
1309 1219 header->time[4] = header->acquisitionTime[4];
1310 1220 header->time[5] = header->acquisitionTime[5];
1311 1221
1312 1222 // SET SID
1313 1223 header->sid = sid;
1314 1224
1315 1225 // SET PKTNR
1316 1226 header->pktNr = i+1; // PKT_NR
1317 1227
1318 1228 // SEND PACKET
1319 1229 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1320 1230 if (status != RTEMS_SUCCESSFUL) {
1321 1231 ret = LFR_DEFAULT;
1322 1232 }
1323 1233 }
1324 1234
1325 1235 return ret;
1326 1236 }
1327 1237
1328 1238 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1329 1239 Header_TM_LFR_SCIENCE_CWF_t *header )
1330 1240 {
1331 1241 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1332 1242 *
1333 1243 * @param waveform points to the buffer containing the data that will be send.
1334 1244 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1335 1245 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1336 1246 * contain information to setup the transmission of the data packets.
1337 1247 *
1338 1248 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1339 1249 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1340 1250 *
1341 1251 */
1342 1252
1343 1253 unsigned int i;
1344 1254 int ret;
1345 1255 unsigned int coarseTime;
1346 1256 unsigned int fineTime;
1347 1257 rtems_status_code status;
1348 1258 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1349 1259 char *dataPtr;
1350 1260 unsigned char sid;
1351 1261
1352 1262 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1353 1263 spw_ioctl_send_CWF.options = 0;
1354 1264
1355 1265 ret = LFR_DEFAULT;
1356 1266 sid = ring_node_to_send->sid;
1357 1267
1358 1268 coarseTime = ring_node_to_send->coarseTime;
1359 1269 fineTime = ring_node_to_send->fineTime;
1360 1270 dataPtr = (char*) ring_node_to_send->buffer_address;
1361 1271
1362 1272 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
1363 1273 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1364 1274 header->hkBIA = pa_bia_status_info;
1365 1275 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1366 1276 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1367 1277 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1368 1278
1369 1279 //*********************
1370 1280 // SEND CWF3_light DATA
1371 1281 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1372 1282 {
1373 1283 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1374 1284 spw_ioctl_send_CWF.hdr = (char*) header;
1375 1285 // BUILD THE DATA
1376 1286 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1377 1287
1378 1288 // SET PACKET SEQUENCE COUNTER
1379 1289 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1380 1290
1381 1291 // SET SID
1382 1292 header->sid = sid;
1383 1293
1384 1294 // SET PACKET TIME
1385 1295 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1386 1296 //
1387 1297 header->time[0] = header->acquisitionTime[0];
1388 1298 header->time[1] = header->acquisitionTime[1];
1389 1299 header->time[2] = header->acquisitionTime[2];
1390 1300 header->time[3] = header->acquisitionTime[3];
1391 1301 header->time[4] = header->acquisitionTime[4];
1392 1302 header->time[5] = header->acquisitionTime[5];
1393 1303
1394 1304 // SET PACKET ID
1395 1305 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1396 1306 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1397 1307
1398 1308 // SEND PACKET
1399 1309 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1400 1310 if (status != RTEMS_SUCCESSFUL) {
1401 1311 ret = LFR_DEFAULT;
1402 1312 }
1403 1313 }
1404 1314
1405 1315 return ret;
1406 1316 }
1407 1317
1408 1318 void spw_send_asm_f0( ring_node *ring_node_to_send,
1409 1319 Header_TM_LFR_SCIENCE_ASM_t *header )
1410 1320 {
1411 1321 unsigned int i;
1412 1322 unsigned int length = 0;
1413 1323 rtems_status_code status;
1414 1324 unsigned int sid;
1415 1325 float *spectral_matrix;
1416 1326 int coarseTime;
1417 1327 int fineTime;
1418 1328 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1419 1329
1420 1330 sid = ring_node_to_send->sid;
1421 1331 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1422 1332 coarseTime = ring_node_to_send->coarseTime;
1423 1333 fineTime = ring_node_to_send->fineTime;
1424 1334
1425 1335 header->biaStatusInfo = pa_bia_status_info;
1426 1336 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1427 1337
1428 1338 for (i=0; i<3; i++)
1429 1339 {
1430 1340 if ((i==0) || (i==1))
1431 1341 {
1432 1342 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1433 1343 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1434 1344 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1435 1345 ];
1436 1346 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1437 1347 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1438 1348 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1439 1349 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1440 1350 }
1441 1351 else
1442 1352 {
1443 1353 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1444 1354 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1445 1355 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1446 1356 ];
1447 1357 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1448 1358 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1449 1359 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1450 1360 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1451 1361 }
1452 1362
1453 1363 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1454 1364 spw_ioctl_send_ASM.hdr = (char *) header;
1455 1365 spw_ioctl_send_ASM.options = 0;
1456 1366
1457 1367 // (2) BUILD THE HEADER
1458 1368 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1459 1369 header->packetLength[0] = (unsigned char) (length>>8);
1460 1370 header->packetLength[1] = (unsigned char) (length);
1461 1371 header->sid = (unsigned char) sid; // SID
1462 1372 header->pa_lfr_pkt_cnt_asm = 3;
1463 1373 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1464 1374
1465 1375 // (3) SET PACKET TIME
1466 1376 header->time[0] = (unsigned char) (coarseTime>>24);
1467 1377 header->time[1] = (unsigned char) (coarseTime>>16);
1468 1378 header->time[2] = (unsigned char) (coarseTime>>8);
1469 1379 header->time[3] = (unsigned char) (coarseTime);
1470 1380 header->time[4] = (unsigned char) (fineTime>>8);
1471 1381 header->time[5] = (unsigned char) (fineTime);
1472 1382 //
1473 1383 header->acquisitionTime[0] = header->time[0];
1474 1384 header->acquisitionTime[1] = header->time[1];
1475 1385 header->acquisitionTime[2] = header->time[2];
1476 1386 header->acquisitionTime[3] = header->time[3];
1477 1387 header->acquisitionTime[4] = header->time[4];
1478 1388 header->acquisitionTime[5] = header->time[5];
1479 1389
1480 1390 // (4) SEND PACKET
1481 1391 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1482 1392 if (status != RTEMS_SUCCESSFUL) {
1483 1393 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1484 1394 }
1485 1395 }
1486 1396 }
1487 1397
1488 1398 void spw_send_asm_f1( ring_node *ring_node_to_send,
1489 1399 Header_TM_LFR_SCIENCE_ASM_t *header )
1490 1400 {
1491 1401 unsigned int i;
1492 1402 unsigned int length = 0;
1493 1403 rtems_status_code status;
1494 1404 unsigned int sid;
1495 1405 float *spectral_matrix;
1496 1406 int coarseTime;
1497 1407 int fineTime;
1498 1408 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1499 1409
1500 1410 sid = ring_node_to_send->sid;
1501 1411 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1502 1412 coarseTime = ring_node_to_send->coarseTime;
1503 1413 fineTime = ring_node_to_send->fineTime;
1504 1414
1505 1415 header->biaStatusInfo = pa_bia_status_info;
1506 1416 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1507 1417
1508 1418 for (i=0; i<3; i++)
1509 1419 {
1510 1420 if ((i==0) || (i==1))
1511 1421 {
1512 1422 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1513 1423 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1514 1424 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1515 1425 ];
1516 1426 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1517 1427 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1518 1428 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1519 1429 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1520 1430 }
1521 1431 else
1522 1432 {
1523 1433 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1524 1434 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1525 1435 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1526 1436 ];
1527 1437 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1528 1438 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1529 1439 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1530 1440 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1531 1441 }
1532 1442
1533 1443 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1534 1444 spw_ioctl_send_ASM.hdr = (char *) header;
1535 1445 spw_ioctl_send_ASM.options = 0;
1536 1446
1537 1447 // (2) BUILD THE HEADER
1538 1448 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1539 1449 header->packetLength[0] = (unsigned char) (length>>8);
1540 1450 header->packetLength[1] = (unsigned char) (length);
1541 1451 header->sid = (unsigned char) sid; // SID
1542 1452 header->pa_lfr_pkt_cnt_asm = 3;
1543 1453 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1544 1454
1545 1455 // (3) SET PACKET TIME
1546 1456 header->time[0] = (unsigned char) (coarseTime>>24);
1547 1457 header->time[1] = (unsigned char) (coarseTime>>16);
1548 1458 header->time[2] = (unsigned char) (coarseTime>>8);
1549 1459 header->time[3] = (unsigned char) (coarseTime);
1550 1460 header->time[4] = (unsigned char) (fineTime>>8);
1551 1461 header->time[5] = (unsigned char) (fineTime);
1552 1462 //
1553 1463 header->acquisitionTime[0] = header->time[0];
1554 1464 header->acquisitionTime[1] = header->time[1];
1555 1465 header->acquisitionTime[2] = header->time[2];
1556 1466 header->acquisitionTime[3] = header->time[3];
1557 1467 header->acquisitionTime[4] = header->time[4];
1558 1468 header->acquisitionTime[5] = header->time[5];
1559 1469
1560 1470 // (4) SEND PACKET
1561 1471 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1562 1472 if (status != RTEMS_SUCCESSFUL) {
1563 1473 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1564 1474 }
1565 1475 }
1566 1476 }
1567 1477
1568 1478 void spw_send_asm_f2( ring_node *ring_node_to_send,
1569 1479 Header_TM_LFR_SCIENCE_ASM_t *header )
1570 1480 {
1571 1481 unsigned int i;
1572 1482 unsigned int length = 0;
1573 1483 rtems_status_code status;
1574 1484 unsigned int sid;
1575 1485 float *spectral_matrix;
1576 1486 int coarseTime;
1577 1487 int fineTime;
1578 1488 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1579 1489
1580 1490 sid = ring_node_to_send->sid;
1581 1491 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1582 1492 coarseTime = ring_node_to_send->coarseTime;
1583 1493 fineTime = ring_node_to_send->fineTime;
1584 1494
1585 1495 header->biaStatusInfo = pa_bia_status_info;
1586 1496 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1587 1497
1588 1498 for (i=0; i<3; i++)
1589 1499 {
1590 1500
1591 1501 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1592 1502 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1593 1503 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1594 1504 ];
1595 1505 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1596 1506 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1597 1507 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1598 1508 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1599 1509
1600 1510 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1601 1511 spw_ioctl_send_ASM.hdr = (char *) header;
1602 1512 spw_ioctl_send_ASM.options = 0;
1603 1513
1604 1514 // (2) BUILD THE HEADER
1605 1515 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1606 1516 header->packetLength[0] = (unsigned char) (length>>8);
1607 1517 header->packetLength[1] = (unsigned char) (length);
1608 1518 header->sid = (unsigned char) sid; // SID
1609 1519 header->pa_lfr_pkt_cnt_asm = 3;
1610 1520 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1611 1521
1612 1522 // (3) SET PACKET TIME
1613 1523 header->time[0] = (unsigned char) (coarseTime>>24);
1614 1524 header->time[1] = (unsigned char) (coarseTime>>16);
1615 1525 header->time[2] = (unsigned char) (coarseTime>>8);
1616 1526 header->time[3] = (unsigned char) (coarseTime);
1617 1527 header->time[4] = (unsigned char) (fineTime>>8);
1618 1528 header->time[5] = (unsigned char) (fineTime);
1619 1529 //
1620 1530 header->acquisitionTime[0] = header->time[0];
1621 1531 header->acquisitionTime[1] = header->time[1];
1622 1532 header->acquisitionTime[2] = header->time[2];
1623 1533 header->acquisitionTime[3] = header->time[3];
1624 1534 header->acquisitionTime[4] = header->time[4];
1625 1535 header->acquisitionTime[5] = header->time[5];
1626 1536
1627 1537 // (4) SEND PACKET
1628 1538 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1629 1539 if (status != RTEMS_SUCCESSFUL) {
1630 1540 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1631 1541 }
1632 1542 }
1633 1543 }
1634 1544
1635 1545 void spw_send_k_dump( ring_node *ring_node_to_send )
1636 1546 {
1637 1547 rtems_status_code status;
1638 1548 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1639 1549 unsigned int packetLength;
1640 1550 unsigned int size;
1641 1551
1642 1552 PRINTF("spw_send_k_dump\n")
1643 1553
1644 1554 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1645 1555
1646 1556 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1647 1557
1648 1558 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1649 1559
1650 1560 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1651 1561
1652 1562 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1653 1563
1654 1564 if (status == -1){
1655 1565 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1656 1566 }
1657 1567
1658 1568 ring_node_to_send->status = 0x00;
1659 1569 }
General Comments 0
You need to be logged in to leave comments. Login now