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