##// END OF EJS Templates
two fields added to the housekeeping parameters:...
paul -
r265:09ea64972ca9 R3a
parent child
Show More
@@ -1,57 +1,56
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 extern spw_stats spw_backup;
18 17 extern rtems_name timecode_timer_name;
19 18 extern rtems_id timecode_timer_id;
20 19
21 20 // RTEMS TASK
22 21 rtems_task spiq_task( rtems_task_argument argument );
23 22 rtems_task recv_task( rtems_task_argument unused );
24 23 rtems_task send_task( rtems_task_argument argument );
25 24 rtems_task link_task( rtems_task_argument argument );
26 25
27 26 int spacewire_open_link( void );
28 27 int spacewire_start_link( int fd );
29 28 int spacewire_stop_and_start_link( int fd );
30 29 int spacewire_configure_link(int fd );
31 30 int spacewire_several_connect_attemps( void );
32 31 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
33 32 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
34 33 void spacewire_read_statistics( void );
35 34 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code);
36 35 void update_hk_with_grspw_stats(void );
37 36 void increase_unsigned_char_counter( unsigned char *counter );
38 37
39 38 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
40 39 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
41 40 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
42 41 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
43 42 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
44 43 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
45 44 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
46 45 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
47 46 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
48 47 void spw_send_k_dump( ring_node *ring_node_to_send );
49 48
50 49 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
51 50 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
52 51 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
53 52 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
54 53
55 54 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
56 55
57 56 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,83 +1,80
1 1 /** Global variables of the LFR flight software.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * Among global variables, there are:
7 7 * - RTEMS names and id.
8 8 * - APB configuration registers.
9 9 * - waveforms global buffers, used by the waveform picker hardware module to store data.
10 10 * - spectral matrices buffesr, used by the hardware module to store data.
11 11 * - variable related to LFR modes parameters.
12 12 * - the global HK packet buffer.
13 13 * - the global dump parameter buffer.
14 14 *
15 15 */
16 16
17 17 #include <rtems.h>
18 18 #include <grspw.h>
19 19
20 20 #include "ccsds_types.h"
21 21 #include "grlib_regs.h"
22 22 #include "fsw_params.h"
23 23 #include "fsw_params_wf_handler.h"
24 24
25 25 // RTEMS GLOBAL VARIABLES
26 26 rtems_name misc_name[5];
27 27 rtems_name Task_name[20]; /* array of task names */
28 28 rtems_id Task_id[20]; /* array of task ids */
29 29 rtems_name timecode_timer_name;
30 30 rtems_id timecode_timer_id;
31 31 int fdSPW = 0;
32 32 int fdUART = 0;
33 33 unsigned char lfrCurrentMode;
34 34 unsigned char pa_bia_status_info;
35 35 unsigned char thisIsAnASMRestart = 0;
36 36
37 37 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
38 38 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
39 39 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
40 40 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
41 41 // F0 F1 F2 F3
42 42 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
43 43 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
44 44 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
45 45 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
46 46
47 47 //***********************************
48 48 // SPECTRAL MATRICES GLOBAL VARIABLES
49 49
50 50 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
51 51 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
52 52 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
53 53 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
54 54
55 55 // APB CONFIGURATION REGISTERS
56 56 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
57 57 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
58 58 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
59 59 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
60 60
61 61 // MODE PARAMETERS
62 62 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet;
63 63 struct param_local_str param_local;
64 64 unsigned int lastValidEnterModeTime;
65 65
66 66 // HK PACKETS
67 67 Packet_TM_LFR_HK_t housekeeping_packet;
68 68 // message queues occupancy
69 69 unsigned char hk_lfr_q_sd_fifo_size_max;
70 70 unsigned char hk_lfr_q_rv_fifo_size_max;
71 71 unsigned char hk_lfr_q_p0_fifo_size_max;
72 72 unsigned char hk_lfr_q_p1_fifo_size_max;
73 73 unsigned char hk_lfr_q_p2_fifo_size_max;
74 74 // sequence counters are incremented by APID (PID + CAT) and destination ID
75 75 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST;
76 76 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2;
77 77 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID];
78 78 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID];
79 79 unsigned short sequenceCounterHK;
80 80 spw_stats grspw_stats;
81 spw_stats spw_backup;
82
83
@@ -1,1569 +1,1580
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 /** This function reads the SpaceWire statistics from the grspw RTEMS driver.
571 *
572 * @param void
573 *
574 * @return void
575 *
576 * Once they are read, the counters are stored in a global variable used during the building of the
577 * HK packets.
578 *
579 */
580
570 581 rtems_status_code status;
571 582 spw_stats current;
572 583
573 584 // read the current statistics
574 585 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
575 586
576 587 // clear the counters
577 588 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
578 589
579 590 // typedef struct {
580 591 // unsigned int tx_link_err; // NOT IN HK
581 592 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
582 593 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
583 594 // unsigned int rx_eep_err;
584 595 // unsigned int rx_truncated;
585 596 // unsigned int parity_err;
586 597 // unsigned int escape_err;
587 598 // unsigned int credit_err;
588 599 // unsigned int write_sync_err;
589 600 // unsigned int disconnect_err;
590 601 // unsigned int early_ep;
591 602 // unsigned int invalid_address;
592 603 // unsigned int packets_sent;
593 604 // unsigned int packets_received;
594 605 // } spw_stats;
595 606
596 607 // rx_eep_err
597 608 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
598 609 // rx_truncated
599 610 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
600 611 // parity_err
601 612 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
602 613 // escape_err
603 614 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
604 615 // credit_err
605 616 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
606 617 // write_sync_err
607 618 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
608 619 // disconnect_err
609 620 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
610 621 // early_ep
611 622 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
612 623 // invalid_address
613 624 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
614 625 // packets_sent
615 626 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
616 627 // packets_received
617 628 grspw_stats.packets_received= grspw_stats.packets_received + current.packets_received;
618 629
619 630 }
620 631
621 632 void spacewire_get_last_error( void )
622 633 {
623 634 static spw_stats previous;
624 635 spw_stats current;
625 636 rtems_status_code status;
626 637
627 638 unsigned int hk_lfr_last_er_rid;
628 639 unsigned char hk_lfr_last_er_code;
629 640 int coarseTime;
630 641 int fineTime;
631 642 unsigned char update_hk_lfr_last_er;
632 643
633 644 update_hk_lfr_last_er = 0;
634 645
635 646 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
636 647
637 648 // get current time
638 649 coarseTime = time_management_regs->coarse_time;
639 650 fineTime = time_management_regs->fine_time;
640 651
641 652 // typedef struct {
642 653 // unsigned int tx_link_err; // NOT IN HK
643 654 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
644 655 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
645 656 // unsigned int rx_eep_err;
646 657 // unsigned int rx_truncated;
647 658 // unsigned int parity_err;
648 659 // unsigned int escape_err;
649 660 // unsigned int credit_err;
650 661 // unsigned int write_sync_err;
651 662 // unsigned int disconnect_err;
652 663 // unsigned int early_ep;
653 664 // unsigned int invalid_address;
654 665 // unsigned int packets_sent;
655 666 // unsigned int packets_received;
656 667 // } spw_stats;
657 668
658 669 // tx_link_err *** no code associated to this field
659 670 // rx_rmap_header_crc_err *** LE *** in HK
660 671 if (previous.rx_rmap_header_crc_err != current.rx_rmap_header_crc_err)
661 672 {
662 673 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
663 674 hk_lfr_last_er_code = CODE_HEADER_CRC;
664 675 update_hk_lfr_last_er = 1;
665 676 }
666 677 // rx_rmap_data_crc_err *** LE *** NOT IN HK
667 678 if (previous.rx_rmap_data_crc_err != current.rx_rmap_data_crc_err)
668 679 {
669 680 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
670 681 hk_lfr_last_er_code = CODE_DATA_CRC;
671 682 update_hk_lfr_last_er = 1;
672 683 }
673 684 // rx_eep_err
674 685 if (previous.rx_eep_err != current.rx_eep_err)
675 686 {
676 687 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
677 688 hk_lfr_last_er_code = CODE_EEP;
678 689 update_hk_lfr_last_er = 1;
679 690 }
680 691 // rx_truncated
681 692 if (previous.rx_truncated != current.rx_truncated)
682 693 {
683 694 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
684 695 hk_lfr_last_er_code = CODE_RX_TOO_BIG;
685 696 update_hk_lfr_last_er = 1;
686 697 }
687 698 // parity_err
688 699 if (previous.parity_err != current.parity_err)
689 700 {
690 701 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
691 702 hk_lfr_last_er_code = CODE_PARITY;
692 703 update_hk_lfr_last_er = 1;
693 704 }
694 705 // escape_err
695 706 if (previous.parity_err != current.parity_err)
696 707 {
697 708 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
698 709 hk_lfr_last_er_code = CODE_ESCAPE;
699 710 update_hk_lfr_last_er = 1;
700 711 }
701 712 // credit_err
702 713 if (previous.credit_err != current.credit_err)
703 714 {
704 715 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
705 716 hk_lfr_last_er_code = CODE_CREDIT;
706 717 update_hk_lfr_last_er = 1;
707 718 }
708 719 // write_sync_err
709 720 if (previous.write_sync_err != current.write_sync_err)
710 721 {
711 722 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
712 723 hk_lfr_last_er_code = CODE_WRITE_SYNC;
713 724 update_hk_lfr_last_er = 1;
714 725 }
715 726 // disconnect_err
716 727 if (previous.disconnect_err != current.disconnect_err)
717 728 {
718 729 hk_lfr_last_er_rid = RID_LE_LFR_DPU_SPW;
719 730 hk_lfr_last_er_code = CODE_DISCONNECT;
720 731 update_hk_lfr_last_er = 1;
721 732 }
722 733 // early_ep
723 734 if (previous.early_ep != current.early_ep)
724 735 {
725 736 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
726 737 hk_lfr_last_er_code = CODE_EARLY_EOP_EEP;
727 738 update_hk_lfr_last_er = 1;
728 739 }
729 740 // invalid_address
730 741 if (previous.invalid_address != current.invalid_address)
731 742 {
732 743 hk_lfr_last_er_rid = RID_ME_LFR_DPU_SPW;
733 744 hk_lfr_last_er_code = CODE_INVALID_ADDRESS;
734 745 update_hk_lfr_last_er = 1;
735 746 }
736 747
737 748 // if a field has changed, update the hk_last_er fields
738 749 if (update_hk_lfr_last_er == 1)
739 750 {
740 751 update_hk_lfr_last_er_fields( hk_lfr_last_er_rid, hk_lfr_last_er_code );
741 752 }
742 753
743 754 previous = current;
744 755 }
745 756
746 757 void update_hk_lfr_last_er_fields(unsigned int rid, unsigned char code)
747 758 {
748 759 unsigned char *coarseTimePtr;
749 760 unsigned char *fineTimePtr;
750 761
751 762 coarseTimePtr = (unsigned char*) &time_management_regs->coarse_time;
752 763 fineTimePtr = (unsigned char*) &time_management_regs->fine_time;
753 764
754 765 housekeeping_packet.hk_lfr_last_er_rid[0] = (unsigned char) ((rid & 0xff00) >> 8 );
755