##// END OF EJS Templates
added spacewire_get_last_error() call to the function spacewire_read_statistics
paul -
r269:46635fba5689 R3a
parent child
Show More
@@ -1,56 +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 rtems_name timecode_timer_name;
18 18 extern rtems_id timecode_timer_id;
19 19
20 20 // RTEMS TASK
21 21 rtems_task spiq_task( rtems_task_argument argument );
22 22 rtems_task recv_task( rtems_task_argument unused );
23 23 rtems_task send_task( rtems_task_argument argument );
24 24 rtems_task link_task( rtems_task_argument argument );
25 25
26 26 int spacewire_open_link( void );
27 27 int spacewire_start_link( int fd );
28 28 int spacewire_stop_and_start_link( int fd );
29 29 int spacewire_configure_link(int fd );
30 30 int spacewire_several_connect_attemps( void );
31 31 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
32 32 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
33 33 void spacewire_read_statistics( void );
34 void spacewire_get_last_error( void );
34 35 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code);
35 36 void update_hk_with_grspw_stats(void );
36 37 void increase_unsigned_char_counter( unsigned char *counter );
37 38
38 39 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
39 40 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
40 41 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
41 42 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
42 43 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
43 44 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
44 45 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
45 46 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
46 47 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
47 48 void spw_send_k_dump( ring_node *ring_node_to_send );
48 49
49 50 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
50 51 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
51 52 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
52 53 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
53 54
54 55 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
55 56
56 57 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,1580 +1,1582
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 spacewire_get_last_error();
585
584 586 // read the current statistics
585 587 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
586 588
587 589 // clear the counters
588 590 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
589 591
590 592 // typedef struct {
591 593 // unsigned int tx_link_err; // NOT IN HK
592 594 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
593 595 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
594 596 // unsigned int rx_eep_err;
595 597 // unsigned int rx_truncated;
596 598 // unsigned int parity_err;
597 599 // unsigned int escape_err;
598 600 // unsigned int credit_err;
599 601 // unsigned int write_sync_err;
600 602 // unsigned int disconnect_err;
601 603 // unsigned int early_ep;
602 604 // unsigned int invalid_address;
603 605 // unsigned int packets_sent;
604 606 // unsigned int packets_received;
605 607 // } spw_stats;
606 608
607 609 // rx_eep_err
608 610 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
609 611 // rx_truncated
610 612 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
611 613 // parity_err
612 614 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
613 615 // escape_err
614 616 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
615 617 // credit_err
616 618 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
617 619 // write_sync_err
618 620 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
619 621 // disconnect_err
620 622 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
621 623 // early_ep
622 624 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
623 625 // invalid_address
624 626 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
625 627 // packets_sent
626 628 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
627 629 // packets_received
628 630 grspw_stats.packets_received= grspw_stats.packets_received + current.packets_received;
629 631
630 632 }
631 633
632 634 void spacewire_get_last_error( void )
633 635 {
634 636 static spw_stats previous;
635 637 spw_stats current;
636 638 rtems_status_code status;
637 639
638 640 unsigned int hk_lfr_last_er_rid;
639 641 unsigned char hk_lfr_last_er_code;
640 642 int coarseTime;
641 643 int fineTime;
642 644 unsigned char update_hk_lfr_last_er;
643 645
644 646 update_hk_lfr_last_er = 0;
645 647
646 648 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
647 649
648 650 // get current time
649 651 coarseTime = time_management_regs->coarse_time;
650 652 fineTime = time_management_regs->fine_time;
651 653
652 654 // typedef struct {
653 655 // unsigned int tx_link_err; // NOT IN HK
654 656 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
655 657 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
656 658 // unsigned int rx_eep_err;
657 659 // unsigned int rx_truncated;
658 660 // unsigned int parity_err;
659 661 // unsigned int escape_err;
660 662 // unsigned int credit_err;
661 663 // unsigned int write_sync_err;
662 664 // unsigned int disconnect_err;
663 665 // unsigned int early_ep;
664 666 // unsigned int invalid_address;
665 667 // unsigned int packets_sent;
666 668 // unsigned int packets_received;
667 669 // } spw_stats;
668 670
669 671 // tx_link_err *** no code associated to this field
670 672 // rx_rmap_header_crc_err *** LE *** in HK
671 673 if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
672 674 {
673 675 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
674 676 hk_lfr_last_er_code = CODE_HEADER_CRC;
675 677 update_hk_lfr_last_er = 1;
676 678 }
677 679 // rx_rmap_data_crc_err *** LE *** NOT IN HK
678 680 if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
679 681 {
680 682 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
681 683 hk_lfr_last_er_code = CODE_DATA_CRC;
682 684 update_hk_lfr_last_er = 1;
683 685 }
684 686 // rx_eep_err
685 687 if (previous.rx_eep_err != current.rx_eep_err)
686 688 {
687 689 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
688 690 hk_lfr_last_er_code = CODE_EEP;
689 691 update_hk_lfr_last_er = 1;
690 692 }
691 693 // rx_truncated
692 694 if (previous.rx_truncated != current.rx_truncated)
693 695 {
694 696 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
695 697 hk_lfr_last_er_code = CODE_RX_TOO_BIG;
696 698 update_hk_lfr_last_er = 1;
697 699 }
698 700 // parity_err
699 701 if (previous.parity_err != current.parity_err)
700 702 {
701 703 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
702 704 hk_lfr_last_er_code = CODE_PARITY;
703 705 update_hk_lfr_last_er = 1;
704 706 }
705 707 // escape_err
706 708 if (previous.parity_err != current.parity_err)
707 709 {
708 710 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
709 711 hk_lfr_last_er_code = CODE_ESCAPE;
710 712 update_hk_lfr_last_er = 1;
711 713 }
712 714 // credit_err
713 715 if (previous.credit_err != current.credit_err)
714 716 {
715 717 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
716 718 hk_lfr_last_er_code = CODE_CREDIT;
717 719 update_hk_lfr_last_er = 1;
718 720 }
719 721 // write_sync_err
720 722 if (previous.write_sync_err != current.write_sync_err)
721 723 {
722 724 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
723 725 hk_lfr_last_er_code = CODE_WRITE_SYNC;
724 726 update_hk_lfr_last_er = 1;
725 727 }
726 728 // disconnect_err
727 729 if (previous.disconnect_err != current.disconnect_err)
728 730 {
729 731 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
730 732 hk_lfr_last_er_code = CODE_DISCONNECT;
731 733 update_hk_lfr_last_er = 1;
732 734 }
733 735 // early_ep
734 736 if (previous.early_ep != current.early_ep)
735 737 {
736 738 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
737 739 hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
738 740 update_hk_lfr_last_er = 1;
739 741 }
740 742 // invalid_address
741 743 if (previous.invalid_address != current.invalid_address)
742 744 {
743 745 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
744 746 hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
745 747 update_hk_lfr_last_er = 1;
746 748 }
747 749
748 750 // if a field has changed, update the hk_last_er fields
749 751 if (update_hk_lfr_last_er == 1)
750 752 {
751 753 update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
752 754 }
753 755
754 756 previous = current;
755 757 }
756 758
757 759 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
758 760 {
759 761 unsigned char *coarseTimePtr;
760 762 unsigned char *fineTimePtr;
761 763
762 764 coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
763 765 fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
764 766
765 767 housekeeping_packet.hk_lfr_last_er_rid[0] = (unsigned char) ((rid & 0xff00) >> 8 );
766 768 housekeeping_packet.hk_lfr_last_er_rid[1] = (unsigned char) (rid & 0x00ff);
767 769 housekeeping_packet.hk_lfr_last_er_code = code;
768 770 housekeeping_packet.hk_lfr_last_er_time[0] = coarseTimePtr[0];
769 771 housekeeping_packet.hk_lfr_last_er_time[1] = coarseTimePtr[1];
770 772 housekeeping_packet.hk_lfr_last_er_time[2] = coarseTimePtr[2];
771 773 housekeeping_packet.hk_lfr_last_er_time[3] = coarseTimePtr[3];
772 774 housekeeping_packet.hk_lfr_last_er_time[4] = fineTimePtr[2];
773 775 housekeeping_packet.hk_lfr_last_er_time[5] = fineTimePtr[3];
774 776 }
775 777
776 778 void update_hk_with_grspw_stats( void )
777 779 {
778 780 //****************************
779 781 // DPU_SPACEWIRE_IF_STATISTICS
780 782 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (grspw_stats.packets_received >> 8);
781 783 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (grspw_stats.packets_received);
782 784 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (grspw_stats.packets_sent >> 8);
783 785 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (grspw_stats.packets_sent);
784 786
785 787 //******************************************
786 788 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
787 789 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) grspw_stats.parity_err;
788 790 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) grspw_stats.disconnect_err;
789 791 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) grspw_stats.escape_err;
790 792 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) grspw_stats.credit_err;
791 793 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) grspw_stats.write_sync_err;
792 794
793 795 //*********************************************
794 796 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
795 797 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) grspw_stats.early_ep;
796 798 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) grspw_stats.invalid_address;
797 799 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) grspw_stats.rx_eep_err;
798 800 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) grspw_stats.rx_truncated;
799 801 }
800 802
801 803 void increase_unsigned_char_counter( unsigned char *counter )
802 804 {
803 805 // update the number of valid timecodes that have been received
804 806 if (*counter == 255)
805 807 {
806 808 *counter = 0;
807 809 }
808 810 else
809 811 {
810 812 *counter = *counter + 1;
811 813 }
812 814 }
813 815
814 816 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
815 817 {
816 818 static unsigned char initStep = 1;
817 819
818 820 unsigned char currentTimecodeCtr;
819 821
820 822 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
821 823
822 824 if (initStep == 1)
823 825 {
824 826 if (currentTimecodeCtr == previousTimecodeCtr)
825 827 {
826 828 //************************
827 829 // HK_LFR_TIMECODE_MISSING
828 830 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
829 831 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
830 832 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
831 833 }
832 834 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
833 835 {
834 836 // the timecode value has changed and the value is valid, this is unexpected because
835 837 // the timer should not have fired, the timecode_irq_handler should have been raised
836 838 }
837 839 else
838 840 {
839 841 //************************
840 842 // HK_LFR_TIMECODE_INVALID
841 843 // the timecode value has changed and the value is not valid, no tickout has been generated
842 844 // this is why the timer has fired
843 845 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
844 846 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_INVALID );
845 847 }
846 848 }
847 849 else
848 850 {
849 851 initStep = 1;
850 852 //************************
851 853 // HK_LFR_TIMECODE_MISSING
852 854 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
853 855 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_MISSING );
854 856 }
855 857
856 858 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
857 859 }
858 860
859 861 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
860 862 {
861 863 /** This function checks the coherency between the incoming timecode and the last valid timecode.
862 864 *
863 865 * @param currentTimecodeCtr is the incoming timecode
864 866 *
865 867 * @return returned codes::
866 868 * - LFR_DEFAULT
867 869 * - LFR_SUCCESSFUL
868 870 *
869 871 */
870 872
871 873 static unsigned char firstTickout = 1;
872 874 unsigned char ret;
873 875
874 876 ret = LFR_DEFAULT;
875 877
876 878 if (firstTickout == 0)
877 879 {
878 880 if (currentTimecodeCtr == 0)
879 881 {
880 882 if (previousTimecodeCtr == 63)
881 883 {
882 884 ret = LFR_SUCCESSFUL;
883 885 }
884 886 else
885 887 {
886 888 ret = LFR_DEFAULT;
887 889 }
888 890 }
889 891 else
890 892 {
891 893 if (currentTimecodeCtr == (previousTimecodeCtr +1))
892 894 {
893 895 ret = LFR_SUCCESSFUL;
894 896 }
895 897 else
896 898 {
897 899 ret = LFR_DEFAULT;
898 900 }
899 901 }
900 902 }
901 903 else
902 904 {
903 905 firstTickout = 0;
904 906 ret = LFR_SUCCESSFUL;
905 907 }
906 908
907 909 return ret;
908 910 }
909 911
910 912 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
911 913 {
912 914 unsigned int ret;
913 915
914 916 ret = LFR_DEFAULT;
915 917
916 918 if (timecode == internalTime)
917 919 {
918 920 ret = LFR_SUCCESSFUL;
919 921 }
920 922 else
921 923 {
922 924 ret = LFR_DEFAULT;
923 925 }
924 926
925 927 return ret;
926 928 }
927 929
928 930 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
929 931 {
930 932 // a tickout has been emitted, perform actions on the incoming timecode
931 933
932 934 unsigned char incomingTimecode;
933 935 unsigned char updateTime;
934 936 unsigned char internalTime;
935 937 rtems_status_code status;
936 938
937 939 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
938 940 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
939 941 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
940 942
941 943 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
942 944
943 945 // update the number of tickout that have been generated
944 946 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
945 947
946 948 //**************************
947 949 // HK_LFR_TIMECODE_ERRONEOUS
948 950 // MISSING and INVALID are handled by the timecode_timer_routine service routine
949 951 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
950 952 {
951 953 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
952 954 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
953 955 update_hk_lfr_last_er_fields( RID_LE_LFR_TIMEC, CODE_ERRONEOUS );
954 956 }
955 957
956 958 //************************
957 959 // HK_LFR_TIME_TIMECODE_IT
958 960 // check the coherency between the SpaceWire timecode and the Internal Time
959 961 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
960 962 {
961 963 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
962 964 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_IT );
963 965 }
964 966
965 967 //********************
966 968 // HK_LFR_TIMECODE_CTR
967 969 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
968 970 if (incomingTimecode != updateTime)
969 971 {
970 972 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
971 973 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_TIMECODE_CTR );
972 974 }
973 975
974 976 // launch the timecode timer to detect missing or invalid timecodes
975 977 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
976 978 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
977 979 if (status != RTEMS_SUCCESSFUL)
978 980 {
979 981 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_14 );
980 982 }
981 983 }
982 984
983 985 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
984 986 {
985 987 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
986 988 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
987 989 header->reserved = DEFAULT_RESERVED;
988 990 header->userApplication = CCSDS_USER_APP;
989 991 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
990 992 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
991 993 header->packetLength[0] = 0x00;
992 994 header->packetLength[1] = 0x00;
993 995 // DATA FIELD HEADER
994 996 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
995 997 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
996 998 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
997 999 header->destinationID = TM_DESTINATION_ID_GROUND;
998 1000 header->time[0] = 0x00;
999 1001 header->time[0] = 0x00;
1000 1002 header->time[0] = 0x00;
1001 1003 header->time[0] = 0x00;
1002 1004 header->time[0] = 0x00;
1003 1005 header->time[0] = 0x00;
1004 1006 // AUXILIARY DATA HEADER
1005 1007 header->sid = 0x00;
1006 1008 header->hkBIA = DEFAULT_HKBIA;
1007 1009 header->blkNr[0] = 0x00;
1008 1010 header->blkNr[1] = 0x00;
1009 1011 }
1010 1012
1011 1013 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
1012 1014 {
1013 1015 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1014 1016 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1015 1017 header->reserved = DEFAULT_RESERVED;
1016 1018 header->userApplication = CCSDS_USER_APP;
1017 1019 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1018 1020 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1019 1021 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1020 1022 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1021 1023 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1022 1024 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1023 1025 // DATA FIELD HEADER
1024 1026 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1025 1027 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1026 1028 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
1027 1029 header->destinationID = TM_DESTINATION_ID_GROUND;
1028 1030 header->time[0] = 0x00;
1029 1031 header->time[0] = 0x00;
1030 1032 header->time[0] = 0x00;
1031 1033 header->time[0] = 0x00;
1032 1034 header->time[0] = 0x00;
1033 1035 header->time[0] = 0x00;
1034 1036 // AUXILIARY DATA HEADER
1035 1037 header->sid = 0x00;
1036 1038 header->hkBIA = DEFAULT_HKBIA;
1037 1039 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
1038 1040 header->pktNr = 0x00;
1039 1041 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1040 1042 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1041 1043 }
1042 1044
1043 1045 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
1044 1046 {
1045 1047 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
1046 1048 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
1047 1049 header->reserved = DEFAULT_RESERVED;
1048 1050 header->userApplication = CCSDS_USER_APP;
1049 1051 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1050 1052 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1051 1053 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
1052 1054 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
1053 1055 header->packetLength[0] = 0x00;
1054 1056 header->packetLength[1] = 0x00;
1055 1057 // DATA FIELD HEADER
1056 1058 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
1057 1059 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
1058 1060 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
1059 1061 header->destinationID = TM_DESTINATION_ID_GROUND;
1060 1062 header->time[0] = 0x00;
1061 1063 header->time[0] = 0x00;
1062 1064 header->time[0] = 0x00;
1063 1065 header->time[0] = 0x00;
1064 1066 header->time[0] = 0x00;
1065 1067 header->time[0] = 0x00;
1066 1068 // AUXILIARY DATA HEADER
1067 1069 header->sid = 0x00;
1068 1070 header->biaStatusInfo = 0x00;
1069 1071 header->pa_lfr_pkt_cnt_asm = 0x00;
1070 1072 header->pa_lfr_pkt_nr_asm = 0x00;
1071 1073 header->pa_lfr_asm_blk_nr[0] = 0x00;
1072 1074 header->pa_lfr_asm_blk_nr[1] = 0x00;
1073 1075 }
1074 1076
1075 1077 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
1076 1078 Header_TM_LFR_SCIENCE_CWF_t *header )
1077 1079 {
1078 1080 /** This function sends CWF CCSDS packets (F2, F1 or F0).
1079 1081 *
1080 1082 * @param waveform points to the buffer containing the data that will be send.
1081 1083 * @param sid is the source identifier of the data that will be sent.
1082 1084 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1083 1085 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1084 1086 * contain information to setup the transmission of the data packets.
1085 1087 *
1086 1088 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1087 1089 *
1088 1090 */
1089 1091
1090 1092 unsigned int i;
1091 1093 int ret;
1092 1094 unsigned int coarseTime;
1093 1095 unsigned int fineTime;
1094 1096 rtems_status_code status;
1095 1097 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1096 1098 int *dataPtr;
1097 1099 unsigned char sid;
1098 1100
1099 1101 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1100 1102 spw_ioctl_send_CWF.options = 0;
1101 1103
1102 1104 ret = LFR_DEFAULT;
1103 1105 sid = (unsigned char) ring_node_to_send->sid;
1104 1106
1105 1107 coarseTime = ring_node_to_send->coarseTime;
1106 1108 fineTime = ring_node_to_send->fineTime;
1107 1109 dataPtr = (int*) ring_node_to_send->buffer_address;
1108 1110
1109 1111 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
1110 1112 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
1111 1113 header->hkBIA = pa_bia_status_info;
1112 1114 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1113 1115 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
1114 1116 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
1115 1117
1116 1118 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
1117 1119 {
1118 1120 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
1119 1121 spw_ioctl_send_CWF.hdr = (char*) header;
1120 1122 // BUILD THE DATA
1121 1123 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
1122 1124
1123 1125 // SET PACKET SEQUENCE CONTROL
1124 1126 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1125 1127
1126 1128 // SET SID
1127 1129 header->sid = sid;
1128 1130
1129 1131 // SET PACKET TIME
1130 1132 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
1131 1133 //
1132 1134 header->time[0] = header->acquisitionTime[0];
1133 1135 header->time[1] = header->acquisitionTime[1];
1134 1136 header->time[2] = header->acquisitionTime[2];
1135 1137 header->time[3] = header->acquisitionTime[3];
1136 1138 header->time[4] = header->acquisitionTime[4];
1137 1139 header->time[5] = header->acquisitionTime[5];
1138 1140
1139 1141 // SET PACKET ID
1140 1142 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
1141 1143 {
1142 1144 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
1143 1145 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
1144 1146 }
1145 1147 else
1146 1148 {
1147 1149 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1148 1150 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1149 1151 }
1150 1152
1151 1153 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1152 1154 if (status != RTEMS_SUCCESSFUL) {
1153 1155 ret = LFR_DEFAULT;
1154 1156 }
1155 1157 }
1156 1158
1157 1159 return ret;
1158 1160 }
1159 1161
1160 1162 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1161 1163 Header_TM_LFR_SCIENCE_SWF_t *header )
1162 1164 {
1163 1165 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1164 1166 *
1165 1167 * @param waveform points to the buffer containing the data that will be send.
1166 1168 * @param sid is the source identifier of the data that will be sent.
1167 1169 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1168 1170 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1169 1171 * contain information to setup the transmission of the data packets.
1170 1172 *
1171 1173 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1172 1174 *
1173 1175 */
1174 1176
1175 1177 unsigned int i;
1176 1178 int ret;
1177 1179 unsigned int coarseTime;
1178 1180 unsigned int fineTime;
1179 1181 rtems_status_code status;
1180 1182 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1181 1183 int *dataPtr;
1182 1184 unsigned char sid;
1183 1185
1184 1186 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1185 1187 spw_ioctl_send_SWF.options = 0;
1186 1188
1187 1189 ret = LFR_DEFAULT;
1188 1190
1189 1191 coarseTime = ring_node_to_send->coarseTime;
1190 1192 fineTime = ring_node_to_send->fineTime;
1191 1193 dataPtr = (int*) ring_node_to_send->buffer_address;
1192 1194 sid = ring_node_to_send->sid;
1193 1195
1194 1196 header->hkBIA = pa_bia_status_info;
1195 1197 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1196 1198
1197 1199 for (i=0; i<7; i++) // send waveform
1198 1200 {
1199 1201 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1200 1202 spw_ioctl_send_SWF.hdr = (char*) header;
1201 1203
1202 1204 // SET PACKET SEQUENCE CONTROL
1203 1205 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1204 1206
1205 1207 // SET PACKET LENGTH AND BLKNR
1206 1208 if (i == 6)
1207 1209 {
1208 1210 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1209 1211 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
1210 1212 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1211 1213 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
1212 1214 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1213 1215 }
1214 1216 else
1215 1217 {
1216 1218 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1217 1219 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
1218 1220 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1219 1221 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
1220 1222 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1221 1223 }
1222 1224
1223 1225 // SET PACKET TIME
1224 1226 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1225 1227 //
1226 1228 header->time[0] = header->acquisitionTime[0];
1227 1229 header->time[1] = header->acquisitionTime[1];
1228 1230 header->time[2] = header->acquisitionTime[2];
1229 1231 header->time[3] = header->acquisitionTime[3];
1230 1232 header->time[4] = header->acquisitionTime[4];
1231 1233 header->time[5] = header->acquisitionTime[5];
1232 1234
1233 1235 // SET SID
1234 1236 header->sid = sid;
1235 1237
1236 1238 // SET PKTNR
1237 1239 header->pktNr = i+1; // PKT_NR
1238 1240
1239 1241 // SEND PACKET
1240 1242 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1241 1243 if (status != RTEMS_SUCCESSFUL) {
1242 1244 ret = LFR_DEFAULT;
1243 1245 }
1244 1246 }
1245 1247
1246 1248 return ret;
1247 1249 }
1248 1250
1249 1251 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1250 1252 Header_TM_LFR_SCIENCE_CWF_t *header )
1251 1253 {
1252 1254 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1253 1255 *
1254 1256 * @param waveform points to the buffer containing the data that will be send.
1255 1257 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1256 1258 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1257 1259 * contain information to setup the transmission of the data packets.
1258 1260 *
1259 1261 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1260 1262 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1261 1263 *
1262 1264 */
1263 1265
1264 1266 unsigned int i;
1265 1267 int ret;
1266 1268 unsigned int coarseTime;
1267 1269 unsigned int fineTime;
1268 1270 rtems_status_code status;
1269 1271 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1270 1272 char *dataPtr;
1271 1273 unsigned char sid;
1272 1274
1273 1275 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1274 1276 spw_ioctl_send_CWF.options = 0;
1275 1277
1276 1278 ret = LFR_DEFAULT;
1277 1279 sid = ring_node_to_send->sid;
1278 1280
1279 1281 coarseTime = ring_node_to_send->coarseTime;
1280 1282 fineTime = ring_node_to_send->fineTime;
1281 1283 dataPtr = (char*) ring_node_to_send->buffer_address;
1282 1284
1283 1285 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
1284 1286 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1285 1287 header->hkBIA = pa_bia_status_info;
1286 1288 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1287 1289 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1288 1290 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1289 1291
1290 1292 //*********************
1291 1293 // SEND CWF3_light DATA
1292 1294 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1293 1295 {
1294 1296 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1295 1297 spw_ioctl_send_CWF.hdr = (char*) header;
1296 1298 // BUILD THE DATA
1297 1299 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1298 1300
1299 1301 // SET PACKET SEQUENCE COUNTER
1300 1302 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1301 1303
1302 1304 // SET SID
1303 1305 header->sid = sid;
1304 1306
1305 1307 // SET PACKET TIME
1306 1308 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1307 1309 //
1308 1310 header->time[0] = header->acquisitionTime[0];
1309 1311 header->time[1] = header->acquisitionTime[1];
1310 1312 header->time[2] = header->acquisitionTime[2];
1311 1313 header->time[3] = header->acquisitionTime[3];
1312 1314 header->time[4] = header->acquisitionTime[4];
1313 1315 header->time[5] = header->acquisitionTime[5];
1314 1316
1315 1317 // SET PACKET ID
1316 1318 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1317 1319 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1318 1320
1319 1321 // SEND PACKET
1320 1322 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1321 1323 if (status != RTEMS_SUCCESSFUL) {
1322 1324 ret = LFR_DEFAULT;
1323 1325 }
1324 1326 }
1325 1327
1326 1328 return ret;
1327 1329 }
1328 1330
1329 1331 void spw_send_asm_f0( ring_node *ring_node_to_send,
1330 1332 Header_TM_LFR_SCIENCE_ASM_t *header )
1331 1333 {
1332 1334 unsigned int i;
1333 1335 unsigned int length = 0;
1334 1336 rtems_status_code status;
1335 1337 unsigned int sid;
1336 1338 float *spectral_matrix;
1337 1339 int coarseTime;
1338 1340 int fineTime;
1339 1341 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1340 1342
1341 1343 sid = ring_node_to_send->sid;
1342 1344 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1343 1345 coarseTime = ring_node_to_send->coarseTime;
1344 1346 fineTime = ring_node_to_send->fineTime;
1345 1347
1346 1348 header->biaStatusInfo = pa_bia_status_info;
1347 1349 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1348 1350
1349 1351 for (i=0; i<3; i++)
1350 1352 {
1351 1353 if ((i==0) || (i==1))
1352 1354 {
1353 1355 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1354 1356 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1355 1357 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1356 1358 ];
1357 1359 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1358 1360 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1359 1361 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1360 1362 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1361 1363 }
1362 1364 else
1363 1365 {
1364 1366 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1365 1367 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1366 1368 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1367 1369 ];
1368 1370 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1369 1371 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1370 1372 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1371 1373 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1372 1374 }
1373 1375
1374 1376 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1375 1377 spw_ioctl_send_ASM.hdr = (char *) header;
1376 1378 spw_ioctl_send_ASM.options = 0;
1377 1379
1378 1380 // (2) BUILD THE HEADER
1379 1381 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1380 1382 header->packetLength[0] = (unsigned char) (length>>8);
1381 1383 header->packetLength[1] = (unsigned char) (length);
1382 1384 header->sid = (unsigned char) sid; // SID
1383 1385 header->pa_lfr_pkt_cnt_asm = 3;
1384 1386 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1385 1387
1386 1388 // (3) SET PACKET TIME
1387 1389 header->time[0] = (unsigned char) (coarseTime>>24);
1388 1390 header->time[1] = (unsigned char) (coarseTime>>16);
1389 1391 header->time[2] = (unsigned char) (coarseTime>>8);
1390 1392 header->time[3] = (unsigned char) (coarseTime);
1391 1393 header->time[4] = (unsigned char) (fineTime>>8);
1392 1394 header->time[5] = (unsigned char) (fineTime);
1393 1395 //
1394 1396 header->acquisitionTime[0] = header->time[0];
1395 1397 header->acquisitionTime[1] = header->time[1];
1396 1398 header->acquisitionTime[2] = header->time[2];
1397 1399 header->acquisitionTime[3] = header->time[3];
1398 1400 header->acquisitionTime[4] = header->time[4];
1399 1401 header->acquisitionTime[5] = header->time[5];
1400 1402
1401 1403 // (4) SEND PACKET
1402 1404 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1403 1405 if (status != RTEMS_SUCCESSFUL) {
1404 1406 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1405 1407 }
1406 1408 }
1407 1409 }
1408 1410
1409 1411 void spw_send_asm_f1( ring_node *ring_node_to_send,
1410 1412 Header_TM_LFR_SCIENCE_ASM_t *header )
1411 1413 {
1412 1414 unsigned int i;
1413 1415 unsigned int length = 0;
1414 1416 rtems_status_code status;
1415 1417 unsigned int sid;
1416 1418 float *spectral_matrix;
1417 1419 int coarseTime;
1418 1420 int fineTime;
1419 1421 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1420 1422
1421 1423 sid = ring_node_to_send->sid;
1422 1424 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1423 1425 coarseTime = ring_node_to_send->coarseTime;
1424 1426 fineTime = ring_node_to_send->fineTime;
1425 1427
1426 1428 header->biaStatusInfo = pa_bia_status_info;
1427 1429 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1428 1430
1429 1431 for (i=0; i<3; i++)
1430 1432 {
1431 1433 if ((i==0) || (i==1))
1432 1434 {
1433 1435 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1434 1436 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1435 1437 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1436 1438 ];
1437 1439 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1438 1440 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1439 1441 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1440 1442 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1441 1443 }
1442 1444 else
1443 1445 {
1444 1446 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1445 1447 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1446 1448 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1447 1449 ];
1448 1450 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1449 1451 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1450 1452 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1451 1453 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1452 1454 }
1453 1455
1454 1456 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1455 1457 spw_ioctl_send_ASM.hdr = (char *) header;
1456 1458 spw_ioctl_send_ASM.options = 0;
1457 1459
1458 1460 // (2) BUILD THE HEADER
1459 1461 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1460 1462 header->packetLength[0] = (unsigned char) (length>>8);
1461 1463 header->packetLength[1] = (unsigned char) (length);
1462 1464 header->sid = (unsigned char) sid; // SID
1463 1465 header->pa_lfr_pkt_cnt_asm = 3;
1464 1466 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1465 1467
1466 1468 // (3) SET PACKET TIME
1467 1469 header->time[0] = (unsigned char) (coarseTime>>24);
1468 1470 header->time[1] = (unsigned char) (coarseTime>>16);
1469 1471 header->time[2] = (unsigned char) (coarseTime>>8);
1470 1472 header->time[3] = (unsigned char) (coarseTime);
1471 1473 header->time[4] = (unsigned char) (fineTime>>8);
1472 1474 header->time[5] = (unsigned char) (fineTime);
1473 1475 //
1474 1476 header->acquisitionTime[0] = header->time[0];
1475 1477 header->acquisitionTime[1] = header->time[1];
1476 1478 header->acquisitionTime[2] = header->time[2];
1477 1479 header->acquisitionTime[3] = header->time[3];
1478 1480 header->acquisitionTime[4] = header->time[4];
1479 1481 header->acquisitionTime[5] = header->time[5];
1480 1482
1481 1483 // (4) SEND PACKET
1482 1484 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1483 1485 if (status != RTEMS_SUCCESSFUL) {
1484 1486 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1485 1487 }
1486 1488 }
1487 1489 }
1488 1490
1489 1491 void spw_send_asm_f2( ring_node *ring_node_to_send,
1490 1492 Header_TM_LFR_SCIENCE_ASM_t *header )
1491 1493 {
1492 1494 unsigned int i;
1493 1495 unsigned int length = 0;
1494 1496 rtems_status_code status;
1495 1497 unsigned int sid;
1496 1498 float *spectral_matrix;
1497 1499 int coarseTime;
1498 1500 int fineTime;
1499 1501 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1500 1502
1501 1503 sid = ring_node_to_send->sid;
1502 1504 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1503 1505 coarseTime = ring_node_to_send->coarseTime;
1504 1506 fineTime = ring_node_to_send->fineTime;
1505 1507
1506 1508 header->biaStatusInfo = pa_bia_status_info;
1507 1509 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1508 1510
1509 1511 for (i=0; i<3; i++)
1510 1512 {
1511 1513
1512 1514 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1513 1515 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1514 1516 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1515 1517 ];
1516 1518 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1517 1519 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1518 1520 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1519 1521 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1520 1522
1521 1523 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1522 1524 spw_ioctl_send_ASM.hdr = (char *) header;
1523 1525 spw_ioctl_send_ASM.options = 0;
1524 1526
1525 1527 // (2) BUILD THE HEADER
1526 1528 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1527 1529 header->packetLength[0] = (unsigned char) (length>>8);
1528 1530 header->packetLength[1] = (unsigned char) (length);
1529 1531 header->sid = (unsigned char) sid; // SID
1530 1532 header->pa_lfr_pkt_cnt_asm = 3;
1531 1533 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1532 1534
1533 1535 // (3) SET PACKET TIME
1534 1536 header->time[0] = (unsigned char) (coarseTime>>24);
1535 1537 header->time[1] = (unsigned char) (coarseTime>>16);
1536 1538 header->time[2] = (unsigned char) (coarseTime>>8);
1537 1539 header->time[3] = (unsigned char) (coarseTime);
1538 1540 header->time[4] = (unsigned char) (fineTime>>8);
1539 1541 header->time[5] = (unsigned char) (fineTime);
1540 1542 //
1541 1543 header->acquisitionTime[0] = header->time[0];
1542 1544 header->acquisitionTime[1] = header->time[1];
1543 1545 header->acquisitionTime[2] = header->time[2];
1544 1546 header->acquisitionTime[3] = header->time[3];
1545 1547 header->acquisitionTime[4] = header->time[4];
1546 1548 header->acquisitionTime[5] = header->time[5];
1547 1549
1548 1550 // (4) SEND PACKET
1549 1551 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1550 1552 if (status != RTEMS_SUCCESSFUL) {
1551 1553 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1552 1554 }
1553 1555 }
1554 1556 }
1555 1557
1556 1558 void spw_send_k_dump( ring_node *ring_node_to_send )
1557 1559 {
1558 1560 rtems_status_code status;
1559 1561 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1560 1562 unsigned int packetLength;
1561 1563 unsigned int size;
1562 1564
1563 1565 PRINTF("spw_send_k_dump\n")
1564 1566
1565 1567 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1566 1568
1567 1569 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1568 1570
1569 1571 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1570 1572
1571 1573 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1572 1574
1573 1575 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1574 1576
1575 1577 if (status == -1){
1576 1578 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1577 1579 }
1578 1580
1579 1581 ring_node_to_send->status = 0x00;
1580 1582 }
General Comments 0
You need to be logged in to leave comments. Login now