##// END OF EJS Templates
rev 2.0.2.3...
paul -
r191:88d58b8c0419 VHDL_0_1_28
parent child
Show More
@@ -0,0 +1,13
1 # LOAD FSW USING LINK 1
2 SpwPlugin0.StarDundeeSelectLinkNumber( 1 )
3
4 dsu3plugin0.openFile("/opt/DEV_PLE/FSW-qt/bin/fsw")
5 dsu3plugin0.loadFile()
6
7 dsu3plugin0.run()
8
9 # START SENDING TIMECODES AT 1 Hz
10 SpwPlugin0.StarDundeeStartTimecodes( 1 )
11
12 # it is possible to change the time code frequency
13 #RMAPPlugin0.changeTimecodeFrequency(2)
@@ -0,0 +1,12
1 # LOAD FSW USING LINK 1
2 SpwPlugin0.StarDundeeSelectLinkNumber( 2 )
3
4 dsu3plugin0.openFile("/opt/DEV_PLE/timegen-qt/bin/timegen")
5 dsu3plugin0.loadFile()
6
7 dsu3plugin0.run()
8
9 # START SENDING TIMECODES AT 1 Hz
10 SpwPlugin0.StarDundeeStartTimecodes( 1 )
11
12 SpwPlugin0.StarDundeeSelectLinkNumber( 1 )
@@ -0,0 +1,29
1 #!/usr/bin/lppmon -e
2
3 import time
4
5 proxy.loadSysDriver("SpwPlugin","SpwPlugin0")
6 SpwPlugin0.selectBridge("STAR-Dundee Spw USB Brick")
7
8 proxy.loadSysDriverToParent("dsu3plugin","SpwPlugin0")
9 proxy.loadSysDriverToParent("LFRControlPlugin","SpwPlugin0")
10
11 availableBrickCount = SpwPlugin0.StarDundeeGetAvailableBrickCount()
12 print "availableBrickCount = ", availableBrickCount
13
14 SpwPlugin0.StarDundeeSelectBrick(1)
15 SpwPlugin0.StarDundeeSetBrickAsARouter(1)
16 SpwPlugin0.connectBridge()
17
18 #SpwPlugin0.TCPServerSetIP("127.0.0.1")
19 SpwPlugin0.TCPServerConnect()
20
21 #LFRControlPlugin0.SetSpwServerIP(129,104,27,164)
22 LFRControlPlugin0.TCPServerConnect()
23
24 dsu3plugin0.openFile("/opt/DEV_PLE/FSW-qt/bin/fsw")
25 dsu3plugin0.loadFile()
26 dsu3plugin0.run()
27
28 LFRControlPlugin0.TMEchoBridgeOpenPort()
29
@@ -1,21 +1,22
1 1 syntax: glob
2 2 *.pdf
3 3 *~
4 4 *.o
5 5 *.gcno
6 6 *.gcda
7 7 *.html
8 8 *.zip
9 9 tests/*.err
10 10 doc
11 11 *.srec
12 12 FSW-qt/bin/fsw
13 timegen-qt/bin/timegen
13 14 src/LFR_basic-parameters
14 15 *.pro.user.*
15 16 FSW-qt/bin/spectralmatrix/asm_f0_test_20140403_case1.txt
16 17 FSW-qt/bin/spectralmatrix/asm_f0_test_20140403_case2.txt
17 18 FSW-qt/bin/spectralmatrix/asm_f0_test_paul_1.txt
18 19 run2/src
19 20 run2/trace
20 21 run3/src
21 22 run3/trace
@@ -1,2 +1,2
1 1 a586fe639ac179e95bdc150ebdbab0312f31dc30 LFR_basic-parameters
2 be0dc1c1876987307ddfc0fb47044f6d41815866 header/lfr_common_headers
2 611fe904e4b4e05736a8a618c561980d10bceead header/lfr_common_headers
@@ -1,112 +1,112
1 1 TEMPLATE = app
2 2 # CONFIG += console v8 sim
3 3 # CONFIG options = verbose *** boot_messages *** debug_messages *** cpu_usage_report *** stack_report *** vhdl_dev *** debug_tch
4 4 # lpp_dpu_destid
5 5 CONFIG += console verbose lpp_dpu_destid
6 6 CONFIG -= qt
7 7
8 8 include(./sparc.pri)
9 9
10 10 # flight software version
11 11 SWVERSION=-1-0
12 12 DEFINES += SW_VERSION_N1=2 # major
13 13 DEFINES += SW_VERSION_N2=0 # minor
14 14 DEFINES += SW_VERSION_N3=2 # patch
15 DEFINES += SW_VERSION_N4=2 # internal
15 DEFINES += SW_VERSION_N4=3 # internal
16 16
17 17 # <GCOV>
18 18 #QMAKE_CFLAGS_RELEASE += -fprofile-arcs -ftest-coverage
19 19 #LIBS += -lgcov /opt/GCOV/01A/lib/overload.o -lc
20 20 # </GCOV>
21 21
22 22 # <CHANGE BEFORE FLIGHT>
23 23 contains( CONFIG, lpp_dpu_destid ) {
24 24 DEFINES += LPP_DPU_DESTID
25 25 }
26 26 # </CHANGE BEFORE FLIGHT>
27 27
28 28 contains( CONFIG, debug_tch ) {
29 29 DEFINES += DEBUG_TCH
30 30 }
31 31 DEFINES += MSB_FIRST_TCH
32 32
33 33 contains( CONFIG, vhdl_dev ) {
34 34 DEFINES += VHDL_DEV
35 35 }
36 36
37 37 contains( CONFIG, verbose ) {
38 38 DEFINES += PRINT_MESSAGES_ON_CONSOLE
39 39 }
40 40
41 41 contains( CONFIG, debug_messages ) {
42 42 DEFINES += DEBUG_MESSAGES
43 43 }
44 44
45 45 contains( CONFIG, cpu_usage_report ) {
46 46 DEFINES += PRINT_TASK_STATISTICS
47 47 }
48 48
49 49 contains( CONFIG, stack_report ) {
50 50 DEFINES += PRINT_STACK_REPORT
51 51 }
52 52
53 53 contains( CONFIG, boot_messages ) {
54 54 DEFINES += BOOT_MESSAGES
55 55 }
56 56
57 57 #doxygen.target = doxygen
58 58 #doxygen.commands = doxygen ../doc/Doxyfile
59 59 #QMAKE_EXTRA_TARGETS += doxygen
60 60
61 61 TARGET = fsw
62 62
63 63 INCLUDEPATH += \
64 64 $${PWD}/../src \
65 65 $${PWD}/../header \
66 66 $${PWD}/../header/lfr_common_headers \
67 67 $${PWD}/../header/processing \
68 68 $${PWD}/../LFR_basic-parameters
69 69
70 70 SOURCES += \
71 71 ../src/wf_handler.c \
72 72 ../src/tc_handler.c \
73 73 ../src/fsw_misc.c \
74 74 ../src/fsw_init.c \
75 75 ../src/fsw_globals.c \
76 76 ../src/fsw_spacewire.c \
77 77 ../src/tc_load_dump_parameters.c \
78 78 ../src/tm_lfr_tc_exe.c \
79 79 ../src/tc_acceptance.c \
80 80 ../src/processing/fsw_processing.c \
81 81 ../src/processing/avf0_prc0.c \
82 82 ../src/processing/avf1_prc1.c \
83 83 ../src/processing/avf2_prc2.c \
84 84 ../src/lfr_cpu_usage_report.c \
85 85 ../LFR_basic-parameters/basic_parameters.c
86 86
87 87 HEADERS += \
88 88 ../header/wf_handler.h \
89 89 ../header/tc_handler.h \
90 90 ../header/grlib_regs.h \
91 91 ../header/fsw_misc.h \
92 92 ../header/fsw_init.h \
93 93 ../header/fsw_spacewire.h \
94 94 ../header/tc_load_dump_parameters.h \
95 95 ../header/tm_lfr_tc_exe.h \
96 96 ../header/tc_acceptance.h \
97 97 ../header/processing/fsw_processing.h \
98 98 ../header/processing/avf0_prc0.h \
99 99 ../header/processing/avf1_prc1.h \
100 100 ../header/processing/avf2_prc2.h \
101 101 ../header/fsw_params_wf_handler.h \
102 102 ../header/lfr_cpu_usage_report.h \
103 103 ../header/lfr_common_headers/ccsds_types.h \
104 104 ../header/lfr_common_headers/fsw_params.h \
105 105 ../header/lfr_common_headers/fsw_params_nb_bytes.h \
106 106 ../header/lfr_common_headers/fsw_params_processing.h \
107 107 ../header/lfr_common_headers/TC_types.h \
108 108 ../header/lfr_common_headers/tm_byte_positions.h \
109 109 ../LFR_basic-parameters/basic_parameters.h \
110 110 ../LFR_basic-parameters/basic_parameters_params.h \
111 111 ../header/GscMemoryLPP.hpp
112 112
@@ -1,1117 +1,1117
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 //***********
26 26 // RTEMS TASK
27 27 rtems_task spiq_task(rtems_task_argument unused)
28 28 {
29 29 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
30 30 *
31 31 * @param unused is the starting argument of the RTEMS task
32 32 *
33 33 */
34 34
35 35 rtems_event_set event_out;
36 36 rtems_status_code status;
37 37 int linkStatus;
38 38
39 39 BOOT_PRINTF("in SPIQ *** \n")
40 40
41 41 while(true){
42 42 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
43 43 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
44 44
45 45 // [0] SUSPEND RECV AND SEND TASKS
46 46 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
47 47 if ( status != RTEMS_SUCCESSFUL ) {
48 48 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
49 49 }
50 50 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
51 51 if ( status != RTEMS_SUCCESSFUL ) {
52 52 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
53 53 }
54 54
55 55 // [1] CHECK THE LINK
56 56 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
57 57 if ( linkStatus != 5) {
58 58 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
59 59 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
60 60 }
61 61
62 62 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
63 63 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
64 64 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
65 65 {
66 66 spacewire_compute_stats_offsets();
67 67 status = spacewire_reset_link( );
68 68 }
69 69 else // [2.b] in run state, start the link
70 70 {
71 71 status = spacewire_stop_and_start_link( fdSPW ); // start the link
72 72 if ( status != RTEMS_SUCCESSFUL)
73 73 {
74 74 PRINTF1("in SPIQ *** ERR spacewire_start_link %d\n", status)
75 75 }
76 76 }
77 77
78 78 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
79 79 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
80 80 {
81 81 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
82 82 if ( status != RTEMS_SUCCESSFUL ) {
83 83 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
84 84 }
85 85 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
86 86 if ( status != RTEMS_SUCCESSFUL ) {
87 87 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
88 88 }
89 89 }
90 90 else // [3.b] the link is not in run state, go in STANDBY mode
91 91 {
92 92 status = stop_current_mode();
93 93 if ( status != RTEMS_SUCCESSFUL ) {
94 94 PRINTF1("in SPIQ *** ERR stop_current_mode *** code %d\n", status)
95 95 }
96 96 status = enter_mode( LFR_MODE_STANDBY, 0 );
97 97 if ( status != RTEMS_SUCCESSFUL ) {
98 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
99 99 }
100 100 // wake the WTDG task up to wait for the link recovery
101 101 status = rtems_event_send ( Task_id[TASKID_WTDG], RTEMS_EVENT_0 );
102 102 status = rtems_task_suspend( RTEMS_SELF );
103 103 }
104 104 }
105 105 }
106 106
107 107 rtems_task recv_task( rtems_task_argument unused )
108 108 {
109 109 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
110 110 *
111 111 * @param unused is the starting argument of the RTEMS task
112 112 *
113 113 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
114 114 * 1. It reads the incoming data.
115 115 * 2. Launches the acceptance procedure.
116 116 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
117 117 *
118 118 */
119 119
120 120 int len;
121 121 ccsdsTelecommandPacket_t currentTC;
122 122 unsigned char computed_CRC[ 2 ];
123 123 unsigned char currentTC_LEN_RCV[ 2 ];
124 124 unsigned char destinationID;
125 125 unsigned int estimatedPacketLength;
126 126 unsigned int parserCode;
127 127 rtems_status_code status;
128 128 rtems_id queue_recv_id;
129 129 rtems_id queue_send_id;
130 130
131 131 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
132 132
133 133 status = get_message_queue_id_recv( &queue_recv_id );
134 134 if (status != RTEMS_SUCCESSFUL)
135 135 {
136 136 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
137 137 }
138 138
139 139 status = get_message_queue_id_send( &queue_send_id );
140 140 if (status != RTEMS_SUCCESSFUL)
141 141 {
142 142 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
143 143 }
144 144
145 145 BOOT_PRINTF("in RECV *** \n")
146 146
147 147 while(1)
148 148 {
149 149 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
150 150 if (len == -1){ // error during the read call
151 151 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
152 152 }
153 153 else {
154 154 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
155 155 PRINTF("in RECV *** packet lenght too short\n")
156 156 }
157 157 else {
158 158 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
159 159 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
160 160 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
161 161 // CHECK THE TC
162 162 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
163 163 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
164 164 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
165 165 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
166 166 || (parserCode == WRONG_SRC_ID) )
167 167 { // send TM_LFR_TC_EXE_CORRUPTED
168 168 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
169 169 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
170 170 &&
171 171 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
172 172 )
173 173 {
174 174 if ( parserCode == WRONG_SRC_ID )
175 175 {
176 176 destinationID = SID_TC_GROUND;
177 177 }
178 178 else
179 179 {
180 180 destinationID = currentTC.sourceID;
181 181 }
182 182 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
183 183 computed_CRC, currentTC_LEN_RCV,
184 184 destinationID );
185 185 }
186 186 }
187 187 else
188 188 { // send valid TC to the action launcher
189 189 status = rtems_message_queue_send( queue_recv_id, &currentTC,
190 190 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
191 191 }
192 192 }
193 193 }
194 194 }
195 195 }
196 196
197 197 rtems_task send_task( rtems_task_argument argument)
198 198 {
199 199 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
200 200 *
201 201 * @param unused is the starting argument of the RTEMS task
202 202 *
203 203 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
204 204 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
205 205 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
206 206 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
207 207 * data it contains.
208 208 *
209 209 */
210 210
211 211 rtems_status_code status; // RTEMS status code
212 212 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
213 213 ring_node *incomingRingNodePtr;
214 214 int ring_node_address;
215 215 char *charPtr;
216 216 spw_ioctl_pkt_send *spw_ioctl_send;
217 217 size_t size; // size of the incoming TC packet
218 218 u_int32_t count;
219 219 rtems_id queue_id;
220 220 unsigned char sid;
221 221
222 222 incomingRingNodePtr = NULL;
223 223 ring_node_address = 0;
224 224 charPtr = (char *) &ring_node_address;
225 225 sid = 0;
226 226
227 227 init_header_cwf( &headerCWF );
228 228 init_header_swf( &headerSWF );
229 229 init_header_asm( &headerASM );
230 230
231 231 status = get_message_queue_id_send( &queue_id );
232 232 if (status != RTEMS_SUCCESSFUL)
233 233 {
234 234 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
235 235 }
236 236
237 237 BOOT_PRINTF("in SEND *** \n")
238 238
239 239 while(1)
240 240 {
241 241 status = rtems_message_queue_receive( queue_id, incomingData, &size,
242 242 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
243 243
244 244 if (status!=RTEMS_SUCCESSFUL)
245 245 {
246 246 PRINTF1("in SEND *** (1) ERR = %d\n", status)
247 247 }
248 248 else
249 249 {
250 250 if ( size == sizeof(ring_node*) )
251 251 {
252 252 charPtr[0] = incomingData[0];
253 253 charPtr[1] = incomingData[1];
254 254 charPtr[2] = incomingData[2];
255 255 charPtr[3] = incomingData[3];
256 256 incomingRingNodePtr = (ring_node*) ring_node_address;
257 257 sid = incomingRingNodePtr->sid;
258 258 if ( (sid==SID_NORM_CWF_LONG_F3)
259 259 || (sid==SID_BURST_CWF_F2 )
260 260 || (sid==SID_SBM1_CWF_F1 )
261 261 || (sid==SID_SBM2_CWF_F2 ))
262 262 {
263 263 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
264 264 }
265 265 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
266 266 {
267 267 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
268 268 }
269 269 else if ( (sid==SID_NORM_CWF_F3) )
270 270 {
271 271 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
272 272 }
273 273 else if ( (sid==SID_NORM_ASM_F0) || (SID_NORM_ASM_F1) || (SID_NORM_ASM_F2) )
274 274 {
275 275 spw_send_asm( incomingRingNodePtr, &headerASM );
276 276 }
277 277 else
278 278 {
279 279 printf("unexpected sid = %d\n", sid);
280 280 }
281 281 }
282 282 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
283 283 {
284 284 status = write( fdSPW, incomingData, size );
285 285 if (status == -1){
286 286 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
287 287 }
288 288 }
289 289 else // the incoming message is a spw_ioctl_pkt_send structure
290 290 {
291 291 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
292 292 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
293 293 if (status == -1){
294 294 printf("size = %d, %x, %x, %x, %x, %x\n",
295 295 size,
296 296 incomingData[0],
297 297 incomingData[1],
298 298 incomingData[2],
299 299 incomingData[3],
300 300 incomingData[4]);
301 301 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
302 302 }
303 303 }
304 304 }
305 305
306 306 status = rtems_message_queue_get_number_pending( queue_id, &count );
307 307 if (status != RTEMS_SUCCESSFUL)
308 308 {
309 309 PRINTF1("in SEND *** (3) ERR = %d\n", status)
310 310 }
311 311 else
312 312 {
313 313 if (count > maxCount)
314 314 {
315 315 maxCount = count;
316 316 }
317 317 }
318 318 }
319 319 }
320 320
321 321 rtems_task wtdg_task( rtems_task_argument argument )
322 322 {
323 323 rtems_event_set event_out;
324 324 rtems_status_code status;
325 325 int linkStatus;
326 326
327 327 BOOT_PRINTF("in WTDG ***\n")
328 328
329 329 while(1)
330 330 {
331 331 // wait for an RTEMS_EVENT
332 332 rtems_event_receive( RTEMS_EVENT_0,
333 333 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
334 334 PRINTF("in WTDG *** wait for the link\n")
335 335 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
336 336 while( linkStatus != 5) // wait for the link
337 337 {
338 338 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
339 339 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
340 340 }
341 341
342 342 status = spacewire_stop_and_start_link( fdSPW );
343 343
344 344 if (status != RTEMS_SUCCESSFUL)
345 345 {
346 346 PRINTF1("in WTDG *** ERR link not started %d\n", status)
347 347 }
348 348 else
349 349 {
350 350 PRINTF("in WTDG *** OK link started\n")
351 351 }
352 352
353 353 // restart the SPIQ task
354 354 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
355 355 if ( status != RTEMS_SUCCESSFUL ) {
356 356 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
357 357 }
358 358
359 359 // restart RECV and SEND
360 360 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
361 361 if ( status != RTEMS_SUCCESSFUL ) {
362 362 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
363 363 }
364 364 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
365 365 if ( status != RTEMS_SUCCESSFUL ) {
366 366 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
367 367 }
368 368 }
369 369 }
370 370
371 371 //****************
372 372 // OTHER FUNCTIONS
373 373 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
374 374 {
375 375 /** This function opens the SpaceWire link.
376 376 *
377 377 * @return a valid file descriptor in case of success, -1 in case of a failure
378 378 *
379 379 */
380 380 rtems_status_code status;
381 381
382 382 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
383 383 if ( fdSPW < 0 ) {
384 384 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
385 385 }
386 386 else
387 387 {
388 388 status = RTEMS_SUCCESSFUL;
389 389 }
390 390
391 391 return status;
392 392 }
393 393
394 394 int spacewire_start_link( int fd )
395 395 {
396 396 rtems_status_code status;
397 397
398 398 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
399 399 // -1 default hardcoded driver timeout
400 400
401 401 return status;
402 402 }
403 403
404 404 int spacewire_stop_and_start_link( int fd )
405 405 {
406 406 rtems_status_code status;
407 407
408 408 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
409 409 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
410 410 // -1 default hardcoded driver timeout
411 411
412 412 return status;
413 413 }
414 414
415 415 int spacewire_configure_link( int fd )
416 416 {
417 417 /** This function configures the SpaceWire link.
418 418 *
419 419 * @return GR-RTEMS-DRIVER directive status codes:
420 420 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
421 421 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
422 422 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
423 423 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
424 424 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
425 425 * - 5 EIO - Error when writing to grswp hardware registers.
426 426 * - 2 ENOENT - No such file or directory
427 427 */
428 428
429 429 rtems_status_code status;
430 430
431 431 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
432 432 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
433 433
434 434 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
435 435 if (status!=RTEMS_SUCCESSFUL) {
436 436 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
437 437 }
438 438 //
439 439 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
440 440 if (status!=RTEMS_SUCCESSFUL) {
441 441 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
442 442 }
443 443 //
444 444 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
445 445 if (status!=RTEMS_SUCCESSFUL) {
446 446 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
447 447 }
448 448 //
449 449 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
450 450 if (status!=RTEMS_SUCCESSFUL) {
451 451 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
452 452 }
453 453 //
454 454 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
455 455 if (status!=RTEMS_SUCCESSFUL) {
456 456 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
457 457 }
458 458 //
459 459 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
460 460 if (status!=RTEMS_SUCCESSFUL) {
461 461 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
462 462 }
463 463 //
464 464 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
465 465 if (status!=RTEMS_SUCCESSFUL) {
466 466 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
467 467 }
468 468
469 469 return status;
470 470 }
471 471
472 472 int spacewire_reset_link( void )
473 473 {
474 474 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
475 475 *
476 476 * @return RTEMS directive status code:
477 477 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
478 478 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
479 479 *
480 480 */
481 481
482 482 rtems_status_code status_spw;
483 483 rtems_status_code status;
484 484 int i;
485 485
486 486 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
487 487 {
488 488 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
489 489
490 490 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
491 491
492 492 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
493 493
494 494 status_spw = spacewire_stop_and_start_link( fdSPW );
495 495 if ( status_spw != RTEMS_SUCCESSFUL )
496 496 {
497 497 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
498 498 }
499 499
500 500 if ( status_spw == RTEMS_SUCCESSFUL)
501 501 {
502 502 break;
503 503 }
504 504 }
505 505
506 506 return status_spw;
507 507 }
508 508
509 509 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
510 510 {
511 511 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
512 512 *
513 513 * @param val is the value, 0 or 1, used to set the value of the NP bit.
514 514 * @param regAddr is the address of the GRSPW control register.
515 515 *
516 516 * NP is the bit 20 of the GRSPW control register.
517 517 *
518 518 */
519 519
520 520 unsigned int *spwptr = (unsigned int*) regAddr;
521 521
522 522 if (val == 1) {
523 523 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
524 524 }
525 525 if (val== 0) {
526 526 *spwptr = *spwptr & 0xffdfffff;
527 527 }
528 528 }
529 529
530 530 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
531 531 {
532 532 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
533 533 *
534 534 * @param val is the value, 0 or 1, used to set the value of the RE bit.
535 535 * @param regAddr is the address of the GRSPW control register.
536 536 *
537 537 * RE is the bit 16 of the GRSPW control register.
538 538 *
539 539 */
540 540
541 541 unsigned int *spwptr = (unsigned int*) regAddr;
542 542
543 543 if (val == 1)
544 544 {
545 545 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
546 546 }
547 547 if (val== 0)
548 548 {
549 549 *spwptr = *spwptr & 0xfffdffff;
550 550 }
551 551 }
552 552
553 553 void spacewire_compute_stats_offsets( void )
554 554 {
555 555 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
556 556 *
557 557 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
558 558 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
559 559 * during the open systel call).
560 560 *
561 561 */
562 562
563 563 spw_stats spacewire_stats_grspw;
564 564 rtems_status_code status;
565 565
566 566 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
567 567
568 568 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
569 569 + spacewire_stats.packets_received;
570 570 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
571 571 + spacewire_stats.packets_sent;
572 572 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
573 573 + spacewire_stats.parity_err;
574 574 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
575 575 + spacewire_stats.disconnect_err;
576 576 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
577 577 + spacewire_stats.escape_err;
578 578 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
579 579 + spacewire_stats.credit_err;
580 580 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
581 581 + spacewire_stats.write_sync_err;
582 582 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
583 583 + spacewire_stats.rx_rmap_header_crc_err;
584 584 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
585 585 + spacewire_stats.rx_rmap_data_crc_err;
586 586 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
587 587 + spacewire_stats.early_ep;
588 588 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
589 589 + spacewire_stats.invalid_address;
590 590 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
591 591 + spacewire_stats.rx_eep_err;
592 592 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
593 593 + spacewire_stats.rx_truncated;
594 594 }
595 595
596 596 void spacewire_update_statistics( void )
597 597 {
598 598 rtems_status_code status;
599 599 spw_stats spacewire_stats_grspw;
600 600
601 601 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
602 602
603 603 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
604 604 + spacewire_stats_grspw.packets_received;
605 605 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
606 606 + spacewire_stats_grspw.packets_sent;
607 607 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
608 608 + spacewire_stats_grspw.parity_err;
609 609 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
610 610 + spacewire_stats_grspw.disconnect_err;
611 611 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
612 612 + spacewire_stats_grspw.escape_err;
613 613 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
614 614 + spacewire_stats_grspw.credit_err;
615 615 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
616 616 + spacewire_stats_grspw.write_sync_err;
617 617 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
618 618 + spacewire_stats_grspw.rx_rmap_header_crc_err;
619 619 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
620 620 + spacewire_stats_grspw.rx_rmap_data_crc_err;
621 621 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
622 622 + spacewire_stats_grspw.early_ep;
623 623 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
624 624 + spacewire_stats_grspw.invalid_address;
625 625 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
626 626 + spacewire_stats_grspw.rx_eep_err;
627 627 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
628 628 + spacewire_stats_grspw.rx_truncated;
629 629 //spacewire_stats.tx_link_err;
630 630
631 631 //****************************
632 632 // DPU_SPACEWIRE_IF_STATISTICS
633 633 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
634 634 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
635 635 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
636 636 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
637 637 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
638 638 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
639 639
640 640 //******************************************
641 641 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
642 642 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
643 643 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
644 644 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
645 645 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
646 646 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
647 647
648 648 //*********************************************
649 649 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
650 650 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
651 651 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
652 652 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
653 653 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
654 654 }
655 655
656 656 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
657 657 {
658 658 // a valid timecode has been received, write it in the HK report
659 659 unsigned int * grspwPtr;
660 660
661 661 grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
662 662
663 housekeeping_packet.hk_lfr_dpu_spw_last_timc = (unsigned char) (grspwPtr[0] & 0x3f); // [11 1111]
663 housekeeping_packet.hk_lfr_dpu_spw_last_timc = (unsigned char) (grspwPtr[0] & 0xff); // [11 1111]
664 664
665 665 // update the number of valid timecodes that have been received
666 666 if (housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt == 255)
667 667 {
668 668 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = 0;
669 669 }
670 670 else
671 671 {
672 672 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt + 1;
673 673 }
674 674 }
675 675
676 676 rtems_timer_service_routine user_routine( rtems_id timer_id, void *user_data )
677 677 {
678 678 int linkStatus;
679 679 rtems_status_code status;
680 680
681 681 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
682 682
683 683 if ( linkStatus == 5) {
684 684 PRINTF("in spacewire_reset_link *** link is running\n")
685 685 status = RTEMS_SUCCESSFUL;
686 686 }
687 687 }
688 688
689 689 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
690 690 {
691 691 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
692 692 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
693 693 header->reserved = DEFAULT_RESERVED;
694 694 header->userApplication = CCSDS_USER_APP;
695 695 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
696 696 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
697 697 header->packetLength[0] = 0x00;
698 698 header->packetLength[1] = 0x00;
699 699 // DATA FIELD HEADER
700 700 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
701 701 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
702 702 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
703 703 header->destinationID = TM_DESTINATION_ID_GROUND;
704 704 header->time[0] = 0x00;
705 705 header->time[0] = 0x00;
706 706 header->time[0] = 0x00;
707 707 header->time[0] = 0x00;
708 708 header->time[0] = 0x00;
709 709 header->time[0] = 0x00;
710 710 // AUXILIARY DATA HEADER
711 711 header->sid = 0x00;
712 712 header->hkBIA = DEFAULT_HKBIA;
713 713 header->blkNr[0] = 0x00;
714 714 header->blkNr[1] = 0x00;
715 715 }
716 716
717 717 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
718 718 {
719 719 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
720 720 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
721 721 header->reserved = DEFAULT_RESERVED;
722 722 header->userApplication = CCSDS_USER_APP;
723 723 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
724 724 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
725 725 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
726 726 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
727 727 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
728 728 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
729 729 // DATA FIELD HEADER
730 730 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
731 731 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
732 732 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
733 733 header->destinationID = TM_DESTINATION_ID_GROUND;
734 734 header->time[0] = 0x00;
735 735 header->time[0] = 0x00;
736 736 header->time[0] = 0x00;
737 737 header->time[0] = 0x00;
738 738 header->time[0] = 0x00;
739 739 header->time[0] = 0x00;
740 740 // AUXILIARY DATA HEADER
741 741 header->sid = 0x00;
742 742 header->hkBIA = DEFAULT_HKBIA;
743 743 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
744 744 header->pktNr = 0x00;
745 745 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
746 746 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
747 747 }
748 748
749 749 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
750 750 {
751 751 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
752 752 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
753 753 header->reserved = DEFAULT_RESERVED;
754 754 header->userApplication = CCSDS_USER_APP;
755 755 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
756 756 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
757 757 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
758 758 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
759 759 header->packetLength[0] = 0x00;
760 760 header->packetLength[1] = 0x00;
761 761 // DATA FIELD HEADER
762 762 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
763 763 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
764 764 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE; // service subtype
765 765 header->destinationID = TM_DESTINATION_ID_GROUND;
766 766 header->time[0] = 0x00;
767 767 header->time[0] = 0x00;
768 768 header->time[0] = 0x00;
769 769 header->time[0] = 0x00;
770 770 header->time[0] = 0x00;
771 771 header->time[0] = 0x00;
772 772 // AUXILIARY DATA HEADER
773 773 header->sid = 0x00;
774 774 header->biaStatusInfo = 0x00;
775 775 header->pa_lfr_pkt_cnt_asm = 0x00;
776 776 header->pa_lfr_pkt_nr_asm = 0x00;
777 777 header->pa_lfr_asm_blk_nr[0] = 0x00;
778 778 header->pa_lfr_asm_blk_nr[1] = 0x00;
779 779 }
780 780
781 781 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
782 782 Header_TM_LFR_SCIENCE_CWF_t *header )
783 783 {
784 784 /** This function sends CWF CCSDS packets (F2, F1 or F0).
785 785 *
786 786 * @param waveform points to the buffer containing the data that will be send.
787 787 * @param sid is the source identifier of the data that will be sent.
788 788 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
789 789 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
790 790 * contain information to setup the transmission of the data packets.
791 791 *
792 792 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
793 793 *
794 794 */
795 795
796 796 unsigned int i;
797 797 int ret;
798 798 unsigned int coarseTime;
799 799 unsigned int fineTime;
800 800 rtems_status_code status;
801 801 spw_ioctl_pkt_send spw_ioctl_send_CWF;
802 802 int *dataPtr;
803 803 unsigned char sid;
804 804
805 805 spw_ioctl_send_CWF.hlen = TM_HEADER_LEN + 4 + 10; // + 4 is for the protocole extra header, + 10 is for the auxiliary header
806 806 spw_ioctl_send_CWF.options = 0;
807 807
808 808 ret = LFR_DEFAULT;
809 809 sid = (unsigned char) ring_node_to_send->sid;
810 810
811 811 coarseTime = ring_node_to_send->coarseTime;
812 812 fineTime = ring_node_to_send->fineTime;
813 813 dataPtr = (int*) ring_node_to_send->buffer_address;
814 814
815 815 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
816 816 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
817 817 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
818 818 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
819 819
820 820 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
821 821 {
822 822 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
823 823 spw_ioctl_send_CWF.hdr = (char*) header;
824 824 // BUILD THE DATA
825 825 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
826 826
827 827 // SET PACKET SEQUENCE CONTROL
828 828 increment_seq_counter_source_id( header->packetSequenceControl, sid );
829 829
830 830 // SET SID
831 831 header->sid = sid;
832 832
833 833 // SET PACKET TIME
834 834 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
835 835 //
836 836 header->time[0] = header->acquisitionTime[0];
837 837 header->time[1] = header->acquisitionTime[1];
838 838 header->time[2] = header->acquisitionTime[2];
839 839 header->time[3] = header->acquisitionTime[3];
840 840 header->time[4] = header->acquisitionTime[4];
841 841 header->time[5] = header->acquisitionTime[5];
842 842
843 843 // SET PACKET ID
844 844 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
845 845 {
846 846 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
847 847 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
848 848 }
849 849 else
850 850 {
851 851 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
852 852 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
853 853 }
854 854
855 855 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
856 856 if (status != RTEMS_SUCCESSFUL) {
857 857 printf("%d-%d, ERR %d\n", sid, i, (int) status);
858 858 ret = LFR_DEFAULT;
859 859 }
860 860 }
861 861
862 862 return ret;
863 863 }
864 864
865 865 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
866 866 Header_TM_LFR_SCIENCE_SWF_t *header )
867 867 {
868 868 /** This function sends SWF CCSDS packets (F2, F1 or F0).
869 869 *
870 870 * @param waveform points to the buffer containing the data that will be send.
871 871 * @param sid is the source identifier of the data that will be sent.
872 872 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
873 873 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
874 874 * contain information to setup the transmission of the data packets.
875 875 *
876 876 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
877 877 *
878 878 */
879 879
880 880 unsigned int i;
881 881 int ret;
882 882 unsigned int coarseTime;
883 883 unsigned int fineTime;
884 884 rtems_status_code status;
885 885 spw_ioctl_pkt_send spw_ioctl_send_SWF;
886 886 int *dataPtr;
887 887 unsigned char sid;
888 888
889 889 spw_ioctl_send_SWF.hlen = TM_HEADER_LEN + 4 + 12; // + 4 is for the protocole extra header, + 12 is for the auxiliary header
890 890 spw_ioctl_send_SWF.options = 0;
891 891
892 892 ret = LFR_DEFAULT;
893 893
894 894 coarseTime = ring_node_to_send->coarseTime;
895 895 fineTime = ring_node_to_send->fineTime;
896 896 dataPtr = (int*) ring_node_to_send->buffer_address;
897 897 sid = ring_node_to_send->sid;
898 898
899 899 for (i=0; i<7; i++) // send waveform
900 900 {
901 901 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
902 902 spw_ioctl_send_SWF.hdr = (char*) header;
903 903
904 904 // SET PACKET SEQUENCE CONTROL
905 905 increment_seq_counter_source_id( header->packetSequenceControl, sid );
906 906
907 907 // SET PACKET LENGTH AND BLKNR
908 908 if (i == 6)
909 909 {
910 910 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
911 911 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
912 912 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
913 913 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
914 914 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
915 915 }
916 916 else
917 917 {
918 918 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
919 919 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
920 920 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
921 921 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
922 922 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
923 923 }
924 924
925 925 // SET PACKET TIME
926 926 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
927 927 //
928 928 header->time[0] = header->acquisitionTime[0];
929 929 header->time[1] = header->acquisitionTime[1];
930 930 header->time[2] = header->acquisitionTime[2];
931 931 header->time[3] = header->acquisitionTime[3];
932 932 header->time[4] = header->acquisitionTime[4];
933 933 header->time[5] = header->acquisitionTime[5];
934 934
935 935 // SET SID
936 936 header->sid = sid;
937 937
938 938 // SET PKTNR
939 939 header->pktNr = i+1; // PKT_NR
940 940
941 941 // SEND PACKET
942 942 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
943 943 if (status != RTEMS_SUCCESSFUL) {
944 944 printf("%d-%d, ERR %d\n", sid, i, (int) status);
945 945 ret = LFR_DEFAULT;
946 946 }
947 947 }
948 948
949 949 return ret;
950 950 }
951 951
952 952 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
953 953 Header_TM_LFR_SCIENCE_CWF_t *header )
954 954 {
955 955 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
956 956 *
957 957 * @param waveform points to the buffer containing the data that will be send.
958 958 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
959 959 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
960 960 * contain information to setup the transmission of the data packets.
961 961 *
962 962 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
963 963 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
964 964 *
965 965 */
966 966
967 967 unsigned int i;
968 968 int ret;
969 969 unsigned int coarseTime;
970 970 unsigned int fineTime;
971 971 rtems_status_code status;
972 972 spw_ioctl_pkt_send spw_ioctl_send_CWF;
973 973 char *dataPtr;
974 974 unsigned char sid;
975 975
976 976 spw_ioctl_send_CWF.hlen = TM_HEADER_LEN + 4 + 10; // + 4 is for the protocole extra header, + 10 is for the auxiliary header
977 977 spw_ioctl_send_CWF.options = 0;
978 978
979 979 ret = LFR_DEFAULT;
980 980 sid = ring_node_to_send->sid;
981 981
982 982 coarseTime = ring_node_to_send->coarseTime;
983 983 fineTime = ring_node_to_send->fineTime;
984 984 dataPtr = (char*) ring_node_to_send->buffer_address;
985 985
986 986 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
987 987 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
988 988 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
989 989 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
990 990
991 991 //*********************
992 992 // SEND CWF3_light DATA
993 993 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
994 994 {
995 995 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
996 996 spw_ioctl_send_CWF.hdr = (char*) header;
997 997 // BUILD THE DATA
998 998 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
999 999
1000 1000 // SET PACKET SEQUENCE COUNTER
1001 1001 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1002 1002
1003 1003 // SET SID
1004 1004 header->sid = sid;
1005 1005
1006 1006 // SET PACKET TIME
1007 1007 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1008 1008 //
1009 1009 header->time[0] = header->acquisitionTime[0];
1010 1010 header->time[1] = header->acquisitionTime[1];
1011 1011 header->time[2] = header->acquisitionTime[2];
1012 1012 header->time[3] = header->acquisitionTime[3];
1013 1013 header->time[4] = header->acquisitionTime[4];
1014 1014 header->time[5] = header->acquisitionTime[5];
1015 1015
1016 1016 // SET PACKET ID
1017 1017 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1018 1018 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1019 1019
1020 1020 // SEND PACKET
1021 1021 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1022 1022 if (status != RTEMS_SUCCESSFUL) {
1023 1023 printf("%d-%d, ERR %d\n", sid, i, (int) status);
1024 1024 ret = LFR_DEFAULT;
1025 1025 }
1026 1026 }
1027 1027
1028 1028 return ret;
1029 1029 }
1030 1030
1031 1031 void spw_send_asm( ring_node *ring_node_to_send,
1032 1032 Header_TM_LFR_SCIENCE_ASM_t *header )
1033 1033 {
1034 1034 unsigned int i;
1035 1035 unsigned int length = 0;
1036 1036 rtems_status_code status;
1037 1037 unsigned int sid;
1038 1038 char *spectral_matrix;
1039 1039 int coarseTime;
1040 1040 int fineTime;
1041 1041 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1042 1042
1043 1043 sid = ring_node_to_send->sid;
1044 1044 spectral_matrix = (char*) ring_node_to_send->buffer_address;
1045 1045 coarseTime = ring_node_to_send->coarseTime;
1046 1046 fineTime = ring_node_to_send->fineTime;
1047 1047
1048 1048 for (i=0; i<2; i++)
1049 1049 {
1050 1050 // (1) BUILD THE DATA
1051 1051 switch(sid)
1052 1052 {
1053 1053 case SID_NORM_ASM_F0:
1054 1054 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F0_IN_BYTES / 2; // 2 packets will be sent
1055 1055 spw_ioctl_send_ASM.data = &spectral_matrix[
1056 1056 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0) ) * NB_VALUES_PER_SM ) * 2
1057 1057 ];
1058 1058 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0;
1059 1059 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0) >> 8 ); // BLK_NR MSB
1060 1060 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0); // BLK_NR LSB
1061 1061 break;
1062 1062 case SID_NORM_ASM_F1:
1063 1063 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F1_IN_BYTES / 2; // 2 packets will be sent
1064 1064 spw_ioctl_send_ASM.data = &spectral_matrix[
1065 1065 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1) ) * NB_VALUES_PER_SM ) * 2
1066 1066 ];
1067 1067 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1;
1068 1068 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1) >> 8 ); // BLK_NR MSB
1069 1069 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1); // BLK_NR LSB
1070 1070 break;
1071 1071 case SID_NORM_ASM_F2:
1072 1072 spw_ioctl_send_ASM.dlen = TOTAL_SIZE_ASM_F2_IN_BYTES / 2; // 2 packets will be sent
1073 1073 spw_ioctl_send_ASM.data = &spectral_matrix[
1074 1074 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM ) * 2
1075 1075 ];
1076 1076 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1077 1077 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1078 1078 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1079 1079 break;
1080 1080 default:
1081 1081 PRINTF1("ERR *** in spw_send_asm *** unexpected sid %d\n", sid)
1082 1082 break;
1083 1083 }
1084 1084 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM + CCSDS_PROTOCOLE_EXTRA_BYTES;
1085 1085 spw_ioctl_send_ASM.hdr = (char *) header;
1086 1086 spw_ioctl_send_ASM.options = 0;
1087 1087
1088 1088 // (2) BUILD THE HEADER
1089 1089 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1090 1090 header->packetLength[0] = (unsigned char) (length>>8);
1091 1091 header->packetLength[1] = (unsigned char) (length);
1092 1092 header->sid = (unsigned char) sid; // SID
1093 1093 header->pa_lfr_pkt_cnt_asm = 2;
1094 1094 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1095 1095
1096 1096 // (3) SET PACKET TIME
1097 1097 header->time[0] = (unsigned char) (coarseTime>>24);
1098 1098 header->time[1] = (unsigned char) (coarseTime>>16);
1099 1099 header->time[2] = (unsigned char) (coarseTime>>8);
1100 1100 header->time[3] = (unsigned char) (coarseTime);
1101 1101 header->time[4] = (unsigned char) (fineTime>>8);
1102 1102 header->time[5] = (unsigned char) (fineTime);
1103 1103 //
1104 1104 header->acquisitionTime[0] = header->time[0];
1105 1105 header->acquisitionTime[1] = header->time[1];
1106 1106 header->acquisitionTime[2] = header->time[2];
1107 1107 header->acquisitionTime[3] = header->time[3];
1108 1108 header->acquisitionTime[4] = header->time[4];
1109 1109 header->acquisitionTime[5] = header->time[5];
1110 1110
1111 1111 // (4) SEND PACKET
1112 1112 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1113 1113 if (status != RTEMS_SUCCESSFUL) {
1114 1114 printf("in ASM_send *** ERR %d\n", (int) status);
1115 1115 }
1116 1116 }
1117 1117 }
@@ -1,1117 +1,1118
1 1 /** Functions and tasks related to TeleCommand handling.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle TeleCommands:\n
7 7 * action launching\n
8 8 * TC parsing\n
9 9 * ...
10 10 *
11 11 */
12 12
13 13 #include "tc_handler.h"
14 14 #include "math.h"
15 15
16 16 //***********
17 17 // RTEMS TASK
18 18
19 19 rtems_task actn_task( rtems_task_argument unused )
20 20 {
21 21 /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
22 22 *
23 23 * @param unused is the starting argument of the RTEMS task
24 24 *
25 25 * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
26 26 * on the incoming TeleCommand.
27 27 *
28 28 */
29 29
30 30 int result;
31 31 rtems_status_code status; // RTEMS status code
32 32 ccsdsTelecommandPacket_t TC; // TC sent to the ACTN task
33 33 size_t size; // size of the incoming TC packet
34 34 unsigned char subtype; // subtype of the current TC packet
35 35 unsigned char time[6];
36 36 rtems_id queue_rcv_id;
37 37 rtems_id queue_snd_id;
38 38
39 39 status = get_message_queue_id_recv( &queue_rcv_id );
40 40 if (status != RTEMS_SUCCESSFUL)
41 41 {
42 42 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
43 43 }
44 44
45 45 status = get_message_queue_id_send( &queue_snd_id );
46 46 if (status != RTEMS_SUCCESSFUL)
47 47 {
48 48 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
49 49 }
50 50
51 51 result = LFR_SUCCESSFUL;
52 52 subtype = 0; // subtype of the current TC packet
53 53
54 54 BOOT_PRINTF("in ACTN *** \n")
55 55
56 56 while(1)
57 57 {
58 58 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
59 59 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
60 60 getTime( time ); // set time to the current time
61 61 if (status!=RTEMS_SUCCESSFUL)
62 62 {
63 63 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
64 64 }
65 65 else
66 66 {
67 67 subtype = TC.serviceSubType;
68 68 switch(subtype)
69 69 {
70 70 case TC_SUBTYPE_RESET:
71 71 result = action_reset( &TC, queue_snd_id, time );
72 72 close_action( &TC, result, queue_snd_id );
73 73 break;
74 74 //
75 75 case TC_SUBTYPE_LOAD_COMM:
76 76 result = action_load_common_par( &TC );
77 77 close_action( &TC, result, queue_snd_id );
78 78 break;
79 79 //
80 80 case TC_SUBTYPE_LOAD_NORM:
81 81 result = action_load_normal_par( &TC, queue_snd_id, time );
82 82 close_action( &TC, result, queue_snd_id );
83 83 break;
84 84 //
85 85 case TC_SUBTYPE_LOAD_BURST:
86 86 result = action_load_burst_par( &TC, queue_snd_id, time );
87 87 close_action( &TC, result, queue_snd_id );
88 88 break;
89 89 //
90 90 case TC_SUBTYPE_LOAD_SBM1:
91 91 result = action_load_sbm1_par( &TC, queue_snd_id, time );
92 92 close_action( &TC, result, queue_snd_id );
93 93 break;
94 94 //
95 95 case TC_SUBTYPE_LOAD_SBM2:
96 96 result = action_load_sbm2_par( &TC, queue_snd_id, time );
97 97 close_action( &TC, result, queue_snd_id );
98 98 break;
99 99 //
100 100 case TC_SUBTYPE_DUMP:
101 101 result = action_dump_par( queue_snd_id );
102 102 close_action( &TC, result, queue_snd_id );
103 103 break;
104 104 //
105 105 case TC_SUBTYPE_ENTER:
106 106 result = action_enter_mode( &TC, queue_snd_id );
107 107 close_action( &TC, result, queue_snd_id );
108 108 break;
109 109 //
110 110 case TC_SUBTYPE_UPDT_INFO:
111 111 result = action_update_info( &TC, queue_snd_id );
112 112 close_action( &TC, result, queue_snd_id );
113 113 break;
114 114 //
115 115 case TC_SUBTYPE_EN_CAL:
116 116 result = action_enable_calibration( &TC, queue_snd_id, time );
117 117 close_action( &TC, result, queue_snd_id );
118 118 break;
119 119 //
120 120 case TC_SUBTYPE_DIS_CAL:
121 121 result = action_disable_calibration( &TC, queue_snd_id, time );
122 122 close_action( &TC, result, queue_snd_id );
123 123 break;
124 124 //
125 125 case TC_SUBTYPE_UPDT_TIME:
126 126 result = action_update_time( &TC );
127 127 close_action( &TC, result, queue_snd_id );
128 128 break;
129 129 //
130 130 default:
131 131 break;
132 132 }
133 133 }
134 134 }
135 135 }
136 136
137 137 //***********
138 138 // TC ACTIONS
139 139
140 140 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
141 141 {
142 142 /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
143 143 *
144 144 * @param TC points to the TeleCommand packet that is being processed
145 145 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
146 146 *
147 147 */
148 148
149 149 printf("this is the end!!!\n");
150 150 exit(0);
151 151 send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
152 152 return LFR_DEFAULT;
153 153 }
154 154
155 155 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
156 156 {
157 157 /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
158 158 *
159 159 * @param TC points to the TeleCommand packet that is being processed
160 160 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
161 161 *
162 162 */
163 163
164 164 rtems_status_code status;
165 165 unsigned char requestedMode;
166 166 unsigned int *transitionCoarseTime_ptr;
167 167 unsigned int transitionCoarseTime;
168 168 unsigned char * bytePosPtr;
169 169
170 170 bytePosPtr = (unsigned char *) &TC->packetID;
171 171
172 172 requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
173 173 transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
174 174 transitionCoarseTime = (*transitionCoarseTime_ptr) & 0x7fffffff;
175 175
176 176 status = check_mode_value( requestedMode );
177 177
178 178 if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent
179 179 {
180 180 send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
181 181 }
182 182 else // the mode value is consistent, check the transition
183 183 {
184 184 status = check_mode_transition(requestedMode);
185 185 if (status != LFR_SUCCESSFUL)
186 186 {
187 187 PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
188 188 send_tm_lfr_tc_exe_not_executable( TC, queue_id );
189 189 }
190 190 }
191 191
192 192 if ( status == LFR_SUCCESSFUL ) // the transition is valid, enter the mode
193 193 {
194 194 status = check_transition_date( transitionCoarseTime );
195 195 if (status != LFR_SUCCESSFUL)
196 196 {
197 197 PRINTF("ERR *** in action_enter_mode *** check_transition_date\n")
198 198 send_tm_lfr_tc_exe_inconsistent( TC, queue_id,
199 199 BYTE_POS_CP_LFR_ENTER_MODE_TIME,
200 200 bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME + 3 ] );
201 201 }
202 202 }
203 203
204 204 if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode
205 205 {
206 206 PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
207 207 status = enter_mode( requestedMode, transitionCoarseTime );
208 208 }
209 209
210 210 return status;
211 211 }
212 212
213 213 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
214 214 {
215 215 /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
216 216 *
217 217 * @param TC points to the TeleCommand packet that is being processed
218 218 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
219 219 *
220 220 * @return LFR directive status code:
221 221 * - LFR_DEFAULT
222 222 * - LFR_SUCCESSFUL
223 223 *
224 224 */
225 225
226 226 unsigned int val;
227 227 int result;
228 228 unsigned int status;
229 229 unsigned char mode;
230 230 unsigned char * bytePosPtr;
231 231
232 232 bytePosPtr = (unsigned char *) &TC->packetID;
233 233
234 234 // check LFR mode
235 235 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & 0x1e) >> 1;
236 236 status = check_update_info_hk_lfr_mode( mode );
237 237 if (status == LFR_SUCCESSFUL) // check TDS mode
238 238 {
239 239 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0xf0) >> 4;
240 240 status = check_update_info_hk_tds_mode( mode );
241 241 }
242 242 if (status == LFR_SUCCESSFUL) // check THR mode
243 243 {
244 244 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0x0f);
245 245 status = check_update_info_hk_thr_mode( mode );
246 246 }
247 247 if (status == LFR_SUCCESSFUL) // if the parameter check is successful
248 248 {
249 249 val = housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * 256
250 250 + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
251 251 val++;
252 252 housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> 8);
253 253 housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
254 254 }
255 255
256 256 result = status;
257 257
258 258 return result;
259 259 }
260 260
261 261 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
262 262 {
263 263 /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
264 264 *
265 265 * @param TC points to the TeleCommand packet that is being processed
266 266 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
267 267 *
268 268 */
269 269
270 270 int result;
271 271
272 272 result = LFR_DEFAULT;
273 273
274 274 startCalibration();
275 275
276 276 result = LFR_SUCCESSFUL;
277 277
278 278 return result;
279 279 }
280 280
281 281 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
282 282 {
283 283 /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
284 284 *
285 285 * @param TC points to the TeleCommand packet that is being processed
286 286 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
287 287 *
288 288 */
289 289
290 290 int result;
291 291
292 292 result = LFR_DEFAULT;
293 293
294 294 stopCalibration();
295 295
296 296 result = LFR_SUCCESSFUL;
297 297
298 298 return result;
299 299 }
300 300
301 301 int action_update_time(ccsdsTelecommandPacket_t *TC)
302 302 {
303 303 /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
304 304 *
305 305 * @param TC points to the TeleCommand packet that is being processed
306 306 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
307 307 *
308 308 * @return LFR_SUCCESSFUL
309 309 *
310 310 */
311 311
312 312 unsigned int val;
313 313
314 314 time_management_regs->coarse_time_load = (TC->dataAndCRC[0] << 24)
315 315 + (TC->dataAndCRC[1] << 16)
316 316 + (TC->dataAndCRC[2] << 8)
317 317 + TC->dataAndCRC[3];
318 318
319 319 val = housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * 256
320 320 + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
321 321 val++;
322 322 housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> 8);
323 323 housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
324 324
325 325 return LFR_SUCCESSFUL;
326 326 }
327 327
328 328 //*******************
329 329 // ENTERING THE MODES
330 330 int check_mode_value( unsigned char requestedMode )
331 331 {
332 332 int status;
333 333
334 334 if ( (requestedMode != LFR_MODE_STANDBY)
335 335 && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
336 336 && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
337 337 {
338 338 status = LFR_DEFAULT;
339 339 }
340 340 else
341 341 {
342 342 status = LFR_SUCCESSFUL;
343 343 }
344 344
345 345 return status;
346 346 }
347 347
348 348 int check_mode_transition( unsigned char requestedMode )
349 349 {
350 350 /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
351 351 *
352 352 * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
353 353 *
354 354 * @return LFR directive status codes:
355 355 * - LFR_SUCCESSFUL - the transition is authorized
356 356 * - LFR_DEFAULT - the transition is not authorized
357 357 *
358 358 */
359 359
360 360 int status;
361 361
362 362 switch (requestedMode)
363 363 {
364 364 case LFR_MODE_STANDBY:
365 365 if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
366 366 status = LFR_DEFAULT;
367 367 }
368 368 else
369 369 {
370 370 status = LFR_SUCCESSFUL;
371 371 }
372 372 break;
373 373 case LFR_MODE_NORMAL:
374 374 if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
375 375 status = LFR_DEFAULT;
376 376 }
377 377 else {
378 378 status = LFR_SUCCESSFUL;
379 379 }
380 380 break;
381 381 case LFR_MODE_BURST:
382 382 if ( lfrCurrentMode == LFR_MODE_BURST ) {
383 383 status = LFR_DEFAULT;
384 384 }
385 385 else {
386 386 status = LFR_SUCCESSFUL;
387 387 }
388 388 break;
389 389 case LFR_MODE_SBM1:
390 390 if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
391 391 status = LFR_DEFAULT;
392 392 }
393 393 else {
394 394 status = LFR_SUCCESSFUL;
395 395 }
396 396 break;
397 397 case LFR_MODE_SBM2:
398 398 if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
399 399 status = LFR_DEFAULT;
400 400 }
401 401 else {
402 402 status = LFR_SUCCESSFUL;
403 403 }
404 404 break;
405 405 default:
406 406 status = LFR_DEFAULT;
407 407 break;
408 408 }
409 409
410 410 return status;
411 411 }
412 412
413 413 int check_transition_date( unsigned int transitionCoarseTime )
414 414 {
415 415 int status;
416 416 unsigned int localCoarseTime;
417 417 unsigned int deltaCoarseTime;
418 418
419 419 status = LFR_SUCCESSFUL;
420 420
421 421 if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
422 422 {
423 423 status = LFR_SUCCESSFUL;
424 424 }
425 425 else
426 426 {
427 427 localCoarseTime = time_management_regs->coarse_time & 0x7fffffff;
428 428
429 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime)
430
429 431 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
430 432 {
431 433 status = LFR_DEFAULT;
432 PRINTF2("ERR *** in check_transition_date *** transition = %x, local = %x\n", transitionCoarseTime, localCoarseTime)
434 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n")
433 435 }
434 436
435 437 if (status == LFR_SUCCESSFUL)
436 438 {
437 439 deltaCoarseTime = transitionCoarseTime - localCoarseTime;
438 440 if ( deltaCoarseTime > 3 ) // SSS-CP-EQS-323
439 441 {
440 442 status = LFR_DEFAULT;
441 443 PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
442 444 }
443 445 }
444 446 }
445 447
446 448 return status;
447 449 }
448 450
449 451 int stop_current_mode( void )
450 452 {
451 453 /** This function stops the current mode by masking interrupt lines and suspending science tasks.
452 454 *
453 455 * @return RTEMS directive status codes:
454 456 * - RTEMS_SUCCESSFUL - task restarted successfully
455 457 * - RTEMS_INVALID_ID - task id invalid
456 458 * - RTEMS_ALREADY_SUSPENDED - task already suspended
457 459 *
458 460 */
459 461
460 462 rtems_status_code status;
461 463
462 464 status = RTEMS_SUCCESSFUL;
463 465
464 466 // (1) mask interruptions
465 467 LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt
466 468 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
467 469
468 470 // (2) reset waveform picker registers
469 471 reset_wfp_burst_enable(); // reset burst and enable bits
470 472 reset_wfp_status(); // reset all the status bits
471 473
472 474 // (3) reset spectral matrices registers
473 475 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
474 476 reset_sm_status();
475 477
476 478 // reset lfr VHDL module
477 479 reset_lfr();
478 480
479 481 reset_extractSWF(); // reset the extractSWF flag to false
480 482
481 483 // (4) clear interruptions
482 484 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt
483 485 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
484 486
485 487 // <Spectral Matrices simulator>
486 488 LEON_Mask_interrupt( IRQ_SM_SIMULATOR ); // mask spectral matrix interrupt simulator
487 489 timer_stop( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_SM_SIMULATOR );
488 490 LEON_Clear_interrupt( IRQ_SM_SIMULATOR ); // clear spectral matrix interrupt simulator
489 491 // </Spectral Matrices simulator>
490 492
491 493 // suspend several tasks
492 494 if (lfrCurrentMode != LFR_MODE_STANDBY) {
493 495 status = suspend_science_tasks();
494 496 }
495 497
496 498 if (status != RTEMS_SUCCESSFUL)
497 499 {
498 500 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
499 501 }
500 502
501 503 return status;
502 504 }
503 505
504 506 int enter_mode( unsigned char mode, unsigned int transitionCoarseTime )
505 507 {
506 508 /** This function is launched after a mode transition validation.
507 509 *
508 510 * @param mode is the mode in which LFR will be put.
509 511 *
510 512 * @return RTEMS directive status codes:
511 513 * - RTEMS_SUCCESSFUL - the mode has been entered successfully
512 514 * - RTEMS_NOT_SATISFIED - the mode has not been entered successfully
513 515 *
514 516 */
515 517
516 518 rtems_status_code status;
517 519
518 520 //**********************
519 521 // STOP THE CURRENT MODE
520 522 status = stop_current_mode();
521 523 if (status != RTEMS_SUCCESSFUL)
522 524 {
523 525 PRINTF1("ERR *** in enter_mode *** stop_current_mode with mode = %d\n", mode)
524 526 }
525 527
526 528 //*************************
527 529 // ENTER THE REQUESTED MODE
528 530 if ( (mode == LFR_MODE_NORMAL) || (mode == LFR_MODE_BURST)
529 531 || (mode == LFR_MODE_SBM1) || (mode == LFR_MODE_SBM2) )
530 532 {
531 533 #ifdef PRINT_TASK_STATISTICS
532 534 rtems_cpu_usage_reset();
533 535 maxCount = 0;
534 536 #endif
535 537 status = restart_science_tasks( mode );
536 538 launch_spectral_matrix( );
537 539 launch_waveform_picker( mode, transitionCoarseTime );
538 540 // launch_spectral_matrix_simu( );
539 541 }
540 542 else if ( mode == LFR_MODE_STANDBY )
541 543 {
542 544 #ifdef PRINT_TASK_STATISTICS
543 545 rtems_cpu_usage_report();
544 546 #endif
545 547
546 548 #ifdef PRINT_STACK_REPORT
547 549 PRINTF("stack report selected\n")
548 550 rtems_stack_checker_report_usage();
549 551 #endif
550 552 PRINTF1("maxCount = %d\n", maxCount)
551 553 }
552 554 else
553 555 {
554 556 status = RTEMS_UNSATISFIED;
555 557 }
556 558
557 559 if (status != RTEMS_SUCCESSFUL)
558 560 {
559 561 PRINTF1("ERR *** in enter_mode *** status = %d\n", status)
560 562 status = RTEMS_UNSATISFIED;
561 563 }
562 564
563 565 return status;
564 566 }
565 567
566 568 int restart_science_tasks(unsigned char lfrRequestedMode )
567 569 {
568 570 /** This function is used to restart all science tasks.
569 571 *
570 572 * @return RTEMS directive status codes:
571 573 * - RTEMS_SUCCESSFUL - task restarted successfully
572 574 * - RTEMS_INVALID_ID - task id invalid
573 575 * - RTEMS_INCORRECT_STATE - task never started
574 576 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
575 577 *
576 578 * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
577 579 *
578 580 */
579 581
580 582 rtems_status_code status[10];
581 583 rtems_status_code ret;
582 584
583 585 ret = RTEMS_SUCCESSFUL;
584 586
585 587 status[0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
586 588 if (status[0] != RTEMS_SUCCESSFUL)
587 589 {
588 590 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[0])
589 591 }
590 592
591 593 status[1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
592 594 if (status[1] != RTEMS_SUCCESSFUL)
593 595 {
594 596 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[1])
595 597 }
596 598
597 599 status[2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
598 600 if (status[2] != RTEMS_SUCCESSFUL)
599 601 {
600 602 PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[2])
601 603 }
602 604
603 605 status[3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
604 606 if (status[3] != RTEMS_SUCCESSFUL)
605 607 {
606 608 PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[3])
607 609 }
608 610
609 611 status[4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
610 612 if (status[4] != RTEMS_SUCCESSFUL)
611 613 {
612 614 PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[4])
613 615 }
614 616
615 617 status[5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
616 618 if (status[5] != RTEMS_SUCCESSFUL)
617 619 {
618 620 PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[5])
619 621 }
620 622
621 623 status[6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
622 624 if (status[6] != RTEMS_SUCCESSFUL)
623 625 {
624 626 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[6])
625 627 }
626 628
627 629 status[7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
628 630 if (status[7] != RTEMS_SUCCESSFUL)
629 631 {
630 632 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[7])
631 633 }
632 634
633 635 status[8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
634 636 if (status[8] != RTEMS_SUCCESSFUL)
635 637 {
636 638 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[8])
637 639 }
638 640
639 641 status[9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
640 642 if (status[9] != RTEMS_SUCCESSFUL)
641 643 {
642 644 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[9])
643 645 }
644 646
645 647 if ( (status[0] != RTEMS_SUCCESSFUL) || (status[1] != RTEMS_SUCCESSFUL) ||
646 648 (status[2] != RTEMS_SUCCESSFUL) || (status[3] != RTEMS_SUCCESSFUL) ||
647 649 (status[4] != RTEMS_SUCCESSFUL) || (status[5] != RTEMS_SUCCESSFUL) ||
648 650 (status[6] != RTEMS_SUCCESSFUL) || (status[7] != RTEMS_SUCCESSFUL) ||
649 651 (status[8] != RTEMS_SUCCESSFUL) || (status[9] != RTEMS_SUCCESSFUL) )
650 652 {
651 653 ret = RTEMS_UNSATISFIED;
652 654 }
653 655
654 656 return ret;
655 657 }
656 658
657 659 int suspend_science_tasks()
658 660 {
659 661 /** This function suspends the science tasks.
660 662 *
661 663 * @return RTEMS directive status codes:
662 664 * - RTEMS_SUCCESSFUL - task restarted successfully
663 665 * - RTEMS_INVALID_ID - task id invalid
664 666 * - RTEMS_ALREADY_SUSPENDED - task already suspended
665 667 *
666 668 */
667 669
668 670 rtems_status_code status;
669 671
670 672 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
671 673 if (status != RTEMS_SUCCESSFUL)
672 674 {
673 675 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
674 676 }
675 677 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
676 678 {
677 679 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
678 680 if (status != RTEMS_SUCCESSFUL)
679 681 {
680 682 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
681 683 }
682 684 }
683 685 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
684 686 {
685 687 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
686 688 if (status != RTEMS_SUCCESSFUL)
687 689 {
688 690 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
689 691 }
690 692 }
691 693 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
692 694 {
693 695 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
694 696 if (status != RTEMS_SUCCESSFUL)
695 697 {
696 698 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
697 699 }
698 700 }
699 701 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
700 702 {
701 703 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
702 704 if (status != RTEMS_SUCCESSFUL)
703 705 {
704 706 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
705 707 }
706 708 }
707 709 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
708 710 {
709 711 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
710 712 if (status != RTEMS_SUCCESSFUL)
711 713 {
712 714 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
713 715 }
714 716 }
715 717 if (status == RTEMS_SUCCESSFUL) // suspend WFRM
716 718 {
717 719 status = rtems_task_suspend( Task_id[TASKID_WFRM] );
718 720 if (status != RTEMS_SUCCESSFUL)
719 721 {
720 722 PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
721 723 }
722 724 }
723 725 if (status == RTEMS_SUCCESSFUL) // suspend CWF3
724 726 {
725 727 status = rtems_task_suspend( Task_id[TASKID_CWF3] );
726 728 if (status != RTEMS_SUCCESSFUL)
727 729 {
728 730 PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
729 731 }
730 732 }
731 733 if (status == RTEMS_SUCCESSFUL) // suspend CWF2
732 734 {
733 735 status = rtems_task_suspend( Task_id[TASKID_CWF2] );
734 736 if (status != RTEMS_SUCCESSFUL)
735 737 {
736 738 PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
737 739 }
738 740 }
739 741 if (status == RTEMS_SUCCESSFUL) // suspend CWF1
740 742 {
741 743 status = rtems_task_suspend( Task_id[TASKID_CWF1] );
742 744 if (status != RTEMS_SUCCESSFUL)
743 745 {
744 746 PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
745 747 }
746 748 }
747 749
748 750 return status;
749 751 }
750 752
751 753 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
752 754 {
753 755 WFP_reset_current_ring_nodes();
754 756
755 757 reset_waveform_picker_regs();
756 758
757 759 set_wfp_burst_enable_register( mode );
758 760
759 761 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
760 762 LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
761 763
762 764 if (transitionCoarseTime == 0)
763 765 {
764 766 waveform_picker_regs->start_date = time_management_regs->coarse_time;
765 767 }
766 768 else
767 769 {
768 770 waveform_picker_regs->start_date = transitionCoarseTime;
769 771 }
770 772
771 PRINTF1("commutation coarse time = %x\n", transitionCoarseTime)
772 773 }
773 774
774 775 void launch_spectral_matrix( void )
775 776 {
776 777 SM_reset_current_ring_nodes();
777 778
778 779 reset_spectral_matrix_regs();
779 780
780 781 reset_nb_sm();
781 782
782 783 set_sm_irq_onNewMatrix( 1 );
783 784
784 785 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
785 786 LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
786 787
787 788 }
788 789
789 790 void launch_spectral_matrix_simu( void )
790 791 {
791 792 SM_reset_current_ring_nodes();
792 793 reset_spectral_matrix_regs();
793 794 reset_nb_sm();
794 795
795 796 // Spectral Matrices simulator
796 797 timer_start( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_SM_SIMULATOR );
797 798 LEON_Clear_interrupt( IRQ_SM_SIMULATOR );
798 799 LEON_Unmask_interrupt( IRQ_SM_SIMULATOR );
799 800 }
800 801
801 802 void set_sm_irq_onNewMatrix( unsigned char value )
802 803 {
803 804 if (value == 1)
804 805 {
805 806 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x01;
806 807 }
807 808 else
808 809 {
809 810 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffe; // 1110
810 811 }
811 812 }
812 813
813 814 void set_sm_irq_onError( unsigned char value )
814 815 {
815 816 if (value == 1)
816 817 {
817 818 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x02;
818 819 }
819 820 else
820 821 {
821 822 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffd; // 1101
822 823 }
823 824 }
824 825
825 826 //*****************************
826 827 // CONFIGURE CALIBRATION SIGNAL
827 828 void setCalibrationPrescaler( unsigned int prescaler )
828 829 {
829 830 // prescaling of the master clock (25 MHz)
830 831 // master clock is divided by 2^prescaler
831 832 time_management_regs->calPrescaler = prescaler;
832 833 }
833 834
834 835 void setCalibrationDivisor( unsigned int divisionFactor )
835 836 {
836 837 // division of the prescaled clock by the division factor
837 838 time_management_regs->calDivisor = divisionFactor;
838 839 }
839 840
840 841 void setCalibrationData( void ){
841 842 unsigned int k;
842 843 unsigned short data;
843 844 float val;
844 845 float f0;
845 846 float f1;
846 847 float fs;
847 848 float Ts;
848 849 float scaleFactor;
849 850
850 851 f0 = 625;
851 852 f1 = 10000;
852 853 fs = 160256.410;
853 854 Ts = 1. / fs;
854 855 scaleFactor = 0.125 / 0.000654; // 191, 500 mVpp, 2 sinus waves => 250 mVpp each, amplitude = 125 mV
855 856
856 857 time_management_regs->calDataPtr = 0x00;
857 858
858 859 // build the signal for the SCM calibration
859 860 for (k=0; k<256; k++)
860 861 {
861 862 val = sin( 2 * pi * f0 * k * Ts )
862 863 + sin( 2 * pi * f1 * k * Ts );
863 864 data = (unsigned short) ((val * scaleFactor) + 2048);
864 865 time_management_regs->calData = data & 0xfff;
865 866 }
866 867 }
867 868
868 869 void setCalibrationDataInterleaved( void ){
869 870 unsigned int k;
870 871 float val;
871 872 float f0;
872 873 float f1;
873 874 float fs;
874 875 float Ts;
875 876 unsigned short data[384];
876 877 unsigned char *dataPtr;
877 878
878 879 f0 = 625;
879 880 f1 = 10000;
880 881 fs = 240384.615;
881 882 Ts = 1. / fs;
882 883
883 884 time_management_regs->calDataPtr = 0x00;
884 885
885 886 // build the signal for the SCM calibration
886 887 for (k=0; k<384; k++)
887 888 {
888 889 val = sin( 2 * pi * f0 * k * Ts )
889 890 + sin( 2 * pi * f1 * k * Ts );
890 891 data[k] = (unsigned short) (val * 512 + 2048);
891 892 }
892 893
893 894 // write the signal in interleaved mode
894 895 for (k=0; k<128; k++)
895 896 {
896 897 dataPtr = (unsigned char*) &data[k*3 + 2];
897 898 time_management_regs->calData = (data[k*3] & 0xfff)
898 899 + ( (dataPtr[0] & 0x3f) << 12);
899 900 time_management_regs->calData = (data[k*3 + 1] & 0xfff)
900 901 + ( (dataPtr[1] & 0x3f) << 12);
901 902 }
902 903 }
903 904
904 905 void setCalibrationReload( bool state)
905 906 {
906 907 if (state == true)
907 908 {
908 909 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000010; // [0001 0000]
909 910 }
910 911 else
911 912 {
912 913 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffef; // [1110 1111]
913 914 }
914 915 }
915 916
916 917 void setCalibrationEnable( bool state )
917 918 {
918 919 // this bit drives the multiplexer
919 920 if (state == true)
920 921 {
921 922 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000040; // [0100 0000]
922 923 }
923 924 else
924 925 {
925 926 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffbf; // [1011 1111]
926 927 }
927 928 }
928 929
929 930 void setCalibrationInterleaved( bool state )
930 931 {
931 932 // this bit drives the multiplexer
932 933 if (state == true)
933 934 {
934 935 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000020; // [0010 0000]
935 936 }
936 937 else
937 938 {
938 939 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffdf; // [1101 1111]
939 940 }
940 941 }
941 942
942 943 void startCalibration( void )
943 944 {
944 945 setCalibrationEnable( true );
945 946 setCalibrationReload( false );
946 947 }
947 948
948 949 void stopCalibration( void )
949 950 {
950 951 setCalibrationEnable( false );
951 952 setCalibrationReload( true );
952 953 }
953 954
954 955 void configureCalibration( bool interleaved )
955 956 {
956 957 stopCalibration();
957 958 if ( interleaved == true )
958 959 {
959 960 setCalibrationInterleaved( true );
960 961 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
961 962 setCalibrationDivisor( 26 ); // => 240 384
962 963 setCalibrationDataInterleaved();
963 964 }
964 965 else
965 966 {
966 967 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
967 968 setCalibrationDivisor( 38 ); // => 160 256 (39 - 1)
968 969 setCalibrationData();
969 970 }
970 971 }
971 972
972 973 //****************
973 974 // CLOSING ACTIONS
974 975 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
975 976 {
976 977 /** This function is used to update the HK packets statistics after a successful TC execution.
977 978 *
978 979 * @param TC points to the TC being processed
979 980 * @param time is the time used to date the TC execution
980 981 *
981 982 */
982 983
983 984 unsigned int val;
984 985
985 986 housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
986 987 housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
987 988 housekeeping_packet.hk_lfr_last_exe_tc_type[0] = 0x00;
988 989 housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
989 990 housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = 0x00;
990 991 housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
991 992 housekeeping_packet.hk_lfr_last_exe_tc_time[0] = time[0];
992 993 housekeeping_packet.hk_lfr_last_exe_tc_time[1] = time[1];
993 994 housekeeping_packet.hk_lfr_last_exe_tc_time[2] = time[2];
994 995 housekeeping_packet.hk_lfr_last_exe_tc_time[3] = time[3];
995 996 housekeeping_packet.hk_lfr_last_exe_tc_time[4] = time[4];
996 997 housekeeping_packet.hk_lfr_last_exe_tc_time[5] = time[5];
997 998
998 999 val = housekeeping_packet.hk_lfr_exe_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
999 1000 val++;
1000 1001 housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> 8);
1001 1002 housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1002 1003 }
1003 1004
1004 1005 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1005 1006 {
1006 1007 /** This function is used to update the HK packets statistics after a TC rejection.
1007 1008 *
1008 1009 * @param TC points to the TC being processed
1009 1010 * @param time is the time used to date the TC rejection
1010 1011 *
1011 1012 */
1012 1013
1013 1014 unsigned int val;
1014 1015
1015 1016 housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1016 1017 housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1017 1018 housekeeping_packet.hk_lfr_last_rej_tc_type[0] = 0x00;
1018 1019 housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1019 1020 housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = 0x00;
1020 1021 housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1021 1022 housekeeping_packet.hk_lfr_last_rej_tc_time[0] = time[0];
1022 1023 housekeeping_packet.hk_lfr_last_rej_tc_time[1] = time[1];
1023 1024 housekeeping_packet.hk_lfr_last_rej_tc_time[2] = time[2];
1024 1025 housekeeping_packet.hk_lfr_last_rej_tc_time[3] = time[3];
1025 1026 housekeeping_packet.hk_lfr_last_rej_tc_time[4] = time[4];
1026 1027 housekeeping_packet.hk_lfr_last_rej_tc_time[5] = time[5];
1027 1028
1028 1029 val = housekeeping_packet.hk_lfr_rej_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1029 1030 val++;
1030 1031 housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> 8);
1031 1032 housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1032 1033 }
1033 1034
1034 1035 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1035 1036 {
1036 1037 /** This function is the last step of the TC execution workflow.
1037 1038 *
1038 1039 * @param TC points to the TC being processed
1039 1040 * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1040 1041 * @param queue_id is the id of the RTEMS message queue used to send TM packets
1041 1042 * @param time is the time used to date the TC execution
1042 1043 *
1043 1044 */
1044 1045
1045 1046 unsigned char requestedMode;
1046 1047
1047 1048 if (result == LFR_SUCCESSFUL)
1048 1049 {
1049 1050 if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1050 1051 &
1051 1052 !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1052 1053 )
1053 1054 {
1054 1055 send_tm_lfr_tc_exe_success( TC, queue_id );
1055 1056 }
1056 1057 if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1057 1058 {
1058 1059 //**********************************
1059 1060 // UPDATE THE LFRMODE LOCAL VARIABLE
1060 1061 requestedMode = TC->dataAndCRC[1];
1061 1062 housekeeping_packet.lfr_status_word[0] = (unsigned char) ((requestedMode << 4) + 0x0d);
1062 1063 updateLFRCurrentMode();
1063 1064 }
1064 1065 }
1065 1066 else if (result == LFR_EXE_ERROR)
1066 1067 {
1067 1068 send_tm_lfr_tc_exe_error( TC, queue_id );
1068 1069 }
1069 1070 }
1070 1071
1071 1072 //***************************
1072 1073 // Interrupt Service Routines
1073 1074 rtems_isr commutation_isr1( rtems_vector_number vector )
1074 1075 {
1075 1076 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1076 1077 printf("In commutation_isr1 *** Error sending event to DUMB\n");
1077 1078 }
1078 1079 }
1079 1080
1080 1081 rtems_isr commutation_isr2( rtems_vector_number vector )
1081 1082 {
1082 1083 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1083 1084 printf("In commutation_isr2 *** Error sending event to DUMB\n");
1084 1085 }
1085 1086 }
1086 1087
1087 1088 //****************
1088 1089 // OTHER FUNCTIONS
1089 1090 void updateLFRCurrentMode()
1090 1091 {
1091 1092 /** This function updates the value of the global variable lfrCurrentMode.
1092 1093 *
1093 1094 * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1094 1095 *
1095 1096 */
1096 1097 // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1097 1098 lfrCurrentMode = (housekeeping_packet.lfr_status_word[0] & 0xf0) >> 4;
1098 1099 }
1099 1100
1100 1101 void set_lfr_soft_reset( unsigned char value )
1101 1102 {
1102 1103 if (value == 1)
1103 1104 {
1104 1105 time_management_regs->ctrl = time_management_regs->ctrl | 0x00000004; // [0100]
1105 1106 }
1106 1107 else
1107 1108 {
1108 1109 time_management_regs->ctrl = time_management_regs->ctrl & 0xfffffffb; // [1011]
1109 1110 }
1110 1111 }
1111 1112
1112 1113 void reset_lfr( void )
1113 1114 {
1114 1115 set_lfr_soft_reset( 1 );
1115 1116
1116 1117 set_lfr_soft_reset( 0 );
1117 1118 }
@@ -1,1402 +1,1402
1 1 /** Functions and tasks related to waveform packet generation.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle waveforms, in snapshot or continuous format.\n
7 7 *
8 8 */
9 9
10 10 #include "wf_handler.h"
11 11
12 12 //***************
13 13 // waveform rings
14 14 // F0
15 15 ring_node waveform_ring_f0[NB_RING_NODES_F0];
16 16 ring_node *current_ring_node_f0;
17 17 ring_node *ring_node_to_send_swf_f0;
18 18 // F1
19 19 ring_node waveform_ring_f1[NB_RING_NODES_F1];
20 20 ring_node *current_ring_node_f1;
21 21 ring_node *ring_node_to_send_swf_f1;
22 22 ring_node *ring_node_to_send_cwf_f1;
23 23 // F2
24 24 ring_node waveform_ring_f2[NB_RING_NODES_F2];
25 25 ring_node *current_ring_node_f2;
26 26 ring_node *ring_node_to_send_swf_f2;
27 27 ring_node *ring_node_to_send_cwf_f2;
28 28 // F3
29 29 ring_node waveform_ring_f3[NB_RING_NODES_F3];
30 30 ring_node *current_ring_node_f3;
31 31 ring_node *ring_node_to_send_cwf_f3;
32 32 char wf_cont_f3_light[ (NB_SAMPLES_PER_SNAPSHOT) * NB_BYTES_CWF3_LIGHT_BLK ];
33 33
34 34 bool extractSWF = false;
35 35 bool swf_f0_ready = false;
36 36 bool swf_f1_ready = false;
37 37 bool swf_f2_ready = false;
38 38
39 39 int wf_snap_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
40 40 ring_node ring_node_wf_snap_extracted;
41 41
42 42 //*********************
43 43 // Interrupt SubRoutine
44 44
45 45 ring_node * getRingNodeToSendCWF( unsigned char frequencyChannel)
46 46 {
47 47 ring_node *node;
48 48
49 49 node = NULL;
50 50 switch ( frequencyChannel ) {
51 51 case 1:
52 52 node = ring_node_to_send_cwf_f1;
53 53 break;
54 54 case 2:
55 55 node = ring_node_to_send_cwf_f2;
56 56 break;
57 57 case 3:
58 58 node = ring_node_to_send_cwf_f3;
59 59 break;
60 60 default:
61 61 break;
62 62 }
63 63
64 64 return node;
65 65 }
66 66
67 67 ring_node * getRingNodeToSendSWF( unsigned char frequencyChannel)
68 68 {
69 69 ring_node *node;
70 70
71 71 node = NULL;
72 72 switch ( frequencyChannel ) {
73 73 case 0:
74 74 node = ring_node_to_send_swf_f0;
75 75 break;
76 76 case 1:
77 77 node = ring_node_to_send_swf_f1;
78 78 break;
79 79 case 2:
80 80 node = ring_node_to_send_swf_f2;
81 81 break;
82 82 default:
83 83 break;
84 84 }
85 85
86 86 return node;
87 87 }
88 88
89 89 void reset_extractSWF( void )
90 90 {
91 91 extractSWF = false;
92 92 swf_f0_ready = false;
93 93 swf_f1_ready = false;
94 94 swf_f2_ready = false;
95 95 }
96 96
97 97 inline void waveforms_isr_f3( void )
98 98 {
99 99 rtems_status_code spare_status;
100 100
101 101 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_BURST) // in BURST the data are used to place v, e1 and e2 in the HK packet
102 102 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
103 103 { // in modes other than STANDBY and BURST, send the CWF_F3 data
104 104 //***
105 105 // F3
106 106 if ( (waveform_picker_regs->status & 0xc0) != 0x00 ) { // [1100 0000] check the f3 full bits
107 107 ring_node_to_send_cwf_f3 = current_ring_node_f3->previous;
108 108 current_ring_node_f3 = current_ring_node_f3->next;
109 109 if ((waveform_picker_regs->status & 0x40) == 0x40){ // [0100 0000] f3 buffer 0 is full
110 110 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_0_coarse_time;
111 111 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_0_fine_time;
112 112 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->buffer_address;
113 113 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008840; // [1000 1000 0100 0000]
114 114 }
115 115 else if ((waveform_picker_regs->status & 0x80) == 0x80){ // [1000 0000] f3 buffer 1 is full
116 116 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_1_coarse_time;
117 117 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_1_fine_time;
118 118 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address;
119 119 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008880; // [1000 1000 1000 0000]
120 120 }
121 121 if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
122 122 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
123 123 }
124 124 }
125 125 }
126 126 }
127 127
128 128 inline void waveforms_isr_normal( void )
129 129 {
130 130 rtems_status_code status;
131 131
132 132 if ( ( (waveform_picker_regs->status & 0x30) != 0x00 ) // [0011 0000] check the f2 full bits
133 133 && ( (waveform_picker_regs->status & 0x0c) != 0x00 ) // [0000 1100] check the f1 full bits
134 134 && ( (waveform_picker_regs->status & 0x03) != 0x00 )) // [0000 0011] check the f0 full bits
135 135 {
136 136 //***
137 137 // F0
138 138 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
139 139 current_ring_node_f0 = current_ring_node_f0->next;
140 140 if ( (waveform_picker_regs->status & 0x01) == 0x01)
141 141 {
142 142
143 143 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
144 144 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
145 145 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
146 146 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
147 147 }
148 148 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
149 149 {
150 150 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
151 151 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
152 152 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
153 153 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
154 154 }
155 155
156 156 //***
157 157 // F1
158 158 ring_node_to_send_swf_f1 = current_ring_node_f1->previous;
159 159 current_ring_node_f1 = current_ring_node_f1->next;
160 160 if ( (waveform_picker_regs->status & 0x04) == 0x04)
161 161 {
162 162 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
163 163 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
164 164 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
165 165 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
166 166 }
167 167 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
168 168 {
169 169 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
170 170 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
171 171 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
172 172 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
173 173 }
174 174
175 175 //***
176 176 // F2
177 177 ring_node_to_send_swf_f2 = current_ring_node_f2->previous;
178 178 current_ring_node_f2 = current_ring_node_f2->next;
179 179 if ( (waveform_picker_regs->status & 0x10) == 0x10)
180 180 {
181 181 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
182 182 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
183 183 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
184 184 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
185 185 }
186 186 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
187 187 {
188 188 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
189 189 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
190 190 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
191 191 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
192 192 }
193 193 //
194 194 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL );
195 195 if ( status != RTEMS_SUCCESSFUL)
196 196 {
197 197 status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
198 198 }
199 199 }
200 200 }
201 201
202 202 inline void waveforms_isr_burst( void )
203 203 {
204 204 unsigned char status;
205 205 rtems_status_code spare_status;
206 206
207 207 status = (waveform_picker_regs->status & 0x30) >> 4; // [0011 0000] get the status bits for f2
208 208
209 209
210 210 switch(status)
211 211 {
212 212 case 1:
213 213 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
214 214 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
215 215 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
216 216 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
217 217 current_ring_node_f2 = current_ring_node_f2->next;
218 218 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
219 219 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
220 220 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
221 221 }
222 222 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
223 223 break;
224 224 case 2:
225 225 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
226 226 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
227 227 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
228 228 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
229 229 current_ring_node_f2 = current_ring_node_f2->next;
230 230 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
231 231 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
232 232 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
233 233 }
234 234 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
235 235 break;
236 236 default:
237 237 break;
238 238 }
239 239 }
240 240
241 241 inline void waveforms_isr_sbm1( void )
242 242 {
243 243 rtems_status_code status;
244 244
245 245 //***
246 246 // F1
247 247 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bits
248 248 // (1) change the receiving buffer for the waveform picker
249 249 ring_node_to_send_cwf_f1 = current_ring_node_f1->previous;
250 250 current_ring_node_f1 = current_ring_node_f1->next;
251 251 if ( (waveform_picker_regs->status & 0x04) == 0x04)
252 252 {
253 253 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
254 254 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
255 255 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
256 256 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
257 257 }
258 258 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
259 259 {
260 260 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
261 261 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
262 262 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
263 263 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
264 264 }
265 265 // (2) send an event for the the CWF1 task for transmission (and snapshot extraction if needed)
266 266 status = rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_SBM1 );
267 267 }
268 268
269 269 //***
270 270 // F0
271 271 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) { // [0000 0011] check the f0 full bits
272 272 swf_f0_ready = true;
273 273 // change f0 buffer
274 274 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
275 275 current_ring_node_f0 = current_ring_node_f0->next;
276 276 if ( (waveform_picker_regs->status & 0x01) == 0x01)
277 277 {
278 278
279 279 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
280 280 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
281 281 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
282 282 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
283 283 }
284 284 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
285 285 {
286 286 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
287 287 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
288 288 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
289 289 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
290 290 }
291 291 }
292 292
293 293 //***
294 294 // F2
295 295 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bits
296 296 swf_f2_ready = true;
297 297 // change f2 buffer
298 298 ring_node_to_send_swf_f2 = current_ring_node_f2->previous;
299 299 current_ring_node_f2 = current_ring_node_f2->next;
300 300 if ( (waveform_picker_regs->status & 0x10) == 0x10)
301 301 {
302 302 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
303 303 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
304 304 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
305 305 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
306 306 }
307 307 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
308 308 {
309 309 ring_node_to_send_swf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
310 310 ring_node_to_send_swf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
311 311 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
312 312 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
313 313 }
314 314 }
315 315 }
316 316
317 317 inline void waveforms_isr_sbm2( void )
318 318 {
319 319 rtems_status_code status;
320 320
321 321 //***
322 322 // F2
323 323 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bit
324 324 // (1) change the receiving buffer for the waveform picker
325 325 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
326 326 ring_node_to_send_cwf_f2->sid = SID_SBM2_CWF_F2;
327 327 current_ring_node_f2 = current_ring_node_f2->next;
328 328 if ( (waveform_picker_regs->status & 0x10) == 0x10)
329 329 {
330 330 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
331 331 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
332 332 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
333 333 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
334 334 }
335 335 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
336 336 {
337 337 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
338 338 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
339 339 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
340 340 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
341 341 }
342 342 // (2) send an event for the waveforms transmission
343 343 status = rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_SBM2 );
344 344 }
345 345
346 346 //***
347 347 // F0
348 348 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) { // [0000 0011] check the f0 full bit
349 349 swf_f0_ready = true;
350 350 // change f0 buffer
351 351 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
352 352 current_ring_node_f0 = current_ring_node_f0->next;
353 353 if ( (waveform_picker_regs->status & 0x01) == 0x01)
354 354 {
355 355
356 356 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
357 357 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
358 358 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
359 359 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
360 360 }
361 361 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
362 362 {
363 363 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
364 364 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
365 365 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
366 366 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
367 367 }
368 368 }
369 369
370 370 //***
371 371 // F1
372 372 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bit
373 373 swf_f1_ready = true;
374 374 ring_node_to_send_swf_f1 = current_ring_node_f1->previous;
375 375 current_ring_node_f1 = current_ring_node_f1->next;
376 376 if ( (waveform_picker_regs->status & 0x04) == 0x04)
377 377 {
378 378 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
379 379 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
380 380 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
381 381 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
382 382 }
383 383 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
384 384 {
385 385 ring_node_to_send_swf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
386 386 ring_node_to_send_swf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
387 387 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
388 388 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
389 389 }
390 390 }
391 391 }
392 392
393 393 rtems_isr waveforms_isr( rtems_vector_number vector )
394 394 {
395 395 /** This is the interrupt sub routine called by the waveform picker core.
396 396 *
397 397 * This ISR launch different actions depending mainly on two pieces of information:
398 398 * 1. the values read in the registers of the waveform picker.
399 399 * 2. the current LFR mode.
400 400 *
401 401 */
402 402
403 403 // STATUS
404 404 // new error error buffer full
405 405 // 15 14 13 12 11 10 9 8
406 406 // f3 f2 f1 f0 f3 f2 f1 f0
407 407 //
408 408 // ready buffer
409 409 // 7 6 5 4 3 2 1 0
410 410 // f3_1 f3_0 f2_1 f2_0 f1_1 f1_0 f0_1 f0_0
411 411
412 412 rtems_status_code spare_status;
413 413
414 414 waveforms_isr_f3();
415 415
416 416 if ( (waveform_picker_regs->status & 0xff00) != 0x00) // [1111 1111 0000 0000] check the error bits
417 417 {
418 418 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_10 );
419 419 }
420 420
421 421 switch(lfrCurrentMode)
422 422 {
423 423 //********
424 424 // STANDBY
425 425 case(LFR_MODE_STANDBY):
426 426 break;
427 427
428 428 //******
429 429 // NORMAL
430 430 case(LFR_MODE_NORMAL):
431 431 waveforms_isr_normal();
432 432 break;
433 433
434 434 //******
435 435 // BURST
436 436 case(LFR_MODE_BURST):
437 437 waveforms_isr_burst();
438 438 break;
439 439
440 440 //*****
441 441 // SBM1
442 442 case(LFR_MODE_SBM1):
443 443 waveforms_isr_sbm1();
444 444 break;
445 445
446 446 //*****
447 447 // SBM2
448 448 case(LFR_MODE_SBM2):
449 449 waveforms_isr_sbm2();
450 450 break;
451 451
452 452 //********
453 453 // DEFAULT
454 454 default:
455 455 break;
456 456 }
457 457 }
458 458
459 459 //************
460 460 // RTEMS TASKS
461 461
462 462 rtems_task wfrm_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
463 463 {
464 464 /** This RTEMS task is dedicated to the transmission of snapshots of the NORMAL mode.
465 465 *
466 466 * @param unused is the starting argument of the RTEMS task
467 467 *
468 468 * The following data packets are sent by this task:
469 469 * - TM_LFR_SCIENCE_NORMAL_SWF_F0
470 470 * - TM_LFR_SCIENCE_NORMAL_SWF_F1
471 471 * - TM_LFR_SCIENCE_NORMAL_SWF_F2
472 472 *
473 473 */
474 474
475 475 rtems_event_set event_out;
476 476 rtems_id queue_id;
477 477 rtems_status_code status;
478 478 bool resynchronisationEngaged;
479 479 ring_node *ring_node_wf_snap_extracted_ptr;
480 480
481 481 ring_node_wf_snap_extracted_ptr = (ring_node *) &ring_node_wf_snap_extracted;
482 482
483 483 resynchronisationEngaged = false;
484 484
485 485 status = get_message_queue_id_send( &queue_id );
486 486 if (status != RTEMS_SUCCESSFUL)
487 487 {
488 488 PRINTF1("in WFRM *** ERR get_message_queue_id_send %d\n", status)
489 489 }
490 490
491 491 BOOT_PRINTF("in WFRM ***\n")
492 492
493 493 while(1){
494 494 // wait for an RTEMS_EVENT
495 495 rtems_event_receive(RTEMS_EVENT_MODE_NORMAL | RTEMS_EVENT_MODE_SBM1
496 496 | RTEMS_EVENT_MODE_SBM2 | RTEMS_EVENT_MODE_SBM2_WFRM,
497 497 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
498 498 if(resynchronisationEngaged == false)
499 499 { // engage resynchronisation
500 500 snapshot_resynchronization( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
501 501 resynchronisationEngaged = true;
502 502 }
503 503 else
504 504 { // reset delta_snapshot to the nominal value
505 505 PRINTF("no resynchronisation, reset delta_snapshot to the nominal value\n")
506 506 set_wfp_delta_snapshot();
507 507 resynchronisationEngaged = false;
508 508 }
509 509 //
510 510
511 511 if (event_out == RTEMS_EVENT_MODE_NORMAL)
512 512 {
513 513 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_NORMAL\n")
514 514 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
515 515 ring_node_to_send_swf_f1->sid = SID_NORM_SWF_F1;
516 516 ring_node_to_send_swf_f2->sid = SID_NORM_SWF_F2;
517 517 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
518 518 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f1, sizeof( ring_node* ) );
519 519 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f2, sizeof( ring_node* ) );
520 520 }
521 521 if (event_out == RTEMS_EVENT_MODE_SBM1)
522 522 {
523 523 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM1\n")
524 524 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
525 525 ring_node_wf_snap_extracted_ptr->sid = SID_NORM_SWF_F1;
526 526 ring_node_to_send_swf_f2->sid = SID_NORM_SWF_F2;
527 527 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
528 528 status = rtems_message_queue_send( queue_id, &ring_node_wf_snap_extracted_ptr, sizeof( ring_node* ) );
529 529 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f2, sizeof( ring_node* ) );
530 530 }
531 531 if (event_out == RTEMS_EVENT_MODE_SBM2)
532 532 {
533 533 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM2\n")
534 534 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
535 535 ring_node_to_send_swf_f1->sid = SID_NORM_SWF_F1;
536 536 ring_node_wf_snap_extracted_ptr->sid = SID_NORM_SWF_F2;
537 537 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
538 538 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f1, sizeof( ring_node* ) );
539 539 status = rtems_message_queue_send( queue_id, &ring_node_wf_snap_extracted_ptr, sizeof( ring_node* ) );
540 540 }
541 541 }
542 542 }
543 543
544 544 rtems_task cwf3_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
545 545 {
546 546 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f3.
547 547 *
548 548 * @param unused is the starting argument of the RTEMS task
549 549 *
550 550 * The following data packet is sent by this task:
551 551 * - TM_LFR_SCIENCE_NORMAL_CWF_F3
552 552 *
553 553 */
554 554
555 555 rtems_event_set event_out;
556 556 rtems_id queue_id;
557 557 rtems_status_code status;
558 558 ring_node ring_node_cwf3_light;
559 559
560 560 status = get_message_queue_id_send( &queue_id );
561 561 if (status != RTEMS_SUCCESSFUL)
562 562 {
563 563 PRINTF1("in CWF3 *** ERR get_message_queue_id_send %d\n", status)
564 564 }
565 565
566 566 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
567 567
568 568 // init the ring_node_cwf3_light structure
569 569 ring_node_cwf3_light.buffer_address = (int) wf_cont_f3_light;
570 570 ring_node_cwf3_light.coarseTime = 0x00;
571 571 ring_node_cwf3_light.fineTime = 0x00;
572 572 ring_node_cwf3_light.next = NULL;
573 573 ring_node_cwf3_light.previous = NULL;
574 574 ring_node_cwf3_light.sid = SID_NORM_CWF_F3;
575 575 ring_node_cwf3_light.status = 0x00;
576 576
577 577 BOOT_PRINTF("in CWF3 ***\n")
578 578
579 579 while(1){
580 580 // wait for an RTEMS_EVENT
581 581 rtems_event_receive( RTEMS_EVENT_0,
582 582 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
583 583 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
584 584 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode==LFR_MODE_SBM2) )
585 585 {
586 586 if ( (parameter_dump_packet.sy_lfr_n_cwf_long_f3 & 0x01) == 0x01)
587 587 {
588 588 PRINTF("send CWF_LONG_F3\n")
589 589 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
590 590 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf_f3, sizeof( ring_node* ) );
591 591 }
592 592 else
593 593 {
594 594 PRINTF("send CWF_F3 (light)\n")
595 595 send_waveform_CWF3_light( ring_node_to_send_cwf_f3, &ring_node_cwf3_light, queue_id );
596 596 }
597 597
598 598 }
599 599 else
600 600 {
601 601 PRINTF1("in CWF3 *** lfrCurrentMode is %d, no data will be sent\n", lfrCurrentMode)
602 602 }
603 603 }
604 604 }
605 605
606 606 rtems_task cwf2_task(rtems_task_argument argument) // ONLY USED IN BURST AND SBM2
607 607 {
608 608 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f2.
609 609 *
610 610 * @param unused is the starting argument of the RTEMS task
611 611 *
612 612 * The following data packet is sent by this function:
613 613 * - TM_LFR_SCIENCE_BURST_CWF_F2
614 614 * - TM_LFR_SCIENCE_SBM2_CWF_F2
615 615 *
616 616 */
617 617
618 618 rtems_event_set event_out;
619 619 rtems_id queue_id;
620 620 rtems_status_code status;
621 621 ring_node *ring_node_to_send;
622 622 unsigned long long int acquisitionTimeF0_asLong;
623 623
624 624 acquisitionTimeF0_asLong = 0x00;
625 625
626 626 status = get_message_queue_id_send( &queue_id );
627 627 if (status != RTEMS_SUCCESSFUL)
628 628 {
629 629 PRINTF1("in CWF2 *** ERR get_message_queue_id_send %d\n", status)
630 630 }
631 631
632 632 BOOT_PRINTF("in CWF2 ***\n")
633 633
634 634 while(1){
635 635 // wait for an RTEMS_EVENT
636 636 rtems_event_receive( RTEMS_EVENT_MODE_BURST | RTEMS_EVENT_MODE_SBM2,
637 637 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
638 638 ring_node_to_send = getRingNodeToSendCWF( 2 );
639 639 if (event_out == RTEMS_EVENT_MODE_BURST)
640 640 {
641 641 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
642 642 }
643 643 if (event_out == RTEMS_EVENT_MODE_SBM2)
644 644 {
645 645 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
646 646 // launch snapshot extraction if needed
647 647 if (extractSWF == true)
648 648 {
649 649 ring_node_to_send_swf_f2 = ring_node_to_send_cwf_f2;
650 650 // extract the snapshot
651 651 build_snapshot_from_ring( ring_node_to_send_swf_f2, 2, acquisitionTimeF0_asLong );
652 652 // send the snapshot when built
653 653 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM2 );
654 654 extractSWF = false;
655 655 }
656 656 if (swf_f0_ready && swf_f1_ready)
657 657 {
658 658 extractSWF = true;
659 659 // record the acquition time of the fΓ  snapshot to use to build the snapshot at f2
660 660 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
661 661 swf_f0_ready = false;
662 662 swf_f1_ready = false;
663 663 }
664 664 }
665 665 }
666 666 }
667 667
668 668 rtems_task cwf1_task(rtems_task_argument argument) // ONLY USED IN SBM1
669 669 {
670 670 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f1.
671 671 *
672 672 * @param unused is the starting argument of the RTEMS task
673 673 *
674 674 * The following data packet is sent by this function:
675 675 * - TM_LFR_SCIENCE_SBM1_CWF_F1
676 676 *
677 677 */
678 678
679 679 rtems_event_set event_out;
680 680 rtems_id queue_id;
681 681 rtems_status_code status;
682 682
683 683 ring_node * ring_node_to_send_cwf;
684 684
685 685 status = get_message_queue_id_send( &queue_id );
686 686 if (status != RTEMS_SUCCESSFUL)
687 687 {
688 688 PRINTF1("in CWF1 *** ERR get_message_queue_id_send %d\n", status)
689 689 }
690 690
691 691 BOOT_PRINTF("in CWF1 ***\n")
692 692
693 693 while(1){
694 694 // wait for an RTEMS_EVENT
695 695 rtems_event_receive( RTEMS_EVENT_MODE_SBM1,
696 696 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
697 697 ring_node_to_send_cwf = getRingNodeToSendCWF( 1 );
698 698 ring_node_to_send_cwf_f1->sid = SID_SBM1_CWF_F1;
699 699 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
700 700 // launch snapshot extraction if needed
701 701 if (extractSWF == true)
702 702 {
703 703 ring_node_to_send_swf_f1 = ring_node_to_send_cwf;
704 704 // launch the snapshot extraction
705 705 status = rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_MODE_SBM1 );
706 706 extractSWF = false;
707 707 }
708 708 if (swf_f0_ready == true)
709 709 {
710 710 extractSWF = true;
711 711 swf_f0_ready = false; // this step shall be executed only one time
712 712 }
713 713 if ((swf_f1_ready == true) && (swf_f2_ready == true)) // swf_f1 is ready after the extraction
714 714 {
715 715 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM1 );
716 716 swf_f1_ready = false;
717 717 swf_f2_ready = false;
718 718 }
719 719 }
720 720 }
721 721
722 722 rtems_task swbd_task(rtems_task_argument argument)
723 723 {
724 724 /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers.
725 725 *
726 726 * @param unused is the starting argument of the RTEMS task
727 727 *
728 728 */
729 729
730 730 rtems_event_set event_out;
731 731 unsigned long long int acquisitionTimeF0_asLong;
732 732
733 733 acquisitionTimeF0_asLong = 0x00;
734 734
735 735 BOOT_PRINTF("in SWBD ***\n")
736 736
737 737 while(1){
738 738 // wait for an RTEMS_EVENT
739 739 rtems_event_receive( RTEMS_EVENT_MODE_SBM1 | RTEMS_EVENT_MODE_SBM2,
740 740 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
741 741 if (event_out == RTEMS_EVENT_MODE_SBM1)
742 742 {
743 743 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
744 744 build_snapshot_from_ring( ring_node_to_send_swf_f1, 1, acquisitionTimeF0_asLong );
745 745 swf_f1_ready = true; // the snapshot has been extracted and is ready to be sent
746 746 }
747 747 else
748 748 {
749 749 PRINTF1("in SWBD *** unexpected rtems event received %x\n", (int) event_out)
750 750 }
751 751 }
752 752 }
753 753
754 754 //******************
755 755 // general functions
756 756
757 757 void WFP_init_rings( void )
758 758 {
759 759 // F0 RING
760 760 init_ring( waveform_ring_f0, NB_RING_NODES_F0, wf_buffer_f0, WFRM_BUFFER );
761 761 // F1 RING
762 762 init_ring( waveform_ring_f1, NB_RING_NODES_F1, wf_buffer_f1, WFRM_BUFFER );
763 763 // F2 RING
764 764 init_ring( waveform_ring_f2, NB_RING_NODES_F2, wf_buffer_f2, WFRM_BUFFER );
765 765 // F3 RING
766 766 init_ring( waveform_ring_f3, NB_RING_NODES_F3, wf_buffer_f3, WFRM_BUFFER );
767 767
768 768 ring_node_wf_snap_extracted.buffer_address = (int) wf_snap_extracted;
769 769
770 770 DEBUG_PRINTF1("waveform_ring_f0 @%x\n", (unsigned int) waveform_ring_f0)
771 771 DEBUG_PRINTF1("waveform_ring_f1 @%x\n", (unsigned int) waveform_ring_f1)
772 772 DEBUG_PRINTF1("waveform_ring_f2 @%x\n", (unsigned int) waveform_ring_f2)
773 773 DEBUG_PRINTF1("waveform_ring_f3 @%x\n", (unsigned int) waveform_ring_f3)
774 774 DEBUG_PRINTF1("wf_buffer_f0 @%x\n", (unsigned int) wf_buffer_f0)
775 775 DEBUG_PRINTF1("wf_buffer_f1 @%x\n", (unsigned int) wf_buffer_f1)
776 776 DEBUG_PRINTF1("wf_buffer_f2 @%x\n", (unsigned int) wf_buffer_f2)
777 777 DEBUG_PRINTF1("wf_buffer_f3 @%x\n", (unsigned int) wf_buffer_f3)
778 778
779 779 }
780 780
781 781 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize )
782 782 {
783 783 unsigned char i;
784 784
785 785 //***************
786 786 // BUFFER ADDRESS
787 787 for(i=0; i<nbNodes; i++)
788 788 {
789 789 ring[i].coarseTime = 0x00;
790 790 ring[i].fineTime = 0x00;
791 791 ring[i].sid = 0x00;
792 792 ring[i].status = 0x00;
793 793 ring[i].buffer_address = (int) &buffer[ i * bufferSize ];
794 794 }
795 795
796 796 //*****
797 797 // NEXT
798 798 ring[ nbNodes - 1 ].next = (ring_node*) &ring[ 0 ];
799 799 for(i=0; i<nbNodes-1; i++)
800 800 {
801 801 ring[i].next = (ring_node*) &ring[ i + 1 ];
802 802 }
803 803
804 804 //*********
805 805 // PREVIOUS
806 806 ring[ 0 ].previous = (ring_node*) &ring[ nbNodes - 1 ];
807 807 for(i=1; i<nbNodes; i++)
808 808 {
809 809 ring[i].previous = (ring_node*) &ring[ i - 1 ];
810 810 }
811 811 }
812 812
813 813 void WFP_reset_current_ring_nodes( void )
814 814 {
815 815 current_ring_node_f0 = waveform_ring_f0[0].next;
816 816 current_ring_node_f1 = waveform_ring_f1[0].next;
817 817 current_ring_node_f2 = waveform_ring_f2[0].next;
818 818 current_ring_node_f3 = waveform_ring_f3[0].next;
819 819
820 820 ring_node_to_send_swf_f0 = waveform_ring_f0;
821 821 ring_node_to_send_swf_f1 = waveform_ring_f1;
822 822 ring_node_to_send_swf_f2 = waveform_ring_f2;
823 823
824 824 ring_node_to_send_cwf_f1 = waveform_ring_f1;
825 825 ring_node_to_send_cwf_f2 = waveform_ring_f2;
826 826 ring_node_to_send_cwf_f3 = waveform_ring_f3;
827 827 }
828 828
829 829 int send_waveform_CWF3_light( ring_node *ring_node_to_send, ring_node *ring_node_cwf3_light, rtems_id queue_id )
830 830 {
831 831 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
832 832 *
833 833 * @param waveform points to the buffer containing the data that will be send.
834 834 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
835 835 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
836 836 * contain information to setup the transmission of the data packets.
837 837 *
838 838 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
839 839 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
840 840 *
841 841 */
842 842
843 843 unsigned int i;
844 844 int ret;
845 845 rtems_status_code status;
846 846
847 847 char *sample;
848 848 int *dataPtr;
849 849
850 850 ret = LFR_DEFAULT;
851 851
852 852 dataPtr = (int*) ring_node_to_send->buffer_address;
853 853
854 854 ring_node_cwf3_light->coarseTime = ring_node_to_send->coarseTime;
855 855 ring_node_cwf3_light->fineTime = ring_node_to_send->fineTime;
856 856
857 857 //**********************
858 858 // BUILD CWF3_light DATA
859 859 for ( i=0; i< NB_SAMPLES_PER_SNAPSHOT; i++)
860 860 {
861 861 sample = (char*) &dataPtr[ (i * NB_WORDS_SWF_BLK) ];
862 862 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) ] = sample[ 0 ];
863 863 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 1 ] = sample[ 1 ];
864 864 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 2 ] = sample[ 2 ];
865 865 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 3 ] = sample[ 3 ];
866 866 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 4 ] = sample[ 4 ];
867 867 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 5 ] = sample[ 5 ];
868 868 }
869 869
870 870 // SEND PACKET
871 871 status = rtems_message_queue_send( queue_id, &ring_node_cwf3_light, sizeof( ring_node* ) );
872 872 if (status != RTEMS_SUCCESSFUL) {
873 873 printf("%d-%d, ERR %d\n", SID_NORM_CWF_F3, i, (int) status);
874 874 ret = LFR_DEFAULT;
875 875 }
876 876
877 877 return ret;
878 878 }
879 879
880 880 void compute_acquisition_time( unsigned int coarseTime, unsigned int fineTime,
881 881 unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char * acquisitionTime )
882 882 {
883 883 unsigned long long int acquisitionTimeAsLong;
884 884 unsigned char localAcquisitionTime[6];
885 885 double deltaT;
886 886
887 887 deltaT = 0.;
888 888
889 889 localAcquisitionTime[0] = (unsigned char) ( coarseTime >> 24 );
890 890 localAcquisitionTime[1] = (unsigned char) ( coarseTime >> 16 );
891 891 localAcquisitionTime[2] = (unsigned char) ( coarseTime >> 8 );
892 892 localAcquisitionTime[3] = (unsigned char) ( coarseTime );
893 893 localAcquisitionTime[4] = (unsigned char) ( fineTime >> 8 );
894 894 localAcquisitionTime[5] = (unsigned char) ( fineTime );
895 895
896 896 acquisitionTimeAsLong = ( (unsigned long long int) localAcquisitionTime[0] << 40 )
897 897 + ( (unsigned long long int) localAcquisitionTime[1] << 32 )
898 898 + ( (unsigned long long int) localAcquisitionTime[2] << 24 )
899 899 + ( (unsigned long long int) localAcquisitionTime[3] << 16 )
900 900 + ( (unsigned long long int) localAcquisitionTime[4] << 8 )
901 901 + ( (unsigned long long int) localAcquisitionTime[5] );
902 902
903 903 switch( sid )
904 904 {
905 905 case SID_NORM_SWF_F0:
906 906 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 24576. ;
907 907 break;
908 908
909 909 case SID_NORM_SWF_F1:
910 910 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 4096. ;
911 911 break;
912 912
913 913 case SID_NORM_SWF_F2:
914 914 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 256. ;
915 915 break;
916 916
917 917 case SID_SBM1_CWF_F1:
918 918 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 4096. ;
919 919 break;
920 920
921 921 case SID_SBM2_CWF_F2:
922 922 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
923 923 break;
924 924
925 925 case SID_BURST_CWF_F2:
926 926 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
927 927 break;
928 928
929 929 case SID_NORM_CWF_F3:
930 930 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF_SHORT_F3 * 65536. / 16. ;
931 931 break;
932 932
933 933 case SID_NORM_CWF_LONG_F3:
934 934 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 16. ;
935 935 break;
936 936
937 937 default:
938 938 PRINTF1("in compute_acquisition_time *** ERR unexpected sid %d\n", sid)
939 939 deltaT = 0.;
940 940 break;
941 941 }
942 942
943 943 acquisitionTimeAsLong = acquisitionTimeAsLong + (unsigned long long int) deltaT;
944 944 //
945 945 acquisitionTime[0] = (unsigned char) (acquisitionTimeAsLong >> 40);
946 946 acquisitionTime[1] = (unsigned char) (acquisitionTimeAsLong >> 32);
947 947 acquisitionTime[2] = (unsigned char) (acquisitionTimeAsLong >> 24);
948 948 acquisitionTime[3] = (unsigned char) (acquisitionTimeAsLong >> 16);
949 949 acquisitionTime[4] = (unsigned char) (acquisitionTimeAsLong >> 8 );
950 950 acquisitionTime[5] = (unsigned char) (acquisitionTimeAsLong );
951 951
952 952 }
953 953
954 954 void build_snapshot_from_ring( ring_node *ring_node_to_send, unsigned char frequencyChannel, unsigned long long int acquisitionTimeF0_asLong )
955 955 {
956 956 unsigned int i;
957 957 unsigned long long int centerTime_asLong;
958 958 unsigned long long int acquisitionTime_asLong;
959 959 unsigned long long int bufferAcquisitionTime_asLong;
960 960 unsigned char *ptr1;
961 961 unsigned char *ptr2;
962 962 unsigned char *timeCharPtr;
963 963 unsigned char nb_ring_nodes;
964 964 unsigned long long int frequency_asLong;
965 965 unsigned long long int nbTicksPerSample_asLong;
966 966 unsigned long long int nbSamplesPart1_asLong;
967 967 unsigned long long int sampleOffset_asLong;
968 968
969 969 unsigned int deltaT_F0;
970 970 unsigned int deltaT_F1;
971 971 unsigned long long int deltaT_F2;
972 972
973 973 deltaT_F0 = 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
974 974 deltaT_F1 = 16384; // (2048. / 4096. / 2.) * 65536. = 16384;
975 975 deltaT_F2 = 262144; // (2048. / 256. / 2.) * 65536. = 262144;
976 976 sampleOffset_asLong = 0x00;
977 977
978 978 // (1) get the f0 acquisition time => the value is passed in argument
979 979
980 980 // (2) compute the central reference time
981 981 centerTime_asLong = acquisitionTimeF0_asLong + deltaT_F0;
982 982
983 983 // (3) compute the acquisition time of the current snapshot
984 984 switch(frequencyChannel)
985 985 {
986 986 case 1: // 1 is for F1 = 4096 Hz
987 987 acquisitionTime_asLong = centerTime_asLong - deltaT_F1;
988 988 nb_ring_nodes = NB_RING_NODES_F1;
989 989 frequency_asLong = 4096;
990 990 nbTicksPerSample_asLong = 16; // 65536 / 4096;
991 991 break;
992 992 case 2: // 2 is for F2 = 256 Hz
993 993 acquisitionTime_asLong = centerTime_asLong - deltaT_F2;
994 994 nb_ring_nodes = NB_RING_NODES_F2;
995 995 frequency_asLong = 256;
996 996 nbTicksPerSample_asLong = 256; // 65536 / 256;
997 997 break;
998 998 default:
999 999 acquisitionTime_asLong = centerTime_asLong;
1000 1000 frequency_asLong = 256;
1001 1001 nbTicksPerSample_asLong = 256;
1002 1002 break;
1003 1003 }
1004 1004
1005 1005 //****************************************************************************
1006 1006 // (4) search the ring_node with the acquisition time <= acquisitionTime_asLong
1007 1007 for (i=0; i<nb_ring_nodes; i++)
1008 1008 {
1009 1009 PRINTF1("%d ... ", i)
1010 1010 bufferAcquisitionTime_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send->coarseTime );
1011 1011 if (bufferAcquisitionTime_asLong <= acquisitionTime_asLong)
1012 1012 {
1013 1013 PRINTF1("buffer found with acquisition time = %llx\n", bufferAcquisitionTime_asLong)
1014 1014 break;
1015 1015 }
1016 1016 ring_node_to_send = ring_node_to_send->previous;
1017 1017 }
1018 1018
1019 1019 // (5) compute the number of samples to take in the current buffer
1020 1020 sampleOffset_asLong = ((acquisitionTime_asLong - bufferAcquisitionTime_asLong) * frequency_asLong ) >> 16;
1021 1021 nbSamplesPart1_asLong = NB_SAMPLES_PER_SNAPSHOT - sampleOffset_asLong;
1022 1022 PRINTF2("sampleOffset_asLong = %lld, nbSamplesPart1_asLong = %lld\n", sampleOffset_asLong, nbSamplesPart1_asLong)
1023 1023
1024 1024 // (6) compute the final acquisition time
1025 1025 acquisitionTime_asLong = bufferAcquisitionTime_asLong +
1026 1026 sampleOffset_asLong * nbTicksPerSample_asLong;
1027 1027
1028 1028 // (7) copy the acquisition time at the beginning of the extrated snapshot
1029 1029 ptr1 = (unsigned char*) &acquisitionTime_asLong;
1030 1030 // fine time
1031 1031 ptr2 = (unsigned char*) &ring_node_wf_snap_extracted.fineTime;
1032 1032 ptr2[2] = ptr1[ 4 + 2 ];
1033 1033 ptr2[3] = ptr1[ 5 + 2 ];
1034 1034 // coarse time
1035 1035 ptr2 = (unsigned char*) &ring_node_wf_snap_extracted.coarseTime;
1036 1036 ptr2[0] = ptr1[ 0 + 2 ];
1037 1037 ptr2[1] = ptr1[ 1 + 2 ];
1038 1038 ptr2[2] = ptr1[ 2 + 2 ];
1039 1039 ptr2[3] = ptr1[ 3 + 2 ];
1040 1040
1041 1041 // re set the synchronization bit
1042 1042 timeCharPtr = (unsigned char*) &ring_node_to_send->coarseTime;
1043 1043 ptr2[0] = ptr2[0] | (timeCharPtr[0] & 0x80); // [1000 0000]
1044 1044
1045 1045 if ( (nbSamplesPart1_asLong >= NB_SAMPLES_PER_SNAPSHOT) | (nbSamplesPart1_asLong < 0) )
1046 1046 {
1047 1047 nbSamplesPart1_asLong = 0;
1048 1048 }
1049 1049 // copy the part 1 of the snapshot in the extracted buffer
1050 1050 for ( i = 0; i < (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i++ )
1051 1051 {
1052 1052 wf_snap_extracted[i] =
1053 1053 ((int*) ring_node_to_send->buffer_address)[ i + (sampleOffset_asLong * NB_WORDS_SWF_BLK) ];
1054 1054 }
1055 1055 // copy the part 2 of the snapshot in the extracted buffer
1056 1056 ring_node_to_send = ring_node_to_send->next;
1057 1057 for ( i = (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i < (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ )
1058 1058 {
1059 1059 wf_snap_extracted[i] =
1060 1060 ((int*) ring_node_to_send->buffer_address)[ (i-(nbSamplesPart1_asLong * NB_WORDS_SWF_BLK)) ];
1061 1061 }
1062 1062 }
1063 1063
1064 1064 void snapshot_resynchronization( unsigned char *timePtr )
1065 1065 {
1066 1066 unsigned long long int acquisitionTime;
1067 1067 unsigned long long int centerTime;
1068 1068 unsigned long long int previousTick;
1069 1069 unsigned long long int nextTick;
1070 1070 unsigned long long int deltaPreviousTick;
1071 1071 unsigned long long int deltaNextTick;
1072 1072 unsigned int deltaTickInF2;
1073 1073 double deltaPrevious;
1074 1074 double deltaNext;
1075 1075
1076 1076 acquisitionTime = get_acquisition_time( timePtr );
1077 1077
1078 1078 // compute center time
1079 1079 centerTime = acquisitionTime + 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
1080 1080 previousTick = centerTime - (centerTime & 0xffff);
1081 1081 nextTick = previousTick + 65536;
1082 1082
1083 1083 deltaPreviousTick = centerTime - previousTick;
1084 1084 deltaNextTick = nextTick - centerTime;
1085 1085
1086 1086 deltaPrevious = ((double) deltaPreviousTick) / 65536. * 1000.;
1087 1087 deltaNext = ((double) deltaNextTick) / 65536. * 1000.;
1088 1088
1089 1089 PRINTF2("delta previous = %f ms, delta next = %f ms\n", deltaPrevious, deltaNext)
1090 1090 PRINTF2("delta previous = %llu, delta next = %llu\n", deltaPreviousTick, deltaNextTick)
1091 1091
1092 1092 // which tick is the closest
1093 1093 if (deltaPreviousTick > deltaNextTick)
1094 1094 {
1095 1095 deltaTickInF2 = floor( (deltaNext * 256. / 1000.) ); // the division by 2 is important here
1096 1096 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + deltaTickInF2;
1097 1097 printf("correction of = + %u\n", deltaTickInF2);
1098 1098 }
1099 1099 else
1100 1100 {
1101 1101 deltaTickInF2 = floor( (deltaPrevious * 256. / 1000.) ); // the division by 2 is important here
1102 1102 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot - deltaTickInF2;
1103 1103 printf("correction of = - %u\n", deltaTickInF2);
1104 1104 }
1105 1105 }
1106 1106
1107 1107 //**************
1108 1108 // wfp registers
1109 1109 void reset_wfp_burst_enable( void )
1110 1110 {
1111 1111 /** This function resets the waveform picker burst_enable register.
1112 1112 *
1113 1113 * The burst bits [f2 f1 f0] and the enable bits [f3 f2 f1 f0] are set to 0.
1114 1114 *
1115 1115 */
1116 1116
1117 1117 // [1000 000] burst f2, f1, f0 enable f3, f2, f1, f0
1118 1118 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable & 0x80;
1119 1119 }
1120 1120
1121 1121 void reset_wfp_status( void )
1122 1122 {
1123 1123 /** This function resets the waveform picker status register.
1124 1124 *
1125 1125 * All status bits are set to 0 [new_err full_err full].
1126 1126 *
1127 1127 */
1128 1128
1129 1129 waveform_picker_regs->status = 0xffff;
1130 1130 }
1131 1131
1132 1132 void reset_wfp_buffer_addresses( void )
1133 1133 {
1134 1134 // F0
1135 1135 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->previous->buffer_address; // 0x08
1136 1136 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address; // 0x0c
1137 1137 // F1
1138 1138 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->previous->buffer_address; // 0x10
1139 1139 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address; // 0x14
1140 1140 // F2
1141 1141 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->previous->buffer_address; // 0x18
1142 1142 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address; // 0x1c
1143 1143 // F3
1144 1144 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->previous->buffer_address; // 0x20
1145 1145 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address; // 0x24
1146 1146 }
1147 1147
1148 1148 void reset_waveform_picker_regs( void )
1149 1149 {
1150 1150 /** This function resets the waveform picker module registers.
1151 1151 *
1152 1152 * The registers affected by this function are located at the following offset addresses:
1153 1153 * - 0x00 data_shaping
1154 1154 * - 0x04 run_burst_enable
1155 1155 * - 0x08 addr_data_f0
1156 1156 * - 0x0C addr_data_f1
1157 1157 * - 0x10 addr_data_f2
1158 1158 * - 0x14 addr_data_f3
1159 1159 * - 0x18 status
1160 1160 * - 0x1C delta_snapshot
1161 1161 * - 0x20 delta_f0
1162 1162 * - 0x24 delta_f0_2
1163 1163 * - 0x28 delta_f1
1164 1164 * - 0x2c delta_f2
1165 1165 * - 0x30 nb_data_by_buffer
1166 1166 * - 0x34 nb_snapshot_param
1167 1167 * - 0x38 start_date
1168 1168 * - 0x3c nb_word_in_buffer
1169 1169 *
1170 1170 */
1171 1171
1172 1172 set_wfp_data_shaping(); // 0x00 *** R1 R0 SP1 SP0 BW
1173 1173
1174 1174 reset_wfp_burst_enable(); // 0x04 *** [run *** burst f2, f1, f0 *** enable f3, f2, f1, f0 ]
1175 1175
1176 1176 reset_wfp_buffer_addresses();
1177 1177
1178 1178 reset_wfp_status(); // 0x18
1179 1179
1180 1180 set_wfp_delta_snapshot(); // 0x1c *** 300 s => 0x12bff
1181 1181
1182 1182 set_wfp_delta_f0_f0_2(); // 0x20, 0x24
1183 1183
1184 1184 set_wfp_delta_f1(); // 0x28
1185 1185
1186 1186 set_wfp_delta_f2(); // 0x2c
1187 1187
1188 1188 DEBUG_PRINTF1("delta_snapshot %x\n", waveform_picker_regs->delta_snapshot)
1189 1189 DEBUG_PRINTF1("delta_f0 %x\n", waveform_picker_regs->delta_f0)
1190 1190 DEBUG_PRINTF1("delta_f0_2 %x\n", waveform_picker_regs->delta_f0_2)
1191 1191 DEBUG_PRINTF1("delta_f1 %x\n", waveform_picker_regs->delta_f1)
1192 1192 DEBUG_PRINTF1("delta_f2 %x\n", waveform_picker_regs->delta_f2)
1193 1193 // 2688 = 8 * 336
1194 1194 waveform_picker_regs->nb_data_by_buffer = 0xa7f; // 0x30 *** 2688 - 1 => nb samples -1
1195 1195 waveform_picker_regs->snapshot_param = 0xa80; // 0x34 *** 2688 => nb samples
1196 1196 waveform_picker_regs->start_date = 0x7fffffff; // 0x38
1197 1197 //
1198 1198 // coarse time and fine time registers are not initialized, they are volatile
1199 1199 //
1200 1200 waveform_picker_regs->buffer_length = 0x1f8;// buffer length in burst = 3 * 2688 / 16 = 504 = 0x1f8
1201 1201 }
1202 1202
1203 1203 void set_wfp_data_shaping( void )
1204 1204 {
1205 1205 /** This function sets the data_shaping register of the waveform picker module.
1206 1206 *
1207 1207 * The value is read from one field of the parameter_dump_packet structure:\n
1208 1208 * bw_sp0_sp1_r0_r1
1209 1209 *
1210 1210 */
1211 1211
1212 1212 unsigned char data_shaping;
1213 1213
1214 1214 // get the parameters for the data shaping [BW SP0 SP1 R0 R1] in sy_lfr_common1 and configure the register
1215 1215 // waveform picker : [R1 R0 SP1 SP0 BW]
1216 1216
1217 1217 data_shaping = parameter_dump_packet.bw_sp0_sp1_r0_r1;
1218 1218
1219 1219 waveform_picker_regs->data_shaping =
1220 1220 ( (data_shaping & 0x10) >> 4 ) // BW
1221 1221 + ( (data_shaping & 0x08) >> 2 ) // SP0
1222 1222 + ( (data_shaping & 0x04) ) // SP1
1223 1223 + ( (data_shaping & 0x02) << 2 ) // R0
1224 1224 + ( (data_shaping & 0x01) << 4 ); // R1
1225 1225
1226 1226 // this is a temporary way to set R2, compatible with the release 2 of the flight software
1227 1227 waveform_picker_regs->data_shaping = waveform_picker_regs->data_shaping + ( (0x1) << 5 ); // R2
1228 1228 }
1229 1229
1230 1230 void set_wfp_burst_enable_register( unsigned char mode )
1231 1231 {
1232 1232 /** This function sets the waveform picker burst_enable register depending on the mode.
1233 1233 *
1234 1234 * @param mode is the LFR mode to launch.
1235 1235 *
1236 1236 * The burst bits shall be before the enable bits.
1237 1237 *
1238 1238 */
1239 1239
1240 1240 // [0000 0000] burst f2, f1, f0 enable f3 f2 f1 f0
1241 1241 // the burst bits shall be set first, before the enable bits
1242 1242 switch(mode) {
1243 1243 case(LFR_MODE_NORMAL):
1244 1244 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enable
1245 1245 waveform_picker_regs->run_burst_enable = 0x0f; // [0000 1111] enable f3 f2 f1 f0
1246 1246 break;
1247 1247 case(LFR_MODE_BURST):
1248 1248 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1249 1249 // waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x04; // [0100] enable f2
1250 1250 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0c; // [1100] enable f3 AND f2
1251 1251 break;
1252 1252 case(LFR_MODE_SBM1):
1253 1253 waveform_picker_regs->run_burst_enable = 0x20; // [0010 0000] f1 burst enabled
1254 1254 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1255 1255 break;
1256 1256 case(LFR_MODE_SBM2):
1257 1257 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1258 1258 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1259 1259 break;
1260 1260 default:
1261 1261 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enabled, no waveform enabled
1262 1262 break;
1263 1263 }
1264 1264 }
1265 1265
1266 1266 void set_wfp_delta_snapshot( void )
1267 1267 {
1268 1268 /** This function sets the delta_snapshot register of the waveform picker module.
1269 1269 *
1270 1270 * The value is read from two (unsigned char) of the parameter_dump_packet structure:
1271 1271 * - sy_lfr_n_swf_p[0]
1272 1272 * - sy_lfr_n_swf_p[1]
1273 1273 *
1274 1274 */
1275 1275
1276 1276 unsigned int delta_snapshot;
1277 1277 unsigned int delta_snapshot_in_T2;
1278 1278
1279 1279 delta_snapshot = parameter_dump_packet.sy_lfr_n_swf_p[0]*256
1280 1280 + parameter_dump_packet.sy_lfr_n_swf_p[1];
1281 1281
1282 1282 delta_snapshot_in_T2 = delta_snapshot * 256;
1283 1283 waveform_picker_regs->delta_snapshot = delta_snapshot_in_T2 - 1; // max 4 bytes
1284 1284 }
1285 1285
1286 1286 void set_wfp_delta_f0_f0_2( void )
1287 1287 {
1288 1288 unsigned int delta_snapshot;
1289 1289 unsigned int nb_samples_per_snapshot;
1290 1290 float delta_f0_in_float;
1291 1291
1292 1292 delta_snapshot = waveform_picker_regs->delta_snapshot;
1293 1293 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1294 1294 delta_f0_in_float =nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 24576.) * 256.;
1295 1295
1296 1296 waveform_picker_regs->delta_f0 = delta_snapshot - floor( delta_f0_in_float );
1297 waveform_picker_regs->delta_f0_2 = 0x7; // max 7 bits
1297 waveform_picker_regs->delta_f0_2 = 0x30; // 48 = 11 0000, max 7 bits
1298 1298 }
1299 1299
1300 1300 void set_wfp_delta_f1( void )
1301 1301 {
1302 1302 unsigned int delta_snapshot;
1303 1303 unsigned int nb_samples_per_snapshot;
1304 1304 float delta_f1_in_float;
1305 1305
1306 1306 delta_snapshot = waveform_picker_regs->delta_snapshot;
1307 1307 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1308 1308 delta_f1_in_float = nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 4096.) * 256.;
1309 1309
1310 1310 waveform_picker_regs->delta_f1 = delta_snapshot - floor( delta_f1_in_float );
1311 1311 }
1312 1312
1313 1313 void set_wfp_delta_f2()
1314 1314 {
1315 1315 unsigned int delta_snapshot;
1316 1316 unsigned int nb_samples_per_snapshot;
1317 1317
1318 1318 delta_snapshot = waveform_picker_regs->delta_snapshot;
1319 1319 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1320 1320
1321 1321 waveform_picker_regs->delta_f2 = delta_snapshot - nb_samples_per_snapshot / 2;
1322 1322 }
1323 1323
1324 1324 //*****************
1325 1325 // local parameters
1326 1326
1327 1327 void increment_seq_counter_source_id( unsigned char *packet_sequence_control, unsigned int sid )
1328 1328 {
1329 1329 /** This function increments the parameter "sequence_cnt" depending on the sid passed in argument.
1330 1330 *
1331 1331 * @param packet_sequence_control is a pointer toward the parameter sequence_cnt to update.
1332 1332 * @param sid is the source identifier of the packet being updated.
1333 1333 *
1334 1334 * REQ-LFR-SRS-5240 / SSS-CP-FS-590
1335 1335 * The sequence counters shall wrap around from 2^14 to zero.
1336 1336 * The sequence counter shall start at zero at startup.
1337 1337 *
1338 1338 * REQ-LFR-SRS-5239 / SSS-CP-FS-580
1339 1339 * All TM_LFR_SCIENCE_ packets are sent to ground, i.e. destination id = 0
1340 1340 *
1341 1341 */
1342 1342
1343 1343 unsigned short *sequence_cnt;
1344 1344 unsigned short segmentation_grouping_flag;
1345 1345 unsigned short new_packet_sequence_control;
1346 1346 rtems_mode initial_mode_set;
1347 1347 rtems_mode current_mode_set;
1348 1348 rtems_status_code status;
1349 1349
1350 1350 //******************************************
1351 1351 // CHANGE THE MODE OF THE CALLING RTEMS TASK
1352 1352 status = rtems_task_mode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &initial_mode_set );
1353 1353
1354 1354 if ( (sid == SID_NORM_SWF_F0) || (sid == SID_NORM_SWF_F1) || (sid == SID_NORM_SWF_F2)
1355 1355 || (sid == SID_NORM_CWF_F3) || (sid == SID_NORM_CWF_LONG_F3)
1356 1356 || (sid == SID_BURST_CWF_F2)
1357 1357 || (sid == SID_NORM_ASM_F0) || (sid == SID_NORM_ASM_F1) || (sid == SID_NORM_ASM_F2)
1358 1358 || (sid == SID_NORM_BP1_F0) || (sid == SID_NORM_BP1_F1) || (sid == SID_NORM_BP1_F2)
1359 1359 || (sid == SID_NORM_BP2_F0) || (sid == SID_NORM_BP2_F1) || (sid == SID_NORM_BP2_F2)
1360 1360 || (sid == SID_BURST_BP1_F0) || (sid == SID_BURST_BP2_F0)
1361 1361 || (sid == SID_BURST_BP1_F1) || (sid == SID_BURST_BP2_F1) )
1362 1362 {
1363 1363 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_NORMAL_BURST;
1364 1364 }
1365 1365 else if ( (sid ==SID_SBM1_CWF_F1) || (sid ==SID_SBM2_CWF_F2)
1366 1366 || (sid == SID_SBM1_BP1_F0) || (sid == SID_SBM1_BP2_F0)
1367 1367 || (sid == SID_SBM2_BP1_F0) || (sid == SID_SBM2_BP2_F0)
1368 1368 || (sid == SID_SBM2_BP1_F1) || (sid == SID_SBM2_BP2_F1) )
1369 1369 {
1370 1370 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_SBM1_SBM2;
1371 1371 }
1372 1372 else
1373 1373 {
1374 1374 sequence_cnt = (unsigned short *) NULL;
1375 1375 PRINTF1("in increment_seq_counter_source_id *** ERR apid_destid %d not known\n", sid)
1376 1376 }
1377 1377
1378 1378 if (sequence_cnt != NULL)
1379 1379 {
1380 1380 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
1381 1381 *sequence_cnt = (*sequence_cnt) & 0x3fff;
1382 1382
1383 1383 new_packet_sequence_control = segmentation_grouping_flag | (*sequence_cnt) ;
1384 1384
1385 1385 packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> 8);
1386 1386 packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control );
1387 1387
1388 1388 // increment the sequence counter
1389 1389 if ( *sequence_cnt < SEQ_CNT_MAX)
1390 1390 {
1391 1391 *sequence_cnt = *sequence_cnt + 1;
1392 1392 }
1393 1393 else
1394 1394 {
1395 1395 *sequence_cnt = 0;
1396 1396 }
1397 1397 }
1398 1398
1399 1399 //***********************************
1400 1400 // RESET THE MODE OF THE CALLING TASK
1401 1401 status = rtems_task_mode( initial_mode_set, RTEMS_PREEMPT_MASK, &current_mode_set );
1402 1402 }
@@ -1,725 +1,728
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 unsigned int localCoarseTime;
20 20
21 21 void resetLocalCoarseTime()
22 22 {
23 23 localCoarseTime = 0;
24 24 }
25 25
26 26 void setLocalCoarseTime( unsigned int value )
27 27 {
28 28 localCoarseTime = value;
29 29 }
30 30
31 31 unsigned int getLocalCoarseTime()
32 32 {
33 33 return localCoarseTime;
34 34 }
35 35
36 36 void incrementLocalCoarseTime()
37 37 {
38 38 localCoarseTime = localCoarseTime + 1;
39 39 }
40 40
41 41 //***********
42 42 // RTEMS TASK
43 43 rtems_task spiq_task(rtems_task_argument unused)
44 44 {
45 45 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
46 46 *
47 47 * @param unused is the starting argument of the RTEMS task
48 48 *
49 49 */
50 50
51 51 rtems_event_set event_out;
52 52 rtems_status_code status;
53 53 int linkStatus;
54 54
55 55 BOOT_PRINTF("in SPIQ *** \n")
56 56
57 57 while(true){
58 58 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
59 59 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
60 60
61 61 // [0] SUSPEND RECV AND SEND TASKS
62 62 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
63 63 if ( status != RTEMS_SUCCESSFUL ) {
64 64 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
65 65 }
66 66 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
67 67 if ( status != RTEMS_SUCCESSFUL ) {
68 68 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
69 69 }
70 70
71 71 // [1] CHECK THE LINK
72 72 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
73 73 if ( linkStatus != 5) {
74 74 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
75 75 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
76 76 }
77 77
78 78 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
79 79 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
80 80 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
81 81 {
82 82 spacewire_compute_stats_offsets();
83 83 status = spacewire_reset_link( );
84 84 }
85 85 else // [2.b] in run state, start the link
86 86 {
87 87 status = spacewire_stop_and_start_link( fdSPW ); // start the link
88 88 if ( status != RTEMS_SUCCESSFUL)
89 89 {
90 90 PRINTF1("in SPIQ *** ERR spacewire_start_link %d\n", status)
91 91 }
92 92 }
93 93
94 94 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
95 95 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
96 96 {
97 97 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
98 98 if ( status != RTEMS_SUCCESSFUL ) {
99 99 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
100 100 }
101 101 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
102 102 if ( status != RTEMS_SUCCESSFUL ) {
103 103 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
104 104 }
105 105 }
106 106 else // [3.b] the link is not in run state, go in STANDBY mode
107 107 {
108 108 status = stop_current_mode();
109 109 if ( status != RTEMS_SUCCESSFUL ) {
110 110 PRINTF1("in SPIQ *** ERR stop_current_mode *** code %d\n", status)
111 111 }
112 112 status = enter_mode( LFR_MODE_STANDBY, 0 );
113 113 if ( status != RTEMS_SUCCESSFUL ) {
114 114 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
115 115 }
116 116 // wake the WTDG task up to wait for the link recovery
117 117 status = rtems_event_send ( Task_id[TASKID_WTDG], RTEMS_EVENT_0 );
118 118 status = rtems_task_suspend( RTEMS_SELF );
119 119 }
120 120 }
121 121 }
122 122
123 123 rtems_task recv_task( rtems_task_argument unused )
124 124 {
125 125 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
126 126 *
127 127 * @param unused is the starting argument of the RTEMS task
128 128 *
129 129 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
130 130 * 1. It reads the incoming data.
131 131 * 2. Launches the acceptance procedure.
132 132 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
133 133 *
134 134 */
135 135
136 136 int len;
137 137 ccsdsTelecommandPacket_t currentTC;
138 138 unsigned char computed_CRC[ 2 ];
139 139 unsigned char currentTC_LEN_RCV[ 2 ];
140 140 unsigned char destinationID;
141 141 unsigned int estimatedPacketLength;
142 142 unsigned int parserCode;
143 143 rtems_status_code status;
144 144 rtems_id queue_recv_id;
145 145 rtems_id queue_send_id;
146 146
147 147 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
148 148
149 149 status = get_message_queue_id_recv( &queue_recv_id );
150 150 if (status != RTEMS_SUCCESSFUL)
151 151 {
152 152 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
153 153 }
154 154
155 155 status = get_message_queue_id_send( &queue_send_id );
156 156 if (status != RTEMS_SUCCESSFUL)
157 157 {
158 158 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
159 159 }
160 160
161 161 BOOT_PRINTF("in RECV *** \n")
162 162
163 163 while(1)
164 164 {
165 165 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
166 166 if (len == -1){ // error during the read call
167 167 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
168 168 }
169 169 else {
170 170 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
171 171 PRINTF("in RECV *** packet lenght too short\n")
172 172 }
173 173 else {
174 174 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
175 175 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
176 176 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
177 177 // CHECK THE TC
178 178 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
179 179 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
180 180 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
181 181 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
182 182 || (parserCode == WRONG_SRC_ID) )
183 183 { // send TM_LFR_TC_EXE_CORRUPTED
184 184 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
185 185 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
186 186 &&
187 187 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
188 188 )
189 189 {
190 190 if ( parserCode == WRONG_SRC_ID )
191 191 {
192 192 destinationID = SID_TC_GROUND;
193 193 }
194 194 else
195 195 {
196 196 destinationID = currentTC.sourceID;
197 197 }
198 198 }
199 199 }
200 200 else
201 201 { // send valid TC to the action launcher
202 202 status = rtems_message_queue_send( queue_recv_id, &currentTC,
203 203 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
204 204 }
205 205 }
206 206 }
207 207 }
208 208 }
209 209
210 210 rtems_task send_task( rtems_task_argument argument)
211 211 {
212 212 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
213 213 *
214 214 * @param unused is the starting argument of the RTEMS task
215 215 *
216 216 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
217 217 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
218 218 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
219 219 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
220 220 * data it contains.
221 221 *
222 222 */
223 223
224 224 rtems_status_code status; // RTEMS status code
225 225 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
226 226 spw_ioctl_pkt_send *spw_ioctl_send;
227 227 size_t size; // size of the incoming TC packet
228 228 u_int32_t count;
229 229 rtems_id queue_id;
230 230
231 231 status = get_message_queue_id_send( &queue_id );
232 232 if (status != RTEMS_SUCCESSFUL)
233 233 {
234 234 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
235 235 }
236 236
237 237 BOOT_PRINTF("in SEND *** \n")
238 238
239 239 while(1)
240 240 {
241 241 status = rtems_message_queue_receive( queue_id, incomingData, &size,
242 242 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
243 243
244 244 if (status!=RTEMS_SUCCESSFUL)
245 245 {
246 246 PRINTF1("in SEND *** (1) ERR = %d\n", status)
247 247 }
248 248 else
249 249 {
250 250 if ((incomingData[0] == CCSDS_DESTINATION_ID) || (incomingData[0] == (char) 0xfe)) // the incoming message is a ccsds packet
251 251 {
252 252 status = write( fdSPW, incomingData, size );
253 253 if (status == -1){
254 254 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
255 255 }
256 256 }
257 257 else // the incoming message is a spw_ioctl_pkt_send structure
258 258 {
259 259 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
260 260 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
261 261 if (status == -1){
262 262 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
263 263 }
264 264 }
265 265 }
266 266
267 267 status = rtems_message_queue_get_number_pending( queue_id, &count );
268 268 if (status != RTEMS_SUCCESSFUL)
269 269 {
270 270 PRINTF1("in SEND *** (3) ERR = %d\n", status)
271 271 }
272 272 else
273 273 {
274 274 if (count > maxCount)
275 275 {
276 276 maxCount = count;
277 277 }
278 278 }
279 279 }
280 280 }
281 281
282 282 rtems_task wtdg_task( rtems_task_argument argument )
283 283 {
284 284 rtems_event_set event_out;
285 285 rtems_status_code status;
286 286 int linkStatus;
287 287
288 288 BOOT_PRINTF("in WTDG ***\n")
289 289
290 290 while(1)
291 291 {
292 292 // wait for an RTEMS_EVENT
293 293 rtems_event_receive( RTEMS_EVENT_0,
294 294 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
295 295 PRINTF("in WTDG *** wait for the link\n")
296 296 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
297 297 while( linkStatus != 5) // wait for the link
298 298 {
299 299 rtems_task_wake_after( 10 );
300 300 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
301 301 }
302 302
303 303 status = spacewire_stop_and_start_link( fdSPW );
304 304
305 305 if (status != RTEMS_SUCCESSFUL)
306 306 {
307 307 PRINTF1("in WTDG *** ERR link not started %d\n", status)
308 308 }
309 309 else
310 310 {
311 311 PRINTF("in WTDG *** OK link started\n")
312 312 }
313 313
314 314 // restart the SPIQ task
315 315 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
316 316 if ( status != RTEMS_SUCCESSFUL ) {
317 317 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
318 318 }
319 319
320 320 // restart RECV and SEND
321 321 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
322 322 if ( status != RTEMS_SUCCESSFUL ) {
323 323 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
324 324 }
325 325 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
326 326 if ( status != RTEMS_SUCCESSFUL ) {
327 327 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
328 328 }
329 329 }
330 330 }
331 331
332 332 //****************
333 333 // OTHER FUNCTIONS
334 334 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
335 335 {
336 336 /** This function opens the SpaceWire link.
337 337 *
338 338 * @return a valid file descriptor in case of success, -1 in case of a failure
339 339 *
340 340 */
341 341 rtems_status_code status;
342 342
343 343 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
344 344 if ( fdSPW < 0 ) {
345 345 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
346 346 }
347 347 else
348 348 {
349 349 status = RTEMS_SUCCESSFUL;
350 350 }
351 351
352 352 return status;
353 353 }
354 354
355 355 int spacewire_start_link( int fd )
356 356 {
357 357 rtems_status_code status;
358 358
359 359 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
360 360 // -1 default hardcoded driver timeout
361 361
362 362 return status;
363 363 }
364 364
365 365 int spacewire_stop_and_start_link( int fd )
366 366 {
367 367 rtems_status_code status;
368 368
369 369 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
370 370 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
371 371 // -1 default hardcoded driver timeout
372 372
373 373 return status;
374 374 }
375 375
376 376 int spacewire_configure_link( int fd )
377 377 {
378 378 /** This function configures the SpaceWire link.
379 379 *
380 380 * @return GR-RTEMS-DRIVER directive status codes:
381 381 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
382 382 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
383 383 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
384 384 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
385 385 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
386 386 * - 5 EIO - Error when writing to grswp hardware registers.
387 387 * - 2 ENOENT - No such file or directory
388 388 */
389 389
390 390 rtems_status_code status;
391 391
392 392 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
393 393 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
394 394
395 395 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
396 396 if (status!=RTEMS_SUCCESSFUL) {
397 397 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
398 398 }
399 399 //
400 400 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
401 401 if (status!=RTEMS_SUCCESSFUL) {
402 402 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
403 403 }
404 404 //
405 405 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
406 406 if (status!=RTEMS_SUCCESSFUL) {
407 407 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
408 408 }
409 409 //
410 410 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
411 411 if (status!=RTEMS_SUCCESSFUL) {
412 412 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
413 413 }
414 414 //
415 415 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 0); // transmission blocks
416 416 if (status!=RTEMS_SUCCESSFUL) {
417 417 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
418 418 }
419 419 //
420 420 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
421 421 if (status!=RTEMS_SUCCESSFUL) {
422 422 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
423 423 }
424 424 //
425 425 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
426 426 if (status!=RTEMS_SUCCESSFUL) {
427 427 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
428 428 }
429 429
430 430 return status;
431 431 }
432 432
433 433 int spacewire_reset_link( void )
434 434 {
435 435 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
436 436 *
437 437 * @return RTEMS directive status code:
438 438 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
439 439 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
440 440 *
441 441 */
442 442
443 443 rtems_status_code status_spw;
444 444 int i;
445 445
446 446 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
447 447 {
448 448 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
449 449
450 450 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
451 451
452 452 status_spw = spacewire_stop_and_start_link( fdSPW );
453 453 if ( status_spw != RTEMS_SUCCESSFUL )
454 454 {
455 455 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
456 456 }
457 457
458 458 if ( status_spw == RTEMS_SUCCESSFUL)
459 459 {
460 460 break;
461 461 }
462 462 }
463 463
464 464 return status_spw;
465 465 }
466 466
467 467 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
468 468 {
469 469 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
470 470 *
471 471 * @param val is the value, 0 or 1, used to set the value of the NP bit.
472 472 * @param regAddr is the address of the GRSPW control register.
473 473 *
474 474 * NP is the bit 20 of the GRSPW control register.
475 475 *
476 476 */
477 477
478 478 unsigned int *spwptr = (unsigned int*) regAddr;
479 479
480 480 if (val == 1) {
481 481 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
482 482 }
483 483 if (val== 0) {
484 484 *spwptr = *spwptr & 0xffdfffff;
485 485 }
486 486 }
487 487
488 488 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
489 489 {
490 490 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
491 491 *
492 492 * @param val is the value, 0 or 1, used to set the value of the RE bit.
493 493 * @param regAddr is the address of the GRSPW control register.
494 494 *
495 495 * RE is the bit 16 of the GRSPW control register.
496 496 *
497 497 */
498 498
499 499 unsigned int *spwptr = (unsigned int*) regAddr;
500 500
501 501 if (val == 1)
502 502 {
503 503 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
504 504 }
505 505 if (val== 0)
506 506 {
507 507 *spwptr = *spwptr & 0xfffdffff;
508 508 }
509 509 }
510 510
511 511 void spacewire_compute_stats_offsets( void )
512 512 {
513 513 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
514 514 *
515 515 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
516 516 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
517 517 * during the open systel call).
518 518 *
519 519 */
520 520
521 521 spw_stats spacewire_stats_grspw;
522 522 rtems_status_code status;
523 523
524 524 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
525 525
526 526 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
527 527 + spacewire_stats.packets_received;
528 528 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
529 529 + spacewire_stats.packets_sent;
530 530 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
531 531 + spacewire_stats.parity_err;
532 532 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
533 533 + spacewire_stats.disconnect_err;
534 534 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
535 535 + spacewire_stats.escape_err;
536 536 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
537 537 + spacewire_stats.credit_err;
538 538 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
539 539 + spacewire_stats.write_sync_err;
540 540 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
541 541 + spacewire_stats.rx_rmap_header_crc_err;
542 542 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
543 543 + spacewire_stats.rx_rmap_data_crc_err;
544 544 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
545 545 + spacewire_stats.early_ep;
546 546 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
547 547 + spacewire_stats.invalid_address;
548 548 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
549 549 + spacewire_stats.rx_eep_err;
550 550 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
551 551 + spacewire_stats.rx_truncated;
552 552 }
553 553
554 554 void spacewire_update_statistics( void )
555 555 {
556 556 rtems_status_code status;
557 557 spw_stats spacewire_stats_grspw;
558 558
559 559 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
560 560
561 561 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
562 562 + spacewire_stats_grspw.packets_received;
563 563 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
564 564 + spacewire_stats_grspw.packets_sent;
565 565 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
566 566 + spacewire_stats_grspw.parity_err;
567 567 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
568 568 + spacewire_stats_grspw.disconnect_err;
569 569 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
570 570 + spacewire_stats_grspw.escape_err;
571 571 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
572 572 + spacewire_stats_grspw.credit_err;
573 573 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
574 574 + spacewire_stats_grspw.write_sync_err;
575 575 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
576 576 + spacewire_stats_grspw.rx_rmap_header_crc_err;
577 577 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
578 578 + spacewire_stats_grspw.rx_rmap_data_crc_err;
579 579 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
580 580 + spacewire_stats_grspw.early_ep;
581 581 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
582 582 + spacewire_stats_grspw.invalid_address;
583 583 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
584 584 + spacewire_stats_grspw.rx_eep_err;
585 585 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
586 586 + spacewire_stats_grspw.rx_truncated;
587 587 //spacewire_stats.tx_link_err;
588 588
589 589 //****************************
590 590 // DPU_SPACEWIRE_IF_STATISTICS
591 591 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
592 592 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
593 593 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
594 594 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
595 595 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
596 596 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
597 597
598 598 //******************************************
599 599 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
600 600 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
601 601 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
602 602 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
603 603 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
604 604 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
605 605
606 606 //*********************************************
607 607 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
608 608 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
609 609 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
610 610 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
611 611 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
612 612 }
613 613
614 614 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
615 615 {
616 616 struct grgpio_regs_str *grgpio_regs = (struct grgpio_regs_str *) REGS_ADDR_GRGPIO;
617 617
618 incrementLocalCoarseTime();
619
618 620 //*******
619 621 // GPIO 2
620 622 if ( get_transitionCoarseTime() == getLocalCoarseTime() )
621 623 {
622 624 grgpio_regs->io_port_output_register = grgpio_regs->io_port_output_register | 0x04; // [0000 0100]
623 625 }
624 626 else
625 627 {
626 628 grgpio_regs->io_port_output_register = grgpio_regs->io_port_output_register & 0xfb; // [1111 1011]
627 629 }
628 630
629 631 //*******
630 632 // GPIO 3
631 633 if ( (grgpio_regs->io_port_output_register & 0x08) == 0x08 )
632 634 {
633 635 grgpio_regs->io_port_output_register = grgpio_regs->io_port_output_register & 0xf7; // [1111 0111]
634 636 }
635 637 else
636 638 {
637 639 grgpio_regs->io_port_output_register = grgpio_regs->io_port_output_register | 0x08; // [0000 1000]
638 640 }
639 641
640 642 rtems_event_send( rtems_task_id_updt, RTEMS_EVENT_0);
641 643 }
642 644
643 645 rtems_timer_service_routine user_routine( rtems_id timer_id, void *user_data )
644 646 {
645 647 int linkStatus;
646 648 rtems_status_code status;
647 649
648 650 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
649 651
650 652 if ( linkStatus == 5) {
651 653 PRINTF("in spacewire_reset_link *** link is running\n")
652 654 status = RTEMS_SUCCESSFUL;
653 655 }
654 656 }
655 657
656 658 rtems_task updt_task(rtems_task_argument unused)
657 659 {
658 660
659 661 rtems_event_set event_out;
660 662 rtems_status_code status;
661 663 rtems_id queue_id;
664 unsigned int coarseTimeToSend;
662 665
663 666 Packet_TC_LFR_UPDATE_TIME_WITH_HEADER_t update_time_packet;
664 667
665 668 resetLocalCoarseTime();
666 669 reset_transitionCoarseTime();
667 670
668 671 status = get_message_queue_id_send( &queue_id );
669 672 if (status != RTEMS_SUCCESSFUL)
670 673 {
671 674 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
672 675 }
673 676
674 677 update_time_packet.targetLogicalAddress = 0xfe;
675 678 update_time_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
676 679 update_time_packet.reserved = DEFAULT_RESERVED;
677 680 update_time_packet.userApplication = CCSDS_USER_APP;
678 681 update_time_packet.packetID[0] = (unsigned char) (TC_LFR_PACKET_ID >> 8);
679 682 update_time_packet.packetID[1] = (unsigned char) (TC_LFR_PACKET_ID );
680 683 update_time_packet.packetSequenceControl[0] = (unsigned char) (TC_LFR_PACKET_SEQUENCE_CONTROL >> 8);
681 684 update_time_packet.packetSequenceControl[1] = (unsigned char) (TC_LFR_PACKET_SEQUENCE_CONTROL );
682 685 update_time_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_LFR_UPDATE_TIME >> 8);
683 686 update_time_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_LFR_UPDATE_TIME );
684 687
685 688 update_time_packet.ccsdsSecHeaderFlag_pusVersion_ack = 0x19;
686 689 update_time_packet.serviceType = TC_TYPE_LFR_UPDATE_TIME;
687 690 update_time_packet.serviceSubType = TC_SUBTYPE_UPDATE_TIME;
688 691 update_time_packet.sourceID = SID_TC_RPW_INTERNAL;
689 692
690 693 BOOT_PRINTF("in UPDT *** \n")
691 694
692 695 while(true){
693 696 rtems_event_receive(RTEMS_EVENT_0, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
694 697
695 incrementLocalCoarseTime();
696 updateTimePacket( getLocalCoarseTime() , &update_time_packet);
697 printf("UPDT will send %x as coarse time in 700 ms\n", getLocalCoarseTime());
698 coarseTimeToSend = getLocalCoarseTime() + 1;
699 updateTimePacket( coarseTimeToSend, &update_time_packet);
700 printf("UPDT will send %x as coarse time in 700 ms\n", coarseTimeToSend);
698 701
699 702 rtems_task_wake_after( 70 ); // 70 => 700 ms
700 703
701 704 status = rtems_message_queue_urgent( queue_id, &update_time_packet,
702 705 PACKET_LENGTH_TC_LFR_UPDATE_TIME + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES
703 706 + 0); // 1 is for the star dundee extra byte
704 707 if (status != RTEMS_SUCCESSFUL) {
705 708 PRINTF1("in HOUS *** ERR send: %d\n", status)
706 709 }
707 710 }
708 711 }
709 712
710 713 void updateTimePacket(unsigned int time, Packet_TC_LFR_UPDATE_TIME_WITH_HEADER_t *packet)
711 714 {
712 715 unsigned char crcAsTwoBytes[2];
713 716
714 717 packet->cp_rpw_time[0] = (unsigned char) (time >> 24);
715 718 packet->cp_rpw_time[1] = (unsigned char) (time >> 16);
716 719 packet->cp_rpw_time[2] = (unsigned char) (time >> 8);
717 720 packet->cp_rpw_time[3] = (unsigned char) (time);
718 721 packet->cp_rpw_time[4] = 0; // fine time MSB
719 722 packet->cp_rpw_time[5] = 0; // fine time LSB
720 723
721 724 GetCRCAsTwoBytes((unsigned char*) &packet->packetID, crcAsTwoBytes,
722 725 PACKET_LENGTH_TC_LFR_UPDATE_TIME + CCSDS_TC_TM_PACKET_OFFSET - 2);
723 726 packet->crc[0] = crcAsTwoBytes[0];
724 727 packet->crc[1] = crcAsTwoBytes[1];
725 728 }
@@ -1,248 +1,250
1 1 /** Functions and tasks related to TeleCommand handling.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle TeleCommands:\n
7 7 * action launching\n
8 8 * TC parsing\n
9 9 * ...
10 10 *
11 11 */
12 12
13 13 #include "tc_handler.h"
14 14
15 15 //***********
16 16 // RTEMS TASK
17 17
18 18 unsigned int incomingTransitionCoarseTime;
19 19
20 20 void reset_transitionCoarseTime( void )
21 21 {
22 22 incomingTransitionCoarseTime = 0xffffffff;
23 23 }
24 24
25 25 void set_transitionCoarseTime( unsigned int value )
26 26 {
27 27 incomingTransitionCoarseTime = value;
28 28 }
29 29
30 30 unsigned int get_transitionCoarseTime( void )
31 31 {
32 32 return incomingTransitionCoarseTime;
33 33 }
34 34
35 35 rtems_task actn_task( rtems_task_argument unused )
36 36 {
37 37 /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
38 38 *
39 39 * @param unused is the starting argument of the RTEMS task
40 40 *
41 41 * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
42 42 * on the incoming TeleCommand.
43 43 *
44 44 */
45 45
46 46 int result;
47 47 rtems_status_code status; // RTEMS status code
48 48 ccsdsTelecommandPacket_t TC; // TC sent to the ACTN task
49 49 size_t size; // size of the incoming TC packet
50 50 unsigned char subtype; // subtype of the current TC packet
51 51 unsigned char time[6];
52 52 rtems_id queue_rcv_id;
53 53 rtems_id queue_snd_id;
54 54
55 55 status = get_message_queue_id_recv( &queue_rcv_id );
56 56 if (status != RTEMS_SUCCESSFUL)
57 57 {
58 58 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
59 59 }
60 60
61 61 status = get_message_queue_id_send( &queue_snd_id );
62 62 if (status != RTEMS_SUCCESSFUL)
63 63 {
64 64 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
65 65 }
66 66
67 67 result = LFR_SUCCESSFUL;
68 68 subtype = 0; // subtype of the current TC packet
69 69
70 70 BOOT_PRINTF("in ACTN *** \n")
71 71
72 72 while(1)
73 73 {
74 74 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
75 75 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
76 76 getTime( time ); // set time to the current time
77 77 if (status!=RTEMS_SUCCESSFUL)
78 78 {
79 79 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
80 80 }
81 81 else
82 82 {
83 83 subtype = TC.serviceSubType;
84 84 switch(subtype)
85 85 {
86 86 case TC_SUBTYPE_ENTER:
87 87 result = action_enter_mode( &TC, queue_snd_id );
88 88 break;
89 89 case TC_SUBTYPE_UPDATE_TIME:
90 90 result = action_update_time( &TC );
91 91 break;
92 92 default:
93 93 break;
94 94 }
95 95 }
96 96 }
97 97 }
98 98
99 99 //***********
100 100 // TC ACTIONS
101 101
102 102 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
103 103 {
104 104 return LFR_SUCCESSFUL;
105 105 }
106 106
107 107 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
108 108 {
109 109 unsigned int *transitionCoarseTime_ptr;
110 110 unsigned int transitionCoarseTime;
111 111 unsigned char * bytePosPtr;
112 112
113 113 bytePosPtr = (unsigned char *) &TC->packetID;
114 114
115 115 transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
116 116 transitionCoarseTime = transitionCoarseTime_ptr[0] & 0x7fffffff;
117 117 printf("local coarse time (without sync bit) = %x, requested transitionCoarseTime = %x\n",
118 118 getLocalCoarseTime(),
119 119 transitionCoarseTime);
120 120
121 121 set_transitionCoarseTime( transitionCoarseTime );
122 122
123 123 return LFR_SUCCESSFUL;
124 124 }
125 125
126 126 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
127 127 {
128 128 return LFR_SUCCESSFUL;
129 129 }
130 130
131 131 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
132 132 {
133 133 return LFR_SUCCESSFUL;
134 134 }
135 135
136 136 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
137 137 {
138 138 return LFR_SUCCESSFUL;
139 139 }
140 140
141 141 int action_update_time(ccsdsTelecommandPacket_t *TC)
142 142 {
143 143 unsigned int incomingCoarseTime;
144 unsigned int currentLocalCoarseTime;
144 145
145 146 incomingCoarseTime = (TC->dataAndCRC[0] << 24)
146 147 + (TC->dataAndCRC[1] << 16)
147 148 + (TC->dataAndCRC[2] << 8)
148 149 + TC->dataAndCRC[3];
149 150
151 currentLocalCoarseTime = getLocalCoarseTime();
150 152 setLocalCoarseTime( incomingCoarseTime );
151 printf( "localCoarseTime set to: %x\n", getLocalCoarseTime() );
153 printf( "currentLocalCoarseTime = %x, localCoarseTime set to: %x\n", currentLocalCoarseTime, getLocalCoarseTime() );
152 154
153 155 return LFR_SUCCESSFUL;
154 156 }
155 157
156 158 //*******************
157 159 // ENTERING THE MODES
158 160 int check_mode_value( unsigned char requestedMode )
159 161 {
160 162 return LFR_SUCCESSFUL;
161 163 }
162 164
163 165 int check_mode_transition( unsigned char requestedMode )
164 166 {
165 167 return LFR_SUCCESSFUL;
166 168 }
167 169
168 170 int check_transition_date( unsigned int transitionCoarseTime )
169 171 {
170 172 return LFR_SUCCESSFUL;
171 173 }
172 174
173 175 int stop_current_mode( void )
174 176 {
175 177 return LFR_SUCCESSFUL;
176 178 }
177 179
178 180 int enter_mode( unsigned char mode, unsigned int transitionCoarseTime )
179 181 {
180 182 return LFR_SUCCESSFUL;
181 183 }
182 184
183 185 int restart_science_tasks(unsigned char lfrRequestedMode )
184 186 {
185 187 return LFR_SUCCESSFUL;
186 188 }
187 189
188 190 int suspend_science_tasks()
189 191 {
190 192 return LFR_SUCCESSFUL;
191 193 }
192 194
193 195 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
194 196 {
195 197 }
196 198
197 199 void launch_spectral_matrix( void )
198 200 {
199 201 }
200 202
201 203 void launch_spectral_matrix_simu( void )
202 204 {
203 205 }
204 206
205 207 void set_irq_on_new_ready_matrix( unsigned char value )
206 208 {
207 209 }
208 210
209 211 void set_run_matrix_spectral( unsigned char value )
210 212 {
211 213 }
212 214
213 215 //****************
214 216 // CLOSING ACTIONS
215 217 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
216 218 {
217 219 }
218 220
219 221 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
220 222 {
221 223 }
222 224
223 225 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
224 226 {
225 227 }
226 228
227 229 //***************************
228 230 // Interrupt Service Routines
229 231 rtems_isr commutation_isr1( rtems_vector_number vector )
230 232 {
231 233 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
232 234 printf("In commutation_isr1 *** Error sending event to DUMB\n");
233 235 }
234 236 }
235 237
236 238 rtems_isr commutation_isr2( rtems_vector_number vector )
237 239 {
238 240 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
239 241 printf("In commutation_isr2 *** Error sending event to DUMB\n");
240 242 }
241 243 }
242 244
243 245 //****************
244 246 // OTHER FUNCTIONS
245 247 void updateLFRCurrentMode()
246 248 {
247 249 }
248 250
@@ -1,81 +1,81
1 1 TEMPLATE = app
2 2 # CONFIG += console v8 sim
3 3 # CONFIG options = verbose *** boot_messages *** debug_messages *** cpu_usage_report *** stack_report *** vhdl_dev *** debug_tch
4 4 CONFIG += console verbose
5 5 CONFIG -= qt
6 6
7 7 include(./sparc.pri)
8 8
9 9 # flight software version
10 10 SWVERSION=-1-0
11 11 DEFINES += SW_VERSION_N1=0 # major
12 12 DEFINES += SW_VERSION_N2=0 # minor
13 13 DEFINES += SW_VERSION_N3=0 # patch
14 DEFINES += SW_VERSION_N4=1 # internal
14 DEFINES += SW_VERSION_N4=2 # internal
15 15
16 16 contains( CONFIG, debug_tch ) {
17 17 DEFINES += DEBUG_TCH
18 18 }
19 19
20 20 contains( CONFIG, vhdl_dev ) {
21 21 DEFINES += VHDL_DEV
22 22 }
23 23
24 24 contains( CONFIG, verbose ) {
25 25 DEFINES += PRINT_MESSAGES_ON_CONSOLE
26 26 }
27 27
28 28 contains( CONFIG, debug_messages ) {
29 29 DEFINES += DEBUG_MESSAGES
30 30 }
31 31
32 32 contains( CONFIG, cpu_usage_report ) {
33 33 DEFINES += PRINT_TASK_STATISTICS
34 34 }
35 35
36 36 contains( CONFIG, stack_report ) {
37 37 DEFINES += PRINT_STACK_REPORT
38 38 }
39 39
40 40 contains( CONFIG, boot_messages ) {
41 41 DEFINES += BOOT_MESSAGES
42 42 }
43 43
44 44 #doxygen.target = doxygen
45 45 #doxygen.commands = doxygen ../doc/Doxyfile
46 46 #QMAKE_EXTRA_TARGETS += doxygen
47 47
48 48 TARGET = timegen
49 49
50 50 INCLUDEPATH += \
51 51 ./src \
52 52 ./header \
53 53 ./header/processing \
54 54 ./src/LFR_basic-parameters
55 55
56 56 SOURCES += \
57 57 ./src/tc_handler.c \
58 58 ./src/fsw_misc.c \
59 59 ./src/fsw_init.c \
60 60 ./src/fsw_globals.c \
61 61 ./src/fsw_spacewire.c \
62 62 ./src/tc_acceptance.c \
63 63 ./src/LFR_basic-parameters/basic_parameters.c
64 64
65 65 HEADERS += \
66 66 ./header/tc_handler.h \
67 67 ./header/grlib_regs.h \
68 68 ./header/fsw_params.h \
69 69 ./header/fsw_misc.h \
70 70 ./header/fsw_init.h \
71 71 ./header/ccsds_types.h \
72 72 ./header/fsw_spacewire.h \
73 73 ./header/tc_acceptance.h \
74 74 ./header/fsw_params_nb_bytes.h \
75 75 ./header/fsw_params_processing.h \
76 76 ./header/fsw_params_wf_handler.h \
77 77 ./header/lfr_cpu_usage_report.h \
78 78 ./src/LFR_basic-parameters/basic_parameters.h \
79 79 ./src/LFR_basic-parameters/basic_parameters_params.h \
80 80 ../header/TC_types.h
81 81
General Comments 0
You need to be logged in to leave comments. Login now