##// END OF EJS Templates
spacewire statistics management modified...
paul -
r264:2120c4473911 R3a
parent child
Show More
@@ -1,59 +1,57
1 1 #ifndef FSW_SPACEWIRE_H_INCLUDED
2 2 #define FSW_SPACEWIRE_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6
7 7 #include <fcntl.h> // for O_RDWR
8 8 #include <unistd.h> // for the read call
9 9 #include <sys/ioctl.h> // for the ioctl call
10 10 #include <errno.h>
11 11
12 12 #include "fsw_params.h"
13 13 #include "tc_handler.h"
14 14 #include "fsw_init.h"
15 15
16 16 extern spw_stats grspw_stats;
17 17 extern spw_stats spw_backup;
18 18 extern rtems_name timecode_timer_name;
19 19 extern rtems_id timecode_timer_id;
20 20
21 21 // RTEMS TASK
22 22 rtems_task spiq_task( rtems_task_argument argument );
23 23 rtems_task recv_task( rtems_task_argument unused );
24 24 rtems_task send_task( rtems_task_argument argument );
25 25 rtems_task link_task( rtems_task_argument argument );
26 26
27 27 int spacewire_open_link( void );
28 28 int spacewire_start_link( int fd );
29 29 int spacewire_stop_and_start_link( int fd );
30 30 int spacewire_configure_link(int fd );
31 31 int spacewire_several_connect_attemps( void );
32 32 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
33 33 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
34 void spacewire_save_stats( void );
35 void spacewire_restore_stats( void );
36 void spacewire_update_statistics( void );
34 void spacewire_read_statistics( void );
37 35 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code);
38 void update_hk_with_grspw_stats( spw_stats stats );
36 void update_hk_with_grspw_stats(void );
39 37 void increase_unsigned_char_counter( unsigned char *counter );
40 38
41 39 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
42 40 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
43 41 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
44 42 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
45 43 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
46 44 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
47 45 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
48 46 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
49 47 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
50 48 void spw_send_k_dump( ring_node *ring_node_to_send );
51 49
52 50 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
53 51 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
54 52 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
55 53 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
56 54
57 55 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
58 56
59 57 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,804 +1,804
1 1 /** General usage functions and RTEMS tasks.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 */
7 7
8 8 #include "fsw_misc.h"
9 9
10 10 void timer_configure(unsigned char timer, unsigned int clock_divider,
11 11 unsigned char interrupt_level, rtems_isr (*timer_isr)() )
12 12 {
13 13 /** This function configures a GPTIMER timer instantiated in the VHDL design.
14 14 *
15 15 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
16 16 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
17 17 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
18 18 * @param interrupt_level is the interrupt level that the timer drives.
19 19 * @param timer_isr is the interrupt subroutine that will be attached to the IRQ driven by the timer.
20 20 *
21 21 * Interrupt levels are described in the SPARC documentation sparcv8.pdf p.76
22 22 *
23 23 */
24 24
25 25 rtems_status_code status;
26 26 rtems_isr_entry old_isr_handler;
27 27
28 28 gptimer_regs->timer[timer].ctrl = 0x00; // reset the control register
29 29
30 30 status = rtems_interrupt_catch( timer_isr, interrupt_level, &old_isr_handler) ; // see sparcv8.pdf p.76 for interrupt levels
31 31 if (status!=RTEMS_SUCCESSFUL)
32 32 {
33 33 PRINTF("in configure_timer *** ERR rtems_interrupt_catch\n")
34 34 }
35 35
36 36 timer_set_clock_divider( timer, clock_divider);
37 37 }
38 38
39 39 void timer_start(unsigned char timer)
40 40 {
41 41 /** This function starts a GPTIMER timer.
42 42 *
43 43 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
44 44 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
45 45 *
46 46 */
47 47
48 48 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
49 49 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000004; // LD load value from the reload register
50 50 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000001; // EN enable the timer
51 51 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000002; // RS restart
52 52 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000008; // IE interrupt enable
53 53 }
54 54
55 55 void timer_stop(unsigned char timer)
56 56 {
57 57 /** This function stops a GPTIMER timer.
58 58 *
59 59 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
60 60 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
61 61 *
62 62 */
63 63
64 64 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xfffffffe; // EN enable the timer
65 65 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xffffffef; // IE interrupt enable
66 66 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
67 67 }
68 68
69 69 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider)
70 70 {
71 71 /** This function sets the clock divider of a GPTIMER timer.
72 72 *
73 73 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
74 74 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
75 75 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
76 76 *
77 77 */
78 78
79 79 gptimer_regs->timer[timer].reload = clock_divider; // base clock frequency is 1 MHz
80 80 }
81 81
82 82 // WATCHDOG
83 83
84 84 rtems_isr watchdog_isr( rtems_vector_number vector )
85 85 {
86 86 rtems_status_code status_code;
87 87
88 88 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_12 );
89 89
90 90 PRINTF("watchdog_isr *** this is the end, exit(0)\n");
91 91
92 92 exit(0);
93 93 }
94 94
95 95 void watchdog_configure(void)
96 96 {
97 97 /** This function configure the watchdog.
98 98 *
99 99 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
100 100 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
101 101 *
102 102 * The watchdog is a timer provided by the GPTIMER IP core of the GRLIB.
103 103 *
104 104 */
105 105
106 106 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt during configuration
107 107
108 108 timer_configure( TIMER_WATCHDOG, CLKDIV_WATCHDOG, IRQ_SPARC_GPTIMER_WATCHDOG, watchdog_isr );
109 109
110 110 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
111 111 }
112 112
113 113 void watchdog_stop(void)
114 114 {
115 115 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt line
116 116 timer_stop( TIMER_WATCHDOG );
117 117 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
118 118 }
119 119
120 120 void watchdog_reload(void)
121 121 {
122 122 /** This function reloads the watchdog timer counter with the timer reload value.
123 123 *
124 124 * @param void
125 125 *
126 126 * @return void
127 127 *
128 128 */
129 129
130 130 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
131 131 }
132 132
133 133 void watchdog_start(void)
134 134 {
135 135 /** This function starts the watchdog timer.
136 136 *
137 137 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
138 138 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
139 139 *
140 140 */
141 141
142 142 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
143 143
144 144 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000010; // clear pending IRQ if any
145 145 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
146 146 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000001; // EN enable the timer
147 147 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000008; // IE interrupt enable
148 148
149 149 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
150 150
151 151 }
152 152
153 153 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
154 154 {
155 155 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
156 156
157 157 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
158 158
159 159 return 0;
160 160 }
161 161
162 162 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
163 163 {
164 164 /** This function sets the scaler reload register of the apbuart module
165 165 *
166 166 * @param regs is the address of the apbuart registers in memory
167 167 * @param value is the value that will be stored in the scaler register
168 168 *
169 169 * The value shall be set by the software to get data on the serial interface.
170 170 *
171 171 */
172 172
173 173 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
174 174
175 175 apbuart_regs->scaler = value;
176 176
177 177 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
178 178 }
179 179
180 180 //************
181 181 // RTEMS TASKS
182 182
183 183 rtems_task load_task(rtems_task_argument argument)
184 184 {
185 185 BOOT_PRINTF("in LOAD *** \n")
186 186
187 187 rtems_status_code status;
188 188 unsigned int i;
189 189 unsigned int j;
190 190 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
191 191 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
192 192
193 193 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
194 194
195 195 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
196 196 if( status != RTEMS_SUCCESSFUL ) {
197 197 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
198 198 }
199 199
200 200 i = 0;
201 201 j = 0;
202 202
203 203 watchdog_configure();
204 204
205 205 watchdog_start();
206 206
207 207 set_sy_lfr_watchdog_enabled( true );
208 208
209 209 while(1){
210 210 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
211 211 watchdog_reload();
212 212 i = i + 1;
213 213 if ( i == 10 )
214 214 {
215 215 i = 0;
216 216 j = j + 1;
217 217 PRINTF1("%d\n", j)
218 218 }
219 219 #ifdef DEBUG_WATCHDOG
220 220 if (j == 3 )
221 221 {
222 222 status = rtems_task_delete(RTEMS_SELF);
223 223 }
224 224 #endif
225 225 }
226 226 }
227 227
228 228 rtems_task hous_task(rtems_task_argument argument)
229 229 {
230 230 rtems_status_code status;
231 231 rtems_status_code spare_status;
232 232 rtems_id queue_id;
233 233 rtems_rate_monotonic_period_status period_status;
234 234
235 235 status = get_message_queue_id_send( &queue_id );
236 236 if (status != RTEMS_SUCCESSFUL)
237 237 {
238 238 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
239 239 }
240 240
241 241 BOOT_PRINTF("in HOUS ***\n");
242 242
243 243 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
244 244 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
245 245 if( status != RTEMS_SUCCESSFUL ) {
246 246 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status );
247 247 }
248 248 }
249 249
250 250 status = rtems_rate_monotonic_cancel(HK_id);
251 251 if( status != RTEMS_SUCCESSFUL ) {
252 252 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status );
253 253 }
254 254 else {
255 255 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n");
256 256 }
257 257
258 258 // startup phase
259 259 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
260 260 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
261 261 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
262 262 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
263 263 {
264 264 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
265 265 {
266 266 break; // break if LFR is synchronized
267 267 }
268 268 else
269 269 {
270 270 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
271 271 // sched_yield();
272 272 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
273 273 }
274 274 }
275 275 status = rtems_rate_monotonic_cancel(HK_id);
276 276 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
277 277
278 278 set_hk_lfr_reset_cause( POWER_ON );
279 279
280 280 while(1){ // launch the rate monotonic task
281 281 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
282 282 if ( status != RTEMS_SUCCESSFUL ) {
283 283 PRINTF1( "in HOUS *** ERR period: %d\n", status);
284 284 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
285 285 }
286 286 else {
287 287 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
288 288 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
289 289 increment_seq_counter( &sequenceCounterHK );
290 290
291 291 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
292 292 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
293 293 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
294 294 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
295 295 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
296 296 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
297 297
298 spacewire_update_statistics();
298 spacewire_read_statistics();
299 299
300 update_hk_with_grspw_stats( grspw_stats );
300 update_hk_with_grspw_stats();
301 301
302 302 set_hk_lfr_time_not_synchro();
303 303
304 304 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
305 305 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
306 306 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
307 307 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
308 308 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
309 309
310 310 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
311 311 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
312 312 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
313 313 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
314 314 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
315 315
316 316 hk_lfr_le_me_he_update();
317 317
318 318 // SEND PACKET
319 319 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
320 320 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
321 321 if (status != RTEMS_SUCCESSFUL) {
322 322 PRINTF1("in HOUS *** ERR send: %d\n", status)
323 323 }
324 324 }
325 325 }
326 326
327 327 PRINTF("in HOUS *** deleting task\n")
328 328
329 329 status = rtems_task_delete( RTEMS_SELF ); // should not return
330 330
331 331 return;
332 332 }
333 333
334 334 rtems_task dumb_task( rtems_task_argument unused )
335 335 {
336 336 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
337 337 *
338 338 * @param unused is the starting argument of the RTEMS task
339 339 *
340 340 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
341 341 *
342 342 */
343 343
344 344 unsigned int i;
345 345 unsigned int intEventOut;
346 346 unsigned int coarse_time = 0;
347 347 unsigned int fine_time = 0;
348 348 rtems_event_set event_out;
349 349
350 350 char *DumbMessages[15] = {"in DUMB *** default", // RTEMS_EVENT_0
351 351 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
352 352 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
353 353 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
354 354 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
355 355 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
356 356 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
357 357 "ready for dump", // RTEMS_EVENT_7
358 358 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
359 359 "tick", // RTEMS_EVENT_9
360 360 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
361 361 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11
362 362 "WATCHDOG timer", // RTEMS_EVENT_12
363 363 "TIMECODE timer", // RTEMS_EVENT_13
364 364 "TIMECODE ISR" // RTEMS_EVENT_14
365 365 };
366 366
367 367 BOOT_PRINTF("in DUMB *** \n")
368 368
369 369 while(1){
370 370 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
371 371 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
372 372 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13
373 373 | RTEMS_EVENT_14,
374 374 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
375 375 intEventOut = (unsigned int) event_out;
376 376 for ( i=0; i<32; i++)
377 377 {
378 378 if ( ((intEventOut >> i) & 0x0001) != 0)
379 379 {
380 380 coarse_time = time_management_regs->coarse_time;
381 381 fine_time = time_management_regs->fine_time;
382 382 if (i==12)
383 383 {
384 384 PRINTF1("%s\n", DumbMessages[12])
385 385 }
386 386 if (i==13)
387 387 {
388 388 PRINTF1("%s\n", DumbMessages[13])
389 389 }
390 390 if (i==14)
391 391 {
392 392 PRINTF1("%s\n", DumbMessages[1])
393 393 }
394 394 }
395 395 }
396 396 }
397 397 }
398 398
399 399 //*****************************
400 400 // init housekeeping parameters
401 401
402 402 void init_housekeeping_parameters( void )
403 403 {
404 404 /** This function initialize the housekeeping_packet global variable with default values.
405 405 *
406 406 */
407 407
408 408 unsigned int i = 0;
409 409 unsigned char *parameters;
410 410 unsigned char sizeOfHK;
411 411
412 412 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
413 413
414 414 parameters = (unsigned char*) &housekeeping_packet;
415 415
416 416 for(i = 0; i< sizeOfHK; i++)
417 417 {
418 418 parameters[i] = 0x00;
419 419 }
420 420
421 421 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
422 422 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
423 423 housekeeping_packet.reserved = DEFAULT_RESERVED;
424 424 housekeeping_packet.userApplication = CCSDS_USER_APP;
425 425 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
426 426 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
427 427 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
428 428 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
429 429 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
430 430 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
431 431 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
432 432 housekeeping_packet.serviceType = TM_TYPE_HK;
433 433 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
434 434 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
435 435 housekeeping_packet.sid = SID_HK;
436 436
437 437 // init status word
438 438 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
439 439 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
440 440 // init software version
441 441 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
442 442 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
443 443 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
444 444 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
445 445 // init fpga version
446 446 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
447 447 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
448 448 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
449 449 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
450 450
451 451 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
452 452 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
453 453 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
454 454 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
455 455 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
456 456 }
457 457
458 458 void increment_seq_counter( unsigned short *packetSequenceControl )
459 459 {
460 460 /** This function increment the sequence counter passes in argument.
461 461 *
462 462 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
463 463 *
464 464 */
465 465
466 466 unsigned short segmentation_grouping_flag;
467 467 unsigned short sequence_cnt;
468 468
469 469 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
470 470 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
471 471
472 472 if ( sequence_cnt < SEQ_CNT_MAX)
473 473 {
474 474 sequence_cnt = sequence_cnt + 1;
475 475 }
476 476 else
477 477 {
478 478 sequence_cnt = 0;
479 479 }
480 480
481 481 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
482 482 }
483 483
484 484 void getTime( unsigned char *time)
485 485 {
486 486 /** This function write the current local time in the time buffer passed in argument.
487 487 *
488 488 */
489 489
490 490 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
491 491 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
492 492 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
493 493 time[3] = (unsigned char) (time_management_regs->coarse_time);
494 494 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
495 495 time[5] = (unsigned char) (time_management_regs->fine_time);
496 496 }
497 497
498 498 unsigned long long int getTimeAsUnsignedLongLongInt( )
499 499 {
500 500 /** This function write the current local time in the time buffer passed in argument.
501 501 *
502 502 */
503 503 unsigned long long int time;
504 504
505 505 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
506 506 + time_management_regs->fine_time;
507 507
508 508 return time;
509 509 }
510 510
511 511 void send_dumb_hk( void )
512 512 {
513 513 Packet_TM_LFR_HK_t dummy_hk_packet;
514 514 unsigned char *parameters;
515 515 unsigned int i;
516 516 rtems_id queue_id;
517 517
518 518 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
519 519 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
520 520 dummy_hk_packet.reserved = DEFAULT_RESERVED;
521 521 dummy_hk_packet.userApplication = CCSDS_USER_APP;
522 522 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
523 523 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
524 524 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
525 525 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
526 526 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
527 527 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
528 528 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
529 529 dummy_hk_packet.serviceType = TM_TYPE_HK;
530 530 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
531 531 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
532 532 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
533 533 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
534 534 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
535 535 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
536 536 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
537 537 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
538 538 dummy_hk_packet.sid = SID_HK;
539 539
540 540 // init status word
541 541 dummy_hk_packet.lfr_status_word[0] = 0xff;
542 542 dummy_hk_packet.lfr_status_word[1] = 0xff;
543 543 // init software version
544 544 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
545 545 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
546 546 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
547 547 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
548 548 // init fpga version
549 549 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
550 550 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
551 551 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
552 552 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
553 553
554 554 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
555 555
556 556 for (i=0; i<100; i++)
557 557 {
558 558 parameters[i] = 0xff;
559 559 }
560 560
561 561 get_message_queue_id_send( &queue_id );
562 562
563 563 rtems_message_queue_send( queue_id, &dummy_hk_packet,
564 564 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
565 565 }
566 566
567 567 void get_temperatures( unsigned char *temperatures )
568 568 {
569 569 unsigned char* temp_scm_ptr;
570 570 unsigned char* temp_pcb_ptr;
571 571 unsigned char* temp_fpga_ptr;
572 572
573 573 // SEL1 SEL0
574 574 // 0 0 => PCB
575 575 // 0 1 => FPGA
576 576 // 1 0 => SCM
577 577
578 578 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
579 579 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
580 580 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
581 581
582 582 temperatures[0] = temp_scm_ptr[2];
583 583 temperatures[1] = temp_scm_ptr[3];
584 584 temperatures[2] = temp_pcb_ptr[2];
585 585 temperatures[3] = temp_pcb_ptr[3];
586 586 temperatures[4] = temp_fpga_ptr[2];
587 587 temperatures[5] = temp_fpga_ptr[3];
588 588 }
589 589
590 590 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
591 591 {
592 592 unsigned char* v_ptr;
593 593 unsigned char* e1_ptr;
594 594 unsigned char* e2_ptr;
595 595
596 596 v_ptr = (unsigned char *) &waveform_picker_regs->v;
597 597 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
598 598 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
599 599
600 600 spacecraft_potential[0] = v_ptr[2];
601 601 spacecraft_potential[1] = v_ptr[3];
602 602 spacecraft_potential[2] = e1_ptr[2];
603 603 spacecraft_potential[3] = e1_ptr[3];
604 604 spacecraft_potential[4] = e2_ptr[2];
605 605 spacecraft_potential[5] = e2_ptr[3];
606 606 }
607 607
608 608 void get_cpu_load( unsigned char *resource_statistics )
609 609 {
610 610 unsigned char cpu_load;
611 611
612 612 cpu_load = lfr_rtems_cpu_usage_report();
613 613
614 614 // HK_LFR_CPU_LOAD
615 615 resource_statistics[0] = cpu_load;
616 616
617 617 // HK_LFR_CPU_LOAD_MAX
618 618 if (cpu_load > resource_statistics[1])
619 619 {
620 620 resource_statistics[1] = cpu_load;
621 621 }
622 622
623 623 // CPU_LOAD_AVE
624 624 resource_statistics[2] = 0;
625 625
626 626 #ifndef PRINT_TASK_STATISTICS
627 627 rtems_cpu_usage_reset();
628 628 #endif
629 629
630 630 }
631 631
632 632 void set_hk_lfr_sc_potential_flag( bool state )
633 633 {
634 634 if (state == true)
635 635 {
636 636 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x40; // [0100 0000]
637 637 }
638 638 else
639 639 {
640 640 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xbf; // [1011 1111]
641 641 }
642 642 }
643 643
644 644 void set_hk_lfr_mag_fields_flag( bool state )
645 645 {
646 646 if (state == true)
647 647 {
648 648 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x20; // [0010 0000]
649 649 }
650 650 else
651 651 {
652 652 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xd7; // [1101 1111]
653 653 }
654 654 }
655 655
656 656 void set_sy_lfr_watchdog_enabled( bool state )
657 657 {
658 658 if (state == true)
659 659 {
660 660 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x10; // [0001 0000]
661 661 }
662 662 else
663 663 {
664 664 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xef; // [1110 1111]
665 665 }
666 666 }
667 667
668 668 void set_hk_lfr_calib_enable( bool state )
669 669 {
670 670 if (state == true)
671 671 {
672 672 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x08; // [0000 1000]
673 673 }
674 674 else
675 675 {
676 676 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xf7; // [1111 0111]
677 677 }
678 678 }
679 679
680 680 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
681 681 {
682 682 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
683 683 | (lfr_reset_cause & 0x07 ); // [0000 0111]
684 684 }
685 685
686 686 void hk_lfr_le_me_he_update()
687 687 {
688 688 unsigned int hk_lfr_le_cnt;
689 689 unsigned int hk_lfr_me_cnt;
690 690 unsigned int hk_lfr_he_cnt;
691 691
692 692 hk_lfr_le_cnt = 0;
693 693 hk_lfr_me_cnt = 0;
694 694 hk_lfr_he_cnt = 0;
695 695
696 696 //update the low severity error counter
697 697 hk_lfr_le_cnt =
698 698 housekeeping_packet.hk_lfr_dpu_spw_parity
699 699 + housekeeping_packet.hk_lfr_dpu_spw_disconnect
700 700 + housekeeping_packet.hk_lfr_dpu_spw_escape
701 701 + housekeeping_packet.hk_lfr_dpu_spw_credit
702 702 + housekeeping_packet.hk_lfr_dpu_spw_write_sync
703 703 + housekeeping_packet.hk_lfr_timecode_erroneous
704 704 + housekeeping_packet.hk_lfr_timecode_missing
705 705 + housekeeping_packet.hk_lfr_timecode_invalid
706 706 + housekeeping_packet.hk_lfr_time_timecode_it
707 707 + housekeeping_packet.hk_lfr_time_not_synchro
708 708 + housekeeping_packet.hk_lfr_time_timecode_ctr;
709 709 // housekeeping_packet.hk_lfr_dpu_spw_rx_ahb => not handled by the grspw driver
710 710 // housekeeping_packet.hk_lfr_dpu_spw_tx_ahb => not handled by the grspw driver
711 711
712 712 //update the medium severity error counter
713 713 hk_lfr_me_cnt =
714 714 housekeeping_packet.hk_lfr_dpu_spw_early_eop
715 715 + housekeeping_packet.hk_lfr_dpu_spw_invalid_addr
716 716 + housekeeping_packet.hk_lfr_dpu_spw_eep
717 717 + housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
718 718
719 719 //update the high severity error counter
720 720 hk_lfr_he_cnt = 0;
721 721
722 722 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
723 723 // LE
724 724 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((hk_lfr_le_cnt & 0xff00) >> 8);
725 725 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (hk_lfr_le_cnt & 0x00ff);
726 726 // ME
727 727 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((hk_lfr_me_cnt & 0xff00) >> 8);
728 728 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (hk_lfr_me_cnt & 0x00ff);
729 729 // HE
730 730 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & 0xff00) >> 8);
731 731 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & 0x00ff);
732 732
733 733 }
734 734
735 735 void set_hk_lfr_time_not_synchro()
736 736 {
737 737 static unsigned char synchroLost = 1;
738 738 int synchronizationBit;
739 739
740 740 // get the synchronization bit
741 741 synchronizationBit = (time_management_regs->coarse_time & 0x80000000) >> 31; // 1000 0000 0000 0000
742 742
743 743 switch (synchronizationBit)
744 744 {
745 745 case 0:
746 746 if (synchroLost == 1)
747 747 {
748 748 synchroLost = 0;
749 749 }
750 750 break;
751 751 case 1:
752 752 if (synchroLost == 0 )
753 753 {
754 754 synchroLost = 1;
755 755 increase_unsigned_char_counter(&housekeeping_packet.hk_lfr_time_not_synchro);
756 756 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_NOT_SYNCHRO );
757 757 }
758 758 break;
759 759 default:
760 760 PRINTF1("in hk_lfr_time_not_synchro *** unexpected value for synchronizationBit = %d\n", synchronizationBit);
761 761 break;
762 762 }
763 763
764 764 }
765 765
766 766 void set_hk_lfr_ahb_correctable()
767 767 {
768 768 /** This function builds the error counter hk_lfr_ahb_correctable using the statistics provided
769 769 * by the Cache Control Register (ASI 2, offset 0) and in the Register Protection Control Register (ASR16) on the
770 770 * detected errors in the cache, in the integer unit and in the floating point unit.
771 771 *
772 772 * @param void
773 773 *
774 774 * @return void
775 775 *
776 776 * All errors are summed to set the value of the hk_lfr_ahb_correctable counter.
777 777 *
778 778 */
779 779
780 780 unsigned int ahb_correctable;
781 781 unsigned int instructionErrorCounter;
782 782 unsigned int dataErrorCounter;
783 783 unsigned int fprfErrorCounter;
784 784 unsigned int iurfErrorCounter;
785 785
786 786 CCR_getInstructionAndDataErrorCounters( &instructionErrorCounter, &dataErrorCounter);
787 787 ASR16_get_FPRF_IURF_ErrorCounters( &fprfErrorCounter, &iurfErrorCounter);
788 788
789 789 ahb_correctable = instructionErrorCounter
790 790 + dataErrorCounter
791 791 + fprfErrorCounter
792 792 + iurfErrorCounter
793 793 + housekeeping_packet.hk_lfr_ahb_correctable;
794 794
795 795 if (ahb_correctable > 255)
796 796 {
797 797 housekeeping_packet.hk_lfr_ahb_correctable = 255;
798 798 }
799 799 else
800 800 {
801 801 housekeeping_packet.hk_lfr_ahb_correctable = ahb_correctable;
802 802 }
803 803
804 804 }
@@ -1,1659 +1,1569
1 1 /** Functions related to the SpaceWire interface.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle SpaceWire transmissions:
7 7 * - configuration of the SpaceWire link
8 8 * - SpaceWire related interruption requests processing
9 9 * - transmission of TeleMetry packets by a dedicated RTEMS task
10 10 * - reception of TeleCommands by a dedicated RTEMS task
11 11 *
12 12 */
13 13
14 14 #include "fsw_spacewire.h"
15 15
16 16 rtems_name semq_name;
17 17 rtems_id semq_id;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF;
22 22 Header_TM_LFR_SCIENCE_SWF_t headerSWF;
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM;
24 24
25 25 unsigned char previousTimecodeCtr = 0;
26