##// END OF EJS Templates
Disabled most dead code + set CMake min Ver to 3.5
jeandet -
r402:eb452cd0caf8 R3++ draft
parent child
Show More
@@ -1,14 +1,14
1 cmake_minimum_required (VERSION 3.6)
1 cmake_minimum_required (VERSION 3.5)
2 2 project (LFR_FSW)
3 3
4 4 if(NOT CMAKE_BUILD_TYPE)
5 5 set(CMAKE_BUILD_TYPE "Release" CACHE STRING
6 6 "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
7 7 endif(NOT CMAKE_BUILD_TYPE)
8 8
9 9 set(LFR_BP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/LFR_basic-parameters/basic_parameters.c)
10 10
11 11 SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/sparc")
12 12
13 13 add_subdirectory(libgcov)
14 14 add_subdirectory(src)
@@ -1,117 +1,112
1 1 #ifndef TC_HANDLER_H_INCLUDED
2 2 #define TC_HANDLER_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <leon.h>
6 6
7 7 #include "tc_load_dump_parameters.h"
8 8 #include "tc_acceptance.h"
9 9 #include "tm_lfr_tc_exe.h"
10 10 #include "wf_handler.h"
11 11 #include "fsw_processing.h"
12 12
13 13 #include "lfr_cpu_usage_report.h"
14 14
15 15 #define MAX_DELTA_COARSE_TIME 3
16 16 #define NB_SCIENCE_TASKS 10
17 17 #define NB_ASM_TASKS 6
18 18 #define STATUS_0 0
19 19 #define STATUS_1 1
20 20 #define STATUS_2 2
21 21 #define STATUS_3 3
22 22 #define STATUS_4 4
23 23 #define STATUS_5 5
24 24 #define STATUS_6 6
25 25 #define STATUS_7 7
26 26 #define STATUS_8 8
27 27 #define STATUS_9 9
28 28
29 29 #define CAL_F0 625.
30 30 #define CAL_F1 10000.
31 31 #define CAL_W0 (2. * pi * CAL_F0)
32 32 #define CAL_W1 (2. * pi * CAL_F1)
33 33 #define CAL_A0 1.
34 34 #define CAL_A1 2.
35 35 #define CAL_FS 160256.410
36 36 #define CAL_SCALE_FACTOR (0.250 / 0.000654) // 191, 500 mVpp, 2 sinus waves => 500 mVpp each, amplitude = 250 mV
37 37 #define CAL_NB_PTS 256
38 38 #define CAL_DATA_MASK 0xfff
39 39 #define CAL_F_DIVISOR 38 // 25 MHz => 160 256 (39 - 1)
40 40 #define CAL_F_DIVISOR_MIN 38
41 41 #define CAL_F_DIVISOR_MAX (38*2*2*2*2)
42 42 // INTERLEAVED MODE
43 43 #define CAL_FS_INTER 240384.615
44 44 #define CAL_NB_PTS_INTER 384
45 45 #define CAL_DATA_MASK_INTER 0x3f
46 46 #define CAL_DATA_SHIFT_INTER 12
47 47 #define BYTES_FOR_2_SAMPLES 3 // one need 3 bytes = 24 bits to store 3 samples of 12 bits in interleaved mode
48 48 #define STEPS_FOR_STORAGE_INTER 128
49 49 #define CAL_F_DIVISOR_INTER 26 // 25 MHz => 240 384
50 50
51 51 extern unsigned int lastValidEnterModeTime;
52 52 extern unsigned char oneTcLfrUpdateTimeReceived;
53 53
54 //****
55 // ISR
56 rtems_isr commutation_isr1( rtems_vector_number vector );
57 rtems_isr commutation_isr2( rtems_vector_number vector );
58
59 54 //***********
60 55 // RTEMS TASK
61 56 rtems_task actn_task( rtems_task_argument unused );
62 57
63 58 //***********
64 59 // TC ACTIONS
65 60 int action_reset( ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time );
66 61 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id);
67 62 int action_update_info( ccsdsTelecommandPacket_t *TC, rtems_id queue_id );
68 63 int action_enable_calibration( ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time );
69 64 int action_disable_calibration( ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time );
70 65 int action_update_time( ccsdsTelecommandPacket_t *TC);
71 66
72 67 // mode transition
73 68 int check_mode_value( unsigned char requestedMode );
74 69 int check_mode_transition( unsigned char requestedMode );
75 70 void update_last_valid_transition_date( unsigned int transitionCoarseTime );
76 71 int check_transition_date( unsigned int transitionCoarseTime );
77 72 int stop_spectral_matrices( void );
78 73 int stop_current_mode( void );
79 74 int enter_mode_standby(void );
80 75 int enter_mode_normal( unsigned int transitionCoarseTime );
81 76 int enter_mode_burst( unsigned int transitionCoarseTime );
82 77 int enter_mode_sbm1( unsigned int transitionCoarseTime );
83 78 int enter_mode_sbm2( unsigned int transitionCoarseTime );
84 79 int restart_science_tasks( unsigned char lfrRequestedMode );
85 80 int restart_asm_tasks(unsigned char lfrRequestedMode );
86 81 int suspend_science_tasks(void);
87 82 int suspend_asm_tasks( void );
88 83 void launch_waveform_picker( unsigned char mode , unsigned int transitionCoarseTime );
89 84 void launch_spectral_matrix( void );
90 85 void set_sm_irq_onNewMatrix( unsigned char value );
91 86 void set_sm_irq_onError( unsigned char value );
92 87
93 88 // other functions
94 89 void updateLFRCurrentMode(unsigned char requestedMode);
95 90 void set_lfr_soft_reset( unsigned char value );
96 91 void reset_lfr( void );
97 92 // CALIBRATION
98 93 void setCalibrationPrescaler( unsigned int prescaler );
99 94 void setCalibrationDivisor( unsigned int divisionFactor );
100 95 void setCalibrationData( void );
101 96 void setCalibrationReload( bool state);
102 97 void setCalibrationEnable( bool state );
103 98 void setCalibrationInterleaved( bool state );
104 99 void setCalibration( bool state );
105 100 void configureCalibration( bool interleaved );
106 101 //
107 102 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC , unsigned char *time );
108 103 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC , unsigned char *time );
109 104 void close_action( ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id );
110 105
111 106 extern rtems_status_code get_message_queue_id_send( rtems_id *queue_id );
112 107 extern rtems_status_code get_message_queue_id_recv( rtems_id *queue_id );
113 108
114 109 #endif // TC_HANDLER_H_INCLUDED
115 110
116 111
117 112
@@ -1,20 +1,20
1 cmake_minimum_required(VERSION 3.6)
1 cmake_minimum_required(VERSION 3.5)
2 2 project(libgcov C)
3 3 include(sparc-rtems)
4 4 include(cppcheck)
5 5
6 6 set(LIB_GCOV_SOURCES
7 7 gcov-io.c
8 8 gcov-io.h
9 9 gcov-iov.h
10 10 libgcov.c
11 11 )
12 12 if(Coverage)
13 # add_definitions(-DGCOV_USE_EXIT)
13 add_definitions(-DGCOV_USE_EXIT)
14 14 add_definitions(-DGCOV_ENABLED)
15 15 endif()
16 16 add_library(gcov STATIC ${LIB_GCOV_SOURCES})
17 17
18 18 add_custom_target(gcovr
19 19 COMMAND gcovr --exclude='.*gcov.*' --gcov-executable=${rtems_dir}/bin/sparc-rtems-gcov --object-directory ${CMAKE_BINARY_DIR} -r ${CMAKE_SOURCE_DIR} --html --html-details -o ${CMAKE_CURRENT_BINARY_DIR}/gcov.html && xdg-open ${CMAKE_CURRENT_BINARY_DIR}/gcov.html
20 20 )
@@ -1,39 +1,39
1 1 set(rtems_dir /opt/rtems-4.10/)
2 2
3 3 set(CMAKE_SYSTEM_NAME rtems)
4 4 set(CMAKE_C_COMPILER ${rtems_dir}/bin/sparc-rtems-gcc)
5 5 set(CMAKE_CXX_COMPILER ${rtems_dir}/bin/sparc-rtems-g++)
6 6 set(CMAKE_LINKER ${rtems_dir}/bin/sparc-rtems-g++)
7 7 SET(CMAKE_EXE_LINKER_FLAGS "-static")
8 8 option(fix-b2bst "Activate -mfix-b2bst switch to mitigate \"LEON3FT Stale Cache Entry After Store with Data Tag Parity Error\" errata, GRLIB-TN-0009" ON)
9 9
10 10 option(Coverage "Enables code coverage" OFF)
11 11
12 12
13 13 set(CMAKE_C_FLAGS_RELEASE "-O2")
14 set(CMAKE_C_FLAGS_DEBUG "-O2 -g -fno-inline")
14 set(CMAKE_C_FLAGS_DEBUG "-O2 -g3 -fno-inline")
15 15
16 16
17 17 if(fix-b2bst)
18 18 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfix-b2bst")
19 19 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mfix-b2bst")
20 20 endif()
21 21
22 22
23 23 set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <FLAGS> -Xlinker -Map=<TARGET>.map <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
24 24
25 25 include_directories("${rtems_dir}/sparc-rtems/leon3/lib/include")
26 26
27 27 function (check_b2bst target bin)
28 28 add_custom_command(TARGET ${target}
29 29 POST_BUILD
30 30 COMMAND ${rtems_dir}/bin/sparc-rtems-objdump -d ${bin}/${target} | ${CMAKE_SOURCE_DIR}/sparc/leon3ft-b2bst-scan.tcl
31 31 )
32 32 endfunction()
33 33
34 34 function (build_srec target bin rev)
35 35 add_custom_command(TARGET ${target}
36 36 POST_BUILD
37 37 COMMAND ${rtems_dir}/bin/sparc-rtems-objcopy -j .data -F srec ${bin}/${target} RpwLfrApp_XXXX_data_rev-${rev}.srec && ${rtems_dir}/bin/sparc-rtems-objcopy -j .text -F srec ${bin}/${target} RpwLfrApp_XXXX_text_rev-${rev}.srec
38 38 )
39 39 endfunction()
@@ -1,130 +1,136
1 cmake_minimum_required (VERSION 3.6)
1 cmake_minimum_required (VERSION 3.5)
2 2 project (fsw)
3 3
4 4 include(sparc-rtems)
5 5 include(cppcheck)
6 6
7 7 include_directories("../header"
8 8 "../header/lfr_common_headers"
9 9 "../header/processing"
10 10 "../LFR_basic-parameters"
11 11 "../src")
12 12
13 13 set(SOURCES wf_handler.c
14 14 tc_handler.c
15 15 fsw_misc.c
16 16 fsw_init.c
17 17 fsw_globals.c
18 18 fsw_spacewire.c
19 19 tc_load_dump_parameters.c
20 20 tm_lfr_tc_exe.c
21 21 tc_acceptance.c
22 22 processing/fsw_processing.c
23 23 processing/avf0_prc0.c
24 24 processing/avf1_prc1.c
25 25 processing/avf2_prc2.c
26 26 lfr_cpu_usage_report.c
27 27 ${LFR_BP_SRC}
28 28 ../header/wf_handler.h
29 29 ../header/tc_handler.h
30 30 ../header/grlib_regs.h
31 31 ../header/fsw_misc.h
32 32 ../header/fsw_init.h
33 33 ../header/fsw_spacewire.h
34 34 ../header/tc_load_dump_parameters.h
35 35 ../header/tm_lfr_tc_exe.h
36 36 ../header/tc_acceptance.h
37 37 ../header/processing/fsw_processing.h
38 38 ../header/processing/avf0_prc0.h
39 39 ../header/processing/avf1_prc1.h
40 40 ../header/processing/avf2_prc2.h
41 41 ../header/fsw_params_wf_handler.h
42 42 ../header/lfr_cpu_usage_report.h
43 43 ../header/lfr_common_headers/ccsds_types.h
44 44 ../header/lfr_common_headers/fsw_params.h
45 45 ../header/lfr_common_headers/fsw_params_nb_bytes.h
46 46 ../header/lfr_common_headers/fsw_params_processing.h
47 47 ../header/lfr_common_headers/tm_byte_positions.h
48 48 ../LFR_basic-parameters/basic_parameters.h
49 49 ../LFR_basic-parameters/basic_parameters_params.h
50 50 ../header/GscMemoryLPP.hpp
51 51 )
52 52
53 53
54 54 option(FSW_verbose "Enable verbose LFR" OFF)
55 55 option(FSW_boot_messages "Enable LFR boot messages" OFF)
56 56 option(FSW_debug_messages "Enable LFR debug messages" OFF)
57 57 option(FSW_cpu_usage_report "Enable LFR cpu usage report" OFF)
58 58 option(FSW_stack_report "Enable LFR stack report" OFF)
59 59 option(FSW_vhdl_dev "?" OFF)
60 60 option(FSW_lpp_dpu_destid "Set to debug at LPP" OFF)
61 61 option(FSW_debug_watchdog "Enable debug watchdog" OFF)
62 62 option(FSW_debug_tch "?" OFF)
63 63 option(FSW_Instrument_Scrubbing "Enable scrubbing counter" OFF)
64 option(FSW_Enable_Dead_Code "Enable dead code compilation, this is used to hide by default unused code." OFF)
64 65
65 66 set(SW_VERSION_N1 "3" CACHE STRING "Choose N1 FSW Version." FORCE)
66 67 set(SW_VERSION_N2 "2" CACHE STRING "Choose N2 FSW Version." FORCE)
67 68 set(SW_VERSION_N3 "0" CACHE STRING "Choose N3 FSW Version." FORCE)
68 69 set(SW_VERSION_N4 "22" CACHE STRING "Choose N4 FSW Version." FORCE)
69 70
70 71 if(FSW_verbose)
71 72 add_definitions(-DPRINT_MESSAGES_ON_CONSOLE)
72 73 endif()
73 74 if(FSW_boot_messages)
74 75 add_definitions(-DBOOT_MESSAGES)
75 76 endif()
76 77 if(FSW_debug_messages)
77 78 add_definitions(-DDEBUG_MESSAGES)
78 79 endif()
79 80 if(FSW_cpu_usage_report)
80 81 add_definitions(-DPRINT_TASK_STATISTICS)
81 82 endif()
82 83 if(FSW_stack_report)
83 84 add_definitions(-DPRINT_STACK_REPORT)
84 85 endif()
85 86 if(FSW_vhdl_dev)
86 87 add_definitions(-DVHDL_DEV)
87 88 endif()
88 89 if(FSW_lpp_dpu_destid)
89 90 add_definitions(-DLPP_DPU_DESTID)
90 91 endif()
91 92 if(FSW_debug_watchdog)
92 93 add_definitions(-DDEBUG_WATCHDOG)
93 94 endif()
94 95 if(FSW_debug_tch)
95 96 add_definitions(-DDEBUG_TCH)
96 97 endif()
97 98
99 if(FSW_Enable_Dead_Code)
100 add_definitions(-DENABLE_DEAD_CODE)
101 endif()
102
103
98 104
99 105
100 106 add_definitions(-DMSB_FIRST_TCH)
101 107
102 108 add_definitions(-DSWVERSION=-1-0)
103 109 add_definitions(-DSW_VERSION_N1=${SW_VERSION_N1})
104 110 add_definitions(-DSW_VERSION_N2=${SW_VERSION_N2})
105 111 add_definitions(-DSW_VERSION_N3=${SW_VERSION_N3})
106 112 add_definitions(-DSW_VERSION_N4=${SW_VERSION_N4})
107 113
108 114 add_executable(fsw ${SOURCES})
109 115
110 116 if(FSW_Instrument_Scrubbing)
111 117 add_definitions(-DENABLE_SCRUBBING_COUNTER)
112 118 endif()
113 119
114 120 if(Coverage)
115 121 target_link_libraries(fsw gcov)
116 122 SET_TARGET_PROPERTIES(fsw PROPERTIES COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
117 123 endif()
118 124
119 125
120 126 if(fix-b2bst)
121 127 check_b2bst(fsw ${CMAKE_CURRENT_BINARY_DIR})
122 128 endif()
123 129
124 130 if(NOT FSW_lpp_dpu_destid)
125 131 build_srec(fsw ${CMAKE_CURRENT_BINARY_DIR} "${SW_VERSION_N1}-${SW_VERSION_N2}-${SW_VERSION_N3}-${SW_VERSION_N4}")
126 132 endif()
127 133
128 134
129 135 #add_test_cppcheck(fsw STYLE UNUSED_FUNCTIONS POSSIBLE_ERROR MISSING_INCLUDE)
130 136
@@ -1,1109 +1,1111
1 1 /*------------------------------------------------------------------------------
2 2 -- Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3 3 -- This file is a part of the LFR FSW
4 4 -- Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5 5 --
6 6 -- This program is free software; you can redistribute it and/or modify
7 7 -- it under the terms of the GNU General Public License as published by
8 8 -- the Free Software Foundation; either version 2 of the License, or
9 9 -- (at your option) any later version.
10 10 --
11 11 -- This program is distributed in the hope that it will be useful,
12 12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 -- GNU General Public License for more details.
15 15 --
16 16 -- You should have received a copy of the GNU General Public License
17 17 -- along with this program; if not, write to the Free Software
18 18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 -------------------------------------------------------------------------------*/
20 20 /*-- Author : Paul Leroy
21 21 -- Contact : Alexis Jeandet
22 22 -- Mail : alexis.jeandet@lpp.polytechnique.fr
23 23 ----------------------------------------------------------------------------*/
24 24
25 25 /** General usage functions and RTEMS tasks.
26 26 *
27 27 * @file
28 28 * @author P. LEROY
29 29 *
30 30 */
31 31
32 32 #include "fsw_misc.h"
33 33
34 34 int16_t hk_lfr_sc_v_f3_as_int16 = 0;
35 35 int16_t hk_lfr_sc_e1_f3_as_int16 = 0;
36 36 int16_t hk_lfr_sc_e2_f3_as_int16 = 0;
37 37
38 38 void timer_configure(unsigned char timer, unsigned int clock_divider,
39 39 unsigned char interrupt_level, rtems_isr (*timer_isr)() )
40 40 {
41 41 /** This function configures a GPTIMER timer instantiated in the VHDL design.
42 42 *
43 43 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
44 44 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
45 45 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
46 46 * @param interrupt_level is the interrupt level that the timer drives.
47 47 * @param timer_isr is the interrupt subroutine that will be attached to the IRQ driven by the timer.
48 48 *
49 49 * Interrupt levels are described in the SPARC documentation sparcv8.pdf p.76
50 50 *
51 51 */
52 52
53 53 rtems_status_code status;
54 54 rtems_isr_entry old_isr_handler;
55 55
56 56 old_isr_handler = NULL;
57 57
58 58 gptimer_regs->timer[timer].ctrl = INIT_CHAR; // reset the control register
59 59
60 60 status = rtems_interrupt_catch( timer_isr, interrupt_level, &old_isr_handler) ; // see sparcv8.pdf p.76 for interrupt levels
61 61 if (status!=RTEMS_SUCCESSFUL)
62 62 {
63 63 PRINTF("in configure_timer *** ERR rtems_interrupt_catch\n")
64 64 }
65 65
66 66 timer_set_clock_divider( timer, clock_divider);
67 67 }
68 68
69 #ifdef ENABLE_DEAD_CODE
69 70 void timer_start(unsigned char timer)
70 71 {
71 72 /** This function starts a GPTIMER timer.
72 73 *
73 74 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
74 75 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
75 76 *
76 77 */
77 78
78 79 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_CLEAR_IRQ;
79 80 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_LD;
80 81 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_EN;
81 82 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_RS;
82 83 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_IE;
83 84 }
85 #endif
84 86
85 87 void timer_stop(unsigned char timer)
86 88 {
87 89 /** This function stops a GPTIMER timer.
88 90 *
89 91 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
90 92 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
91 93 *
92 94 */
93 95
94 96 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & GPTIMER_EN_MASK;
95 97 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & GPTIMER_IE_MASK;
96 98 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | GPTIMER_CLEAR_IRQ;
97 99 }
98 100
99 101 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider)
100 102 {
101 103 /** This function sets the clock divider of a GPTIMER timer.
102 104 *
103 105 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
104 106 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
105 107 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
106 108 *
107 109 */
108 110
109 111 gptimer_regs->timer[timer].reload = clock_divider; // base clock frequency is 1 MHz
110 112 }
111 113
112 114 // WATCHDOG, this ISR should never be triggered.
113 115
114 116 rtems_isr watchdog_isr( rtems_vector_number vector )
115 117 {
116 118 rtems_status_code status_code;
117 119
118 120 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_12 );
119 121
120 122 PRINTF("watchdog_isr *** this is the end, exit(0)\n");
121 123
122 124 exit(0);
123 125 }
124 126
125 127 void watchdog_configure(void)
126 128 {
127 129 /** This function configure the watchdog.
128 130 *
129 131 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
130 132 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
131 133 *
132 134 * The watchdog is a timer provided by the GPTIMER IP core of the GRLIB.
133 135 *
134 136 */
135 137
136 138 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt during configuration
137 139
138 140 timer_configure( TIMER_WATCHDOG, CLKDIV_WATCHDOG, IRQ_SPARC_GPTIMER_WATCHDOG, watchdog_isr );
139 141
140 142 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
141 143 }
142 144
143 145 void watchdog_stop(void)
144 146 {
145 147 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt line
146 148 timer_stop( TIMER_WATCHDOG );
147 149 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
148 150 }
149 151
150 152 void watchdog_reload(void)
151 153 {
152 154 /** This function reloads the watchdog timer counter with the timer reload value.
153 155 *
154 156 * @param void
155 157 *
156 158 * @return void
157 159 *
158 160 */
159 161
160 162 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | GPTIMER_LD;
161 163 }
162 164
163 165 void watchdog_start(void)
164 166 {
165 167 /** This function starts the watchdog timer.
166 168 *
167 169 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
168 170 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
169 171 *
170 172 */
171 173
172 174 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
173 175
174 176 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | GPTIMER_CLEAR_IRQ;
175 177 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | GPTIMER_LD;
176 178 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | GPTIMER_EN;
177 179 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | GPTIMER_IE;
178 180
179 181 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
180 182
181 183 }
182 184
183 185 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
184 186 {
185 187 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
186 188
187 189 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
188 190
189 191 return 0;
190 192 }
191 193
192 194 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
193 195 {
194 196 /** This function sets the scaler reload register of the apbuart module
195 197 *
196 198 * @param regs is the address of the apbuart registers in memory
197 199 * @param value is the value that will be stored in the scaler register
198 200 *
199 201 * The value shall be set by the software to get data on the serial interface.
200 202 *
201 203 */
202 204
203 205 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
204 206
205 207 apbuart_regs->scaler = value;
206 208
207 209 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
208 210 }
209 211
210 212 /**
211 213 * @brief load_task starts and keeps the watchdog alive.
212 214 * @param argument
213 215 * @return
214 216 */
215 217
216 218 rtems_task load_task(rtems_task_argument argument)
217 219 {
218 220 BOOT_PRINTF("in LOAD *** \n")
219 221
220 222 rtems_status_code status;
221 223 unsigned int i;
222 224 unsigned int j;
223 225 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
224 226 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
225 227
226 228 watchdog_period_id = RTEMS_ID_NONE;
227 229
228 230 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
229 231
230 232 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
231 233 if( status != RTEMS_SUCCESSFUL ) {
232 234 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
233 235 }
234 236
235 237 i = 0;
236 238 j = 0;
237 239
238 240 watchdog_configure();
239 241
240 242 watchdog_start();
241 243
242 244 set_sy_lfr_watchdog_enabled( true );
243 245
244 246 while(1){
245 247 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
246 248 watchdog_reload();
247 249 i = i + 1;
248 250 if ( i == WATCHDOG_LOOP_PRINTF )
249 251 {
250 252 i = 0;
251 253 j = j + 1;
252 254 PRINTF1("%d\n", j)
253 255 }
254 256 #ifdef DEBUG_WATCHDOG
255 257 if (j == WATCHDOG_LOOP_DEBUG )
256 258 {
257 259 status = rtems_task_delete(RTEMS_SELF);
258 260 }
259 261 #endif
260 262 }
261 263 }
262 264
263 265 /**
264 266 * @brief hous_task produces and sends HK each seconds
265 267 * @param argument
266 268 * @return
267 269 */
268 270 rtems_task hous_task(rtems_task_argument argument)
269 271 {
270 272 rtems_status_code status;
271 273 rtems_status_code spare_status;
272 274 rtems_id queue_id;
273 275 rtems_rate_monotonic_period_status period_status;
274 276 bool isSynchronized;
275 277
276 278 queue_id = RTEMS_ID_NONE;
277 279 memset(&period_status, 0, sizeof(rtems_rate_monotonic_period_status));
278 280 isSynchronized = false;
279 281
280 282 status = get_message_queue_id_send( &queue_id );
281 283 if (status != RTEMS_SUCCESSFUL)
282 284 {
283 285 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
284 286 }
285 287
286 288 BOOT_PRINTF("in HOUS ***\n");
287 289
288 290 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
289 291 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
290 292 if( status != RTEMS_SUCCESSFUL ) {
291 293 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status );
292 294 }
293 295 }
294 296
295 297 status = rtems_rate_monotonic_cancel(HK_id);
296 298 if( status != RTEMS_SUCCESSFUL ) {
297 299 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status );
298 300 }
299 301 else {
300 302 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n");
301 303 }
302 304
303 305 // startup phase
304 306 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
305 307 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
306 308 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
307 309 while( (period_status.state != RATE_MONOTONIC_EXPIRED)
308 310 && (isSynchronized == false) ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
309 311 {
310 312 if ((time_management_regs->coarse_time & VAL_LFR_SYNCHRONIZED) == INT32_ALL_0) // check time synchronization
311 313 {
312 314 isSynchronized = true;
313 315 }
314 316 else
315 317 {
316 318 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
317 319
318 320 status = rtems_task_wake_after( HK_SYNC_WAIT ); // wait HK_SYNCH_WAIT 100 ms = 10 * 10 ms
319 321 }
320 322 }
321 323 status = rtems_rate_monotonic_cancel(HK_id);
322 324 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
323 325
324 326 set_hk_lfr_reset_cause( POWER_ON );
325 327
326 328 while(1){ // launch the rate monotonic task
327 329 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
328 330 if ( status != RTEMS_SUCCESSFUL ) {
329 331 PRINTF1( "in HOUS *** ERR period: %d\n", status);
330 332 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
331 333 }
332 334 else {
333 335 housekeeping_packet.packetSequenceControl[BYTE_0] = (unsigned char) (sequenceCounterHK >> SHIFT_1_BYTE);
334 336 housekeeping_packet.packetSequenceControl[BYTE_1] = (unsigned char) (sequenceCounterHK );
335 337 increment_seq_counter( &sequenceCounterHK );
336 338
337 339 housekeeping_packet.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
338 340 housekeeping_packet.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
339 341 housekeeping_packet.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
340 342 housekeeping_packet.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
341 343 housekeeping_packet.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
342 344 housekeeping_packet.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
343 345
344 346 spacewire_update_hk_lfr_link_state( &housekeeping_packet.lfr_status_word[0] );
345 347
346 348 spacewire_read_statistics();
347 349
348 350 update_hk_with_grspw_stats();
349 351
350 352 set_hk_lfr_time_not_synchro();
351 353
352 354 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
353 355 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
354 356 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
355 357 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
356 358 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
357 359
358 360 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
359 361 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
360 362 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
361 363 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
362 364 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
363 365
364 366 hk_lfr_le_me_he_update();
365 367
366 368 // SEND PACKET
367 369 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
368 370 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
369 371 if (status != RTEMS_SUCCESSFUL) {
370 372 PRINTF1("in HOUS *** ERR send: %d\n", status)
371 373 }
372 374 }
373 375 }
374 376
375 377 PRINTF("in HOUS *** deleting task\n")
376 378
377 379 status = rtems_task_delete( RTEMS_SELF ); // should not return
378 380
379 381 return;
380 382 }
381 383
382 384 /**
383 385 * @brief filter is a Direct-Form-II filter implementation, mostly used to filter electric field for HK
384 386 * @param x, new sample
385 387 * @param ctx, filter context, used to store previous input and output samples
386 388 * @return a new filtered sample
387 389 */
388 390 int filter( int x, filter_ctx* ctx )
389 391 {
390 392 static const int b[NB_COEFFS][NB_COEFFS]={ {B00, B01, B02}, {B10, B11, B12}, {B20, B21, B22} };
391 393 static const int a[NB_COEFFS][NB_COEFFS]={ {A00, A01, A02}, {A10, A11, A12}, {A20, A21, A22} };
392 394 static const int b_gain[NB_COEFFS]={GAIN_B0, GAIN_B1, GAIN_B2};
393 395 static const int a_gain[NB_COEFFS]={GAIN_A0, GAIN_A1, GAIN_A2};
394 396
395 397 int_fast32_t W;
396 398 int i;
397 399
398 400 W = INIT_INT;
399 401 i = INIT_INT;
400 402
401 403 //Direct-Form-II
402 404 for ( i = 0; i < NB_COEFFS; i++ )
403 405 {
404 406 x = x << a_gain[i];
405 407 W = (x - ( a[i][COEFF1] * ctx->W[i][COEFF0] )
406 408 - ( a[i][COEFF2] * ctx->W[i][COEFF1] ) ) >> a_gain[i];
407 409 x = ( b[i][COEFF0] * W )
408 410 + ( b[i][COEFF1] * ctx->W[i][COEFF0] )
409 411 + ( b[i][COEFF2] * ctx->W[i][COEFF1] );
410 412 x = x >> b_gain[i];
411 413 ctx->W[i][1] = ctx->W[i][0];
412 414 ctx->W[i][0] = W;
413 415 }
414 416 return x;
415 417 }
416 418
417 419 /**
418 420 * @brief avgv_task pruduces HK rate elctrical field from F3 data
419 421 * @param argument
420 422 * @return
421 423 */
422 424 rtems_task avgv_task(rtems_task_argument argument)
423 425 {
424 426 #define MOVING_AVERAGE 16
425 427 rtems_status_code status;
426 428 static int32_t v[MOVING_AVERAGE] = {0};
427 429 static int32_t e1[MOVING_AVERAGE] = {0};
428 430 static int32_t e2[MOVING_AVERAGE] = {0};
429 431 static int old_v = 0;
430 432 static int old_e1 = 0;
431 433 static int old_e2 = 0;
432 434 int32_t current_v;
433 435 int32_t current_e1;
434 436 int32_t current_e2;
435 437 int32_t average_v;
436 438 int32_t average_e1;
437 439 int32_t average_e2;
438 440 int32_t newValue_v;
439 441 int32_t newValue_e1;
440 442 int32_t newValue_e2;
441 443 unsigned char k;
442 444 unsigned char indexOfOldValue;
443 445
444 446 static filter_ctx ctx_v = { { {0,0,0}, {0,0,0}, {0,0,0} } };
445 447 static filter_ctx ctx_e1 = { { {0,0,0}, {0,0,0}, {0,0,0} } };
446 448 static filter_ctx ctx_e2 = { { {0,0,0}, {0,0,0}, {0,0,0} } };
447 449
448 450 BOOT_PRINTF("in AVGV ***\n");
449 451
450 452 if (rtems_rate_monotonic_ident( name_avgv_rate_monotonic, &AVGV_id) != RTEMS_SUCCESSFUL) {
451 453 status = rtems_rate_monotonic_create( name_avgv_rate_monotonic, &AVGV_id );
452 454 if( status != RTEMS_SUCCESSFUL ) {
453 455 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status );
454 456 }
455 457 }
456 458
457 459 status = rtems_rate_monotonic_cancel(AVGV_id);
458 460 if( status != RTEMS_SUCCESSFUL ) {
459 461 PRINTF1( "ERR *** in AVGV *** rtems_rate_monotonic_cancel(AVGV_id) ***code: %d\n", status );
460 462 }
461 463 else {
462 464 DEBUG_PRINTF("OK *** in AVGV *** rtems_rate_monotonic_cancel(AVGV_id)\n");
463 465 }
464 466
465 467 // initialize values
466 468 indexOfOldValue = MOVING_AVERAGE - 1;
467 469 current_v = 0;
468 470 current_e1 = 0;
469 471 current_e2 = 0;
470 472 average_v = 0;
471 473 average_e1 = 0;
472 474 average_e2 = 0;
473 475 newValue_v = 0;
474 476 newValue_e1 = 0;
475 477 newValue_e2 = 0;
476 478
477 479 k = INIT_CHAR;
478 480
479 481 while(1)
480 482 { // launch the rate monotonic task
481 483 status = rtems_rate_monotonic_period( AVGV_id, AVGV_PERIOD );
482 484 if ( status != RTEMS_SUCCESSFUL )
483 485 {
484 486 PRINTF1( "in AVGV *** ERR period: %d\n", status);
485 487 }
486 488 else
487 489 {
488 490 current_v = waveform_picker_regs->v;
489 491 current_e1 = waveform_picker_regs->e1;
490 492 current_e2 = waveform_picker_regs->e2;
491 493 if ( (current_v != old_v)
492 494 || (current_e1 != old_e1)
493 495 || (current_e2 != old_e2))
494 496 {
495 497 average_v = filter( current_v, &ctx_v );
496 498 average_e1 = filter( current_e1, &ctx_e1 );
497 499 average_e2 = filter( current_e2, &ctx_e2 );
498 500
499 501 //update int16 values
500 502 hk_lfr_sc_v_f3_as_int16 = (int16_t) average_v;
501 503 hk_lfr_sc_e1_f3_as_int16 = (int16_t) average_e1;
502 504 hk_lfr_sc_e2_f3_as_int16 = (int16_t) average_e2;
503 505 }
504 506 old_v = current_v;
505 507 old_e1 = current_e1;
506 508 old_e2 = current_e2;
507 509 }
508 510 }
509 511
510 512 PRINTF("in AVGV *** deleting task\n");
511 513
512 514 status = rtems_task_delete( RTEMS_SELF ); // should not return
513 515
514 516 return;
515 517 }
516 518
517 519 rtems_task dumb_task( rtems_task_argument unused )
518 520 {
519 521 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
520 522 *
521 523 * @param unused is the starting argument of the RTEMS task
522 524 *
523 525 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
524 526 *
525 527 */
526 528
527 529 unsigned int i;
528 530 unsigned int intEventOut;
529 531 unsigned int coarse_time = 0;
530 532 unsigned int fine_time = 0;
531 533 rtems_event_set event_out;
532 534
533 535 event_out = EVENT_SETS_NONE_PENDING;
534 536
535 537 BOOT_PRINTF("in DUMB *** \n")
536 538
537 539 while(1){
538 540 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
539 541 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
540 542 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13
541 543 | RTEMS_EVENT_14,
542 544 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
543 545 intEventOut = (unsigned int) event_out;
544 546 for ( i=0; i<NB_RTEMS_EVENTS; i++)
545 547 {
546 548 if ( ((intEventOut >> i) & 1) != 0)
547 549 {
548 550 coarse_time = time_management_regs->coarse_time;
549 551 fine_time = time_management_regs->fine_time;
550 552 if (i==EVENT_12)
551 553 {
552 554 PRINTF1("%s\n", DUMB_MESSAGE_12)
553 555 }
554 556 if (i==EVENT_13)
555 557 {
556 558 PRINTF1("%s\n", DUMB_MESSAGE_13)
557 559 }
558 560 if (i==EVENT_14)
559 561 {
560 562 PRINTF1("%s\n", DUMB_MESSAGE_1)
561 563 }
562 564 }
563 565 }
564 566 }
565 567 }
566 568
567 569 rtems_task scrubbing_task( rtems_task_argument unused )
568 570 {
569 571 /** This RTEMS taks is used to avoid entering IDLE task and also scrub memory to increase scubbing frequency.
570 572 *
571 573 * @param unused is the starting argument of the RTEMS task
572 574 *
573 575 * The scrubbing reads continuously memory when no other tasks are ready.
574 576 *
575 577 */
576 578
577 579 BOOT_PRINTF("in SCRUBBING *** \n");
578 580 volatile int i=0;
579 581 volatile float valuef = 1.;
580 582 volatile uint32_t* RAM=(uint32_t*)0x40000000;
581 583 volatile uint32_t value;
582 584 #ifdef ENABLE_SCRUBBING_COUNTER
583 585 housekeeping_packet.lfr_fpga_version[BYTE_0] = 0;
584 586 #endif
585 587 while(1){
586 588 i=(i+1)%(1024*1024);
587 589 valuef += 10.f*(float)RAM[i];
588 590 #ifdef ENABLE_SCRUBBING_COUNTER
589 591 if(i==0)
590 592 {
591 593 housekeeping_packet.lfr_fpga_version[BYTE_0] += 1;
592 594 }
593 595 #endif
594 596 }
595 597 }
596 598
597 599 rtems_task calibration_sweep_task( rtems_task_argument unused )
598 600 {
599 601 /** This RTEMS taks is used to change calibration signal smapling frequency between snapshots.
600 602 *
601 603 * @param unused is the starting argument of the RTEMS task
602 604 *
603 605 * If calibration is enabled, this task will divide by two the calibration signal smapling frequency between snapshots.
604 606 * When minimum sampling frequency is reach it will jump to maximum sampling frequency to loop indefinitely.
605 607 *
606 608 */
607 609 rtems_event_set event_out;
608 610 BOOT_PRINTF("in calibration sweep *** \n");
609 611 rtems_interval ticks_per_seconds = rtems_clock_get_ticks_per_second();
610 612 while(1){
611 613 // Waiting for next F0 snapshot
612 614 rtems_event_receive(RTEMS_EVENT_CAL_SWEEP_WAKE, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out);
613 615 if(time_management_regs->calDACCtrl & BIT_CAL_ENABLE)
614 616 {
615 617 unsigned int delta_snapshot;
616 618 delta_snapshot = (parameter_dump_packet.sy_lfr_n_swf_p[0] * CONST_256)
617 619 + parameter_dump_packet.sy_lfr_n_swf_p[1];
618 620 // We are woken almost in the center of a snapshot -> let's wait for sy_lfr_n_swf_p / 2
619 621 rtems_task_wake_after( ticks_per_seconds * delta_snapshot / 2);
620 622 if(time_management_regs->calDivisor >= CAL_F_DIVISOR_MAX){
621 623 time_management_regs->calDivisor = CAL_F_DIVISOR_MIN;
622 624 }
623 625 else{
624 626 time_management_regs->calDivisor *= 2;
625 627 }
626 628 }
627 629
628 630
629 631
630 632 }
631 633
632 634 }
633 635
634 636
635 637 //*****************************
636 638 // init housekeeping parameters
637 639
638 640 void init_housekeeping_parameters( void )
639 641 {
640 642 /** This function initialize the housekeeping_packet global variable with default values.
641 643 *
642 644 */
643 645
644 646 unsigned int i = 0;
645 647 unsigned char *parameters;
646 648 unsigned char sizeOfHK;
647 649
648 650 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
649 651
650 652 parameters = (unsigned char*) &housekeeping_packet;
651 653
652 654 for(i = 0; i< sizeOfHK; i++)
653 655 {
654 656 parameters[i] = INIT_CHAR;
655 657 }
656 658
657 659 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
658 660 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
659 661 housekeeping_packet.reserved = DEFAULT_RESERVED;
660 662 housekeeping_packet.userApplication = CCSDS_USER_APP;
661 663 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> SHIFT_1_BYTE);
662 664 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
663 665 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
664 666 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
665 667 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> SHIFT_1_BYTE);
666 668 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
667 669 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
668 670 housekeeping_packet.serviceType = TM_TYPE_HK;
669 671 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
670 672 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
671 673 housekeeping_packet.sid = SID_HK;
672 674
673 675 // init status word
674 676 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
675 677 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
676 678 // init software version
677 679 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
678 680 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
679 681 housekeeping_packet.lfr_sw_version[BYTE_2] = SW_VERSION_N3;
680 682 housekeeping_packet.lfr_sw_version[BYTE_3] = SW_VERSION_N4;
681 683 // init fpga version
682 684 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
683 685 housekeeping_packet.lfr_fpga_version[BYTE_0] = parameters[BYTE_1]; // n1
684 686 housekeeping_packet.lfr_fpga_version[BYTE_1] = parameters[BYTE_2]; // n2
685 687 housekeeping_packet.lfr_fpga_version[BYTE_2] = parameters[BYTE_3]; // n3
686 688
687 689 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
688 690 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
689 691 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
690 692 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
691 693 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
692 694 }
693 695
694 696 void increment_seq_counter( unsigned short *packetSequenceControl )
695 697 {
696 698 /** This function increment the sequence counter passes in argument.
697 699 *
698 700 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
699 701 *
700 702 */
701 703
702 704 unsigned short segmentation_grouping_flag;
703 705 unsigned short sequence_cnt;
704 706
705 707 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << SHIFT_1_BYTE; // keep bits 7 downto 6
706 708 sequence_cnt = (*packetSequenceControl) & SEQ_CNT_MASK; // [0011 1111 1111 1111]
707 709
708 710 if ( sequence_cnt < SEQ_CNT_MAX)
709 711 {
710 712 sequence_cnt = sequence_cnt + 1;
711 713 }
712 714 else
713 715 {
714 716 sequence_cnt = 0;
715 717 }
716 718
717 719 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
718 720 }
719 721
720 722 void getTime( unsigned char *time)
721 723 {
722 724 /** This function write the current local time in the time buffer passed in argument.
723 725 *
724 726 */
725 727
726 728 time[0] = (unsigned char) (time_management_regs->coarse_time>>SHIFT_3_BYTES);
727 729 time[1] = (unsigned char) (time_management_regs->coarse_time>>SHIFT_2_BYTES);
728 730 time[2] = (unsigned char) (time_management_regs->coarse_time>>SHIFT_1_BYTE);
729 731 time[3] = (unsigned char) (time_management_regs->coarse_time);
730 732 time[4] = (unsigned char) (time_management_regs->fine_time>>SHIFT_1_BYTE);
731 733 time[5] = (unsigned char) (time_management_regs->fine_time);
732 734 }
733 735
734 736 unsigned long long int getTimeAsUnsignedLongLongInt( )
735 737 {
736 738 /** This function write the current local time in the time buffer passed in argument.
737 739 *
738 740 */
739 741 unsigned long long int time;
740 742
741 743 time = ( (unsigned long long int) (time_management_regs->coarse_time & COARSE_TIME_MASK) << SHIFT_2_BYTES )
742 744 + time_management_regs->fine_time;
743 745
744 746 return time;
745 747 }
746 748
747 749 void get_temperatures( unsigned char *temperatures )
748 750 {
749 751 unsigned char* temp_scm_ptr;
750 752 unsigned char* temp_pcb_ptr;
751 753 unsigned char* temp_fpga_ptr;
752 754
753 755 // SEL1 SEL0
754 756 // 0 0 => PCB
755 757 // 0 1 => FPGA
756 758 // 1 0 => SCM
757 759
758 760 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
759 761 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
760 762 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
761 763
762 764 temperatures[ BYTE_0 ] = temp_scm_ptr[ BYTE_2 ];
763 765 temperatures[ BYTE_1 ] = temp_scm_ptr[ BYTE_3 ];
764 766 temperatures[ BYTE_2 ] = temp_pcb_ptr[ BYTE_2 ];
765 767 temperatures[ BYTE_3 ] = temp_pcb_ptr[ BYTE_3 ];
766 768 temperatures[ BYTE_4 ] = temp_fpga_ptr[ BYTE_2 ];
767 769 temperatures[ BYTE_5 ] = temp_fpga_ptr[ BYTE_3 ];
768 770 }
769 771
770 772 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
771 773 {
772 774 unsigned char* v_ptr;
773 775 unsigned char* e1_ptr;
774 776 unsigned char* e2_ptr;
775 777
776 778 v_ptr = (unsigned char *) &hk_lfr_sc_v_f3_as_int16;
777 779 e1_ptr = (unsigned char *) &hk_lfr_sc_e1_f3_as_int16;
778 780 e2_ptr = (unsigned char *) &hk_lfr_sc_e2_f3_as_int16;
779 781
780 782 spacecraft_potential[BYTE_0] = v_ptr[0];
781 783 spacecraft_potential[BYTE_1] = v_ptr[1];
782 784 spacecraft_potential[BYTE_2] = e1_ptr[0];
783 785 spacecraft_potential[BYTE_3] = e1_ptr[1];
784 786 spacecraft_potential[BYTE_4] = e2_ptr[0];
785 787 spacecraft_potential[BYTE_5] = e2_ptr[1];
786 788 }
787 789
788 790 /**
789 791 * @brief get_cpu_load, computes CPU load, CPU load average and CPU load max
790 792 * @param resource_statistics stores:
791 793 * - CPU load at index 0
792 794 * - CPU load max at index 1
793 795 * - CPU load average at index 2
794 796 *
795 797 * The CPU load average is computed on the last 60 values with a simple moving average.
796 798 */
797 799 void get_cpu_load( unsigned char *resource_statistics )
798 800 {
799 801 #define LOAD_AVG_SIZE 60
800 802 static unsigned char cpu_load_hist[LOAD_AVG_SIZE]={0};
801 803 static char old_avg_pos=0;
802 804 static unsigned int cpu_load_avg;
803 805 unsigned char cpu_load;
804 806
805 807 cpu_load = lfr_rtems_cpu_usage_report();
806 808
807 809 // HK_LFR_CPU_LOAD
808 810 resource_statistics[BYTE_0] = cpu_load;
809 811
810 812 // HK_LFR_CPU_LOAD_MAX
811 813 if (cpu_load > resource_statistics[BYTE_1])
812 814 {
813 815 resource_statistics[BYTE_1] = cpu_load;
814 816 }
815 817
816 818 cpu_load_avg = cpu_load_avg - (unsigned int)cpu_load_hist[(int)old_avg_pos] + (unsigned int)cpu_load;
817 819 cpu_load_hist[(int)old_avg_pos] = cpu_load;
818 820 old_avg_pos += 1;
819 821 old_avg_pos %= LOAD_AVG_SIZE;
820 822 // CPU_LOAD_AVE
821 823 resource_statistics[BYTE_2] = (unsigned char)(cpu_load_avg / LOAD_AVG_SIZE);
822 824 // this will change the way LFR compute usage
823 825 #ifndef PRINT_TASK_STATISTICS
824 826 rtems_cpu_usage_reset();
825 827 #endif
826 828
827 829 }
828 830
829 831 void set_hk_lfr_sc_potential_flag( bool state )
830 832 {
831 833 if (state == true)
832 834 {
833 835 housekeeping_packet.lfr_status_word[1] =
834 836 housekeeping_packet.lfr_status_word[1] | STATUS_WORD_SC_POTENTIAL_FLAG_BIT; // [0100 0000]
835 837 }
836 838 else
837 839 {
838 840 housekeeping_packet.lfr_status_word[1] =
839 841 housekeeping_packet.lfr_status_word[1] & STATUS_WORD_SC_POTENTIAL_FLAG_MASK; // [1011 1111]
840 842 }
841 843 }
842 844
843 845 void set_sy_lfr_pas_filter_enabled( bool state )
844 846 {
845 847 if (state == true)
846 848 {
847 849 housekeeping_packet.lfr_status_word[1] =
848 850 housekeeping_packet.lfr_status_word[1] | STATUS_WORD_PAS_FILTER_ENABLED_BIT; // [0010 0000]
849 851 }
850 852 else
851 853 {
852 854 housekeeping_packet.lfr_status_word[1] =
853 855 housekeeping_packet.lfr_status_word[1] & STATUS_WORD_PAS_FILTER_ENABLED_MASK; // [1101 1111]
854 856 }
855 857 }
856 858
857 859 void set_sy_lfr_watchdog_enabled( bool state )
858 860 {
859 861 if (state == true)
860 862 {
861 863 housekeeping_packet.lfr_status_word[1] =
862 864 housekeeping_packet.lfr_status_word[1] | STATUS_WORD_WATCHDOG_BIT; // [0001 0000]
863 865 }
864 866 else
865 867 {
866 868 housekeeping_packet.lfr_status_word[1] =
867 869 housekeeping_packet.lfr_status_word[1] & STATUS_WORD_WATCHDOG_MASK; // [1110 1111]
868 870 }
869 871 }
870 872
871 873 void set_hk_lfr_calib_enable( bool state )
872 874 {
873 875 if (state == true)
874 876 {
875 877 housekeeping_packet.lfr_status_word[1] =
876 878 housekeeping_packet.lfr_status_word[1] | STATUS_WORD_CALIB_BIT; // [0000 1000]
877 879 }
878 880 else
879 881 {
880 882 housekeeping_packet.lfr_status_word[1] =
881 883 housekeeping_packet.lfr_status_word[1] & STATUS_WORD_CALIB_MASK; // [1111 0111]
882 884 }
883 885 }
884 886
885 887 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
886 888 {
887 889 housekeeping_packet.lfr_status_word[1] =
888 890 housekeeping_packet.lfr_status_word[1] & STATUS_WORD_RESET_CAUSE_MASK; // [1111 1000]
889 891
890 892 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
891 893 | (lfr_reset_cause & STATUS_WORD_RESET_CAUSE_BITS ); // [0000 0111]
892 894
893 895 }
894 896
895 897 void increment_hk_counter( unsigned char newValue, unsigned char oldValue, unsigned int *counter )
896 898 {
897 899 int delta;
898 900
899 901 delta = 0;
900 902
901 903 if (newValue >= oldValue)
902 904 {
903 905 delta = newValue - oldValue;
904 906 }
905 907 else
906 908 {
907 909 delta = (CONST_256 - oldValue) + newValue;
908 910 }
909 911
910 912 *counter = *counter + delta;
911 913 }
912 914
913 915 // Low severity error counters update
914 916 void hk_lfr_le_update( void )
915 917 {
916 918 static hk_lfr_le_t old_hk_lfr_le = {0};
917 919 hk_lfr_le_t new_hk_lfr_le;
918 920 unsigned int counter;
919 921
920 922 counter = (((unsigned int) housekeeping_packet.hk_lfr_le_cnt[0]) * CONST_256) + housekeeping_packet.hk_lfr_le_cnt[1];
921 923
922 924 // DPU
923 925 new_hk_lfr_le.dpu_spw_parity = housekeeping_packet.hk_lfr_dpu_spw_parity;
924 926 new_hk_lfr_le.dpu_spw_disconnect= housekeeping_packet.hk_lfr_dpu_spw_disconnect;
925 927 new_hk_lfr_le.dpu_spw_escape = housekeeping_packet.hk_lfr_dpu_spw_escape;
926 928 new_hk_lfr_le.dpu_spw_credit = housekeeping_packet.hk_lfr_dpu_spw_credit;
927 929 new_hk_lfr_le.dpu_spw_write_sync= housekeeping_packet.hk_lfr_dpu_spw_write_sync;
928 930 // TIMECODE
929 931 new_hk_lfr_le.timecode_erroneous= housekeeping_packet.hk_lfr_timecode_erroneous;
930 932 new_hk_lfr_le.timecode_missing = housekeeping_packet.hk_lfr_timecode_missing;
931 933 new_hk_lfr_le.timecode_invalid = housekeeping_packet.hk_lfr_timecode_invalid;
932 934 // TIME
933 935 new_hk_lfr_le.time_timecode_it = housekeeping_packet.hk_lfr_time_timecode_it;
934 936 new_hk_lfr_le.time_not_synchro = housekeeping_packet.hk_lfr_time_not_synchro;
935 937 new_hk_lfr_le.time_timecode_ctr = housekeeping_packet.hk_lfr_time_timecode_ctr;
936 938 //AHB
937 939 new_hk_lfr_le.ahb_correctable = housekeeping_packet.hk_lfr_ahb_correctable;
938 940 // housekeeping_packet.hk_lfr_dpu_spw_rx_ahb => not handled by the grspw driver
939 941 // housekeeping_packet.hk_lfr_dpu_spw_tx_ahb => not handled by the grspw driver
940 942
941 943 // update the le counter
942 944 // DPU
943 945 increment_hk_counter( new_hk_lfr_le.dpu_spw_parity, old_hk_lfr_le.dpu_spw_parity, &counter );
944 946 increment_hk_counter( new_hk_lfr_le.dpu_spw_disconnect,old_hk_lfr_le.dpu_spw_disconnect, &counter );
945 947 increment_hk_counter( new_hk_lfr_le.dpu_spw_escape, old_hk_lfr_le.dpu_spw_escape, &counter );
946 948 increment_hk_counter( new_hk_lfr_le.dpu_spw_credit, old_hk_lfr_le.dpu_spw_credit, &counter );
947 949 increment_hk_counter( new_hk_lfr_le.dpu_spw_write_sync,old_hk_lfr_le.dpu_spw_write_sync, &counter );
948 950 // TIMECODE
949 951 increment_hk_counter( new_hk_lfr_le.timecode_erroneous,old_hk_lfr_le.timecode_erroneous, &counter );
950 952 increment_hk_counter( new_hk_lfr_le.timecode_missing, old_hk_lfr_le.timecode_missing, &counter );
951 953 increment_hk_counter( new_hk_lfr_le.timecode_invalid, old_hk_lfr_le.timecode_invalid, &counter );
952 954 // TIME
953 955 increment_hk_counter( new_hk_lfr_le.time_timecode_it, old_hk_lfr_le.time_timecode_it, &counter );
954 956 increment_hk_counter( new_hk_lfr_le.time_not_synchro, old_hk_lfr_le.time_not_synchro, &counter );
955 957 increment_hk_counter( new_hk_lfr_le.time_timecode_ctr, old_hk_lfr_le.time_timecode_ctr, &counter );
956 958 // AHB
957 959 increment_hk_counter( new_hk_lfr_le.ahb_correctable, old_hk_lfr_le.ahb_correctable, &counter );
958 960
959 961 // DPU
960 962 old_hk_lfr_le.dpu_spw_parity = new_hk_lfr_le.dpu_spw_parity;
961 963 old_hk_lfr_le.dpu_spw_disconnect= new_hk_lfr_le.dpu_spw_disconnect;
962 964 old_hk_lfr_le.dpu_spw_escape = new_hk_lfr_le.dpu_spw_escape;
963 965 old_hk_lfr_le.dpu_spw_credit = new_hk_lfr_le.dpu_spw_credit;
964 966 old_hk_lfr_le.dpu_spw_write_sync= new_hk_lfr_le.dpu_spw_write_sync;
965 967 // TIMECODE
966 968 old_hk_lfr_le.timecode_erroneous= new_hk_lfr_le.timecode_erroneous;
967 969 old_hk_lfr_le.timecode_missing = new_hk_lfr_le.timecode_missing;
968 970 old_hk_lfr_le.timecode_invalid = new_hk_lfr_le.timecode_invalid;
969 971 // TIME
970 972 old_hk_lfr_le.time_timecode_it = new_hk_lfr_le.time_timecode_it;
971 973 old_hk_lfr_le.time_not_synchro = new_hk_lfr_le.time_not_synchro;
972 974 old_hk_lfr_le.time_timecode_ctr = new_hk_lfr_le.time_timecode_ctr;
973 975 //AHB
974 976 old_hk_lfr_le.ahb_correctable = new_hk_lfr_le.ahb_correctable;
975 977 // housekeeping_packet.hk_lfr_dpu_spw_rx_ahb => not handled by the grspw driver
976 978 // housekeeping_packet.hk_lfr_dpu_spw_tx_ahb => not handled by the grspw driver
977 979
978 980 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
979 981 // LE
980 982 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((counter & BYTE0_MASK) >> SHIFT_1_BYTE);
981 983 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (counter & BYTE1_MASK);
982 984 }
983 985
984 986 // Medium severity error counters update
985 987 void hk_lfr_me_update( void )
986 988 {
987 989 static hk_lfr_me_t old_hk_lfr_me = {0};
988 990 hk_lfr_me_t new_hk_lfr_me;
989 991 unsigned int counter;
990 992
991 993 counter = (((unsigned int) housekeeping_packet.hk_lfr_me_cnt[0]) * CONST_256) + housekeeping_packet.hk_lfr_me_cnt[1];
992 994
993 995 // get the current values
994 996 new_hk_lfr_me.dpu_spw_early_eop = housekeeping_packet.hk_lfr_dpu_spw_early_eop;
995 997 new_hk_lfr_me.dpu_spw_invalid_addr = housekeeping_packet.hk_lfr_dpu_spw_invalid_addr;
996 998 new_hk_lfr_me.dpu_spw_eep = housekeeping_packet.hk_lfr_dpu_spw_eep;
997 999 new_hk_lfr_me.dpu_spw_rx_too_big = housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
998 1000
999 1001 // update the me counter
1000 1002 increment_hk_counter( new_hk_lfr_me.dpu_spw_early_eop, old_hk_lfr_me.dpu_spw_early_eop, &counter );
1001 1003 increment_hk_counter( new_hk_lfr_me.dpu_spw_invalid_addr, old_hk_lfr_me.dpu_spw_invalid_addr, &counter );
1002 1004 increment_hk_counter( new_hk_lfr_me.dpu_spw_eep, old_hk_lfr_me.dpu_spw_eep, &counter );
1003 1005 increment_hk_counter( new_hk_lfr_me.dpu_spw_rx_too_big, old_hk_lfr_me.dpu_spw_rx_too_big, &counter );
1004 1006
1005 1007 // store the counters for the next time
1006 1008 old_hk_lfr_me.dpu_spw_early_eop = new_hk_lfr_me.dpu_spw_early_eop;
1007 1009 old_hk_lfr_me.dpu_spw_invalid_addr = new_hk_lfr_me.dpu_spw_invalid_addr;
1008 1010 old_hk_lfr_me.dpu_spw_eep = new_hk_lfr_me.dpu_spw_eep;
1009 1011 old_hk_lfr_me.dpu_spw_rx_too_big = new_hk_lfr_me.dpu_spw_rx_too_big;
1010 1012
1011 1013 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
1012 1014 // ME
1013 1015 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((counter & BYTE0_MASK) >> SHIFT_1_BYTE);
1014 1016 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (counter & BYTE1_MASK);
1015 1017 }
1016 1018
1017 1019 // High severity error counters update
1018 1020 void hk_lfr_le_me_he_update()
1019 1021 {
1020 1022
1021 1023 unsigned int hk_lfr_he_cnt;
1022 1024
1023 1025 hk_lfr_he_cnt = (((unsigned int) housekeeping_packet.hk_lfr_he_cnt[0]) * 256) + housekeeping_packet.hk_lfr_he_cnt[1];
1024 1026
1025 1027 //update the low severity error counter
1026 1028 hk_lfr_le_update( );
1027 1029
1028 1030 //update the medium severity error counter
1029 1031 hk_lfr_me_update();
1030 1032
1031 1033 //update the high severity error counter
1032 1034 hk_lfr_he_cnt = 0;
1033 1035
1034 1036 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
1035 1037 // HE
1036 1038 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & BYTE0_MASK) >> SHIFT_1_BYTE);
1037 1039 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & BYTE1_MASK);
1038 1040
1039 1041 }
1040 1042
1041 1043 void set_hk_lfr_time_not_synchro()
1042 1044 {
1043 1045 static unsigned char synchroLost = 1;
1044 1046 int synchronizationBit;
1045 1047
1046 1048 // get the synchronization bit
1047 1049 synchronizationBit =
1048 1050 (time_management_regs->coarse_time & VAL_LFR_SYNCHRONIZED) >> BIT_SYNCHRONIZATION; // 1000 0000 0000 0000
1049 1051
1050 1052 switch (synchronizationBit)
1051 1053 {
1052 1054 case 0:
1053 1055 if (synchroLost == 1)
1054 1056 {
1055 1057 synchroLost = 0;
1056 1058 }
1057 1059 break;
1058 1060 case 1:
1059 1061 if (synchroLost == 0 )
1060 1062 {
1061 1063 synchroLost = 1;
1062 1064 increase_unsigned_char_counter(&housekeeping_packet.hk_lfr_time_not_synchro);
1063 1065 update_hk_lfr_last_er_fields( RID_LE_LFR_TIME, CODE_NOT_SYNCHRO );
1064 1066 }
1065 1067 break;
1066 1068 default:
1067 1069 PRINTF1("in hk_lfr_time_not_synchro *** unexpected value for synchronizationBit = %d\n", synchronizationBit);
1068 1070 break;
1069 1071 }
1070 1072
1071 1073 }
1072 1074
1073 1075 void set_hk_lfr_ahb_correctable() // CRITICITY L
1074 1076 {
1075 1077 /** This function builds the error counter hk_lfr_ahb_correctable using the statistics provided
1076 1078 * by the Cache Control Register (ASI 2, offset 0) and in the Register Protection Control Register (ASR16) on the
1077 1079 * detected errors in the cache, in the integer unit and in the floating point unit.
1078 1080 *
1079 1081 * @param void
1080 1082 *
1081 1083 * @return void
1082 1084 *
1083 1085 * All errors are summed to set the value of the hk_lfr_ahb_correctable counter.
1084 1086 *
1085 1087 */
1086 1088
1087 1089 unsigned int ahb_correctable;
1088 1090 unsigned int instructionErrorCounter;
1089 1091 unsigned int dataErrorCounter;
1090 1092 unsigned int fprfErrorCounter;
1091 1093 unsigned int iurfErrorCounter;
1092 1094
1093 1095 instructionErrorCounter = 0;
1094 1096 dataErrorCounter = 0;
1095 1097 fprfErrorCounter = 0;
1096 1098 iurfErrorCounter = 0;
1097 1099
1098 1100 CCR_getInstructionAndDataErrorCounters( &instructionErrorCounter, &dataErrorCounter);
1099 1101 ASR16_get_FPRF_IURF_ErrorCounters( &fprfErrorCounter, &iurfErrorCounter);
1100 1102
1101 1103 ahb_correctable = instructionErrorCounter
1102 1104 + dataErrorCounter
1103 1105 + fprfErrorCounter
1104 1106 + iurfErrorCounter
1105 1107 + housekeeping_packet.hk_lfr_ahb_correctable;
1106 1108
1107 1109 housekeeping_packet.hk_lfr_ahb_correctable = (unsigned char) (ahb_correctable & INT8_ALL_F); // [1111 1111]
1108 1110
1109 1111 }
@@ -1,504 +1,500
1 1 /*------------------------------------------------------------------------------
2 2 -- Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3 3 -- This file is a part of the LFR FSW
4 4 -- Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5 5 --
6 6 -- This program is free software; you can redistribute it and/or modify
7 7 -- it under the terms of the GNU General Public License as published by
8 8 -- the Free Software Foundation; either version 2 of the License, or
9 9 -- (at your option) any later version.
10 10 --
11 11 -- This program is distributed in the hope that it will be useful,
12 12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 -- GNU General Public License for more details.
15 15 --
16 16 -- You should have received a copy of the GNU General Public License
17 17 -- along with this program; if not, write to the Free Software
18 18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 -------------------------------------------------------------------------------*/
20 20 /*-- Author : Paul Leroy
21 21 -- Contact : Alexis Jeandet
22 22 -- Mail : alexis.jeandet@lpp.polytechnique.fr
23 23 ----------------------------------------------------------------------------*/
24 24 /** Functions related to TeleCommand acceptance.
25 25 *
26 26 * @file
27 27 * @author P. LEROY
28 28 *
29 29 * A group of functions to handle TeleCommands parsing.\n
30 30 *
31 31 */
32 32
33 33 #include "tc_acceptance.h"
34 34 #include <stdio.h>
35 35
36 36 unsigned int lookUpTableForCRC[CONST_256] = {0};
37 37
38 38 //**********************
39 39 // GENERAL USE FUNCTIONS
40 40 unsigned int Crc_opt( unsigned char D, unsigned int Chk)
41 41 {
42 42 /** This function generate the CRC for one byte and returns the value of the new syndrome.
43 43 *
44 44 * @param D is the current byte of data.
45 45 * @param Chk is the current syndrom value.
46 46 *
47 47 * @return the value of the new syndrome on two bytes.
48 48 *
49 49 */
50 50
51 51 return(((Chk << SHIFT_1_BYTE) & BYTE0_MASK)^lookUpTableForCRC [(((Chk >> SHIFT_1_BYTE)^D) & BYTE1_MASK)]);
52 52 }
53 53
54 54 void initLookUpTableForCRC( void )
55 55 {
56 56 /** This function is used to initiates the look-up table for fast CRC computation.
57 57 *
58 58 * The global table lookUpTableForCRC[256] is initiated.
59 59 *
60 60 */
61 61
62 62 unsigned int i;
63 63 unsigned int tmp;
64 64
65 65 for (i=0; i<CONST_256; i++)
66 66 {
67 67 tmp = 0;
68 68 if((i & BIT_0) != 0) {
69 69 tmp = tmp ^ CONST_CRC_0;
70 70 }
71 71 if((i & BIT_1) != 0) {
72 72 tmp = tmp ^ CONST_CRC_1;
73 73 }
74 74 if((i & BIT_2) != 0) {
75 75 tmp = tmp ^ CONST_CRC_2;
76 76 }
77 77 if((i & BIT_3) != 0) {
78 78 tmp = tmp ^ CONST_CRC_3;
79 79 }
80 80 if((i & BIT_4) != 0) {
81 81 tmp = tmp ^ CONST_CRC_4;
82 82 }
83 83 if((i & BIT_5) != 0) {
84 84 tmp = tmp ^ CONST_CRC_5;
85 85 }
86 86 if((i & BIT_6) != 0) {
87 87 tmp = tmp ^ CONST_CRC_6;
88 88 }
89 89 if((i & BIT_7) != 0) {
90 90 tmp = tmp ^ CONST_CRC_7;
91 91 }
92 92 lookUpTableForCRC[i] = tmp;
93 93 }
94 94 }
95 95
96 96 void GetCRCAsTwoBytes(unsigned char* data, unsigned char* crcAsTwoBytes, unsigned int sizeOfData)
97 97 {
98 98 /** This function calculates a two bytes Cyclic Redundancy Code.
99 99 *
100 100 * @param data points to a buffer containing the data on which to compute the CRC.
101 101 * @param crcAsTwoBytes points points to a two bytes buffer in which the CRC is stored.
102 102 * @param sizeOfData is the number of bytes of *data* used to compute the CRC.
103 103 *
104 104 * The specification of the Cyclic Redundancy Code is described in the following document: ECSS-E-70-41-A.
105 105 *
106 106 */
107 107
108 108 unsigned int Chk;
109 109 int j;
110 110 Chk = CRC_RESET; // reset the syndrom to all ones
111 111 for (j=0; j<sizeOfData; j++) {
112 112 Chk = Crc_opt(data[j], Chk);
113 113 }
114 114 crcAsTwoBytes[0] = (unsigned char) (Chk >> SHIFT_1_BYTE);
115 115 crcAsTwoBytes[1] = (unsigned char) (Chk & BYTE1_MASK);
116 116 }
117 117
118 118 //*********************
119 119 // ACCEPTANCE FUNCTIONS
120 120 int tc_parser(ccsdsTelecommandPacket_t * TCPacket, unsigned int estimatedPacketLength, unsigned char *computed_CRC)
121 121 {
122 122 /** This function parses TeleCommands.
123 123 *
124 124 * @param TC points to the TeleCommand that will be parsed.
125 125 * @param estimatedPacketLength is the PACKET_LENGTH field calculated from the effective length of the received packet.
126 126 *
127 127 * @return Status code of the parsing.
128 128 *
129 129 * The parsing checks:
130 130 * - process id
131 131 * - category
132 132 * - length: a global check is performed and a per subtype check also
133 133 * - type
134 134 * - subtype
135 135 * - crc
136 136 *
137 137 */
138 138
139 139 int status;
140 140 int status_crc;
141 141 unsigned char pid;
142 142 unsigned char category;
143 143 unsigned int packetLength;
144 144 unsigned char packetType;
145 145 unsigned char packetSubtype;
146 146 unsigned char sid;
147 147
148 148 status = CCSDS_TM_VALID;
149 149
150 150 // APID check *** APID on 2 bytes
151 151 pid = ((TCPacket->packetID[0] & BITS_PID_0) << SHIFT_4_BITS)
152 152 + ( (TCPacket->packetID[1] >> SHIFT_4_BITS) & BITS_PID_1 ); // PID = 11 *** 7 bits xxxxx210 7654xxxx
153 153 category = (TCPacket->packetID[1] & BITS_CAT); // PACKET_CATEGORY = 12 *** 4 bits xxxxxxxx xxxx3210
154 154 packetLength = (TCPacket->packetLength[0] * CONST_256) + TCPacket->packetLength[1];
155 155 packetType = TCPacket->serviceType;
156 156 packetSubtype = TCPacket->serviceSubType;
157 157 sid = TCPacket->sourceID;
158 158
159 159 if ( pid != CCSDS_PROCESS_ID ) // CHECK THE PROCESS ID
160 160 {
161 161 status = ILLEGAL_APID;
162 162 }
163 163 if (status == CCSDS_TM_VALID) // CHECK THE CATEGORY
164 164 {
165 165 if ( category != CCSDS_PACKET_CATEGORY )
166 166 {
167 167 status = ILLEGAL_APID;
168 168 }
169 169 }
170 170 if (status == CCSDS_TM_VALID) // CHECK THE PACKET_LENGTH FIELD AND THE ESTIMATED PACKET_LENGTH COMPLIANCE
171 171 {
172 172 if (packetLength != estimatedPacketLength ) {
173 173 status = WRONG_LEN_PKT;
174 174 }
175 175 }
176 176 if (status == CCSDS_TM_VALID) // CHECK THAT THE PACKET DOES NOT EXCEED THE MAX SIZE
177 177 {
178 178 if ( packetLength > CCSDS_TC_PKT_MAX_SIZE ) {
179 179 status = WRONG_LEN_PKT;
180 180 }
181 181 }
182 182 if (status == CCSDS_TM_VALID) // CHECK THE TYPE
183 183 {
184 184 status = tc_check_type( packetType );
185 185 }
186 186 if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE
187 187 {
188 188 status = tc_check_type_subtype( packetType, packetSubtype );
189 189 }
190 190 if (status == CCSDS_TM_VALID) // CHECK THE SID
191 191 {
192 192 status = tc_check_sid( sid );
193 193 }
194 194 if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE AND LENGTH COMPLIANCE
195 195 {
196 196 status = tc_check_length( packetSubtype, packetLength );
197 197 }
198 198 status_crc = tc_check_crc( TCPacket, estimatedPacketLength, computed_CRC );
199 199 if (status == CCSDS_TM_VALID ) // CHECK CRC
200 200 {
201 201 status = status_crc;
202 202 }
203 203
204 204 return status;
205 205 }
206 206
207 207 int tc_check_type( unsigned char packetType )
208 208 {
209 209 /** This function checks that the type of a TeleCommand is valid.
210 210 *
211 211 * @param packetType is the type to check.
212 212 *
213 213 * @return Status code CCSDS_TM_VALID or ILL_TYPE.
214 214 *
215 215 */
216 216
217 217 int status;
218 218
219 219 status = ILL_TYPE;
220 220
221 221 if ( (packetType == TC_TYPE_GEN) || (packetType == TC_TYPE_TIME))
222 222 {
223 223 status = CCSDS_TM_VALID;
224 224 }
225 else
226 {
227 status = ILL_TYPE;
228 }
229 225
230 226 return status;
231 227 }
232 228
233 229 int tc_check_type_subtype( unsigned char packetType, unsigned char packetSubType )
234 230 {
235 231 /** This function checks that the subtype of a TeleCommand is valid and coherent with the type.
236 232 *
237 233 * @param packetType is the type of the TC.
238 234 * @param packetSubType is the subtype to check.
239 235 *
240 236 * @return Status code CCSDS_TM_VALID or ILL_SUBTYPE.
241 237 *
242 238 */
243 239
244 240 int status;
245 241
246 242 switch(packetType)
247 243 {
248 244 case TC_TYPE_GEN:
249 245 if ( (packetSubType == TC_SUBTYPE_RESET)
250 246 || (packetSubType == TC_SUBTYPE_LOAD_COMM)
251 247 || (packetSubType == TC_SUBTYPE_LOAD_NORM) || (packetSubType == TC_SUBTYPE_LOAD_BURST)
252 248 || (packetSubType == TC_SUBTYPE_LOAD_SBM1) || (packetSubType == TC_SUBTYPE_LOAD_SBM2)
253 249 || (packetSubType == TC_SUBTYPE_DUMP)
254 250 || (packetSubType == TC_SUBTYPE_ENTER)
255 251 || (packetSubType == TC_SUBTYPE_UPDT_INFO)
256 252 || (packetSubType == TC_SUBTYPE_EN_CAL) || (packetSubType == TC_SUBTYPE_DIS_CAL)
257 253 || (packetSubType == TC_SUBTYPE_LOAD_K) || (packetSubType == TC_SUBTYPE_DUMP_K)
258 254 || (packetSubType == TC_SUBTYPE_LOAD_FBINS)
259 255 || (packetSubType == TC_SUBTYPE_LOAD_FILTER_PAR))
260 256 {
261 257 status = CCSDS_TM_VALID;
262 258 }
263 259 else
264 260 {
265 261 status = ILL_SUBTYPE;
266 262 }
267 263 break;
268 264
269 265 case TC_TYPE_TIME:
270 266 if (packetSubType == TC_SUBTYPE_UPDT_TIME)
271 267 {
272 268 status = CCSDS_TM_VALID;
273 269 }
274 270 else
275 271 {
276 272 status = ILL_SUBTYPE;
277 273 }
278 274 break;
279 275
280 276 default:
281 277 status = ILL_SUBTYPE;
282 278 break;
283 279 }
284 280
285 281 return status;
286 282 }
287 283
288 284 int tc_check_sid( unsigned char sid )
289 285 {
290 286 /** This function checks that the sid of a TeleCommand is valid.
291 287 *
292 288 * @param sid is the sid to check.
293 289 *
294 290 * @return Status code CCSDS_TM_VALID or CORRUPTED.
295 291 *
296 292 */
297 293
298 294 int status;
299 295
300 296 status = WRONG_SRC_ID;
301 297
302 298 if ( (sid == SID_TC_MISSION_TIMELINE) || (sid == SID_TC_TC_SEQUENCES) || (sid == SID_TC_RECOVERY_ACTION_CMD)
303 299 || (sid == SID_TC_BACKUP_MISSION_TIMELINE)
304 300 || (sid == SID_TC_DIRECT_CMD) || (sid == SID_TC_SPARE_GRD_SRC1) || (sid == SID_TC_SPARE_GRD_SRC2)
305 301 || (sid == SID_TC_OBCP) || (sid == SID_TC_SYSTEM_CONTROL) || (sid == SID_TC_AOCS)
306 302 || (sid == SID_TC_RPW_INTERNAL))
307 303 {
308 304 status = CCSDS_TM_VALID;
309 305 }
310 306 else
311 307 {
312 308 status = WRONG_SRC_ID;
313 309 }
314 310
315 311 return status;
316 312 }
317 313
318 314 int tc_check_length( unsigned char packetSubType, unsigned int length )
319 315 {
320 316 /** This function checks that the subtype and the length are compliant.
321 317 *
322 318 * @param packetSubType is the subtype to check.
323 319 * @param length is the length to check.
324 320 *
325 321 * @return Status code CCSDS_TM_VALID or ILL_TYPE.
326 322 *
327 323 */
328 324
329 325 int status;
330 326
331 327 status = LFR_SUCCESSFUL;
332 328
333 329 switch(packetSubType)
334 330 {
335 331 case TC_SUBTYPE_RESET:
336 332 if (length!=(TC_LEN_RESET-CCSDS_TC_TM_PACKET_OFFSET)) {
337 333 status = WRONG_LEN_PKT;
338 334 }
339 335 else {
340 336 status = CCSDS_TM_VALID;
341 337 }
342 338 break;
343 339 case TC_SUBTYPE_LOAD_COMM:
344 340 if (length!=(TC_LEN_LOAD_COMM-CCSDS_TC_TM_PACKET_OFFSET)) {
345 341 status = WRONG_LEN_PKT;
346 342 }
347 343 else {
348 344 status = CCSDS_TM_VALID;
349 345 }
350 346 break;
351 347 case TC_SUBTYPE_LOAD_NORM:
352 348 if (length!=(TC_LEN_LOAD_NORM-CCSDS_TC_TM_PACKET_OFFSET)) {
353 349 status = WRONG_LEN_PKT;
354 350 }
355 351 else {
356 352 status = CCSDS_TM_VALID;
357 353 }
358 354 break;
359 355 case TC_SUBTYPE_LOAD_BURST:
360 356 if (length!=(TC_LEN_LOAD_BURST-CCSDS_TC_TM_PACKET_OFFSET)) {
361 357 status = WRONG_LEN_PKT;
362 358 }
363 359 else {
364 360 status = CCSDS_TM_VALID;
365 361 }
366 362 break;
367 363 case TC_SUBTYPE_LOAD_SBM1:
368 364 if (length!=(TC_LEN_LOAD_SBM1-CCSDS_TC_TM_PACKET_OFFSET)) {
369 365 status = WRONG_LEN_PKT;
370 366 }
371 367 else {
372 368 status = CCSDS_TM_VALID;
373 369 }
374 370 break;
375 371 case TC_SUBTYPE_LOAD_SBM2:
376 372 if (length!=(TC_LEN_LOAD_SBM2-CCSDS_TC_TM_PACKET_OFFSET)) {
377 373 status = WRONG_LEN_PKT;
378 374 }
379 375 else {
380 376 status = CCSDS_TM_VALID;
381 377 }
382 378 break;
383 379 case TC_SUBTYPE_DUMP:
384 380 if (length!=(TC_LEN_DUMP-CCSDS_TC_TM_PACKET_OFFSET)) {
385 381 status = WRONG_LEN_PKT;
386 382 }
387 383 else {
388 384 status = CCSDS_TM_VALID;
389 385 }
390 386 break;
391 387 case TC_SUBTYPE_ENTER:
392 388 if (length!=(TC_LEN_ENTER-CCSDS_TC_TM_PACKET_OFFSET)) {
393 389 status = WRONG_LEN_PKT;
394 390 }
395 391 else {
396 392 status = CCSDS_TM_VALID;
397 393 }
398 394 break;
399 395 case TC_SUBTYPE_UPDT_INFO:
400 396 if (length!=(TC_LEN_UPDT_INFO-CCSDS_TC_TM_PACKET_OFFSET)) {
401 397 status = WRONG_LEN_PKT;
402 398 }
403 399 else {
404 400 status = CCSDS_TM_VALID;
405 401 }
406 402 break;
407 403 case TC_SUBTYPE_EN_CAL:
408 404 if (length!=(TC_LEN_EN_CAL-CCSDS_TC_TM_PACKET_OFFSET)) {
409 405 status = WRONG_LEN_PKT;
410 406 }
411 407 else {
412 408 status = CCSDS_TM_VALID;
413 409 }
414 410 break;
415 411 case TC_SUBTYPE_DIS_CAL:
416 412 if (length!=(TC_LEN_DIS_CAL-CCSDS_TC_TM_PACKET_OFFSET)) {
417 413 status = WRONG_LEN_PKT;
418 414 }
419 415 else {
420 416 status = CCSDS_TM_VALID;
421 417 }
422 418 break;
423 419 case TC_SUBTYPE_LOAD_K:
424 420 if (length!=(TC_LEN_LOAD_K-CCSDS_TC_TM_PACKET_OFFSET)) {
425 421 status = WRONG_LEN_PKT;
426 422 }
427 423 else {
428 424 status = CCSDS_TM_VALID;
429 425 }
430 426 break;
431 427 case TC_SUBTYPE_DUMP_K:
432 428 if (length!=(TC_LEN_DUMP_K-CCSDS_TC_TM_PACKET_OFFSET)) {
433 429 status = WRONG_LEN_PKT;
434 430 }
435 431 else {
436 432 status = CCSDS_TM_VALID;
437 433 }
438 434 break;
439 435 case TC_SUBTYPE_LOAD_FBINS:
440 436 if (length!=(TC_LEN_LOAD_FBINS-CCSDS_TC_TM_PACKET_OFFSET)) {
441 437 status = WRONG_LEN_PKT;
442 438 }
443 439 else {
444 440 status = CCSDS_TM_VALID;
445 441 }
446 442 break;
447 443 case TC_SUBTYPE_LOAD_FILTER_PAR:
448 444 if (length!=(TC_LEN_LOAD_FILTER_PAR-CCSDS_TC_TM_PACKET_OFFSET)) {
449 445 status = WRONG_LEN_PKT;
450 446 }
451 447 else {
452 448 status = CCSDS_TM_VALID;
453 449 }
454 450 break;
455 451 case TC_SUBTYPE_UPDT_TIME:
456 452 if (length!=(TC_LEN_UPDT_TIME-CCSDS_TC_TM_PACKET_OFFSET)) {
457 453 status = WRONG_LEN_PKT;
458 454 }
459 455 else {
460 456 status = CCSDS_TM_VALID;
461 457 }
462 458 break;
463 459 default: // if the subtype is not a legal value, return ILL_SUBTYPE
464 460 status = ILL_SUBTYPE;
465 461 break ;
466 462 }
467 463
468 464 return status;
469 465 }
470 466
471 467 int tc_check_crc( ccsdsTelecommandPacket_t * TCPacket, unsigned int length, unsigned char *computed_CRC )
472 468 {
473 469 /** This function checks the CRC validity of the corresponding TeleCommand packet.
474 470 *
475 471 * @param TCPacket points to the TeleCommand packet to check.
476 472 * @param length is the length of the TC packet.
477 473 *
478 474 * @return Status code CCSDS_TM_VALID or INCOR_CHECKSUM.
479 475 *
480 476 */
481 477
482 478 int status;
483 479 unsigned char * CCSDSContent;
484 480
485 481 status = INCOR_CHECKSUM;
486 482
487 483 CCSDSContent = (unsigned char*) TCPacket->packetID;
488 484 GetCRCAsTwoBytes(CCSDSContent, computed_CRC, length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC); // 2 CRC bytes removed from the calculation of the CRC
489 485
490 486 if (computed_CRC[0] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC]) {
491 487 status = INCOR_CHECKSUM;
492 488 }
493 489 else if (computed_CRC[1] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET -1]) {
494 490 status = INCOR_CHECKSUM;
495 491 }
496 492 else {
497 493 status = CCSDS_TM_VALID;
498 494 }
499 495
500 496 return status;
501 497 }
502 498
503 499
504 500
@@ -1,1702 +1,1692
1 1 /*------------------------------------------------------------------------------
2 2 -- Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3 3 -- This file is a part of the LFR FSW
4 4 -- Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5 5 --
6 6 -- This program is free software; you can redistribute it and/or modify
7 7 -- it under the terms of the GNU General Public License as published by
8 8 -- the Free Software Foundation; either version 2 of the License, or
9 9 -- (at your option) any later version.
10 10 --
11 11 -- This program is distributed in the hope that it will be useful,
12 12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 -- GNU General Public License for more details.
15 15 --
16 16 -- You should have received a copy of the GNU General Public License
17 17 -- along with this program; if not, write to the Free Software
18 18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 -------------------------------------------------------------------------------*/
20 20 /*-- Author : Paul Leroy
21 21 -- Contact : Alexis Jeandet
22 22 -- Mail : alexis.jeandet@lpp.polytechnique.fr
23 23 ----------------------------------------------------------------------------*/
24 24 /** Functions and tasks related to TeleCommand handling.
25 25 *
26 26 * @file
27 27 * @author P. LEROY
28 28 *
29 29 * A group of functions to handle TeleCommands:\n
30 30 * action launching\n
31 31 * TC parsing\n
32 32 * ...
33 33 *
34 34 */
35 35
36 36 #include "tc_handler.h"
37 37 #include "math.h"
38 38
39 39 //***********
40 40 // RTEMS TASK
41 41
42 42 rtems_task actn_task( rtems_task_argument unused )
43 43 {
44 44 /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
45 45 *
46 46 * @param unused is the starting argument of the RTEMS task
47 47 *
48 48 * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
49 49 * on the incoming TeleCommand.
50 50 *
51 51 */
52 52
53 53 int result;
54 54 rtems_status_code status; // RTEMS status code
55 55 ccsdsTelecommandPacket_t __attribute__((aligned(4))) TC; // TC sent to the ACTN task
56 56 size_t size; // size of the incoming TC packet
57 57 unsigned char subtype; // subtype of the current TC packet
58 58 unsigned char time[BYTES_PER_TIME];
59 59 rtems_id queue_rcv_id;
60 60 rtems_id queue_snd_id;
61 61
62 62 memset(&TC, 0, sizeof(ccsdsTelecommandPacket_t));
63 63 size = 0;
64 64 queue_rcv_id = RTEMS_ID_NONE;
65 65 queue_snd_id = RTEMS_ID_NONE;
66 66
67 67 status = get_message_queue_id_recv( &queue_rcv_id );
68 68 if (status != RTEMS_SUCCESSFUL)
69 69 {
70 70 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
71 71 }
72 72
73 73 status = get_message_queue_id_send( &queue_snd_id );
74 74 if (status != RTEMS_SUCCESSFUL)
75 75 {
76 76 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
77 77 }
78 78
79 79 result = LFR_SUCCESSFUL;
80 80 subtype = 0; // subtype of the current TC packet
81 81
82 82 BOOT_PRINTF("in ACTN *** \n");
83 83
84 84 while(1)
85 85 {
86 86 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
87 87 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
88 88 getTime( time ); // set time to the current time
89 89 if (status!=RTEMS_SUCCESSFUL)
90 90 {
91 91 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
92 92 }
93 93 else
94 94 {
95 95 subtype = TC.serviceSubType;
96 96 switch(subtype)
97 97 {
98 98 case TC_SUBTYPE_RESET:
99 99 result = action_reset( &TC, queue_snd_id, time );
100 100 close_action( &TC, result, queue_snd_id );
101 101 break;
102 102 case TC_SUBTYPE_LOAD_COMM:
103 103 result = action_load_common_par( &TC );
104 104 close_action( &TC, result, queue_snd_id );
105 105 break;
106 106 case TC_SUBTYPE_LOAD_NORM:
107 107 result = action_load_normal_par( &TC, queue_snd_id, time );
108 108 close_action( &TC, result, queue_snd_id );
109 109 break;
110 110 case TC_SUBTYPE_LOAD_BURST:
111 111 result = action_load_burst_par( &TC, queue_snd_id, time );
112 112 close_action( &TC, result, queue_snd_id );
113 113 break;
114 114 case TC_SUBTYPE_LOAD_SBM1:
115 115 result = action_load_sbm1_par( &TC, queue_snd_id, time );
116 116 close_action( &TC, result, queue_snd_id );
117 117 break;
118 118 case TC_SUBTYPE_LOAD_SBM2:
119 119 result = action_load_sbm2_par( &TC, queue_snd_id, time );
120 120 close_action( &TC, result, queue_snd_id );
121 121 break;
122 122 case TC_SUBTYPE_DUMP:
123 123 result = action_dump_par( &TC, queue_snd_id );
124 124 close_action( &TC, result, queue_snd_id );
125 125 break;
126 126 case TC_SUBTYPE_ENTER:
127 127 result = action_enter_mode( &TC, queue_snd_id );
128 128 close_action( &TC, result, queue_snd_id );
129 129 break;
130 130 case TC_SUBTYPE_UPDT_INFO:
131 131 result = action_update_info( &TC, queue_snd_id );
132 132 close_action( &TC, result, queue_snd_id );
133 133 break;
134 134 case TC_SUBTYPE_EN_CAL:
135 135 result = action_enable_calibration( &TC, queue_snd_id, time );
136 136 close_action( &TC, result, queue_snd_id );
137 137 break;
138 138 case TC_SUBTYPE_DIS_CAL:
139 139 result = action_disable_calibration( &TC, queue_snd_id, time );
140 140 close_action( &TC, result, queue_snd_id );
141 141 break;
142 142 case TC_SUBTYPE_LOAD_K:
143 143 result = action_load_kcoefficients( &TC, queue_snd_id, time );
144 144 close_action( &TC, result, queue_snd_id );
145 145 break;
146 146 case TC_SUBTYPE_DUMP_K:
147 147 result = action_dump_kcoefficients( &TC, queue_snd_id, time );
148 148 close_action( &TC, result, queue_snd_id );
149 149 break;
150 150 case TC_SUBTYPE_LOAD_FBINS:
151 151 result = action_load_fbins_mask( &TC, queue_snd_id, time );
152 152 close_action( &TC, result, queue_snd_id );
153 153 break;
154 154 case TC_SUBTYPE_LOAD_FILTER_PAR:
155 155 result = action_load_filter_par( &TC, queue_snd_id, time );
156 156 close_action( &TC, result, queue_snd_id );
157 157 break;
158 158 case TC_SUBTYPE_UPDT_TIME:
159 159 result = action_update_time( &TC );
160 160 close_action( &TC, result, queue_snd_id );
161 161 break;
162 162 default:
163 163 break;
164 164 }
165 165 }
166 166 }
167 167 }
168 168
169 169 //***********
170 170 // TC ACTIONS
171 171
172 172 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
173 173 {
174 174 /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
175 175 *
176 176 * @param TC points to the TeleCommand packet that is being processed
177 177 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
178 178 *
179 179 */
180 180
181 181 PRINTF("this is the end!!!\n");
182 182 #ifdef GCOV_ENABLED
183 183 #ifndef GCOV_USE_EXIT
184 184 extern void gcov_exit (void);
185 185 gcov_exit();
186 186 #endif
187 187 #endif
188 188 exit(0);
189 189
190 190 send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
191 191
192 192 return LFR_DEFAULT;
193 193 }
194 194
195 195 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
196 196 {
197 197 /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
198 198 *
199 199 * @param TC points to the TeleCommand packet that is being processed
200 200 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
201 201 *
202 202 */
203 203
204 204 rtems_status_code status;
205 205 unsigned char requestedMode;
206 206 unsigned int transitionCoarseTime;
207 207 unsigned char * bytePosPtr;
208 208
209 209 bytePosPtr = (unsigned char *) &TC->packetID;
210 210 requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
211 211 copyInt32ByChar( (char*) &transitionCoarseTime, &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
212 212 transitionCoarseTime = transitionCoarseTime & COARSE_TIME_MASK;
213 213 status = check_mode_value( requestedMode );
214 214
215 215 if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent
216 216 {
217 217 send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
218 218 }
219 219
220 220 else // the mode value is valid, check the transition
221 221 {
222 222 status = check_mode_transition(requestedMode);
223 223 if (status != LFR_SUCCESSFUL)
224 224 {
225 225 PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
226 226 send_tm_lfr_tc_exe_not_executable( TC, queue_id );
227 227 }
228 228 }
229 229
230 230 if ( status == LFR_SUCCESSFUL ) // the transition is valid, check the date
231 231 {
232 232 status = check_transition_date( transitionCoarseTime );
233 233 if (status != LFR_SUCCESSFUL)
234 234 {
235 235 PRINTF("ERR *** in action_enter_mode *** check_transition_date\n");
236 236 send_tm_lfr_tc_exe_not_executable(TC, queue_id );
237 237 }
238 238 }
239 239
240 240 if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode
241 241 {
242 242 PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
243 243
244 244 switch(requestedMode)
245 245 {
246 246 case LFR_MODE_STANDBY:
247 247 status = enter_mode_standby();
248 248 break;
249 249 case LFR_MODE_NORMAL:
250 250 status = enter_mode_normal( transitionCoarseTime );
251 251 break;
252 252 case LFR_MODE_BURST:
253 253 status = enter_mode_burst( transitionCoarseTime );
254 254 break;
255 255 case LFR_MODE_SBM1:
256 256 status = enter_mode_sbm1( transitionCoarseTime );
257 257 break;
258 258 case LFR_MODE_SBM2:
259 259 status = enter_mode_sbm2( transitionCoarseTime );
260 260 break;
261 261 default:
262 262 break;
263 263 }
264 264
265 265 if (status != RTEMS_SUCCESSFUL)
266 266 {
267 267 status = LFR_EXE_ERROR;
268 268 }
269 269 }
270 270
271 271 return status;
272 272 }
273 273
274 274 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
275 275 {
276 276 /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
277 277 *
278 278 * @param TC points to the TeleCommand packet that is being processed
279 279 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
280 280 *
281 281 * @return LFR directive status code:
282 282 * - LFR_DEFAULT
283 283 * - LFR_SUCCESSFUL
284 284 *
285 285 */
286 286
287 287 unsigned int val;
288 288 unsigned int status;
289 289 unsigned char mode;
290 290 unsigned char * bytePosPtr;
291 291 int pos;
292 292 float value;
293 293
294 294 pos = INIT_CHAR;
295 295 value = INIT_FLOAT;
296 296
297 297 status = LFR_DEFAULT;
298 298
299 299 bytePosPtr = (unsigned char *) &TC->packetID;
300 300
301 301 // check LFR mode
302 302 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & BITS_LFR_MODE) >> SHIFT_LFR_MODE;
303 303 status = check_update_info_hk_lfr_mode( mode );
304 304 if (status == LFR_SUCCESSFUL) // check TDS mode
305 305 {
306 306 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_TDS_MODE) >> SHIFT_TDS_MODE;
307 307 status = check_update_info_hk_tds_mode( mode );
308 308 }
309 309 if (status == LFR_SUCCESSFUL) // check THR mode
310 310 {
311 311 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & BITS_THR_MODE);
312 312 status = check_update_info_hk_thr_mode( mode );
313 313 }
314 314 if (status == LFR_SUCCESSFUL) // check reaction wheels frequencies
315 315 {
316 316 status = check_all_sy_lfr_rw_f(TC, &pos, &value);
317 317 }
318 318
319 319 // if the parameters checking succeeds, udpate all parameters
320 320 if (status == LFR_SUCCESSFUL)
321 321 {
322 322 // pa_bia_status_info
323 323 // => pa_bia_mode_mux_set 3 bits
324 324 // => pa_bia_mode_hv_enabled 1 bit
325 325 // => pa_bia_mode_bias1_enabled 1 bit
326 326 // => pa_bia_mode_bias2_enabled 1 bit
327 327 // => pa_bia_mode_bias3_enabled 1 bit
328 328 // => pa_bia_on_off (cp_dpu_bias_on_off)
329 329 pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & BITS_BIA; // [1111 1110]
330 330 pa_bia_status_info = pa_bia_status_info
331 331 | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 1);
332 332
333 333 // REACTION_WHEELS_FREQUENCY, copy the incoming parameters in the local variable (to be copied in HK packets)
334 334 getReactionWheelsFrequencies( TC );
335 335 set_hk_lfr_sc_rw_f_flags();
336 336 build_sy_lfr_rw_masks();
337 337
338 338 // once the masks are built, they have to be merged with the fbins_mask
339 339 merge_fbins_masks();
340 340
341 341 // increase the TC_LFR_UPDATE_INFO counter
342 342 if (status == LFR_SUCCESSFUL) // if the parameter check is successful
343 343 {
344 344 val = (housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * CONST_256)
345 345 + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
346 346 val++;
347 347 housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
348 348 housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
349 349 }
350 350 }
351 351
352 352 return status;
353 353 }
354 354
355 355 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
356 356 {
357 357 /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
358 358 *
359 359 * @param TC points to the TeleCommand packet that is being processed
360 360 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
361 361 *
362 362 */
363 363
364 364 int result;
365 365
366 366 result = LFR_DEFAULT;
367 367
368 368 setCalibration( true );
369 369
370 370 result = LFR_SUCCESSFUL;
371 371
372 372 return result;
373 373 }
374 374
375 375 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
376 376 {
377 377 /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
378 378 *
379 379 * @param TC points to the TeleCommand packet that is being processed
380 380 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
381 381 *
382 382 */
383 383
384 384 int result;
385 385
386 386 result = LFR_DEFAULT;
387 387
388 388 setCalibration( false );
389 389
390 390 result = LFR_SUCCESSFUL;
391 391
392 392 return result;
393 393 }
394 394
395 395 int action_update_time(ccsdsTelecommandPacket_t *TC)
396 396 {
397 397 /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
398 398 *
399 399 * @param TC points to the TeleCommand packet that is being processed
400 400 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
401 401 *
402 402 * @return LFR_SUCCESSFUL
403 403 *
404 404 */
405 405
406 406 unsigned int val;
407 407
408 408 time_management_regs->coarse_time_load = (TC->dataAndCRC[BYTE_0] << SHIFT_3_BYTES)
409 409 + (TC->dataAndCRC[BYTE_1] << SHIFT_2_BYTES)
410 410 + (TC->dataAndCRC[BYTE_2] << SHIFT_1_BYTE)
411 411 + TC->dataAndCRC[BYTE_3];
412 412
413 413 val = (housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * CONST_256)
414 414 + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
415 415 val++;
416 416 housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
417 417 housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
418 418
419 419 oneTcLfrUpdateTimeReceived = 1;
420 420
421 421 return LFR_SUCCESSFUL;
422 422 }
423 423
424 424 //*******************
425 425 // ENTERING THE MODES
426 426 int check_mode_value( unsigned char requestedMode )
427 427 {
428 428 int status;
429 429
430 430 status = LFR_DEFAULT;
431 431
432 432 if ( (requestedMode != LFR_MODE_STANDBY)
433 433 && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
434 434 && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
435 435 {
436 436 status = LFR_DEFAULT;
437 437 }
438 438 else
439 439 {
440 440 status = LFR_SUCCESSFUL;
441 441 }
442 442
443 443 return status;
444 444 }
445 445
446 446 int check_mode_transition( unsigned char requestedMode )
447 447 {
448 448 /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
449 449 *
450 450 * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
451 451 *
452 452 * @return LFR directive status codes:
453 453 * - LFR_SUCCESSFUL - the transition is authorized
454 454 * - LFR_DEFAULT - the transition is not authorized
455 455 *
456 456 */
457 457
458 458 int status;
459 459
460 460 switch (requestedMode)
461 461 {
462 462 case LFR_MODE_STANDBY:
463 463 if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
464 464 status = LFR_DEFAULT;
465 465 }
466 466 else
467 467 {
468 468 status = LFR_SUCCESSFUL;
469 469 }
470 470 break;
471 471 case LFR_MODE_NORMAL:
472 472 if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
473 473 status = LFR_DEFAULT;
474 474 }
475 475 else {
476 476 status = LFR_SUCCESSFUL;
477 477 }
478 478 break;
479 479 case LFR_MODE_BURST:
480 480 if ( lfrCurrentMode == LFR_MODE_BURST ) {
481 481 status = LFR_DEFAULT;
482 482 }
483 483 else {
484 484 status = LFR_SUCCESSFUL;
485 485 }
486 486 break;
487 487 case LFR_MODE_SBM1:
488 488 if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
489 489 status = LFR_DEFAULT;
490 490 }
491 491 else {
492 492 status = LFR_SUCCESSFUL;
493 493 }
494 494 break;
495 495 case LFR_MODE_SBM2:
496 496 if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
497 497 status = LFR_DEFAULT;
498 498 }
499 499 else {
500 500 status = LFR_SUCCESSFUL;
501 501 }
502 502 break;
503 503 default:
504 504 status = LFR_DEFAULT;
505 505 break;
506 506 }
507 507
508 508 return status;
509 509 }
510 510
511 511 void update_last_valid_transition_date( unsigned int transitionCoarseTime )
512 512 {
513 513 if (transitionCoarseTime == 0)
514 514 {
515 515 lastValidEnterModeTime = time_management_regs->coarse_time + 1;
516 516 PRINTF1("lastValidEnterModeTime = 0x%x (transitionCoarseTime = 0 => coarse_time+1)\n", lastValidEnterModeTime);
517 517 }
518 518 else
519 519 {
520 520 lastValidEnterModeTime = transitionCoarseTime;
521 521 PRINTF1("lastValidEnterModeTime = 0x%x\n", transitionCoarseTime);
522 522 }
523 523 }
524 524
525 525 int check_transition_date( unsigned int transitionCoarseTime )
526 526 {
527 527 int status;
528 528 unsigned int localCoarseTime;
529 529 unsigned int deltaCoarseTime;
530 530
531 531 status = LFR_SUCCESSFUL;
532 532
533 533 if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
534 534 {
535 535 status = LFR_SUCCESSFUL;
536 536 }
537 537 else
538 538 {
539 539 localCoarseTime = time_management_regs->coarse_time & COARSE_TIME_MASK;
540 540
541 541 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
542 542
543 543 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
544 544 {
545 545 status = LFR_DEFAULT;
546 546 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
547 547 }
548 548
549 549 if (status == LFR_SUCCESSFUL)
550 550 {
551 551 deltaCoarseTime = transitionCoarseTime - localCoarseTime;
552 552 if ( deltaCoarseTime > MAX_DELTA_COARSE_TIME ) // SSS-CP-EQS-323
553 553 {
554 554 status = LFR_DEFAULT;
555 555 PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
556 556 }
557 557 }
558 558 }
559 559
560 560 return status;
561 561 }
562 562
563 563 int restart_asm_activities( unsigned char lfrRequestedMode )
564 564 {
565 565 rtems_status_code status;
566 566
567 567 status = stop_spectral_matrices();
568 568
569 569 thisIsAnASMRestart = 1;
570 570
571 571 status = restart_asm_tasks( lfrRequestedMode );
572 572
573 573 launch_spectral_matrix();
574 574
575 575 return status;
576 576 }
577 577
578 578 int stop_spectral_matrices( void )
579 579 {
580 580 /** This function stops and restarts the current mode average spectral matrices activities.
581 581 *
582 582 * @return RTEMS directive status codes:
583 583 * - RTEMS_SUCCESSFUL - task restarted successfully
584 584 * - RTEMS_INVALID_ID - task id invalid
585 585 * - RTEMS_ALREADY_SUSPENDED - task already suspended
586 586 *
587 587 */
588 588
589 589 rtems_status_code status;
590 590
591 591 status = RTEMS_SUCCESSFUL;
592 592
593 593 // (1) mask interruptions
594 594 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // mask spectral matrix interrupt
595 595
596 596 // (2) reset spectral matrices registers
597 597 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
598 598 reset_sm_status();
599 599
600 600 // (3) clear interruptions
601 601 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
602 602
603 603 // suspend several tasks
604 604 if (lfrCurrentMode != LFR_MODE_STANDBY) {
605 605 status = suspend_asm_tasks();
606 606 }
607 607
608 608 if (status != RTEMS_SUCCESSFUL)
609 609 {
610 610 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
611 611 }
612 612
613 613 return status;
614 614 }
615 615
616 616 int stop_current_mode( void )
617 617 {
618 618 /** This function stops the current mode by masking interrupt lines and suspending science tasks.
619 619 *
620 620 * @return RTEMS directive status codes:
621 621 * - RTEMS_SUCCESSFUL - task restarted successfully
622 622 * - RTEMS_INVALID_ID - task id invalid
623 623 * - RTEMS_ALREADY_SUSPENDED - task already suspended
624 624 *
625 625 */
626 626
627 627 rtems_status_code status;
628 628
629 629 status = RTEMS_SUCCESSFUL;
630 630
631 631 // (1) mask interruptions
632 632 LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt
633 633 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
634 634
635 635 // (2) reset waveform picker registers
636 636 reset_wfp_burst_enable(); // reset burst and enable bits
637 637 reset_wfp_status(); // reset all the status bits
638 638
639 639 // (3) reset spectral matrices registers
640 640 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
641 641 reset_sm_status();
642 642
643 643 // reset lfr VHDL module
644 644 reset_lfr();
645 645
646 646 reset_extractSWF(); // reset the extractSWF flag to false
647 647
648 648 // (4) clear interruptions
649 649 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt
650 650 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
651 651
652 652 // suspend several tasks
653 653 if (lfrCurrentMode != LFR_MODE_STANDBY) {
654 654 status = suspend_science_tasks();
655 655 }
656 656
657 657 if (status != RTEMS_SUCCESSFUL)
658 658 {
659 659 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
660 660 }
661 661
662 662 return status;
663 663 }
664 664
665 665 int enter_mode_standby( void )
666 666 {
667 667 /** This function is used to put LFR in the STANDBY mode.
668 668 *
669 669 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
670 670 *
671 671 * @return RTEMS directive status codes:
672 672 * - RTEMS_SUCCESSFUL - task restarted successfully
673 673 * - RTEMS_INVALID_ID - task id invalid
674 674 * - RTEMS_INCORRECT_STATE - task never started
675 675 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
676 676 *
677 677 * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
678 678 * is immediate.
679 679 *
680 680 */
681 681
682 682 int status;
683 683
684 684 status = stop_current_mode(); // STOP THE CURRENT MODE
685 685
686 686 #ifdef PRINT_TASK_STATISTICS
687 687 rtems_cpu_usage_report();
688 688 #endif
689 689
690 690 #ifdef PRINT_STACK_REPORT
691 691 PRINTF("stack report selected\n")
692 692 rtems_stack_checker_report_usage();
693 693 #endif
694 694
695 695 return status;
696 696 }
697 697
698 698 int enter_mode_normal( unsigned int transitionCoarseTime )
699 699 {
700 700 /** This function is used to start the NORMAL mode.
701 701 *
702 702 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
703 703 *
704 704 * @return RTEMS directive status codes:
705 705 * - RTEMS_SUCCESSFUL - task restarted successfully
706 706 * - RTEMS_INVALID_ID - task id invalid
707 707 * - RTEMS_INCORRECT_STATE - task never started
708 708 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
709 709 *
710 710 * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
711 711 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
712 712 *
713 713 */
714 714
715 715 int status;
716 716
717 717 #ifdef PRINT_TASK_STATISTICS
718 718 rtems_cpu_usage_reset();
719 719 #endif
720 720
721 721 status = RTEMS_UNSATISFIED;
722 722
723 723 switch( lfrCurrentMode )
724 724 {
725 725 case LFR_MODE_STANDBY:
726 726 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
727 727 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
728 728 {
729 729 launch_spectral_matrix( );
730 730 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
731 731 }
732 732 break;
733 733 case LFR_MODE_BURST:
734 734 status = stop_current_mode(); // stop the current mode
735 735 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
736 736 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
737 737 {
738 738 launch_spectral_matrix( );
739 739 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
740 740 }
741 741 break;
742 742 case LFR_MODE_SBM1:
743 743 status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
744 744 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
745 745 update_last_valid_transition_date( transitionCoarseTime );
746 746 break;
747 747 case LFR_MODE_SBM2:
748 748 status = restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
749 749 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
750 750 update_last_valid_transition_date( transitionCoarseTime );
751 751 break;
752 752 default:
753 753 break;
754 754 }
755 755
756 756 if (status != RTEMS_SUCCESSFUL)
757 757 {
758 758 PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
759 759 status = RTEMS_UNSATISFIED;
760 760 }
761 761
762 762 return status;
763 763 }
764 764
765 765 int enter_mode_burst( unsigned int transitionCoarseTime )
766 766 {
767 767 /** This function is used to start the BURST mode.
768 768 *
769 769 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
770 770 *
771 771 * @return RTEMS directive status codes:
772 772 * - RTEMS_SUCCESSFUL - task restarted successfully
773 773 * - RTEMS_INVALID_ID - task id invalid
774 774 * - RTEMS_INCORRECT_STATE - task never started
775 775 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
776 776 *
777 777 * The way the BURST mode is started does not depend on the LFR current mode.
778 778 *
779 779 */
780 780
781 781
782 782 int status;
783 783
784 784 #ifdef PRINT_TASK_STATISTICS
785 785 rtems_cpu_usage_reset();
786 786 #endif
787 787
788 788 status = stop_current_mode(); // stop the current mode
789 789 status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
790 790 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
791 791 {
792 792 launch_spectral_matrix( );
793 793 launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
794 794 }
795 795
796 796 if (status != RTEMS_SUCCESSFUL)
797 797 {
798 798 PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
799 799 status = RTEMS_UNSATISFIED;
800 800 }
801 801
802 802 return status;
803 803 }
804 804
805 805 int enter_mode_sbm1( unsigned int transitionCoarseTime )
806 806 {
807 807 /** This function is used to start the SBM1 mode.
808 808 *
809 809 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
810 810 *
811 811 * @return RTEMS directive status codes:
812 812 * - RTEMS_SUCCESSFUL - task restarted successfully
813 813 * - RTEMS_INVALID_ID - task id invalid
814 814 * - RTEMS_INCORRECT_STATE - task never started
815 815 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
816 816 *
817 817 * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
818 818 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
819 819 * cases, the acquisition is completely restarted.
820 820 *
821 821 */
822 822
823 823 int status;
824 824
825 825 #ifdef PRINT_TASK_STATISTICS
826 826 rtems_cpu_usage_reset();
827 827 #endif
828 828
829 829 status = RTEMS_UNSATISFIED;
830 830
831 831 switch( lfrCurrentMode )
832 832 {
833 833 case LFR_MODE_STANDBY:
834 834 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
835 835 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
836 836 {
837 837 launch_spectral_matrix( );
838 838 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
839 839 }
840 840 break;
841 841 case LFR_MODE_NORMAL: // lfrCurrentMode will be updated after the execution of close_action
842 842 status = restart_asm_activities( LFR_MODE_SBM1 );
843 843 status = LFR_SUCCESSFUL;
844 844 update_last_valid_transition_date( transitionCoarseTime );
845 845 break;
846 846 case LFR_MODE_BURST:
847 847 status = stop_current_mode(); // stop the current mode
848 848 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
849 849 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
850 850 {
851 851 launch_spectral_matrix( );
852 852 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
853 853 }
854 854 break;
855 855 case LFR_MODE_SBM2:
856 856 status = restart_asm_activities( LFR_MODE_SBM1 );
857 857 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
858 858 update_last_valid_transition_date( transitionCoarseTime );
859 859 break;
860 860 default:
861 861 break;
862 862 }
863 863
864 864 if (status != RTEMS_SUCCESSFUL)
865 865 {
866 866 PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status);
867 867 status = RTEMS_UNSATISFIED;
868 868 }
869 869
870 870 return status;
871 871 }
872 872
873 873 int enter_mode_sbm2( unsigned int transitionCoarseTime )
874 874 {
875 875 /** This function is used to start the SBM2 mode.
876 876 *
877 877 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
878 878 *
879 879 * @return RTEMS directive status codes:
880 880 * - RTEMS_SUCCESSFUL - task restarted successfully
881 881 * - RTEMS_INVALID_ID - task id invalid
882 882 * - RTEMS_INCORRECT_STATE - task never started
883 883 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
884 884 *
885 885 * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
886 886 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
887 887 * cases, the acquisition is completely restarted.
888 888 *
889 889 */
890 890
891 891 int status;
892 892
893 893 #ifdef PRINT_TASK_STATISTICS
894 894 rtems_cpu_usage_reset();
895 895 #endif
896 896
897 897 status = RTEMS_UNSATISFIED;
898 898
899 899 switch( lfrCurrentMode )
900 900 {
901 901 case LFR_MODE_STANDBY:
902 902 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
903 903 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
904 904 {
905 905 launch_spectral_matrix( );
906 906 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
907 907 }
908 908 break;
909 909 case LFR_MODE_NORMAL:
910 910 status = restart_asm_activities( LFR_MODE_SBM2 );
911 911 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
912 912 update_last_valid_transition_date( transitionCoarseTime );
913 913 break;
914 914 case LFR_MODE_BURST:
915 915 status = stop_current_mode(); // stop the current mode
916 916 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
917 917 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
918 918 {
919 919 launch_spectral_matrix( );
920 920 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
921 921 }
922 922 break;
923 923 case LFR_MODE_SBM1:
924 924 status = restart_asm_activities( LFR_MODE_SBM2 );
925 925 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
926 926 update_last_valid_transition_date( transitionCoarseTime );
927 927 break;
928 928 default:
929 929 break;
930 930 }
931 931
932 932 if (status != RTEMS_SUCCESSFUL)
933 933 {
934 934 PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
935 935 status = RTEMS_UNSATISFIED;
936 936 }
937 937
938 938 return status;
939 939 }
940 940
941 941 int restart_science_tasks( unsigned char lfrRequestedMode )
942 942 {
943 943 /** This function is used to restart all science tasks.
944 944 *
945 945 * @return RTEMS directive status codes:
946 946 * - RTEMS_SUCCESSFUL - task restarted successfully
947 947 * - RTEMS_INVALID_ID - task id invalid
948 948 * - RTEMS_INCORRECT_STATE - task never started
949 949 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
950 950 *
951 951 * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
952 952 *
953 953 */
954 954
955 955 rtems_status_code status[NB_SCIENCE_TASKS];
956 956 rtems_status_code ret;
957 957
958 958 ret = RTEMS_SUCCESSFUL;
959 959
960 960 status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
961 961 if (status[STATUS_0] != RTEMS_SUCCESSFUL)
962 962 {
963 963 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
964 964 }
965 965
966 966 status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
967 967 if (status[STATUS_1] != RTEMS_SUCCESSFUL)
968 968 {
969 969 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
970 970 }
971 971
972 972 status[STATUS_2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
973 973 if (status[STATUS_2] != RTEMS_SUCCESSFUL)
974 974 {
975 975 PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[STATUS_2])
976 976 }
977 977
978 978 status[STATUS_3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
979 979 if (status[STATUS_3] != RTEMS_SUCCESSFUL)
980 980 {
981 981 PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[STATUS_3])
982 982 }
983 983
984 984 status[STATUS_4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
985 985 if (status[STATUS_4] != RTEMS_SUCCESSFUL)
986 986 {
987 987 PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[STATUS_4])
988 988 }
989 989
990 990 status[STATUS_5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
991 991 if (status[STATUS_5] != RTEMS_SUCCESSFUL)
992 992 {
993 993 PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[STATUS_5])
994 994 }
995 995
996 996 status[STATUS_6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
997 997 if (status[STATUS_6] != RTEMS_SUCCESSFUL)
998 998 {
999 999 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_6])
1000 1000 }
1001 1001
1002 1002 status[STATUS_7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1003 1003 if (status[STATUS_7] != RTEMS_SUCCESSFUL)
1004 1004 {
1005 1005 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_7])
1006 1006 }
1007 1007
1008 1008 status[STATUS_8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1009 1009 if (status[STATUS_8] != RTEMS_SUCCESSFUL)
1010 1010 {
1011 1011 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_8])
1012 1012 }
1013 1013
1014 1014 status[STATUS_9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1015 1015 if (status[STATUS_9] != RTEMS_SUCCESSFUL)
1016 1016 {
1017 1017 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_9])
1018 1018 }
1019 1019
1020 1020 if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1021 1021 (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1022 1022 (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) ||
1023 1023 (status[STATUS_6] != RTEMS_SUCCESSFUL) || (status[STATUS_7] != RTEMS_SUCCESSFUL) ||
1024 1024 (status[STATUS_8] != RTEMS_SUCCESSFUL) || (status[STATUS_9] != RTEMS_SUCCESSFUL) )
1025 1025 {
1026 1026 ret = RTEMS_UNSATISFIED;
1027 1027 }
1028 1028
1029 1029 return ret;
1030 1030 }
1031 1031
1032 1032 int restart_asm_tasks( unsigned char lfrRequestedMode )
1033 1033 {
1034 1034 /** This function is used to restart average spectral matrices tasks.
1035 1035 *
1036 1036 * @return RTEMS directive status codes:
1037 1037 * - RTEMS_SUCCESSFUL - task restarted successfully
1038 1038 * - RTEMS_INVALID_ID - task id invalid
1039 1039 * - RTEMS_INCORRECT_STATE - task never started
1040 1040 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
1041 1041 *
1042 1042 * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
1043 1043 *
1044 1044 */
1045 1045
1046 1046 rtems_status_code status[NB_ASM_TASKS];
1047 1047 rtems_status_code ret;
1048 1048
1049 1049 ret = RTEMS_SUCCESSFUL;
1050 1050
1051 1051 status[STATUS_0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
1052 1052 if (status[STATUS_0] != RTEMS_SUCCESSFUL)
1053 1053 {
1054 1054 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[STATUS_0])
1055 1055 }
1056 1056
1057 1057 status[STATUS_1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
1058 1058 if (status[STATUS_1] != RTEMS_SUCCESSFUL)
1059 1059 {
1060 1060 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[STATUS_1])
1061 1061 }
1062 1062
1063 1063 status[STATUS_2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
1064 1064 if (status[STATUS_2] != RTEMS_SUCCESSFUL)
1065 1065 {
1066 1066 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[STATUS_2])
1067 1067 }
1068 1068
1069 1069 status[STATUS_3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
1070 1070 if (status[STATUS_3] != RTEMS_SUCCESSFUL)
1071 1071 {
1072 1072 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[STATUS_3])
1073 1073 }
1074 1074
1075 1075 status[STATUS_4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
1076 1076 if (status[STATUS_4] != RTEMS_SUCCESSFUL)
1077 1077 {
1078 1078 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[STATUS_4])
1079 1079 }
1080 1080
1081 1081 status[STATUS_5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1082 1082 if (status[STATUS_5] != RTEMS_SUCCESSFUL)
1083 1083 {
1084 1084 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[STATUS_5])
1085 1085 }
1086 1086
1087 1087 if ( (status[STATUS_0] != RTEMS_SUCCESSFUL) || (status[STATUS_1] != RTEMS_SUCCESSFUL) ||
1088 1088 (status[STATUS_2] != RTEMS_SUCCESSFUL) || (status[STATUS_3] != RTEMS_SUCCESSFUL) ||
1089 1089 (status[STATUS_4] != RTEMS_SUCCESSFUL) || (status[STATUS_5] != RTEMS_SUCCESSFUL) )
1090 1090 {
1091 1091 ret = RTEMS_UNSATISFIED;
1092 1092 }
1093 1093
1094 1094 return ret;
1095 1095 }
1096 1096
1097 1097 int suspend_science_tasks( void )
1098 1098 {
1099 1099 /** This function suspends the science tasks.
1100 1100 *
1101 1101 * @return RTEMS directive status codes:
1102 1102 * - RTEMS_SUCCESSFUL - task restarted successfully
1103 1103 * - RTEMS_INVALID_ID - task id invalid
1104 1104 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1105 1105 *
1106 1106 */
1107 1107
1108 1108 rtems_status_code status;
1109 1109
1110 1110 PRINTF("in suspend_science_tasks\n")
1111 1111
1112 1112 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1113 1113 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1114 1114 {
1115 1115 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1116 1116 }
1117 1117 else
1118 1118 {
1119 1119 status = RTEMS_SUCCESSFUL;
1120 1120 }
1121 1121 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1122 1122 {
1123 1123 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1124 1124 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1125 1125 {
1126 1126 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1127 1127 }
1128 1128 else
1129 1129 {
1130 1130 status = RTEMS_SUCCESSFUL;
1131 1131 }
1132 1132 }
1133 1133 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1134 1134 {
1135 1135 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1136 1136 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1137 1137 {
1138 1138 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1139 1139 }
1140 1140 else
1141 1141 {
1142 1142 status = RTEMS_SUCCESSFUL;
1143 1143 }
1144 1144 }
1145 1145 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1146 1146 {
1147 1147 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1148 1148 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1149 1149 {
1150 1150 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1151 1151 }
1152 1152 else
1153 1153 {
1154 1154 status = RTEMS_SUCCESSFUL;
1155 1155 }
1156 1156 }
1157 1157 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1158 1158 {
1159 1159 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1160 1160 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1161 1161 {
1162 1162 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1163 1163 }
1164 1164 else
1165 1165 {
1166 1166 status = RTEMS_SUCCESSFUL;
1167 1167 }
1168 1168 }
1169 1169 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1170 1170 {
1171 1171 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1172 1172 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1173 1173 {
1174 1174 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1175 1175 }
1176 1176 else
1177 1177 {
1178 1178 status = RTEMS_SUCCESSFUL;
1179 1179 }
1180 1180 }
1181 1181 if (status == RTEMS_SUCCESSFUL) // suspend WFRM
1182 1182 {
1183 1183 status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1184 1184 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1185 1185 {
1186 1186 PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1187 1187 }
1188 1188 else
1189 1189 {
1190 1190 status = RTEMS_SUCCESSFUL;
1191 1191 }
1192 1192 }
1193 1193 if (status == RTEMS_SUCCESSFUL) // suspend CWF3
1194 1194 {
1195 1195 status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1196 1196 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1197 1197 {
1198 1198 PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1199 1199 }
1200 1200 else
1201 1201 {
1202 1202 status = RTEMS_SUCCESSFUL;
1203 1203 }
1204 1204 }
1205 1205 if (status == RTEMS_SUCCESSFUL) // suspend CWF2
1206 1206 {
1207 1207 status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1208 1208 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1209 1209 {
1210 1210 PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1211 1211 }
1212 1212 else
1213 1213 {
1214 1214 status = RTEMS_SUCCESSFUL;
1215 1215 }
1216 1216 }
1217 1217 if (status == RTEMS_SUCCESSFUL) // suspend CWF1
1218 1218 {
1219 1219 status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1220 1220 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1221 1221 {
1222 1222 PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1223 1223 }
1224 1224 else
1225 1225 {
1226 1226 status = RTEMS_SUCCESSFUL;
1227 1227 }
1228 1228 }
1229 1229
1230 1230 return status;
1231 1231 }
1232 1232
1233 1233 int suspend_asm_tasks( void )
1234 1234 {
1235 1235 /** This function suspends the science tasks.
1236 1236 *
1237 1237 * @return RTEMS directive status codes:
1238 1238 * - RTEMS_SUCCESSFUL - task restarted successfully
1239 1239 * - RTEMS_INVALID_ID - task id invalid
1240 1240 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1241 1241 *
1242 1242 */
1243 1243
1244 1244 rtems_status_code status;
1245 1245
1246 1246 PRINTF("in suspend_science_tasks\n")
1247 1247
1248 1248 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1249 1249 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1250 1250 {
1251 1251 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1252 1252 }
1253 1253 else
1254 1254 {
1255 1255 status = RTEMS_SUCCESSFUL;
1256 1256 }
1257 1257
1258 1258 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1259 1259 {
1260 1260 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1261 1261 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1262 1262 {
1263 1263 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1264 1264 }
1265 1265 else
1266 1266 {
1267 1267 status = RTEMS_SUCCESSFUL;
1268 1268 }
1269 1269 }
1270 1270
1271 1271 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1272 1272 {
1273 1273 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1274 1274 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1275 1275 {
1276 1276 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1277 1277 }
1278 1278 else
1279 1279 {
1280 1280 status = RTEMS_SUCCESSFUL;
1281 1281 }
1282 1282 }
1283 1283
1284 1284 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1285 1285 {
1286 1286 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1287 1287 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1288 1288 {
1289 1289 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1290 1290 }
1291 1291 else
1292 1292 {
1293 1293 status = RTEMS_SUCCESSFUL;
1294 1294 }
1295 1295 }
1296 1296
1297 1297 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1298 1298 {
1299 1299 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1300 1300 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1301 1301 {
1302 1302 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1303 1303 }
1304 1304 else
1305 1305 {
1306 1306 status = RTEMS_SUCCESSFUL;
1307 1307 }
1308 1308 }
1309 1309
1310 1310 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1311 1311 {
1312 1312 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1313 1313 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1314 1314 {
1315 1315 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1316 1316 }
1317 1317 else
1318 1318 {
1319 1319 status = RTEMS_SUCCESSFUL;
1320 1320 }
1321 1321 }
1322 1322
1323 1323 return status;
1324 1324 }
1325 1325
1326 1326 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1327 1327 {
1328 1328
1329 1329 WFP_reset_current_ring_nodes();
1330 1330
1331 1331 reset_waveform_picker_regs();
1332 1332
1333 1333 set_wfp_burst_enable_register( mode );
1334 1334
1335 1335 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1336 1336 LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1337 1337
1338 1338 if (transitionCoarseTime == 0)
1339 1339 {
1340 1340 // instant transition means transition on the next valid date
1341 1341 // this is mandatory to have a good snapshot period and a good correction of the snapshot period
1342 1342 waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1343 1343 }
1344 1344 else
1345 1345 {
1346 1346 waveform_picker_regs->start_date = transitionCoarseTime;
1347 1347 }
1348 1348
1349 1349 update_last_valid_transition_date(waveform_picker_regs->start_date);
1350 1350
1351 1351 }
1352 1352
1353 1353 void launch_spectral_matrix( void )
1354 1354 {
1355 1355 SM_reset_current_ring_nodes();
1356 1356
1357 1357 reset_spectral_matrix_regs();
1358 1358
1359 1359 reset_nb_sm();
1360 1360
1361 1361 set_sm_irq_onNewMatrix( 1 );
1362 1362
1363 1363 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1364 1364 LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1365 1365
1366 1366 }
1367 1367
1368 1368 void set_sm_irq_onNewMatrix( unsigned char value )
1369 1369 {
1370 1370 if (value == 1)
1371 1371 {
1372 1372 spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_NEW_MATRIX;
1373 1373 }
1374 1374 else
1375 1375 {
1376 1376 spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_NEW_MATRIX; // 1110
1377 1377 }
1378 1378 }
1379 1379
1380 1380 void set_sm_irq_onError( unsigned char value )
1381 1381 {
1382 1382 if (value == 1)
1383 1383 {
1384 1384 spectral_matrix_regs->config = spectral_matrix_regs->config | BIT_IRQ_ON_ERROR;
1385 1385 }
1386 1386 else
1387 1387 {
1388 1388 spectral_matrix_regs->config = spectral_matrix_regs->config & MASK_IRQ_ON_ERROR; // 1101
1389 1389 }
1390 1390 }
1391 1391
1392 1392 //*****************************
1393 1393 // CONFIGURE CALIBRATION SIGNAL
1394 1394 void setCalibrationPrescaler( unsigned int prescaler )
1395 1395 {
1396 1396 // prescaling of the master clock (25 MHz)
1397 1397 // master clock is divided by 2^prescaler
1398 1398 time_management_regs->calPrescaler = prescaler;
1399 1399 }
1400 1400
1401 1401 void setCalibrationDivisor( unsigned int divisionFactor )
1402 1402 {
1403 1403 // division of the prescaled clock by the division factor
1404 1404 time_management_regs->calDivisor = divisionFactor;
1405 1405 }
1406 1406
1407 1407 void setCalibrationData( void )
1408 1408 {
1409 1409 /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1410 1410 *
1411 1411 * @param void
1412 1412 *
1413 1413 * @return void
1414 1414 *
1415 1415 */
1416 1416
1417 1417 unsigned int k;
1418 1418 unsigned short data;
1419 1419 float val;
1420 1420 float Ts;
1421 1421
1422 1422 time_management_regs->calDataPtr = INIT_CHAR;
1423 1423
1424 1424 Ts = 1 / CAL_FS;
1425 1425
1426 1426 // build the signal for the SCM calibration
1427 1427 for (k = 0; k < CAL_NB_PTS; k++)
1428 1428 {
1429 1429 val = CAL_A0 * sin( CAL_W0 * k * Ts )
1430 1430 + CAL_A1 * sin( CAL_W1 * k * Ts );
1431 1431 data = (unsigned short) ((val * CAL_SCALE_FACTOR) + CONST_2048);
1432 1432 time_management_regs->calData = data & CAL_DATA_MASK;
1433 1433 }
1434 1434 }
1435 1435
1436 #ifdef ENABLE_DEAD_CODE
1436 1437 void setCalibrationDataInterleaved( void )
1437 1438 {
1438 1439 /** This function is used to store the values used to drive the DAC in order to generate the SCM calibration signal
1439 1440 *
1440 1441 * @param void
1441 1442 *
1442 1443 * @return void
1443 1444 *
1444 1445 * In interleaved mode, one can store more values than in normal mode.
1445 1446 * The data are stored in bunch of 18 bits, 12 bits from one sample and 6 bits from another sample.
1446 1447 * T store 3 values, one need two write operations.
1447 1448 * s1 [ b11 b10 b9 b8 b7 b6 ] s0 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1448 1449 * s1 [ b5 b4 b3 b2 b1 b0 ] s2 [ b11 b10 b9 b8 b7 b6 b5 b3 b2 b1 b0 ]
1449 1450 *
1450 1451 */
1451 1452
1452 1453 unsigned int k;
1453 1454 float val;
1454 1455 float Ts;
1455 1456 unsigned short data[CAL_NB_PTS_INTER];
1456 1457 unsigned char *dataPtr;
1457 1458
1458 1459 Ts = 1 / CAL_FS_INTER;
1459 1460
1460 1461 time_management_regs->calDataPtr = INIT_CHAR;
1461 1462
1462 1463 // build the signal for the SCM calibration
1463 1464 for (k=0; k<CAL_NB_PTS_INTER; k++)
1464 1465 {
1465 1466 val = sin( 2 * pi * CAL_F0 * k * Ts )
1466 1467 + sin( 2 * pi * CAL_F1 * k * Ts );
1467 1468 data[k] = (unsigned short) ((val * CONST_512) + CONST_2048);
1468 1469 }
1469 1470
1470 1471 // write the signal in interleaved mode
1471 1472 for (k=0; k < STEPS_FOR_STORAGE_INTER; k++)
1472 1473 {
1473 1474 dataPtr = (unsigned char*) &data[ (k * BYTES_FOR_2_SAMPLES) + 2 ];
1474 1475 time_management_regs->calData = ( data[ k * BYTES_FOR_2_SAMPLES ] & CAL_DATA_MASK )
1475 1476 + ( (dataPtr[0] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1476 1477 time_management_regs->calData = ( data[(k * BYTES_FOR_2_SAMPLES) + 1] & CAL_DATA_MASK )
1477 1478 + ( (dataPtr[1] & CAL_DATA_MASK_INTER) << CAL_DATA_SHIFT_INTER);
1478 1479 }
1479 1480 }
1481 #endif
1480 1482
1481 1483 void setCalibrationReload( bool state)
1482 1484 {
1483 1485 if (state == true)
1484 1486 {
1485 1487 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_RELOAD; // [0001 0000]
1486 1488 }
1487 1489 else
1488 1490 {
1489 1491 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_RELOAD; // [1110 1111]
1490 1492 }
1491 1493 }
1492 1494
1493 1495 void setCalibrationEnable( bool state )
1494 1496 {
1495 1497 // this bit drives the multiplexer
1496 1498 if (state == true)
1497 1499 {
1498 1500 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_CAL_ENABLE; // [0100 0000]
1499 1501 }
1500 1502 else
1501 1503 {
1502 1504 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_CAL_ENABLE; // [1011 1111]
1503 1505 }
1504 1506 }
1505 1507
1508 #ifdef ENABLE_DEAD_CODE
1506 1509 void setCalibrationInterleaved( bool state )
1507 1510 {
1508 1511 // this bit drives the multiplexer
1509 1512 if (state == true)
1510 1513 {
1511 1514 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | BIT_SET_INTERLEAVED; // [0010 0000]
1512 1515 }
1513 1516 else
1514 1517 {
1515 1518 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & MASK_SET_INTERLEAVED; // [1101 1111]
1516 1519 }
1517 1520 }
1521 #endif
1518 1522
1519 1523 void setCalibration( bool state )
1520 1524 {
1521 1525 if (state == true)
1522 1526 {
1523 1527 setCalibrationEnable( true );
1524 1528 setCalibrationReload( false );
1525 1529 set_hk_lfr_calib_enable( true );
1526 1530 }
1527 1531 else
1528 1532 {
1529 1533 setCalibrationEnable( false );
1530 1534 setCalibrationReload( true );
1531 1535 set_hk_lfr_calib_enable( false );
1532 1536 }
1533 1537 }
1534 1538
1535 1539 void configureCalibration( bool interleaved )
1536 1540 {
1537 1541 setCalibration( false );
1542 #ifdef ENABLE_DEAD_CODE
1538 1543 if ( interleaved == true )
1539 1544 {
1540 1545 setCalibrationInterleaved( true );
1541 1546 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1542 1547 setCalibrationDivisor( CAL_F_DIVISOR_INTER ); // => 240 384
1543 1548 setCalibrationDataInterleaved();
1544 1549 }
1545 1550 else
1551 #endif
1546 1552 {
1547 1553 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1548 1554 setCalibrationDivisor( CAL_F_DIVISOR ); // => 160 256 (39 - 1)
1549 1555 setCalibrationData();
1550 1556 }
1551 1557 }
1552 1558
1553 1559 //****************
1554 1560 // CLOSING ACTIONS
1555 1561 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1556 1562 {
1557 1563 /** This function is used to update the HK packets statistics after a successful TC execution.
1558 1564 *
1559 1565 * @param TC points to the TC being processed
1560 1566 * @param time is the time used to date the TC execution
1561 1567 *
1562 1568 */
1563 1569
1564 1570 unsigned int val;
1565 1571
1566 1572 housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1567 1573 housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1568 1574 housekeeping_packet.hk_lfr_last_exe_tc_type[0] = INIT_CHAR;
1569 1575 housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1570 1576 housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = INIT_CHAR;
1571 1577 housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1572 1578 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_0] = time[BYTE_0];
1573 1579 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_1] = time[BYTE_1];
1574 1580 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_2] = time[BYTE_2];
1575 1581 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_3] = time[BYTE_3];
1576 1582 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_4] = time[BYTE_4];
1577 1583 housekeeping_packet.hk_lfr_last_exe_tc_time[BYTE_5] = time[BYTE_5];
1578 1584
1579 1585 val = (housekeeping_packet.hk_lfr_exe_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1580 1586 val++;
1581 1587 housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1582 1588 housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1583 1589 }
1584 1590
1585 1591 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1586 1592 {
1587 1593 /** This function is used to update the HK packets statistics after a TC rejection.
1588 1594 *
1589 1595 * @param TC points to the TC being processed
1590 1596 * @param time is the time used to date the TC rejection
1591 1597 *
1592 1598 */
1593 1599
1594 1600 unsigned int val;
1595 1601
1596 1602 housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1597 1603 housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1598 1604 housekeeping_packet.hk_lfr_last_rej_tc_type[0] = INIT_CHAR;
1599 1605 housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1600 1606 housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = INIT_CHAR;
1601 1607 housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1602 1608 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_0] = time[BYTE_0];
1603 1609 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_1] = time[BYTE_1];
1604 1610 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_2] = time[BYTE_2];
1605 1611 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_3] = time[BYTE_3];
1606 1612 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_4] = time[BYTE_4];
1607 1613 housekeeping_packet.hk_lfr_last_rej_tc_time[BYTE_5] = time[BYTE_5];
1608 1614
1609 1615 val = (housekeeping_packet.hk_lfr_rej_tc_cnt[0] * CONST_256) + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1610 1616 val++;
1611 1617 housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> SHIFT_1_BYTE);
1612 1618 housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1613 1619 }
1614 1620
1615 1621 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1616 1622 {
1617 1623 /** This function is the last step of the TC execution workflow.
1618 1624 *
1619 1625 * @param TC points to the TC being processed
1620 1626 * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1621 1627 * @param queue_id is the id of the RTEMS message queue used to send TM packets
1622 1628 * @param time is the time used to date the TC execution
1623 1629 *
1624 1630 */
1625 1631
1626 1632 unsigned char requestedMode;
1627 1633
1628 1634 if (result == LFR_SUCCESSFUL)
1629 1635 {
1630 1636 if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1631 1637 &
1632 1638 !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1633 1639 )
1634 1640 {
1635 1641 send_tm_lfr_tc_exe_success( TC, queue_id );
1636 1642 }
1637 1643 if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1638 1644 {
1639 1645 //**********************************
1640 1646 // UPDATE THE LFRMODE LOCAL VARIABLE
1641 1647 requestedMode = TC->dataAndCRC[1];
1642 1648 updateLFRCurrentMode( requestedMode );
1643 1649 }
1644 1650 }
1645 1651 else if (result == LFR_EXE_ERROR)
1646 1652 {
1647 1653 send_tm_lfr_tc_exe_error( TC, queue_id );
1648 1654 }
1649 1655 }
1650 1656
1651 //***************************
1652 // Interrupt Service Routines
1653 rtems_isr commutation_isr1( rtems_vector_number vector )
1654 {
1655 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1656 PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1657 }
1658 }
1659
1660 rtems_isr commutation_isr2( rtems_vector_number vector )
1661 {
1662 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1663 PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1664 }
1665 }
1666
1667 1657 //****************
1668 1658 // OTHER FUNCTIONS
1669 1659 void updateLFRCurrentMode( unsigned char requestedMode )
1670 1660 {
1671 1661 /** This function updates the value of the global variable lfrCurrentMode.
1672 1662 *
1673 1663 * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1674 1664 *
1675 1665 */
1676 1666
1677 1667 // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1678 1668 housekeeping_packet.lfr_status_word[0] = (housekeeping_packet.lfr_status_word[0] & STATUS_WORD_LFR_MODE_MASK)
1679 1669 + (unsigned char) ( requestedMode << STATUS_WORD_LFR_MODE_SHIFT );
1680 1670 lfrCurrentMode = requestedMode;
1681 1671 }
1682 1672
1683 1673 void set_lfr_soft_reset( unsigned char value )
1684 1674 {
1685 1675 if (value == 1)
1686 1676 {
1687 1677 time_management_regs->ctrl = time_management_regs->ctrl | BIT_SOFT_RESET; // [0100]
1688 1678 }
1689 1679 else
1690 1680 {
1691 1681 time_management_regs->ctrl = time_management_regs->ctrl & MASK_SOFT_RESET; // [1011]
1692 1682 }
1693 1683 }
1694 1684
1695 1685 void reset_lfr( void )
1696 1686 {
1697 1687 set_lfr_soft_reset( 1 );
1698 1688
1699 1689 set_lfr_soft_reset( 0 );
1700 1690
1701 1691 set_hk_lfr_sc_potential_flag( true );
1702 1692 }
@@ -1,536 +1,538
1 1 /*------------------------------------------------------------------------------
2 2 -- Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
3 3 -- This file is a part of the LFR FSW
4 4 -- Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
5 5 --
6 6 -- This program is free software; you can redistribute it and/or modify
7 7 -- it under the terms of the GNU General Public License as published by
8 8 -- the Free Software Foundation; either version 2 of the License, or
9 9 -- (at your option) any later version.
10 10 --
11 11 -- This program is distributed in the hope that it will be useful,
12 12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 -- GNU General Public License for more details.
15 15 --
16 16 -- You should have received a copy of the GNU General Public License
17 17 -- along with this program; if not, write to the Free Software
18 18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 -------------------------------------------------------------------------------*/
20 20 /*-- Author : Paul Leroy
21 21 -- Contact : Alexis Jeandet
22 22 -- Mail : alexis.jeandet@lpp.polytechnique.fr
23 23 ----------------------------------------------------------------------------*/
24 24
25 25 /** Functions to send TM packets related to TC parsing and execution.
26 26 *
27 27 * @file
28 28 * @author P. LEROY
29 29 *
30 30 * A group of functions to send appropriate TM packets after parsing and execution:
31 31 * - TM_LFR_TC_EXE_SUCCESS
32 32 * - TM_LFR_TC_EXE_INCONSISTENT
33 33 * - TM_LFR_TC_EXE_NOT_EXECUTABLE
34 34 * - TM_LFR_TC_EXE_NOT_IMPLEMENTED
35 35 * - TM_LFR_TC_EXE_ERROR
36 36 * - TM_LFR_TC_EXE_CORRUPTED
37 37 *
38 38 */
39 39
40 40 #include "tm_lfr_tc_exe.h"
41 41
42 42 int send_tm_lfr_tc_exe_success( ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
43 43 {
44 44 /** This function sends a TM_LFR_TC_EXE_SUCCESS packet in the dedicated RTEMS message queue.
45 45 *
46 46 * @param TC points to the TeleCommand packet that is being processed
47 47 * @param queue_id is the id of the queue which handles TM
48 48 *
49 49 * @return RTEMS directive status code:
50 50 * - RTEMS_SUCCESSFUL - message sent successfully
51 51 * - RTEMS_INVALID_ID - invalid queue id
52 52 * - RTEMS_INVALID_SIZE - invalid message size
53 53 * - RTEMS_INVALID_ADDRESS - buffer is NULL
54 54 * - RTEMS_UNSATISFIED - out of message buffers
55 55 * - RTEMS_TOO_MANY - queue s limit has been reached
56 56 *
57 57 */
58 58
59 59 rtems_status_code status;
60 60 Packet_TM_LFR_TC_EXE_SUCCESS_t TM;
61 61 unsigned char messageSize;
62 62
63 63 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
64 64 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
65 65 TM.reserved = DEFAULT_RESERVED;
66 66 TM.userApplication = CCSDS_USER_APP;
67 67 // PACKET HEADER
68 68 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
69 69 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
70 70 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
71 71 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_SUCCESS >> SHIFT_1_BYTE);
72 72 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_SUCCESS );
73 73 // DATA FIELD HEADER
74 74 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
75 75 TM.serviceType = TM_TYPE_TC_EXE;
76 76 TM.serviceSubType = TM_SUBTYPE_EXE_OK;
77 77 TM.destinationID = TC->sourceID;
78 78 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
79 79 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
80 80 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
81 81 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
82 82 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
83 83 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
84 84 //
85 85 TM.telecommand_pkt_id[0] = TC->packetID[0];
86 86 TM.telecommand_pkt_id[1] = TC->packetID[1];
87 87 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
88 88 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
89 89
90 90 messageSize = PACKET_LENGTH_TC_EXE_SUCCESS + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
91 91
92 92 // SEND DATA
93 93 status = rtems_message_queue_send( queue_id, &TM, messageSize);
94 94 if (status != RTEMS_SUCCESSFUL) {
95 95 PRINTF("in send_tm_lfr_tc_exe_success *** ERR\n")
96 96 }
97 97
98 98 // UPDATE HK FIELDS
99 99 update_last_TC_exe( TC, TM.time );
100 100
101 101 return status;
102 102 }
103 103
104 104 int send_tm_lfr_tc_exe_inconsistent( ccsdsTelecommandPacket_t *TC, rtems_id queue_id,
105 105 unsigned char byte_position, unsigned char rcv_value )
106 106 {
107 107 /** This function sends a TM_LFR_TC_EXE_INCONSISTENT packet in the dedicated RTEMS message queue.
108 108 *
109 109 * @param TC points to the TeleCommand packet that is being processed
110 110 * @param queue_id is the id of the queue which handles TM
111 111 * @param byte_position is the byte position of the MSB of the parameter that has been seen as inconsistent
112 112 * @param rcv_value is the value of the LSB of the parameter that has been detected as inconsistent
113 113 *
114 114 * @return RTEMS directive status code:
115 115 * - RTEMS_SUCCESSFUL - message sent successfully
116 116 * - RTEMS_INVALID_ID - invalid queue id
117 117 * - RTEMS_INVALID_SIZE - invalid message size
118 118 * - RTEMS_INVALID_ADDRESS - buffer is NULL
119 119 * - RTEMS_UNSATISFIED - out of message buffers
120 120 * - RTEMS_TOO_MANY - queue s limit has been reached
121 121 *
122 122 */
123 123
124 124 rtems_status_code status;
125 125 Packet_TM_LFR_TC_EXE_INCONSISTENT_t TM;
126 126 unsigned char messageSize;
127 127
128 128 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
129 129 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
130 130 TM.reserved = DEFAULT_RESERVED;
131 131 TM.userApplication = CCSDS_USER_APP;
132 132 // PACKET HEADER
133 133 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
134 134 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
135 135 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
136 136 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_INCONSISTENT >> SHIFT_1_BYTE);
137 137 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_INCONSISTENT );
138 138 // DATA FIELD HEADER
139 139 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
140 140 TM.serviceType = TM_TYPE_TC_EXE;
141 141 TM.serviceSubType = TM_SUBTYPE_EXE_NOK;
142 142 TM.destinationID = TC->sourceID;
143 143 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
144 144 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
145 145 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
146 146 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
147 147 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
148 148 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
149 149 //
150 150 TM.tc_failure_code[0] = (char) (WRONG_APP_DATA >> SHIFT_1_BYTE);
151 151 TM.tc_failure_code[1] = (char) (WRONG_APP_DATA );
152 152 TM.telecommand_pkt_id[0] = TC->packetID[0];
153 153 TM.telecommand_pkt_id[1] = TC->packetID[1];
154 154 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
155 155 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
156 156 TM.tc_service = TC->serviceType; // type of the rejected TC
157 157 TM.tc_subtype = TC->serviceSubType; // subtype of the rejected TC
158 158 TM.byte_position = byte_position;
159 159 TM.rcv_value = (unsigned char) rcv_value;
160 160
161 161 messageSize = PACKET_LENGTH_TC_EXE_INCONSISTENT + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
162 162
163 163 // SEND DATA
164 164 status = rtems_message_queue_send( queue_id, &TM, messageSize);
165 165 if (status != RTEMS_SUCCESSFUL) {
166 166 PRINTF("in send_tm_lfr_tc_exe_inconsistent *** ERR\n")
167 167 }
168 168
169 169 // UPDATE HK FIELDS
170 170 update_last_TC_rej( TC, TM.time );
171 171
172 172 return status;
173 173 }
174 174
175 175 int send_tm_lfr_tc_exe_not_executable( ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
176 176 {
177 177 /** This function sends a TM_LFR_TC_EXE_NOT_EXECUTABLE packet in the dedicated RTEMS message queue.
178 178 *
179 179 * @param TC points to the TeleCommand packet that is being processed
180 180 * @param queue_id is the id of the queue which handles TM
181 181 *
182 182 * @return RTEMS directive status code:
183 183 * - RTEMS_SUCCESSFUL - message sent successfully
184 184 * - RTEMS_INVALID_ID - invalid queue id
185 185 * - RTEMS_INVALID_SIZE - invalid message size
186 186 * - RTEMS_INVALID_ADDRESS - buffer is NULL
187 187 * - RTEMS_UNSATISFIED - out of message buffers
188 188 * - RTEMS_TOO_MANY - queue s limit has been reached
189 189 *
190 190 */
191 191
192 192 rtems_status_code status;
193 193 Packet_TM_LFR_TC_EXE_NOT_EXECUTABLE_t TM;
194 194 unsigned char messageSize;
195 195
196 196 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
197 197 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
198 198 TM.reserved = DEFAULT_RESERVED;
199 199 TM.userApplication = CCSDS_USER_APP;
200 200 // PACKET HEADER
201 201 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
202 202 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
203 203 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
204 204 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_NOT_EXECUTABLE >> SHIFT_1_BYTE);
205 205 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_NOT_EXECUTABLE );
206 206 // DATA FIELD HEADER
207 207 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
208 208 TM.serviceType = TM_TYPE_TC_EXE;
209 209 TM.serviceSubType = TM_SUBTYPE_EXE_NOK;
210 210 TM.destinationID = TC->sourceID; // default destination id
211 211 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
212 212 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
213 213 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
214 214 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
215 215 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
216 216 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
217 217 //
218 218 TM.tc_failure_code[0] = (char) (TC_NOT_EXE >> SHIFT_1_BYTE);
219 219 TM.tc_failure_code[1] = (char) (TC_NOT_EXE );
220 220 TM.telecommand_pkt_id[0] = TC->packetID[0];
221 221 TM.telecommand_pkt_id[1] = TC->packetID[1];
222 222 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
223 223 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
224 224 TM.tc_service = TC->serviceType; // type of the rejected TC
225 225 TM.tc_subtype = TC->serviceSubType; // subtype of the rejected TC
226 226 TM.lfr_status_word[0] = housekeeping_packet.lfr_status_word[0];
227 227 TM.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1];
228 228
229 229 messageSize = PACKET_LENGTH_TC_EXE_NOT_EXECUTABLE + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
230 230
231 231 // SEND DATA
232 232 status = rtems_message_queue_send( queue_id, &TM, messageSize);
233 233 if (status != RTEMS_SUCCESSFUL) {
234 234 PRINTF("in send_tm_lfr_tc_exe_not_executable *** ERR\n")
235 235 }
236 236
237 237 // UPDATE HK FIELDS
238 238 update_last_TC_rej( TC, TM.time );
239 239
240 240 return status;
241 241 }
242 242
243 #ifdef DENABLE_DEAD_CODE
243 244 int send_tm_lfr_tc_exe_not_implemented( ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time )
244 245 {
245 246 /** This function sends a TM_LFR_TC_EXE_NOT_IMPLEMENTED packet in the dedicated RTEMS message queue.
246 247 *
247 248 * @param TC points to the TeleCommand packet that is being processed
248 249 * @param queue_id is the id of the queue which handles TM
249 250 *
250 251 * @return RTEMS directive status code:
251 252 * - RTEMS_SUCCESSFUL - message sent successfully
252 253 * - RTEMS_INVALID_ID - invalid queue id
253 254 * - RTEMS_INVALID_SIZE - invalid message size
254 255 * - RTEMS_INVALID_ADDRESS - buffer is NULL
255 256 * - RTEMS_UNSATISFIED - out of message buffers
256 257 * - RTEMS_TOO_MANY - queue s limit has been reached
257 258 *
258 259 */
259 260
260 261 rtems_status_code status;
261 262 Packet_TM_LFR_TC_EXE_NOT_IMPLEMENTED_t TM;
262 263 unsigned char messageSize;
263 264
264 265 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
265 266 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
266 267 TM.reserved = DEFAULT_RESERVED;
267 268 TM.userApplication = CCSDS_USER_APP;
268 269 // PACKET HEADER
269 270 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
270 271 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
271 272 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
272 273 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_NOT_IMPLEMENTED >> SHIFT_1_BYTE);
273 274 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_NOT_IMPLEMENTED );
274 275 // DATA FIELD HEADER
275 276 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
276 277 TM.serviceType = TM_TYPE_TC_EXE;
277 278 TM.serviceSubType = TM_SUBTYPE_EXE_NOK;
278 279 TM.destinationID = TC->sourceID; // default destination id
279 280 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
280 281 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
281 282 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
282 283 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
283 284 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
284 285 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
285 286 //
286 287 TM.tc_failure_code[0] = (char) (FUNCT_NOT_IMPL >> SHIFT_1_BYTE);
287 288 TM.tc_failure_code[1] = (char) (FUNCT_NOT_IMPL );
288 289 TM.telecommand_pkt_id[0] = TC->packetID[0];
289 290 TM.telecommand_pkt_id[1] = TC->packetID[1];
290 291 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
291 292 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
292 293 TM.tc_service = TC->serviceType; // type of the rejected TC
293 294 TM.tc_subtype = TC->serviceSubType; // subtype of the rejected TC
294 295
295 296 messageSize = PACKET_LENGTH_TC_EXE_NOT_IMPLEMENTED + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
296 297
297 298 // SEND DATA
298 299 status = rtems_message_queue_send( queue_id, &TM, messageSize);
299 300 if (status != RTEMS_SUCCESSFUL) {
300 301 PRINTF("in send_tm_lfr_tc_exe_not_implemented *** ERR\n")
301 302 }
302 303
303 304 // UPDATE HK FIELDS
304 305 update_last_TC_rej( TC, TM.time );
305 306
306 307 return status;
307 308 }
309 #endif
308 310
309 311 int send_tm_lfr_tc_exe_error( ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
310 312 {
311 313 /** This function sends a TM_LFR_TC_EXE_ERROR packet in the dedicated RTEMS message queue.
312 314 *
313 315 * @param TC points to the TeleCommand packet that is being processed
314 316 * @param queue_id is the id of the queue which handles TM
315 317 *
316 318 * @return RTEMS directive status code:
317 319 * - RTEMS_SUCCESSFUL - message sent successfully
318 320 * - RTEMS_INVALID_ID - invalid queue id
319 321 * - RTEMS_INVALID_SIZE - invalid message size
320 322 * - RTEMS_INVALID_ADDRESS - buffer is NULL
321 323 * - RTEMS_UNSATISFIED - out of message buffers
322 324 * - RTEMS_TOO_MANY - queue s limit has been reached
323 325 *
324 326 */
325 327
326 328 rtems_status_code status;
327 329 Packet_TM_LFR_TC_EXE_ERROR_t TM;
328 330 unsigned char messageSize;
329 331
330 332 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
331 333 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
332 334 TM.reserved = DEFAULT_RESERVED;
333 335 TM.userApplication = CCSDS_USER_APP;
334 336 // PACKET HEADER
335 337 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
336 338 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
337 339 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
338 340 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_ERROR >> SHIFT_1_BYTE);
339 341 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_ERROR );
340 342 // DATA FIELD HEADER
341 343 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
342 344 TM.serviceType = TM_TYPE_TC_EXE;
343 345 TM.serviceSubType = TM_SUBTYPE_EXE_NOK;
344 346 TM.destinationID = TC->sourceID; // default destination id
345 347 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
346 348 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
347 349 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
348 350 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
349 351 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
350 352 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
351 353 //
352 354 TM.tc_failure_code[0] = (char) (FAIL_DETECTED >> SHIFT_1_BYTE);
353 355 TM.tc_failure_code[1] = (char) (FAIL_DETECTED );
354 356 TM.telecommand_pkt_id[0] = TC->packetID[0];
355 357 TM.telecommand_pkt_id[1] = TC->packetID[1];
356 358 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
357 359 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
358 360 TM.tc_service = TC->serviceType; // type of the rejected TC
359 361 TM.tc_subtype = TC->serviceSubType; // subtype of the rejected TC
360 362
361 363 messageSize = PACKET_LENGTH_TC_EXE_ERROR + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
362 364
363 365 // SEND DATA
364 366 status = rtems_message_queue_send( queue_id, &TM, messageSize);
365 367 if (status != RTEMS_SUCCESSFUL) {
366 368 PRINTF("in send_tm_lfr_tc_exe_error *** ERR\n")
367 369 }
368 370
369 371 // UPDATE HK FIELDS
370 372 update_last_TC_rej( TC, TM.time );
371 373
372 374 return status;
373 375 }
374 376
375 377 int send_tm_lfr_tc_exe_corrupted(ccsdsTelecommandPacket_t *TC, rtems_id queue_id,
376 378 unsigned char *computed_CRC, unsigned char *currentTC_LEN_RCV,
377 379 unsigned char destinationID )
378 380 {
379 381 /** This function sends a TM_LFR_TC_EXE_CORRUPTED packet in the dedicated RTEMS message queue.
380 382 *
381 383 * @param TC points to the TeleCommand packet that is being processed
382 384 * @param queue_id is the id of the queue which handles TM
383 385 * @param computed_CRC points to a buffer of two bytes containing the CRC computed during the parsing of the TeleCommand
384 386 * @param currentTC_LEN_RCV points to a buffer of two bytes containing a packet size field computed on the received data
385 387 *
386 388 * @return RTEMS directive status code:
387 389 * - RTEMS_SUCCESSFUL - message sent successfully
388 390 * - RTEMS_INVALID_ID - invalid queue id
389 391 * - RTEMS_INVALID_SIZE - invalid message size
390 392 * - RTEMS_INVALID_ADDRESS - buffer is NULL
391 393 * - RTEMS_UNSATISFIED - out of message buffers
392 394 * - RTEMS_TOO_MANY - queue s limit has been reached
393 395 *
394 396 */
395 397
396 398 rtems_status_code status;
397 399 Packet_TM_LFR_TC_EXE_CORRUPTED_t TM;
398 400 unsigned char messageSize;
399 401 unsigned int packetLength;
400 402 unsigned int estimatedPacketLength;
401 403 unsigned char *packetDataField;
402 404
403 405 packetLength = (TC->packetLength[0] * CONST_256) + TC->packetLength[1]; // compute the packet length parameter written in the TC
404 406 estimatedPacketLength = (unsigned int) ((currentTC_LEN_RCV[0] * CONST_256) + currentTC_LEN_RCV[1]);
405 407 packetDataField = (unsigned char *) &TC->headerFlag_pusVersion_Ack; // get the beginning of the data field
406 408
407 409 TM.targetLogicalAddress = CCSDS_DESTINATION_ID;
408 410 TM.protocolIdentifier = CCSDS_PROTOCOLE_ID;
409 411 TM.reserved = DEFAULT_RESERVED;
410 412 TM.userApplication = CCSDS_USER_APP;
411 413 // PACKET HEADER
412 414 TM.packetID[0] = (unsigned char) (APID_TM_TC_EXE >> SHIFT_1_BYTE);
413 415 TM.packetID[1] = (unsigned char) (APID_TM_TC_EXE );
414 416 increment_seq_counter_destination_id( TM.packetSequenceControl, TC->sourceID );
415 417 TM.packetLength[0] = (unsigned char) (PACKET_LENGTH_TC_EXE_CORRUPTED >> SHIFT_1_BYTE);
416 418 TM.packetLength[1] = (unsigned char) (PACKET_LENGTH_TC_EXE_CORRUPTED );
417 419 // DATA FIELD HEADER
418 420 TM.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
419 421 TM.serviceType = TM_TYPE_TC_EXE;
420 422 TM.serviceSubType = TM_SUBTYPE_EXE_NOK;
421 423 TM.destinationID = destinationID;
422 424 TM.time[BYTE_0] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_3_BYTES);
423 425 TM.time[BYTE_1] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_2_BYTES);
424 426 TM.time[BYTE_2] = (unsigned char) (time_management_regs->coarse_time >> SHIFT_1_BYTE);
425 427 TM.time[BYTE_3] = (unsigned char) (time_management_regs->coarse_time);
426 428 TM.time[BYTE_4] = (unsigned char) (time_management_regs->fine_time >> SHIFT_1_BYTE);
427 429 TM.time[BYTE_5] = (unsigned char) (time_management_regs->fine_time);
428 430 //
429 431 TM.tc_failure_code[0] = (unsigned char) (CORRUPTED >> SHIFT_1_BYTE);
430 432 TM.tc_failure_code[1] = (unsigned char) (CORRUPTED );
431 433 TM.telecommand_pkt_id[0] = TC->packetID[0];
432 434 TM.telecommand_pkt_id[1] = TC->packetID[1];
433 435 TM.pkt_seq_control[0] = TC->packetSequenceControl[0];
434 436 TM.pkt_seq_control[1] = TC->packetSequenceControl[1];
435 437 TM.tc_service = TC->serviceType; // type of the rejected TC
436 438 TM.tc_subtype = TC->serviceSubType; // subtype of the rejected TC
437 439 TM.pkt_len_rcv_value[0] = TC->packetLength[0];
438 440 TM.pkt_len_rcv_value[1] = TC->packetLength[1];
439 441 TM.pkt_datafieldsize_cnt[0] = currentTC_LEN_RCV[0];
440 442 TM.pkt_datafieldsize_cnt[1] = currentTC_LEN_RCV[1];
441 443 TM.rcv_crc[0] = packetDataField[ estimatedPacketLength - 1 ];
442 444 TM.rcv_crc[1] = packetDataField[ estimatedPacketLength ];
443 445 TM.computed_crc[0] = computed_CRC[0];
444 446 TM.computed_crc[1] = computed_CRC[1];
445 447
446 448 messageSize = PACKET_LENGTH_TC_EXE_CORRUPTED + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
447 449
448 450 // SEND DATA
449 451 status = rtems_message_queue_send( queue_id, &TM, messageSize);
450 452 if (status != RTEMS_SUCCESSFUL) {
451 453 PRINTF("in send_tm_lfr_tc_exe_error *** ERR\n")
452 454 }
453 455
454 456 // UPDATE HK FIELDS
455 457 update_last_TC_rej( TC, TM.time );
456 458
457 459 return status;
458 460 }
459 461
460 462 void increment_seq_counter_destination_id( unsigned char *packet_sequence_control, unsigned char destination_id )
461 463 {
462 464 /** This function increment the packet sequence control parameter of a TC, depending on its destination ID.
463 465 *
464 466 * @param packet_sequence_control points to the packet sequence control which will be incremented
465 467 * @param destination_id is the destination ID of the TM, there is one counter by destination ID
466 468 *
467 469 * If the destination ID is not known, a dedicated counter is incremented.
468 470 *
469 471 */
470 472
471 473 unsigned short sequence_cnt;
472 474 unsigned short segmentation_grouping_flag;
473 475 unsigned short new_packet_sequence_control;
474 476 unsigned char i;
475 477
476 478 switch (destination_id)
477 479 {
478 480 case SID_TC_GROUND:
479 481 i = GROUND;
480 482 break;
481 483 case SID_TC_MISSION_TIMELINE:
482 484 i = MISSION_TIMELINE;
483 485 break;
484 486 case SID_TC_TC_SEQUENCES:
485 487 i = TC_SEQUENCES;
486 488 break;
487 489 case SID_TC_RECOVERY_ACTION_CMD:
488 490 i = RECOVERY_ACTION_CMD;
489 491 break;
490 492 case SID_TC_BACKUP_MISSION_TIMELINE:
491 493 i = BACKUP_MISSION_TIMELINE;
492 494 break;
493 495 case SID_TC_DIRECT_CMD:
494 496 i = DIRECT_CMD;
495 497 break;
496 498 case SID_TC_SPARE_GRD_SRC1:
497 499 i = SPARE_GRD_SRC1;
498 500 break;
499 501 case SID_TC_SPARE_GRD_SRC2:
500 502 i = SPARE_GRD_SRC2;
501 503 break;
502 504 case SID_TC_OBCP:
503 505 i = OBCP;
504 506 break;
505 507 case SID_TC_SYSTEM_CONTROL:
506 508 i = SYSTEM_CONTROL;
507 509 break;
508 510 case SID_TC_AOCS:
509 511 i = AOCS;
510 512 break;
511 513 case SID_TC_RPW_INTERNAL:
512 514 i = RPW_INTERNAL;
513 515 break;
514 516 default:
515 517 i = GROUND;
516 518 break;
517 519 }
518 520
519 521 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << SHIFT_1_BYTE;
520 522 sequence_cnt = sequenceCounters_TC_EXE[ i ] & SEQ_CNT_MASK;
521 523
522 524 new_packet_sequence_control = segmentation_grouping_flag | sequence_cnt ;
523 525
524 526 packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> SHIFT_1_BYTE);
525 527 packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control );
526 528
527 529 // increment the sequence counter
528 530 if ( sequenceCounters_TC_EXE[ i ] < SEQ_CNT_MAX )
529 531 {
530 532 sequenceCounters_TC_EXE[ i ] = sequenceCounters_TC_EXE[ i ] + 1;
531 533 }
532 534 else
533 535 {
534 536 sequenceCounters_TC_EXE[ i ] = 0;
535 537 }
536 538 }
General Comments 0
You need to be logged in to leave comments. Login now