##// END OF EJS Templates
Minor bugs corrected before logiscope analysis
paul -
r322:c0603702c8c8 R3_plus draft
parent child
Show More
@@ -1,131 +1,131
1 1 #ifndef FSW_MISC_H_INCLUDED
2 2 #define FSW_MISC_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <stdio.h>
6 6 #include <grspw.h>
7 7 #include <grlib_regs.h>
8 8
9 9 #include "fsw_params.h"
10 10 #include "fsw_spacewire.h"
11 11 #include "lfr_cpu_usage_report.h"
12 12
13 13 #define LFR_RESET_CAUSE_UNKNOWN_CAUSE 0
14 14 #define WATCHDOG_LOOP_PRINTF 10
15 15 #define WATCHDOG_LOOP_DEBUG 3
16 16
17 17 #define DUMB_MESSAGE_NB 15
18 18 #define NB_RTEMS_EVENTS 32
19 19 #define EVENT_12 12
20 20 #define EVENT_13 13
21 21 #define EVENT_14 14
22 22 #define DUMB_MESSAGE_0 "in DUMB *** default"
23 23 #define DUMB_MESSAGE_1 "in DUMB *** timecode_irq_handler"
24 24 #define DUMB_MESSAGE_2 "in DUMB *** f3 buffer changed"
25 25 #define DUMB_MESSAGE_3 "in DUMB *** in SMIQ *** Error sending event to AVF0"
26 26 #define DUMB_MESSAGE_4 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ"
27 27 #define DUMB_MESSAGE_5 "in DUMB *** waveforms_simulator_isr"
28 28 #define DUMB_MESSAGE_6 "VHDL SM *** two buffers f0 ready"
29 29 #define DUMB_MESSAGE_7 "ready for dump"
30 30 #define DUMB_MESSAGE_8 "VHDL ERR *** spectral matrix"
31 31 #define DUMB_MESSAGE_9 "tick"
32 32 #define DUMB_MESSAGE_10 "VHDL ERR *** waveform picker"
33 33 #define DUMB_MESSAGE_11 "VHDL ERR *** unexpected ready matrix values"
34 34 #define DUMB_MESSAGE_12 "WATCHDOG timer"
35 35 #define DUMB_MESSAGE_13 "TIMECODE timer"
36 36 #define DUMB_MESSAGE_14 "TIMECODE ISR"
37 37
38 38 enum lfr_reset_cause_t{
39 39 UNKNOWN_CAUSE,
40 40 POWER_ON,
41 41 TC_RESET,
42 42 WATCHDOG,
43 43 ERROR_RESET,
44 44 UNEXP_RESET
45 45 };
46 46
47 47 typedef struct{
48 48 unsigned char dpu_spw_parity;
49 49 unsigned char dpu_spw_disconnect;
50 50 unsigned char dpu_spw_escape;
51 51 unsigned char dpu_spw_credit;
52 52 unsigned char dpu_spw_write_sync;
53 53 unsigned char timecode_erroneous;
54 54 unsigned char timecode_missing;
55 55 unsigned char timecode_invalid;
56 56 unsigned char time_timecode_it;
57 57 unsigned char time_not_synchro;
58 58 unsigned char time_timecode_ctr;
59 59 unsigned char ahb_correctable;
60 60 } hk_lfr_le_t;
61 61
62 62 typedef struct{
63 63 unsigned char dpu_spw_early_eop;
64 64 unsigned char dpu_spw_invalid_addr;
65 65 unsigned char dpu_spw_eep;
66 66 unsigned char dpu_spw_rx_too_big;
67 67 } hk_lfr_me_t;
68 68
69 69 extern gptimer_regs_t *gptimer_regs;
70 70 extern void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int*, unsigned int* );
71 71 extern void CCR_getInstructionAndDataErrorCounters( unsigned int*, unsigned int* );
72 72
73 rtems_name name_hk_rate_monotonic = 0; // name of the HK rate monotonic
74 rtems_id HK_id = RTEMS_ID_NONE;// id of the HK rate monotonic period
75 rtems_name name_avgv_rate_monotonic = 0; // name of the AVGV rate monotonic
76 rtems_id AVGV_id = RTEMS_ID_NONE;// id of the AVGV rate monotonic period
73 extern rtems_name name_hk_rate_monotonic; // name of the HK rate monotonic
74 extern rtems_id HK_id;// id of the HK rate monotonic period
75 extern rtems_name name_avgv_rate_monotonic; // name of the AVGV rate monotonic
76 extern rtems_id AVGV_id;// id of the AVGV rate monotonic period
77 77
78 78 void timer_configure( unsigned char timer, unsigned int clock_divider,
79 79 unsigned char interrupt_level, rtems_isr (*timer_isr)() );
80 80 void timer_start( unsigned char timer );
81 81 void timer_stop( unsigned char timer );
82 82 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider);
83 83
84 84 // WATCHDOG
85 85 rtems_isr watchdog_isr( rtems_vector_number vector );
86 86 void watchdog_configure(void);
87 87 void watchdog_stop(void);
88 88 void watchdog_reload(void);
89 89 void watchdog_start(void);
90 90
91 91 // SERIAL LINK
92 92 int send_console_outputs_on_apbuart_port( void );
93 93 int enable_apbuart_transmitter( void );
94 94 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value);
95 95
96 96 // RTEMS TASKS
97 97 rtems_task load_task( rtems_task_argument argument );
98 98 rtems_task hous_task( rtems_task_argument argument );
99 99 rtems_task avgv_task( rtems_task_argument argument );
100 100 rtems_task dumb_task( rtems_task_argument unused );
101 101
102 102 void init_housekeeping_parameters( void );
103 103 void increment_seq_counter(unsigned short *packetSequenceControl);
104 104 void getTime( unsigned char *time);
105 105 unsigned long long int getTimeAsUnsignedLongLongInt( );
106 106 void send_dumb_hk( void );
107 107 void get_temperatures( unsigned char *temperatures );
108 108 void get_v_e1_e2_f3( unsigned char *spacecraft_potential );
109 109 void get_cpu_load( unsigned char *resource_statistics );
110 110 void set_hk_lfr_sc_potential_flag( bool state );
111 111 void set_sy_lfr_pas_filter_enabled( bool state );
112 112 void set_sy_lfr_watchdog_enabled( bool state );
113 113 void set_hk_lfr_calib_enable( bool state );
114 114 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause );
115 115 void hk_lfr_le_me_he_update();
116 116 void set_hk_lfr_time_not_synchro();
117 117
118 118 extern int sched_yield( void );
119 119 extern void rtems_cpu_usage_reset();
120 120 extern ring_node *current_ring_node_f3;
121 121 extern ring_node *ring_node_to_send_cwf_f3;
122 122 extern ring_node waveform_ring_f3[];
123 123 extern unsigned short sequenceCounterHK;
124 124
125 125 extern unsigned char hk_lfr_q_sd_fifo_size_max;
126 126 extern unsigned char hk_lfr_q_rv_fifo_size_max;
127 127 extern unsigned char hk_lfr_q_p0_fifo_size_max;
128 128 extern unsigned char hk_lfr_q_p1_fifo_size_max;
129 129 extern unsigned char hk_lfr_q_p2_fifo_size_max;
130 130
131 131 #endif // FSW_MISC_H_INCLUDED
@@ -1,102 +1,106
1 1 /** Global variables of the LFR flight software.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * Among global variables, there are:
7 7 * - RTEMS names and id.
8 8 * - APB configuration registers.
9 9 * - waveforms global buffers, used by the waveform picker hardware module to store data.
10 10 * - spectral matrices buffesr, used by the hardware module to store data.
11 11 * - variable related to LFR modes parameters.
12 12 * - the global HK packet buffer.
13 13 * - the global dump parameter buffer.
14 14 *
15 15 */
16 16
17 17 #include <rtems.h>
18 18 #include <grspw.h>
19 19
20 20 #include "ccsds_types.h"
21 21 #include "grlib_regs.h"
22 22 #include "fsw_params.h"
23 23 #include "fsw_params_wf_handler.h"
24 24
25 25 #define NB_OF_TASKS 20
26 26 #define NB_OF_MISC_NAMES 5
27 27
28 28 // RTEMS GLOBAL VARIABLES
29 29 rtems_name misc_name[NB_OF_MISC_NAMES] = {0};
30 30 rtems_name Task_name[NB_OF_TASKS] = {0}; /* array of task names */
31 31 rtems_id Task_id[NB_OF_TASKS] = {0}; /* array of task ids */
32 rtems_name timecode_timer_name = {0};
33 rtems_id timecode_timer_id = {0};
32 rtems_name timecode_timer_name = 0;
33 rtems_id timecode_timer_id = RTEMS_ID_NONE;
34 rtems_name name_hk_rate_monotonic = 0; // name of the HK rate monotonic
35 rtems_id HK_id = RTEMS_ID_NONE;// id of the HK rate monotonic period
36 rtems_name name_avgv_rate_monotonic = 0; // name of the AVGV rate monotonic
37 rtems_id AVGV_id = RTEMS_ID_NONE;// id of the AVGV rate monotonic period
34 38 int fdSPW = 0;
35 39 int fdUART = 0;
36 40 unsigned char lfrCurrentMode = 0;
37 41 unsigned char pa_bia_status_info = 0;
38 42 unsigned char thisIsAnASMRestart = 0;
39 43 unsigned char oneTcLfrUpdateTimeReceived = 0;
40 44
41 45 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
42 46 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
43 47 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
44 48 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
45 49 // F0 F1 F2 F3
46 50 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
47 51 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
48 52 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
49 53 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100))) = {0};
50 54
51 55 //***********************************
52 56 // SPECTRAL MATRICES GLOBAL VARIABLES
53 57
54 58 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
55 59 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
56 60 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
57 61 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100))) = {0};
58 62
59 63 // APB CONFIGURATION REGISTERS
60 64 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
61 65 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
62 66 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
63 67 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
64 68
65 69 // MODE PARAMETERS
66 70 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet = {0};
67 71 struct param_local_str param_local = {0};
68 72 unsigned int lastValidEnterModeTime = {0};
69 73
70 74 // HK PACKETS
71 75 Packet_TM_LFR_HK_t housekeeping_packet = {0};
72 76 unsigned char cp_rpw_sc_rw_f_flags = 0;
73 77 // message queues occupancy
74 78 unsigned char hk_lfr_q_sd_fifo_size_max = 0;
75 79 unsigned char hk_lfr_q_rv_fifo_size_max = 0;
76 80 unsigned char hk_lfr_q_p0_fifo_size_max = 0;
77 81 unsigned char hk_lfr_q_p1_fifo_size_max = 0;
78 82 unsigned char hk_lfr_q_p2_fifo_size_max = 0;
79 83 // sequence counters are incremented by APID (PID + CAT) and destination ID
80 84 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST = 0;
81 85 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2 = 0;
82 86 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID] = {0};
83 87 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID] = {0};
84 88 unsigned short sequenceCounterHK;
85 89 spw_stats grspw_stats = {0};
86 90
87 91 // TC_LFR_UPDATE_INFO
88 92 float cp_rpw_sc_rw1_f1 = INIT_FLOAT;
89 93 float cp_rpw_sc_rw1_f2 = INIT_FLOAT;
90 94 float cp_rpw_sc_rw2_f1 = INIT_FLOAT;
91 95 float cp_rpw_sc_rw2_f2 = INIT_FLOAT;
92 96 float cp_rpw_sc_rw3_f1 = INIT_FLOAT;
93 97 float cp_rpw_sc_rw3_f2 = INIT_FLOAT;
94 98 float cp_rpw_sc_rw4_f1 = INIT_FLOAT;
95 99 float cp_rpw_sc_rw4_f2 = INIT_FLOAT;
96 100
97 101 // TC_LFR_LOAD_FILTER_PAR
98 102 filterPar_t filterPar = {0};
99 103
100 104 fbins_masks_t fbins_masks = {0};
101 105 unsigned int acquisitionDurations[NB_ACQUISITION_DURATION]
102 106 = {ACQUISITION_DURATION_F0, ACQUISITION_DURATION_F1, ACQUISITION_DURATION_F2};
@@ -1,1631 +1,1631
1 1 /** Functions related to the SpaceWire interface.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle SpaceWire transmissions:
7 7 * - configuration of the SpaceWire link
8 8 * - SpaceWire related interruption requests processing
9 9 * - transmission of TeleMetry packets by a dedicated RTEMS task
10 10 * - reception of TeleCommands by a dedicated RTEMS task
11 11 *
12 12 */
13 13
14 14 #include "fsw_spacewire.h"
15 15
16 16 rtems_name semq_name = 0;
17 17 rtems_id semq_id = RTEMS_ID_NONE;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF = {0};
22 Header_TM_LFR_SCIENCE_SWF_t headerSW = {0};
22 Header_TM_LFR_SCIENCE_SWF_t headerSWF = {0};
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM = {0};
24 24
25 25 unsigned char previousTimecodeCtr = 0;
26 26 unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
27 27
28 28 //***********
29 29 // RTEMS TASK
30 30 rtems_task spiq_task(rtems_task_argument unused)
31 31 {
32 32 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
33 33 *
34 34 * @param unused is the starting argument of the RTEMS task
35 35 *
36 36 */
37 37
38 38 rtems_event_set event_out;
39 39 rtems_status_code status;
40 40 int linkStatus;
41 41
42 42 event_out = EVENT_SETS_NONE_PENDING;
43 43 linkStatus = 0;
44 44
45 45 BOOT_PRINTF("in SPIQ *** \n")
46 46
47 47 while(true){
48 48 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
49 49 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
50 50
51 51 // [0] SUSPEND RECV AND SEND TASKS
52 52 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
53 53 if ( status != RTEMS_SUCCESSFUL ) {
54 54 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
55 55 }
56 56 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
57 57 if ( status != RTEMS_SUCCESSFUL ) {
58 58 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
59 59 }
60 60
61 61 // [1] CHECK THE LINK
62 62 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
63 63 if ( linkStatus != SPW_LINK_OK) {
64 64 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
65 65 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
66 66 }
67 67
68 68 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
69 69 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
70 70 if ( linkStatus != SPW_LINK_OK ) // [2.a] not in run state, reset the link
71 71 {
72 72 spacewire_read_statistics();
73 73 status = spacewire_several_connect_attemps( );
74 74 }
75 75 else // [2.b] in run state, start the link
76 76 {
77 77 status = spacewire_stop_and_start_link( fdSPW ); // start the link
78 78 if ( status != RTEMS_SUCCESSFUL)
79 79 {
80 80 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
81 81 }
82 82 }
83 83
84 84 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
85 85 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
86 86 {
87 87 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
88 88 if ( status != RTEMS_SUCCESSFUL ) {
89 89 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
90 90 }
91 91 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
92 92 if ( status != RTEMS_SUCCESSFUL ) {
93 93 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
94 94 }
95 95 }
96 96 else // [3.b] the link is not in run state, go in STANDBY mode
97 97 {
98 98 status = enter_mode_standby();
99 99 if ( status != RTEMS_SUCCESSFUL )
100 100 {
101 101 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
102 102 }
103 103 {
104 104 updateLFRCurrentMode( LFR_MODE_STANDBY );
105 105 }
106 106 // wake the LINK task up to wait for the link recovery
107 107 status = rtems_event_send ( Task_id[TASKID_LINK], RTEMS_EVENT_0 );
108 108 status = rtems_task_suspend( RTEMS_SELF );
109 109 }
110 110 }
111 111 }
112 112
113 113 rtems_task recv_task( rtems_task_argument unused )
114 114 {
115 115 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
116 116 *
117 117 * @param unused is the starting argument of the RTEMS task
118 118 *
119 119 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
120 120 * 1. It reads the incoming data.
121 121 * 2. Launches the acceptance procedure.
122 122 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
123 123 *
124 124 */
125 125
126 126 int len;
127 127 ccsdsTelecommandPacket_t currentTC;
128 128 unsigned char computed_CRC[ BYTES_PER_CRC ];
129 129 unsigned char currentTC_LEN_RCV[ BYTES_PER_PKT_LEN ];
130 130 unsigned char destinationID;
131 131 unsigned int estimatedPacketLength;
132 132 unsigned int parserCode;
133 133 rtems_status_code status;
134 134 rtems_id queue_recv_id;
135 135 rtems_id queue_send_id;
136 136
137 137 memset( &currentTC, 0, sizeof(ccsdsTelecommandPacket_t) );
138 138 destinationID = 0;
139 139 queue_recv_id = RTEMS_ID_NONE;
140 140 queue_send_id = RTEMS_ID_NONE;
141 141
142 142 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
143 143
144 144 status = get_message_queue_id_recv( &queue_recv_id );
145 145 if (status != RTEMS_SUCCESSFUL)
146 146 {
147 147 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
148 148 }
149 149
150 150 status = get_message_queue_id_send( &queue_send_id );
151 151 if (status != RTEMS_SUCCESSFUL)
152 152 {
153 153 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
154 154 }
155 155
156 156 BOOT_PRINTF("in RECV *** \n")
157 157
158 158 while(1)
159 159 {
160 160 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
161 161 if (len == -1){ // error during the read call
162 162 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
163 163 }
164 164 else {
165 165 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
166 166 PRINTF("in RECV *** packet lenght too short\n")
167 167 }
168 168 else {
169 169 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - PROTID_RES_APP); // => -3 is for Prot ID, Reserved and User App bytes
170 170 //PRINTF1("incoming TC with Length (byte): %d\n", len - 3);
171 171 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> SHIFT_1_BYTE);
172 172 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
173 173 // CHECK THE TC
174 174 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
175 175 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
176 176 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
177 177 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
178 178 || (parserCode == WRONG_SRC_ID) )
179 179 { // send TM_LFR_TC_EXE_CORRUPTED
180 180 PRINTF1("TC corrupted received, with code: %d\n", parserCode);
181 181 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
182 182 &&
183 183 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
184 184 )
185 185 {
186 186 if ( parserCode == WRONG_SRC_ID )
187 187 {
188 188 destinationID = SID_TC_GROUND;
189 189 }
190 190 else
191 191 {
192 192 destinationID = currentTC.sourceID;
193 193 }
194 194 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
195 195 computed_CRC, currentTC_LEN_RCV,
196 196 destinationID );
197 197 }
198 198 }
199 199 else
200 200 { // send valid TC to the action launcher
201 201 status = rtems_message_queue_send( queue_recv_id, &currentTC,
202 202 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + PROTID_RES_APP);
203 203 }
204 204 }
205 205 }
206 206
207 207 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
208 208
209 209 }
210 210 }
211 211
212 212 rtems_task send_task( rtems_task_argument argument)
213 213 {
214 214 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
215 215 *
216 216 * @param unused is the starting argument of the RTEMS task
217 217 *
218 218 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
219 219 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
220 220 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
221 221 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
222 222 * data it contains.
223 223 *
224 224 */
225 225
226 226 rtems_status_code status; // RTEMS status code
227 227 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
228 228 ring_node *incomingRingNodePtr;
229 229 int ring_node_address;
230 230 char *charPtr;
231 231 spw_ioctl_pkt_send *spw_ioctl_send;
232 232 size_t size; // size of the incoming TC packet
233 233 rtems_id queue_send_id;
234 234 unsigned int sid;
235 235 unsigned char sidAsUnsignedChar;
236 236 unsigned char type;
237 237
238 238 incomingRingNodePtr = NULL;
239 239 ring_node_address = 0;
240 240 charPtr = (char *) &ring_node_address;
241 241 size = 0;
242 242 queue_send_id = RTEMS_ID_NONE;
243 243 sid = 0;
244 244 sidAsUnsignedChar = 0;
245 245
246 246 init_header_cwf( &headerCWF );
247 247 init_header_swf( &headerSWF );
248 248 init_header_asm( &headerASM );
249 249
250 250 status = get_message_queue_id_send( &queue_send_id );
251 251 if (status != RTEMS_SUCCESSFUL)
252 252 {
253 253 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
254 254 }
255 255
256 256 BOOT_PRINTF("in SEND *** \n")
257 257
258 258 while(1)
259 259 {
260 260 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
261 261 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
262 262
263 263 if (status!=RTEMS_SUCCESSFUL)
264 264 {
265 265 PRINTF1("in SEND *** (1) ERR = %d\n", status)
266 266 }
267 267 else
268 268 {
269 269 if ( size == sizeof(ring_node*) )
270 270 {
271 271 charPtr[0] = incomingData[0];
272 272 charPtr[1] = incomingData[1];
273 273 charPtr[BYTE_2] = incomingData[BYTE_2];
274 274 charPtr[BYTE_3] = incomingData[BYTE_3];
275 275 incomingRingNodePtr = (ring_node*) ring_node_address;
276 276 sid = incomingRingNodePtr->sid;
277 277 if ( (sid==SID_NORM_CWF_LONG_F3)
278 278 || (sid==SID_BURST_CWF_F2 )
279 279 || (sid==SID_SBM1_CWF_F1 )
280 280 || (sid==SID_SBM2_CWF_F2 ))
281 281 {
282 282 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
283 283 }
284 284 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
285 285 {
286 286 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
287 287 }
288 288 else if ( (sid==SID_NORM_CWF_F3) )
289 289 {
290 290 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
291 291 }
292 292 else if (sid==SID_NORM_ASM_F0)
293 293 {
294 294 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
295 295 }
296 296 else if (sid==SID_NORM_ASM_F1)
297 297 {
298 298 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
299 299 }
300 300 else if (sid==SID_NORM_ASM_F2)
301 301 {
302 302 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
303 303 }
304 304 else if ( sid==TM_CODE_K_DUMP )
305 305 {
306 306 spw_send_k_dump( incomingRingNodePtr );
307 307 }
308 308 else
309 309 {
310 310 PRINTF1("unexpected sid = %d\n", sid);
311 311 }
312 312 }
313 313 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
314 314 {
315 315 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
316 316 sid = sidAsUnsignedChar;
317 317 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
318 318 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
319 319 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
320 320 {
321 321 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
322 322 }
323 323
324 324 status = write( fdSPW, incomingData, size );
325 325 if (status == -1){
326 326 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
327 327 }
328 328 }
329 329 else // the incoming message is a spw_ioctl_pkt_send structure
330 330 {
331 331 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
332 332 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
333 333 if (status == -1){
334 334 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
335 335 }
336 336 }
337 337 }
338 338
339 339 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
340 340
341 341 }
342 342 }
343 343
344 344 rtems_task link_task( rtems_task_argument argument )
345 345 {
346 346 rtems_event_set event_out;
347 347 rtems_status_code status;
348 348 int linkStatus;
349 349
350 350 event_out = EVENT_SETS_NONE_PENDING;
351 351 linkStatus = 0;
352 352
353 353 BOOT_PRINTF("in LINK ***\n")
354 354
355 355 while(1)
356 356 {
357 357 // wait for an RTEMS_EVENT
358 358 rtems_event_receive( RTEMS_EVENT_0,
359 359 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
360 360 PRINTF("in LINK *** wait for the link\n")
361 361 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
362 362 while( linkStatus != SPW_LINK_OK) // wait for the link
363 363 {
364 364 status = rtems_task_wake_after( SPW_LINK_WAIT ); // monitor the link each 100ms
365 365 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
366 366 watchdog_reload();
367 367 }
368 368
369 369 spacewire_read_statistics();
370 370 status = spacewire_stop_and_start_link( fdSPW );
371 371
372 372 if (status != RTEMS_SUCCESSFUL)
373 373 {
374 374 PRINTF1("in LINK *** ERR link not started %d\n", status)
375 375 }
376 376 else
377 377 {
378 378 PRINTF("in LINK *** OK link started\n")
379 379 }
380 380
381 381 // restart the SPIQ task
382 382 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
383 383 if ( status != RTEMS_SUCCESSFUL ) {
384 384 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
385 385 }
386 386
387 387 // restart RECV and SEND
388 388 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
389 389 if ( status != RTEMS_SUCCESSFUL ) {
390 390 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
391 391 }
392 392 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
393 393 if ( status != RTEMS_SUCCESSFUL ) {
394 394 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
395 395 }
396 396 }
397 397 }
398 398
399 399 //****************
400 400 // OTHER FUNCTIONS
401 401 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
402 402 {
403 403 /** This function opens the SpaceWire link.
404 404 *
405 405 * @return a valid file descriptor in case of success, -1 in case of a failure
406 406 *
407 407 */
408 408 rtems_status_code status;
409 409
410 410 status = RTEMS_SUCCESSFUL;
411 411
412 412 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
413 413 if ( fdSPW < 0 ) {
414 414 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
415 415 }
416 416 else
417 417 {
418 418 status = RTEMS_SUCCESSFUL;
419 419 }
420 420
421 421 return status;
422 422 }
423 423
424 424 int spacewire_start_link( int fd )
425 425 {
426 426 rtems_status_code status;
427 427
428 428 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
429 429 // -1 default hardcoded driver timeout
430 430
431 431 return status;
432 432 }
433 433
434 434 int spacewire_stop_and_start_link( int fd )
435 435 {
436 436 rtems_status_code status;
437 437
438 438 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
439 439 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
440 440 // -1 default hardcoded driver timeout
441 441
442 442 return status;
443 443 }
444 444
445 445 int spacewire_configure_link( int fd )
446 446 {
447 447 /** This function configures the SpaceWire link.
448 448 *
449 449 * @return GR-RTEMS-DRIVER directive status codes:
450 450 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
451 451 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
452 452 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
453 453 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
454 454 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
455 455 * - 5 EIO - Error when writing to grswp hardware registers.
456 456 * - 2 ENOENT - No such file or directory
457 457 */
458 458
459 459 rtems_status_code status;
460 460
461 461 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
462 462 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
463 463 spw_ioctl_packetsize packetsize;
464 464
465 465 packetsize.rxsize = SPW_RXSIZE;
466 466 packetsize.txdsize = SPW_TXDSIZE;
467 467 packetsize.txhsize = SPW_TXHSIZE;
468 468
469 469 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
470 470 if (status!=RTEMS_SUCCESSFUL) {
471 471 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
472 472 }
473 473 //
474 474 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
475 475 if (status!=RTEMS_SUCCESSFUL) {
476 476 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
477 477 }
478 478 //
479 479 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
480 480 if (status!=RTEMS_SUCCESSFUL) {
481 481 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
482 482 }
483 483 //
484 484 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
485 485 if (status!=RTEMS_SUCCESSFUL) {
486 486 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
487 487 }
488 488 //
489 489 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
490 490 if (status!=RTEMS_SUCCESSFUL) {
491 491 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
492 492 }
493 493 //
494 494 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
495 495 if (status!=RTEMS_SUCCESSFUL) {
496 496 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
497 497 }
498 498 //
499 499 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, CONF_TCODE_CTRL); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
500 500 if (status!=RTEMS_SUCCESSFUL) {
501 501 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
502 502 }
503 503 //
504 504 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_PACKETSIZE, packetsize); // set rxsize, txdsize and txhsize
505 505 if (status!=RTEMS_SUCCESSFUL) {
506 506 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_PACKETSIZE,\n")
507 507 }
508 508
509 509 return status;
510 510 }
511 511
512 512 int spacewire_several_connect_attemps( void )
513 513 {
514 514 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
515 515 *
516 516 * @return RTEMS directive status code:
517 517 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
518 518 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
519 519 *
520 520 */
521 521
522 522 rtems_status_code status_spw;
523 523 rtems_status_code status;
524 524 int i;
525 525
526 526 status_spw = RTEMS_SUCCESSFUL;
527 527
528 528 i = 0;
529 529 while (i < SY_LFR_DPU_CONNECT_ATTEMPT)
530 530 {
531 531 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
532 532
533 533 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
534 534
535 535 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
536 536
537 537 status_spw = spacewire_stop_and_start_link( fdSPW );
538 538
539 539 if ( status_spw != RTEMS_SUCCESSFUL )
540 540 {
541 541 i = i + 1;
542 542 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw);
543 543 }
544 544 else
545 545 {
546 546 i = SY_LFR_DPU_CONNECT_ATTEMPT;
547 547 }
548 548 }
549 549
550 550 return status_spw;
551 551 }
552 552
553 553 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
554 554 {
555 555 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
556 556 *
557 557 * @param val is the value, 0 or 1, used to set the value of the NP bit.
558 558 * @param regAddr is the address of the GRSPW control register.
559 559 *
560 560 * NP is the bit 20 of the GRSPW control register.
561 561 *
562 562 */
563 563
564 564 unsigned int *spwptr = (unsigned int*) regAddr;
565 565
566 566 if (val == 1) {
567 567 *spwptr = *spwptr | SPW_BIT_NP; // [NP] set the No port force bit
568 568 }
569 569 if (val== 0) {
570 570 *spwptr = *spwptr & SPW_BIT_NP_MASK;
571 571 }
572 572 }
573 573
574 574 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
575 575 {
576 576 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
577 577 *
578 578 * @param val is the value, 0 or 1, used to set the value of the RE bit.
579 579 * @param regAddr is the address of the GRSPW control register.
580 580 *
581 581 * RE is the bit 16 of the GRSPW control register.
582 582 *
583 583 */
584 584
585 585 unsigned int *spwptr = (unsigned int*) regAddr;
586 586
587 587 if (val == 1)
588 588 {
589 589 *spwptr = *spwptr | SPW_BIT_RE; // [RE] set the RMAP Enable bit
590 590 }
591 591 if (val== 0)
592 592 {
593 593 *spwptr = *spwptr & SPW_BIT_RE_MASK;
594 594 }
595 595 }
596 596
597 597 void spacewire_read_statistics( void )
598 598 {
599 599 /** This function reads the SpaceWire statistics from the grspw RTEMS driver.
600 600 *
601 601 * @param void
602 602 *
603 603 * @return void
604 604 *
605 605 * Once they are read, the counters are stored in a global variable used during the building of the
606 606 * HK packets.
607 607 *
608 608 */
609 609
610 610 rtems_status_code status;
611 611 spw_stats current;
612 612
613 613 memset(&current, 0, sizeof(spw_stats));
614 614
615 615 spacewire_get_last_error();
616 616
617 617 // read the current statistics
618 618 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &current );
619 619
620 620 // clear the counters
621 621 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_CLR_STATISTICS );
622 622
623 623 // typedef struct {
624 624 // unsigned int tx_link_err; // NOT IN HK
625 625 // unsigned int rx_rmap_header_crc_err; // NOT IN HK
626 626 // unsigned int rx_rmap_data_crc_err; // NOT IN HK
627 627 // unsigned int rx_eep_err;
628 628 // unsigned int rx_truncated;
629 629 // unsigned int parity_err;
630 630 // unsigned int escape_err;
631 631 // unsigned int credit_err;
632 632 // unsigned int write_sync_err;
633 633 // unsigned int disconnect_err;
634 634 // unsigned int early_ep;
635 635 // unsigned int invalid_address;
636 636 // unsigned int packets_sent;
637 637 // unsigned int packets_received;
638 638 // } spw_stats;
639 639
640 640 // rx_eep_err
641 641 grspw_stats.rx_eep_err = grspw_stats.rx_eep_err + current.rx_eep_err;
642 642 // rx_truncated
643 643 grspw_stats.rx_truncated = grspw_stats.rx_truncated + current.rx_truncated;
644 644 // parity_err
645 645 grspw_stats.parity_err = grspw_stats.parity_err + current.parity_err;
646 646 // escape_err
647 647 grspw_stats.escape_err = grspw_stats.escape_err + current.escape_err;
648 648 // credit_err
649 649 grspw_stats.credit_err = grspw_stats.credit_err + current.credit_err;
650 650 // write_sync_err
651 651 grspw_stats.write_sync_err = grspw_stats.write_sync_err + current.write_sync_err;
652 652 // disconnect_err
653 653 grspw_stats.disconnect_err = grspw_stats.disconnect_err + current.disconnect_err;
654 654 // early_ep
655 655 grspw_stats.early_ep = grspw_stats.early_ep + current.early_ep;
656 656 // invalid_address
657 657 grspw_stats.invalid_address = grspw_stats.invalid_address + current.invalid_address;
658 658 // packets_sent
659 659 grspw_stats.packets_sent = grspw_stats.packets_sent + current.packets_sent;
660 660 // packets_received