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