LCOV - code coverage report
Current view: top level - src - fsw_misc.c (source / functions) Hit Total Coverage
Test: trace.info Lines: 106 122 86.9 %
Date: 2023-02-20 11:47:16 Functions: 5 6 83.3 %

          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             : /** General usage functions and RTEMS tasks.
      26             :  *
      27             :  * @file
      28             :  * @author P. LEROY
      29             :  *
      30             :  */
      31             : 
      32             : #include "fsw_misc.h"
      33             : #include "fsw_compile_warnings.h"
      34             : #include "fsw_debug.h"
      35             : #include "fsw_globals.h"
      36             : #include "fsw_housekeeping.h"
      37             : #include "fsw_watchdog.h"
      38             : #include "processing/iir_filter.h"
      39             : #include "tc_tm/tc_handler.h"
      40             : #include <stdlib.h>
      41             : 
      42             : int16_t hk_lfr_sc_v_f3 = 0;
      43             : int16_t hk_lfr_sc_e1_f3 = 0;
      44             : int16_t hk_lfr_sc_e2_f3 = 0;
      45             : 
      46             : /**
      47             :  * @brief load_task starts and keeps the watchdog alive.
      48             :  * @param argument
      49             :  * @return
      50             :  */
      51             : 
      52           1 : LFR_NO_RETURN rtems_task load_task(rtems_task_argument argument)
      53             : {
      54             :     IGNORE_UNUSED_PARAMETER(argument);
      55             : 
      56             :     BOOT_PRINTF("in LOAD *** \n");
      57             : 
      58             :     rtems_status_code status;
      59             :     unsigned int i;
      60             :     unsigned int j;
      61             :     rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
      62             :     rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
      63             : 
      64           1 :     watchdog_period_id = RTEMS_ID_NONE;
      65             : 
      66           1 :     name_watchdog_rate_monotonic = rtems_build_name('L', 'O', 'A', 'D');
      67             : 
      68           1 :     status = rtems_rate_monotonic_create(name_watchdog_rate_monotonic, &watchdog_period_id);
      69           1 :     if (status != RTEMS_SUCCESSFUL)
      70             :     {
      71             :         LFR_PRINTF("in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status);
      72             :     }
      73             : 
      74           1 :     i = 0;
      75           1 :     j = 0;
      76             : 
      77           1 :     watchdog_configure();
      78             : 
      79           1 :     watchdog_start();
      80             : 
      81           1 :     set_sy_lfr_watchdog_enabled(true);
      82             : 
      83             :     while (1)
      84             :     {
      85         237 :         DEBUG_CHECK_STATUS(rtems_rate_monotonic_period(watchdog_period_id, WATCHDOG_PERIOD));
      86         236 :         watchdog_reload();
      87         236 :         i = i + 1;
      88         236 :         if (i == WATCHDOG_LOOP_PRINTF)
      89             :         {
      90          23 :             i = 0;
      91          23 :             j = j + 1;
      92             :             LFR_PRINTF("%d\n", j);
      93             :         }
      94             : #ifdef DEBUG_WATCHDOG
      95             :         if (j == WATCHDOG_LOOP_DEBUG)
      96             :         {
      97             :             status = rtems_task_delete(RTEMS_SELF);
      98             :         }
      99             : #endif
     100             :     }
     101             : }
     102             : 
     103             : /**
     104             :  * @brief hous_task produces and sends HK each seconds
     105             :  * @param argument
     106             :  * @return
     107             :  */
     108           1 : LFR_NO_RETURN rtems_task hous_task(rtems_task_argument argument)
     109             : {
     110             :     IGNORE_UNUSED_PARAMETER(argument);
     111             : 
     112             :     rtems_status_code status;
     113             :     rtems_id queue_id;
     114             :     rtems_rate_monotonic_period_status period_status;
     115             :     bool isSynchronized;
     116             : 
     117           1 :     queue_id = RTEMS_ID_NONE;
     118           1 :     memset(&period_status, 0, sizeof(rtems_rate_monotonic_period_status));
     119           1 :     isSynchronized = false;
     120             : 
     121           1 :     status = get_message_queue_id_send(&queue_id);
     122           1 :     if (status != RTEMS_SUCCESSFUL)
     123             :     {
     124             :         LFR_PRINTF("in HOUS *** ERR get_message_queue_id_send %d\n", status);
     125             :     }
     126             : 
     127             :     BOOT_PRINTF("in HOUS ***\n");
     128             : 
     129           1 :     if (rtems_rate_monotonic_ident(name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL)
     130             :     {
     131           1 :         status = rtems_rate_monotonic_create(name_hk_rate_monotonic, &HK_id);
     132           1 :         if (status != RTEMS_SUCCESSFUL)
     133             :         {
     134             :             LFR_PRINTF("rtems_rate_monotonic_create failed with status of %d\n", status);
     135             :         }
     136             :     }
     137             : 
     138           1 :     status = rtems_rate_monotonic_cancel(HK_id);
     139           1 :     if (status != RTEMS_SUCCESSFUL)
     140             :     {
     141             :         LFR_PRINTF("ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status);
     142             :     }
     143             :     else
     144             :     {
     145             :         DEBUG_PRINTF("OK  *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n");
     146             :     }
     147             : 
     148             :     // startup phase
     149           1 :     DEBUG_CHECK_STATUS(rtems_rate_monotonic_period(HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks));
     150           1 :     DEBUG_CHECK_STATUS(rtems_rate_monotonic_get_status(HK_id, &period_status));
     151             :     DEBUG_PRINTF("startup HK, HK_id status = %d\n", period_status.state);
     152          44 :     while ((period_status.state != RATE_MONOTONIC_EXPIRED)
     153          21 :         && (isSynchronized == false)) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
     154             :     {
     155          21 :         if ((time_management_regs->coarse_time & VAL_LFR_SYNCHRONIZED)
     156             :             == INT32_ALL_0) // check time synchronization
     157             :         {
     158           0 :             isSynchronized = true;
     159             :         }
     160             :         else
     161             :         {
     162          21 :             DEBUG_CHECK_STATUS(rtems_rate_monotonic_get_status(HK_id, &period_status));
     163             :             // wait HK_SYNCH_WAIT 100 ms = 10 * 10 ms
     164          21 :             DEBUG_CHECK_STATUS(rtems_task_wake_after(HK_SYNC_WAIT));
     165             :         }
     166             :     }
     167           1 :     DEBUG_CHECK_STATUS(rtems_rate_monotonic_cancel(HK_id));
     168             :     DEBUG_PRINTF("startup HK, HK_id status = %d\n", period_status.state);
     169             : 
     170           1 :     set_hk_lfr_reset_cause(POWER_ON);
     171             : 
     172             :     while (1)
     173             :     { // launch the rate monotonic task
     174         235 :         status = rtems_rate_monotonic_period(HK_id, HK_PERIOD);
     175         234 :         if (status != RTEMS_SUCCESSFUL)
     176             :         {
     177             :             LFR_PRINTF("in HOUS *** ERR period: %d\n", status);
     178             :             DEBUG_CHECK_STATUS(send_event_dumb_task(RTEMS_EVENT_6));
     179             :         }
     180             :         else
     181             :         {
     182         234 :             housekeeping_packet.packetSequenceControl[BYTE_0]
     183         234 :                 = (unsigned char)(sequenceCounterHK >> SHIFT_1_BYTE);
     184         234 :             housekeeping_packet.packetSequenceControl[BYTE_1] = (unsigned char)(sequenceCounterHK);
     185         234 :             increment_seq_counter(&sequenceCounterHK);
     186             : 
     187         234 :             housekeeping_packet.time[BYTE_0]
     188         234 :                 = (unsigned char)(time_management_regs->coarse_time >> SHIFT_3_BYTES);
     189         234 :             housekeeping_packet.time[BYTE_1]
     190         234 :                 = (unsigned char)(time_management_regs->coarse_time >> SHIFT_2_BYTES);
     191         234 :             housekeeping_packet.time[BYTE_2]
     192         234 :                 = (unsigned char)(time_management_regs->coarse_time >> SHIFT_1_BYTE);
     193         234 :             housekeeping_packet.time[BYTE_3] = (unsigned char)(time_management_regs->coarse_time);
     194         234 :             housekeeping_packet.time[BYTE_4]
     195         234 :                 = (unsigned char)(time_management_regs->fine_time >> SHIFT_1_BYTE);
     196         234 :             housekeeping_packet.time[BYTE_5] = (unsigned char)(time_management_regs->fine_time);
     197             : 
     198         234 :             spacewire_update_hk_lfr_link_state(&housekeeping_packet.lfr_status_word[0]);
     199             : 
     200         234 :             spacewire_read_statistics();
     201             : 
     202         234 :             update_hk_with_grspw_stats();
     203             : 
     204         234 :             set_hk_lfr_time_not_synchro();
     205             : 
     206         234 :             housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
     207         234 :             housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
     208         234 :             housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
     209         234 :             housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
     210         234 :             housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
     211             : 
     212         234 :             housekeeping_packet.sy_lfr_common_parameters_spare
     213         234 :                 = parameter_dump_packet.sy_lfr_common_parameters_spare;
     214         234 :             housekeeping_packet.sy_lfr_common_parameters
     215         234 :                 = parameter_dump_packet.sy_lfr_common_parameters;
     216             :             encode_temperatures(&housekeeping_packet);
     217         234 :             encode_f3_E_field(
     218             :                 hk_lfr_sc_v_f3, hk_lfr_sc_e1_f3, hk_lfr_sc_e2_f3, &housekeeping_packet);
     219         234 :             encode_cpu_load(&housekeeping_packet);
     220             : 
     221         234 :             hk_lfr_le_me_he_update();
     222             : 
     223             :             // SEND PACKET
     224         234 :             status = rtems_message_queue_send(queue_id, &housekeeping_packet,
     225             :                 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
     226         234 :             if (status != RTEMS_SUCCESSFUL)
     227             :             {
     228             :                 LFR_PRINTF("in HOUS *** ERR send: %d\n", status);
     229             :             }
     230             :         }
     231             :     }
     232             : 
     233             :     LFR_PRINTF("in HOUS *** deleting task\n");
     234             : 
     235             :     DEBUG_CHECK_STATUS(rtems_task_delete(RTEMS_SELF)); // should not return
     236             : }
     237             : 
     238             : 
     239             : /**
     240             :  * @brief avgv_task pruduces HK rate elctrical field from F3 data
     241             :  * @param argument
     242             :  * @return
     243             :  */
     244           1 : LFR_NO_RETURN rtems_task avgv_task(rtems_task_argument argument)
     245             : {
     246             :     IGNORE_UNUSED_PARAMETER(argument);
     247             : 
     248             :     static int old_v = 0;
     249             :     static int old_e1 = 0;
     250             :     static int old_e2 = 0;
     251           1 :     int32_t current_v = 0;
     252           1 :     int32_t current_e1 = 0;
     253           1 :     int32_t current_e2 = 0;
     254           1 :     int32_t average_v = 0;
     255           1 :     int32_t average_e1 = 0;
     256           1 :     int32_t average_e2 = 0;
     257             : 
     258             :     static filter_ctx ctx_v = { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } };
     259             :     static filter_ctx ctx_e1 = { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } };
     260             :     static filter_ctx ctx_e2 = { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } };
     261             : 
     262             :     BOOT_PRINTF("in AVGV ***\n");
     263             : 
     264           1 :     if (rtems_rate_monotonic_ident(name_avgv_rate_monotonic, &AVGV_id) != RTEMS_SUCCESSFUL)
     265             :     {
     266           1 :         DEBUG_CHECK_STATUS(rtems_rate_monotonic_create(name_avgv_rate_monotonic, &AVGV_id));
     267             :     }
     268             : 
     269           1 :     DEBUG_CHECK_STATUS(rtems_rate_monotonic_cancel(AVGV_id));
     270             : 
     271             :     while (1)
     272             :     {
     273             :         // launch the rate monotonic task
     274        3911 :         DEBUG_CHECK_STATUS(rtems_rate_monotonic_period(AVGV_id, AVGV_PERIOD));
     275        3910 :         current_v = waveform_picker_regs->v;
     276        3910 :         current_e1 = waveform_picker_regs->e1;
     277        3910 :         current_e2 = waveform_picker_regs->e2;
     278             :         // this tests is weak but the only way to detect a new sample
     279             :         // it assumes that there is enough noise to flip at least one bit on v, E1 or E2
     280        3910 :         if ((current_v != old_v) || (current_e1 != old_e1) || (current_e2 != old_e2))
     281             :         {
     282        3255 :             average_v = filter(current_v, &ctx_v);
     283        3255 :             average_e1 = filter(current_e1, &ctx_e1);
     284        3255 :             average_e2 = filter(current_e2, &ctx_e2);
     285             : 
     286             :             // update int16 values
     287        3255 :             hk_lfr_sc_v_f3 = (int16_t)average_v;
     288        3255 :             hk_lfr_sc_e1_f3 = (int16_t)average_e1;
     289        3255 :             hk_lfr_sc_e2_f3 = (int16_t)average_e2;
     290             :         }
     291        3910 :         old_v = current_v;
     292        3910 :         old_e1 = current_e1;
     293        3910 :         old_e2 = current_e2;
     294        3910 :     }
     295             : 
     296             :     LFR_PRINTF("in AVGV *** deleting task\n");
     297             : 
     298             :     DEBUG_CHECK_STATUS(rtems_task_delete(RTEMS_SELF)); // should not return
     299             : }
     300             : 
     301           1 : LFR_NO_RETURN rtems_task dumb_task(rtems_task_argument unused)
     302             : {
     303             :     /** This RTEMS taks is used to print messages without affecting the general behaviour of the
     304             :      * software.
     305             :      *
     306             :      * @param unused is the starting argument of the RTEMS task
     307             :      *
     308             :      * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
     309             :      *
     310             :      */
     311             : 
     312             :     IGNORE_UNUSED_PARAMETER(unused);
     313             : 
     314           1 :     unsigned int intEventOut = EVENT_SETS_NONE_PENDING;
     315             :     rtems_event_set event_out;
     316             : 
     317             :     BOOT_PRINTF("in DUMB *** \n");
     318             : 
     319             :     while (1)
     320             :     {
     321           2 :         rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
     322             :                 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7 | RTEMS_EVENT_8
     323             :                 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13 | RTEMS_EVENT_14,
     324             :             RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
     325           1 :         intEventOut = (unsigned int)event_out;
     326          33 :         for (unsigned int i = 0; i < NB_RTEMS_EVENTS; i++)
     327             :         {
     328          32 :             if (((intEventOut >> i) & 1) != 0)
     329             :             {
     330           1 :                 switch (i)
     331             :                 {
     332             :                     case EVENT_12:
     333             :                         LFR_PRINTF("%s\n", DUMB_MESSAGE_12);
     334           0 :                         break;
     335             :                     case EVENT_13:
     336             :                         LFR_PRINTF("%s\n", DUMB_MESSAGE_13);
     337           1 :                         break;
     338             :                     case EVENT_14:
     339             :                         LFR_PRINTF("%s\n", DUMB_MESSAGE_1);
     340             :                         break;
     341             :                     default:
     342             :                         break;
     343             :                 }
     344             :             }
     345             :         }
     346             :     }
     347             : }
     348             : 
     349           0 : LFR_NO_RETURN rtems_task scrubbing_task(rtems_task_argument unused)
     350             : {
     351             :     /** This RTEMS taks is used to avoid entering IDLE task and also scrub memory to increase
     352             :      * scubbing frequency.
     353             :      *
     354             :      * @param unused is the starting argument of the RTEMS task
     355             :      *
     356             :      * The scrubbing reads continuously memory when no other tasks are ready.
     357             :      *
     358             :      */
     359             :     IGNORE_UNUSED_PARAMETER(unused);
     360             : 
     361             :     BOOT_PRINTF("in SCRUBBING *** \n");
     362           0 :     volatile int i = 0;
     363           0 :     volatile float valuef = 1.;
     364           0 :     const volatile uint32_t* const RAM = (uint32_t*)0x40000000;
     365             : 
     366             : #ifdef ENABLE_SCRUBBING_COUNTER
     367             :     housekeeping_packet.lfr_fpga_version[BYTE_0] = 0;
     368             : #endif
     369             :     while (1)
     370             :     {
     371           0 :         i = (i + 1) % (1024 * 1024);
     372           0 :         valuef += 10.f * (float)RAM[i];
     373             : #ifdef ENABLE_SCRUBBING_COUNTER
     374             :         if (i == 0)
     375             :         {
     376             :             housekeeping_packet.lfr_fpga_version[BYTE_0] += 1;
     377             :         }
     378             : #endif
     379           0 :     }
     380             : }
     381             : 
     382           1 : LFR_NO_RETURN rtems_task calibration_sweep_task(rtems_task_argument unused)
     383             : {
     384             :     /** This RTEMS taks is used to change calibration signal smapling frequency between snapshots.
     385             :      *
     386             :      * @param unused is the starting argument of the RTEMS task
     387             :      *
     388             :      * If calibration is enabled, this task will divide by two the calibration signal smapling
     389             :      * frequency between snapshots. When minimum sampling frequency is reach it will jump to maximum
     390             :      * sampling frequency to loop indefinitely.
     391             :      *
     392             :      */
     393             : 
     394             :     IGNORE_UNUSED_PARAMETER(unused);
     395             : 
     396             :     rtems_event_set event_out;
     397             :     BOOT_PRINTF("in calibration sweep *** \n");
     398           1 :     rtems_interval ticks_per_seconds = rtems_clock_get_ticks_per_second();
     399             :     while (1)
     400             :     {
     401             :         // Waiting for next F0 snapshot
     402           1 :         rtems_event_receive(RTEMS_EVENT_CAL_SWEEP_WAKE, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out);
     403           0 :         if (time_management_regs->calDACCtrl & BIT_CAL_ENABLE)
     404             :         {
     405             :             unsigned int delta_snapshot;
     406           0 :             delta_snapshot = (parameter_dump_packet.sy_lfr_n_swf_p[0] * CONST_256)
     407           0 :                 + parameter_dump_packet.sy_lfr_n_swf_p[1];
     408             :             // We are woken almost in the center of a snapshot -> let's wait for sy_lfr_n_swf_p / 2
     409           0 :             rtems_task_wake_after(ticks_per_seconds * delta_snapshot / 2);
     410           0 :             if (time_management_regs->calDivisor >= CAL_F_DIVISOR_MAX)
     411             :             {
     412           0 :                 time_management_regs->calDivisor = CAL_F_DIVISOR_MIN;
     413             :             }
     414             :             else
     415             :             {
     416           0 :                 time_management_regs->calDivisor *= 2;
     417             :             }
     418             :         }
     419             :     }
     420             : }
     421             : 
     422             : 
     423             : //*****************************
     424             : // init housekeeping parameters

Generated by: LCOV version 1.14