LCOV - code coverage report
Current view: top level - src - fsw_spacewire.c (source / functions) Hit Total Coverage
Test: trace.info Lines: 349 639 54.6 %
Date: 2023-02-20 11:47:13 Functions: 18 29 62.1 %

          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(&currentTC, 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         439 :         len = read(fdSPW, (char*)&currentTC, CCSDS_TC_PKT_MAX_SIZE); // the call to read is blocking
     178         438 :         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         438 :             if ((len + 1) < CCSDS_TC_PKT_MIN_SIZE)
     185             :             {
     186             :                 LFR_PRINTF("in RECV *** packet lenght too short\n");
     187             :             }
     188             :             else
     189             :             {
     190         438 :                 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         438 :                 currentTC_LEN_RCV[0] = (unsigned char)(estimatedPacketLength >> SHIFT_1_BYTE);
     194         438 :                 currentTC_LEN_RCV[1] = (unsigned char)(estimatedPacketLength);
     195             :                 // CHECK THE TC
     196         438 :                 parserCode = tc_parser(&currentTC, estimatedPacketLength, computed_CRC);
     197         438 :                 if ((parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
     198             :                     || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
     199             :                     || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
     200         438 :                     || (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(&currentTC, queue_send_id,
     217             :                             computed_CRC, currentTC_LEN_RCV, destinationID));
     218             :                     }
     219             :                 }
     220             :                 else
     221             :                 {
     222             :                     // send valid TC to the action launcher
     223         438 :                     DEBUG_CHECK_STATUS(rtems_message_queue_send(queue_recv_id, &currentTC,
     224             :                         estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + PROTID_RES_APP));
     225             :                 }
     226             :             }
     227             :         }
     228             : 
     229         438 :         update_queue_max_count(queue_recv_id, &hk_lfr_q_rv_fifo_size_max);
     230         438 :     }
     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         892 :         status = rtems_message_queue_receive(
     271             :             queue_send_id, incomingData, &size, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     272             :         DEBUG_CHECK_STATUS(status);
     273             : 
     274         891 :         if (status != RTEMS_SUCCESSFUL)
     275             :         {
     276             :             LFR_PRINTF("in SEND *** (1) ERR = %d\n", status);
     277             :         }
     278             :         else
     279             :         {
     280         891 :             if (size == sizeof(ring_node*))
     281             :             {
     282          20 :                 charPtr[0] = incomingData[0];
     283          20 :                 charPtr[1] = incomingData[1];
     284          20 :                 charPtr[BYTE_2] = incomingData[BYTE_2];
     285          20 :                 charPtr[BYTE_3] = incomingData[BYTE_3];
     286          20 :                 incomingRingNodePtr = (ring_node*)ring_node_address;
     287          20 :                 sid = incomingRingNodePtr->packet_id;
     288          69 :                 if ((sid == SID_NORM_CWF_LONG_F3) || (sid == SID_BURST_CWF_F2)
     289          30 :                     || (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2))
     290             :                 {
     291          19 :                     spw_send_waveform_CWF(incomingRingNodePtr, &headerCWF);
     292             :                 }
     293           1 :                 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           1 :                 else if (sid == SID_NORM_CWF_F3)
     299             :                 {
     300           1 :                     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         871 :             else if (incomingData[0]
     324             :                 == CCSDS_DESTINATION_ID) // the incoming message is a ccsds packet
     325             :             {
     326         871 :                 sid = (unsigned char)incomingData[PACKET_POS_PA_LFR_SID_PKT];
     327         871 :                 type = (unsigned char)incomingData[PACKET_POS_SERVICE_TYPE];
     328         871 :                 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         316 :                     increment_seq_counter_source_id(
     333             :                         (unsigned char*)&incomingData[PACKET_POS_SEQUENCE_CNT], sid);
     334             :                 }
     335             : 
     336         871 :                 status = write(fdSPW, incomingData, size);
     337         871 :                 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         891 :         update_queue_max_count(queue_send_id, &hk_lfr_q_sd_fifo_size_max);
     354         891 :     }
     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         549 : 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         549 :     memset(&current, 0, sizeof(spw_stats));
     605             : 
     606         549 :     spacewire_get_last_error();
     607             : 
     608             :     // read the current statistics
     609         549 :     status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current);
     610             :     DEBUG_CHECK_STATUS(status);
     611             : 
     612             :     // clear the counters
     613         549 :     status = ioctl(fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS);
     614             :     DEBUG_CHECK_STATUS(status);
     615             : 
     616             :     // rx_eep_err
     617         549 :     grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
     618             :     // rx_truncated
     619         549 :     grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
     620             :     // parity_err
     621         549 :     grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
     622             :     // escape_err
     623         549 :     grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
     624             :     // credit_err
     625         549 :     grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
     626             :     // write_sync_err
     627         549 :     grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
     628             :     // disconnect_err
     629         549 :     grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
     630             :     // early_ep
     631         549 :     grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
     632             :     // invalid_address
     633         549 :     grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
     634             :     // packets_sent
     635         549 :     grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
     636             :     // packets_received
     637         549 :     grspw_stats.packets_received = grspw_stats.packets_received + current.packets_received;
     638         549 : }
     639             : 
     640         549 : void spacewire_get_last_error(void)
     641             : {
     642             :     static spw_stats previous = { 0 };
     643             :     spw_stats current;
     644             : 
     645         549 :     unsigned int hk_lfr_last_er_rid = 0;
     646         549 :     unsigned char hk_lfr_last_er_code = 0;
     647         549 :     unsigned char update_hk_lfr_last_er = 0;
     648             : 
     649         549 :     memset(&current, 0, sizeof(spw_stats));
     650             : 
     651         549 :     DEBUG_CHECK_STATUS(ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current));
     652             : 
     653             : 
     654             :     // tx_link_err *** no code associated to this field
     655             :     // rx_rmap_header_crc_err ***  LE *** in HK
     656         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     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         549 :     previous = current;
     740         549 : }
     741             : 
     742         549 : void update_hk_with_grspw_stats(void)
     743             : {
     744             :     //****************************
     745             :     // DPU_SPACEWIRE_IF_STATISTICS
     746         549 :     housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0]
     747         549 :         = (unsigned char)(grspw_stats.packets_received >> SHIFT_1_BYTE);
     748         549 :     housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1]
     749         549 :         = (unsigned char)(grspw_stats.packets_received);
     750         549 :     housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0]
     751         549 :         = (unsigned char)(grspw_stats.packets_sent >> SHIFT_1_BYTE);
     752         549 :     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         549 :     housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char)grspw_stats.parity_err;
     757         549 :     housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char)grspw_stats.disconnect_err;
     758         549 :     housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char)grspw_stats.escape_err;
     759         549 :     housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char)grspw_stats.credit_err;
     760         549 :     housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char)grspw_stats.write_sync_err;
     761             : 
     762             :     //*********************************************
     763             :     // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
     764         549 :     housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char)grspw_stats.early_ep;
     765         549 :     housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char)grspw_stats.invalid_address;
     766         549 :     housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char)grspw_stats.rx_eep_err;
     767         549 :     housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char)grspw_stats.rx_truncated;
     768         549 : }
     769             : 
     770         549 : void spacewire_update_hk_lfr_link_state(unsigned char* hk_lfr_status_word_0)
     771             : {
     772             :     const unsigned int* const statusRegisterPtr
     773         549 :         = (unsigned int*)(REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_STATUS_REGISTER);
     774             :     unsigned char linkState;
     775             : 
     776         549 :     linkState = (unsigned char)(((*statusRegisterPtr) >> SPW_LINK_STAT_POS)
     777             :         & STATUS_WORD_LINK_STATE_BITS); // [0000 0111]
     778             : 
     779         549 :     *hk_lfr_status_word_0
     780         549 :         = *hk_lfr_status_word_0 & STATUS_WORD_LINK_STATE_MASK; // [1111 1000] set link state to 0
     781             : 
     782         549 :     *hk_lfr_status_word_0 = *hk_lfr_status_word_0 | linkState; // update hk_lfr_dpu_spw_link_state
     783         549 : }
     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         400 :     unsigned char ret = LFR_DEFAULT;
     800             : 
     801         400 :     if (firstTickout == 0)
     802             :     {
     803         399 :         if (currentTimecodeCtr == 0)
     804             :         {
     805           6 :             if (previousTimecodeCtr == SPW_TIMECODE_MAX)
     806             :             {
     807           6 :                 ret = LFR_SUCCESSFUL;
     808             :             }
     809             :             else
     810             :             {
     811           0 :                 ret = LFR_DEFAULT;
     812             :             }
     813             :         }
     814             :         else
     815             :         {
     816         393 :             if (currentTimecodeCtr == (previousTimecodeCtr + 1))
     817             :             {
     818         393 :                 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         400 :     return ret;
     833             : }
     834             : 
     835           0 : unsigned int check_timecode_and_internal_time_coherency(
     836             :     unsigned char timecode, unsigned char internalTime)
     837             : {
     838         400 :     unsigned int ret = LFR_DEFAULT;
     839             : 
     840         400 :     if (timecode == internalTime)
     841             :     {
     842          10 :         ret = LFR_SUCCESSFUL;
     843             :     }
     844             :     else
     845             :     {
     846         390 :         ret = LFR_DEFAULT;
     847             :     }
     848             : 
     849         400 :     return ret;
     850             : }
     851             : 
     852         400 : 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         400 :     incomingTimecode = (unsigned char)(grspwPtr[0] & TIMECODE_MASK);
     867         400 :     updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
     868         400 :     internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
     869             : 
     870         400 :     housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
     871             : 
     872             :     // update the number of tickout that have been generated
     873         400 :     housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt
     874         400 :         = 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         800 :     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         800 :     if (check_timecode_and_internal_time_coherency(incomingTimecode, internalTime) == LFR_DEFAULT)
     892             :     {
     893         390 :         housekeeping_packet.hk_lfr_time_timecode_it
     894         390 :             = increase_unsigned_char_counter(housekeeping_packet.hk_lfr_time_timecode_it);
     895         390 :         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         400 :     if (oneTcLfrUpdateTimeReceived == 1 && incomingTimecode != updateTime)
     902             :     {
     903         390 :         housekeeping_packet.hk_lfr_time_timecode_ctr
     904         390 :             = increase_unsigned_char_counter(housekeeping_packet.hk_lfr_time_timecode_ctr);
     905         390 :         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         400 :     previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
     910         400 :     status = rtems_timer_fire_after(
     911             :         timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL);
     912         400 :     if (status != RTEMS_SUCCESSFUL)
     913             :     {
     914             :         send_event_dumb_task(RTEMS_EVENT_14);
     915             :     }
     916         400 : }
     917             : 
     918         206 : 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         206 :     currentTimecodeCtr = (unsigned char)(grspwPtr[0] & TIMECODE_MASK);
     930             : 
     931         206 :     if (initStep == 1)
     932             :     {
     933         206 :         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         205 :             housekeeping_packet.hk_lfr_timecode_missing
     940         205 :                 = increase_unsigned_char_counter(housekeeping_packet.hk_lfr_timecode_missing);
     941         205 :             update_hk_lfr_last_er_fields(RID_LE_LFR_TIMEC, CODE_MISSING);
     942             :         }
     943           1 :         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           1 :             housekeeping_packet.hk_lfr_timecode_invalid
     955           1 :                 = increase_unsigned_char_counter(housekeeping_packet.hk_lfr_timecode_invalid);
     956           1 :             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         206 :     status = send_event_dumb_task(RTEMS_EVENT_13);
     970             :     DEBUG_CHECK_STATUS(status);
     971         206 : }
     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          19 : 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          19 :     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          19 :     spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
    1089          19 :     spw_ioctl_send_CWF.options = 0;
    1090             : 
    1091          19 :     sid = ring_node_to_send->packet_id;
    1092             : 
    1093          19 :     coarseTime = ring_node_to_send->coarseTime;
    1094          19 :     fineTime = ring_node_to_send->fineTime;
    1095          19 :     dataPtr = (volatile int*)ring_node_to_send->buffer_address;
    1096             : 
    1097          19 :     header->packetLength[0] = (unsigned char)(TM_LEN_SCI_CWF_336 >> SHIFT_1_BYTE);
    1098          19 :     header->packetLength[1] = (unsigned char)(TM_LEN_SCI_CWF_336);
    1099          19 :     header->pa_bia_status_info = pa_bia_status_info;
    1100          19 :     header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
    1101          19 :     header->blkNr[0] = (unsigned char)(BLK_NR_CWF >> SHIFT_1_BYTE);
    1102          19 :     header->blkNr[1] = (unsigned char)(BLK_NR_CWF);
    1103             : 
    1104         171 :     for (unsigned char i = 0; i < NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
    1105             :     {
    1106         152 :         spw_ioctl_send_CWF.data = (char*)&dataPtr[(uint32_t)i * BLK_NR_CWF * NB_WORDS_SWF_BLK];
    1107         152 :         spw_ioctl_send_CWF.hdr = (char*)header;
    1108             :         // BUILD THE DATA
    1109         152 :         spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
    1110             : 
    1111             :         // SET PACKET SEQUENCE CONTROL
    1112         152 :         increment_seq_counter_source_id(header->packetSequenceControl, sid);
    1113             : 
    1114             :         // SET SID
    1115         152 :         header->sid = sid;
    1116             : 
    1117             :         // SET PACKET TIME
    1118         152 :         compute_acquisition_time(coarseTime, fineTime, sid, i, header->acquisitionTime);
    1119             :         //
    1120         152 :         header->time[0] = header->acquisitionTime[0];
    1121         152 :         header->time[1] = header->acquisitionTime[1];
    1122         152 :         header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
    1123         152 :         header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
    1124         152 :         header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
    1125         152 :         header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
    1126             : 
    1127             :         // SET PACKET ID
    1128         152 :         if ((sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2))
    1129             :         {
    1130          72 :             header->packetID[0] = (unsigned char)(APID_TM_SCIENCE_SBM1_SBM2 >> SHIFT_1_BYTE);
    1131          72 :             header->packetID[1] = (unsigned char)(APID_TM_SCIENCE_SBM1_SBM2);
    1132             :         }
    1133             :         else
    1134             :         {
    1135          80 :             header->packetID[0] = (unsigned char)(APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
    1136          80 :             header->packetID[1] = (unsigned char)(APID_TM_SCIENCE_NORMAL_BURST);
    1137             :         }
    1138             : 
    1139         152 :         DEBUG_CHECK_STATUS(ioctl(fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF));
    1140             :     }
    1141             : 
    1142          19 :     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           1 : 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           1 :     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           1 :     unsigned char sid = ring_node_to_send->packet_id;
    1252             : 
    1253           1 :     spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
    1254           1 :     spw_ioctl_send_CWF.options = 0;
    1255             : 
    1256           1 :     coarseTime = ring_node_to_send->coarseTime;
    1257           1 :     fineTime = ring_node_to_send->fineTime;
    1258           1 :     dataPtr = (volatile char*)ring_node_to_send->buffer_address;
    1259             : 
    1260           1 :     header->packetLength[0] = (unsigned char)(TM_LEN_SCI_CWF_672 >> SHIFT_1_BYTE);
    1261           1 :     header->packetLength[1] = (unsigned char)(TM_LEN_SCI_CWF_672);
    1262           1 :     header->pa_bia_status_info = pa_bia_status_info;
    1263           1 :     header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
    1264           1 :     header->blkNr[0] = (unsigned char)(BLK_NR_CWF_SHORT_F3 >> SHIFT_1_BYTE);
    1265           1 :     header->blkNr[1] = (unsigned char)(BLK_NR_CWF_SHORT_F3);
    1266             : 
    1267             :     //*********************
    1268             :     // SEND CWF3_light DATA
    1269           5 :     for (unsigned char i = 0; i < NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
    1270             :     {
    1271           4 :         spw_ioctl_send_CWF.data
    1272           4 :             = (char*)&dataPtr[(uint32_t)i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK];
    1273           4 :         spw_ioctl_send_CWF.hdr = (char*)header;
    1274             :         // BUILD THE DATA
    1275           4 :         spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
    1276             : 
    1277             :         // SET PACKET SEQUENCE COUNTER
    1278           4 :         increment_seq_counter_source_id(header->packetSequenceControl, sid);
    1279             : 
    1280             :         // SET SID
    1281           4 :         header->sid = sid;
    1282             : 
    1283             :         // SET PACKET TIME
    1284           4 :         compute_acquisition_time(coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime);
    1285             :         //
    1286           4 :         header->time[BYTE_0] = header->acquisitionTime[BYTE_0];
    1287           4 :         header->time[BYTE_1] = header->acquisitionTime[BYTE_1];
    1288           4 :         header->time[BYTE_2] = header->acquisitionTime[BYTE_2];
    1289           4 :         header->time[BYTE_3] = header->acquisitionTime[BYTE_3];
    1290           4 :         header->time[BYTE_4] = header->acquisitionTime[BYTE_4];
    1291           4 :         header->time[BYTE_5] = header->acquisitionTime[BYTE_5];
    1292             : 
    1293             :         // SET PACKET ID
    1294           4 :         header->packetID[0] = (unsigned char)(APID_TM_SCIENCE_NORMAL_BURST >> SHIFT_1_BYTE);
    1295           4 :         header->packetID[1] = (unsigned char)(APID_TM_SCIENCE_NORMAL_BURST);
    1296             : 
    1297             :         // SEND PACKET
    1298           4 :         status = ioctl(fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF);
    1299             :         DEBUG_CHECK_STATUS(status);
    1300             :     }
    1301             : 
    1302           1 :     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 : }

Generated by: LCOV version 1.14