##// END OF EJS Templates
timecode handling modified:...
paul -
r248:c648c60c0eef R3a
parent child
Show More
@@ -1,2 +1,2
1 1 3081d1f9bb20b2b64a192585337a292a9804e0c5 LFR_basic-parameters
2 ce0c2f17257170a8529605f68687c18f23973087 header/lfr_common_headers
2 084fd0db5e4139a1096789935e32ef498192f395 header/lfr_common_headers
@@ -1,51 +1,54
1 1 #ifndef FSW_INIT_H_INCLUDED
2 2 #define FSW_INIT_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <leon.h>
6 6
7 7 #include "fsw_params.h"
8 8 #include "fsw_misc.h"
9 9 #include "fsw_processing.h"
10 10
11 11 #include "tc_handler.h"
12 12 #include "wf_handler.h"
13 13 #include "fsw_spacewire.h"
14 14
15 15 #include "avf0_prc0.h"
16 16 #include "avf1_prc1.h"
17 17 #include "avf2_prc2.h"
18 18
19 19 extern rtems_name Task_name[20]; /* array of task names */
20 20 extern rtems_id Task_id[20]; /* array of task ids */
21 extern rtems_name timecode_timer_name;
22 extern rtems_id timecode_timer_id;
21 23 extern unsigned char pa_bia_status_info;
22 24
23 25 // RTEMS TASKS
24 26 rtems_task Init( rtems_task_argument argument);
25 27
26 28 // OTHER functions
27 29 void create_names( void );
28 30 int create_all_tasks( void );
29 31 int start_all_tasks( void );
30 32 //
31 33 rtems_status_code create_message_queues( void );
34 rtems_status_code create_timecode_timer( void );
32 35 rtems_status_code get_message_queue_id_send( rtems_id *queue_id );
33 36 rtems_status_code get_message_queue_id_recv( rtems_id *queue_id );
34 37 rtems_status_code get_message_queue_id_prc0( rtems_id *queue_id );
35 38 rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id );
36 39 rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id );
37 40 void update_queue_max_count( rtems_id queue_id, unsigned char*fifo_size_max );
38 41 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize );
39 42 //
40 43 int start_recv_send_tasks( void );
41 44 //
42 45 void init_local_mode_parameters( void );
43 46 void reset_local_time( void );
44 47
45 48 extern void rtems_cpu_usage_report( void );
46 49 extern void rtems_cpu_usage_reset( void );
47 50 extern void rtems_stack_checker_report_usage( void );
48 51
49 52 extern int sched_yield( void );
50 53
51 54 #endif // FSW_INIT_H_INCLUDED
@@ -1,50 +1,56
1 1 #ifndef FSW_SPACEWIRE_H_INCLUDED
2 2 #define FSW_SPACEWIRE_H_INCLUDED
3 3
4 4 #include <rtems.h>
5 5 #include <grspw.h>
6 6
7 7 #include <fcntl.h> // for O_RDWR
8 8 #include <unistd.h> // for the read call
9 9 #include <sys/ioctl.h> // for the ioctl call
10 10 #include <errno.h>
11 11
12 12 #include "fsw_params.h"
13 13 #include "tc_handler.h"
14 14 #include "fsw_init.h"
15 15
16 16 extern spw_stats spacewire_stats;
17 17 extern spw_stats spacewire_stats_backup;
18 extern rtems_name timecode_timer_name;
19 extern rtems_id timecode_timer_id;
18 20
19 21 // RTEMS TASK
20 22 rtems_task spiq_task( rtems_task_argument argument );
21 23 rtems_task recv_task( rtems_task_argument unused );
22 24 rtems_task send_task( rtems_task_argument argument );
23 25 rtems_task wtdg_task( rtems_task_argument argument );
24 26
25 27 int spacewire_open_link( void );
26 28 int spacewire_start_link( int fd );
27 29 int spacewire_stop_and_start_link( int fd );
28 30 int spacewire_configure_link(int fd );
29 31 int spacewire_reset_link( void );
30 32 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
31 33 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
32 34 void spacewire_compute_stats_offsets( void );
33 35 void spacewire_update_statistics( void );
36 void increase_an_unsigned_char_counter( unsigned char *counter );
34 37
35 38 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
36 39 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
37 40 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
38 41 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
39 42 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
40 43 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
41 44 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
42 45 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
43 46 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
44 47 void spw_send_k_dump( ring_node *ring_node_to_send );
45 48
49 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
50 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
51 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
46 52 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
47 53
48 54 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
49 55
50 56 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,80 +1,82
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 // RTEMS GLOBAL VARIABLES
26 26 rtems_name misc_name[5];
27 27 rtems_name Task_name[20]; /* array of task names */
28 28 rtems_id Task_id[20]; /* array of task ids */
29 rtems_name timecode_timer_name;
30 rtems_id timecode_timer_id;
29 31 int fdSPW = 0;
30 32 int fdUART = 0;
31 33 unsigned char lfrCurrentMode;
32 34 unsigned char pa_bia_status_info;
33 35
34 36 // WAVEFORMS GLOBAL VARIABLES // 2048 * 3 * 4 + 2 * 4 = 24576 + 8 bytes = 24584
35 37 // 97 * 256 = 24832 => delta = 248 bytes = 62 words
36 38 // WAVEFORMS GLOBAL VARIABLES // 2688 * 3 * 4 + 2 * 4 = 32256 + 8 bytes = 32264
37 39 // 127 * 256 = 32512 => delta = 248 bytes = 62 words
38 40 // F0 F1 F2 F3
39 41 volatile int wf_buffer_f0[ NB_RING_NODES_F0 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
40 42 volatile int wf_buffer_f1[ NB_RING_NODES_F1 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
41 43 volatile int wf_buffer_f2[ NB_RING_NODES_F2 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
42 44 volatile int wf_buffer_f3[ NB_RING_NODES_F3 * WFRM_BUFFER ] __attribute__((aligned(0x100)));
43 45
44 46 //***********************************
45 47 // SPECTRAL MATRICES GLOBAL VARIABLES
46 48
47 49 // alignment constraints for the spectral matrices buffers => the first data after the time (8 bytes) shall be aligned on 0x00
48 50 volatile int sm_f0[ NB_RING_NODES_SM_F0 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
49 51 volatile int sm_f1[ NB_RING_NODES_SM_F1 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
50 52 volatile int sm_f2[ NB_RING_NODES_SM_F2 * TOTAL_SIZE_SM ] __attribute__((aligned(0x100)));
51 53
52 54 // APB CONFIGURATION REGISTERS
53 55 time_management_regs_t *time_management_regs = (time_management_regs_t*) REGS_ADDR_TIME_MANAGEMENT;
54 56 gptimer_regs_t *gptimer_regs = (gptimer_regs_t *) REGS_ADDR_GPTIMER;
55 57 waveform_picker_regs_0_1_18_t *waveform_picker_regs = (waveform_picker_regs_0_1_18_t*) REGS_ADDR_WAVEFORM_PICKER;
56 58 spectral_matrix_regs_t *spectral_matrix_regs = (spectral_matrix_regs_t*) REGS_ADDR_SPECTRAL_MATRIX;
57 59
58 60 // MODE PARAMETERS
59 61 Packet_TM_LFR_PARAMETER_DUMP_t parameter_dump_packet;
60 62 struct param_local_str param_local;
61 63 unsigned int lastValidEnterModeTime;
62 64
63 65 // HK PACKETS
64 66 Packet_TM_LFR_HK_t housekeeping_packet;
65 67 // message queues occupancy
66 68 unsigned char hk_lfr_q_sd_fifo_size_max;
67 69 unsigned char hk_lfr_q_rv_fifo_size_max;
68 70 unsigned char hk_lfr_q_p0_fifo_size_max;
69 71 unsigned char hk_lfr_q_p1_fifo_size_max;
70 72 unsigned char hk_lfr_q_p2_fifo_size_max;
71 73 // sequence counters are incremented by APID (PID + CAT) and destination ID
72 74 unsigned short sequenceCounters_SCIENCE_NORMAL_BURST;
73 75 unsigned short sequenceCounters_SCIENCE_SBM1_SBM2;
74 76 unsigned short sequenceCounters_TC_EXE[SEQ_CNT_NB_DEST_ID];
75 77 unsigned short sequenceCounters_TM_DUMP[SEQ_CNT_NB_DEST_ID];
76 78 unsigned short sequenceCounterHK;
77 79 spw_stats spacewire_stats;
78 80 spw_stats spacewire_stats_backup;
79 81
80 82
@@ -1,865 +1,891
1 1 /** This is the RTEMS initialization module.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * This module contains two very different information:
7 7 * - specific instructions to configure the compilation of the RTEMS executive
8 8 * - functions related to the fligth softwre initialization, especially the INIT RTEMS task
9 9 *
10 10 */
11 11
12 12 //*************************
13 13 // GPL reminder to be added
14 14 //*************************
15 15
16 16 #include <rtems.h>
17 17
18 18 /* configuration information */
19 19
20 20 #define CONFIGURE_INIT
21 21
22 22 #include <bsp.h> /* for device driver prototypes */
23 23
24 24 /* configuration information */
25 25
26 26 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
27 27 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
28 28
29 29 #define CONFIGURE_MAXIMUM_TASKS 20
30 30 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
31 31 #define CONFIGURE_EXTRA_TASK_STACKS (3 * RTEMS_MINIMUM_STACK_SIZE)
32 32 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
33 33 #define CONFIGURE_INIT_TASK_PRIORITY 1 // instead of 100
34 34 #define CONFIGURE_INIT_TASK_MODE (RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT)
35 35 #define CONFIGURE_INIT_TASK_ATTRIBUTES (RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT)
36 36 #define CONFIGURE_MAXIMUM_DRIVERS 16
37 37 #define CONFIGURE_MAXIMUM_PERIODS 5
38 #define CONFIGURE_MAXIMUM_TIMERS 5 // STAT (1s), send SWF (0.3s), send CWF3 (1s)
38 #define CONFIGURE_MAXIMUM_TIMERS 5 // [spiq] [wtdg] [spacewire_reset_link]
39 39 #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 5
40 40 #ifdef PRINT_STACK_REPORT
41 41 #define CONFIGURE_STACK_CHECKER_ENABLED
42 42 #endif
43 43
44 44 #include <rtems/confdefs.h>
45 45
46 46 /* If --drvmgr was enabled during the configuration of the RTEMS kernel */
47 47 #ifdef RTEMS_DRVMGR_STARTUP
48 48 #ifdef LEON3
49 49 /* Add Timer and UART Driver */
50 50 #ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
51 51 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER
52 52 #endif
53 53 #ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
54 54 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART
55 55 #endif
56 56 #endif
57 57 #define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW /* GRSPW Driver */
58 58 #include <drvmgr/drvmgr_confdefs.h>
59 59 #endif
60 60
61 61 #include "fsw_init.h"
62 62 #include "fsw_config.c"
63 63 #include "GscMemoryLPP.hpp"
64 64
65 65 void initCache()
66 66 {
67 67 unsigned int cacheControlRegister;
68 68
69 69 cacheControlRegister = getCacheControlRegister();
70 70 PRINTF1("(0) cacheControlRegister = %x\n", cacheControlRegister)
71 71
72 72 resetCacheControlRegister();
73 73
74 74 enableInstructionCache();
75 75 enableDataCache();
76 76 enableInstructionBurstFetch();
77 77
78 78 cacheControlRegister = getCacheControlRegister();
79 79 PRINTF1("(1) cacheControlRegister = %x\n", cacheControlRegister)
80 80 }
81 81
82 82 rtems_task Init( rtems_task_argument ignored )
83 83 {
84 84 /** This is the RTEMS INIT taks, it is the first task launched by the system.
85 85 *
86 86 * @param unused is the starting argument of the RTEMS task
87 87 *
88 88 * The INIT task create and run all other RTEMS tasks.
89 89 *
90 90 */
91 91
92 92 //***********
93 93 // INIT CACHE
94 94
95 95 unsigned char *vhdlVersion;
96 96
97 97 reset_lfr();
98 98
99 99 reset_local_time();
100 100
101 101 rtems_cpu_usage_reset();
102 102
103 103 rtems_status_code status;
104 104 rtems_status_code status_spw;
105 105 rtems_isr_entry old_isr_handler;
106 106
107 107 // UART settings
108 108 send_console_outputs_on_apbuart_port();
109 109 set_apbuart_scaler_reload_register(REGS_ADDR_APBUART, APBUART_SCALER_RELOAD_VALUE);
110 110 enable_apbuart_transmitter();
111 111
112 112 DEBUG_PRINTF("\n\n\n\n\nIn INIT *** Now the console is on port COM1\n")
113 113
114 114
115 115 PRINTF("\n\n\n\n\n")
116 116
117 117 initCache();
118 118
119 119 PRINTF("*************************\n")
120 120 PRINTF("** LFR Flight Software **\n")
121 121 PRINTF1("** %d.", SW_VERSION_N1)
122 122 PRINTF1("%d." , SW_VERSION_N2)
123 123 PRINTF1("%d." , SW_VERSION_N3)
124 124 PRINTF1("%d **\n", SW_VERSION_N4)
125 125
126 126 vhdlVersion = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
127 127 PRINTF("** VHDL **\n")
128 128 PRINTF1("** %d.", vhdlVersion[1])
129 129 PRINTF1("%d." , vhdlVersion[2])
130 130 PRINTF1("%d **\n", vhdlVersion[3])
131 131 PRINTF("*************************\n")
132 132 PRINTF("\n\n")
133 133
134 134 init_parameter_dump();
135 135 init_kcoefficients_dump();
136 136 init_local_mode_parameters();
137 137 init_housekeeping_parameters();
138 138 init_k_coefficients_prc0();
139 139 init_k_coefficients_prc1();
140 140 init_k_coefficients_prc2();
141 141 pa_bia_status_info = 0x00;
142 142 update_last_valid_transition_date( DEFAULT_LAST_VALID_TRANSITION_DATE );
143 143
144 144 // waveform picker initialization
145 145 WFP_init_rings(); LEON_Clear_interrupt( IRQ_SPARC_GPTIMER_WATCHDOG ); // initialize the waveform rings
146 146 WFP_reset_current_ring_nodes();
147 147 reset_waveform_picker_regs();
148 148
149 149 // spectral matrices initialization
150 150 SM_init_rings(); // initialize spectral matrices rings
151 151 SM_reset_current_ring_nodes();
152 152 reset_spectral_matrix_regs();
153 153
154 154 // configure calibration
155 155 configureCalibration( false ); // true means interleaved mode, false is for normal mode
156 156
157 157 updateLFRCurrentMode();
158 158
159 159 BOOT_PRINTF1("in INIT *** lfrCurrentMode is %d\n", lfrCurrentMode)
160 160
161 161 create_names(); // create all names
162 162
163 status = create_timecode_timer(); // create the timer used by timecode_irq_handler
164 if (status != RTEMS_SUCCESSFUL)
165 {
166 PRINTF1("in INIT *** ERR in create_timer_timecode, code %d", status)
167 }
168
163 169 status = create_message_queues(); // create message queues
164 170 if (status != RTEMS_SUCCESSFUL)
165 171 {
166 172 PRINTF1("in INIT *** ERR in create_message_queues, code %d", status)
167 173 }
168 174
169 175 status = create_all_tasks(); // create all tasks
170 176 if (status != RTEMS_SUCCESSFUL)
171 177 {
172 178 PRINTF1("in INIT *** ERR in create_all_tasks, code %d\n", status)
173 179 }
174 180
175 181 // **************************
176 182 // <SPACEWIRE INITIALIZATION>
177 183 grspw_timecode_callback = &timecode_irq_handler;
178 184
179 185 status_spw = spacewire_open_link(); // (1) open the link
180 186 if ( status_spw != RTEMS_SUCCESSFUL )
181 187 {
182 188 PRINTF1("in INIT *** ERR spacewire_open_link code %d\n", status_spw )
183 189 }
184 190
185 191 if ( status_spw == RTEMS_SUCCESSFUL ) // (2) configure the link
186 192 {
187 193 status_spw = spacewire_configure_link( fdSPW );
188 194 if ( status_spw != RTEMS_SUCCESSFUL )
189 195 {
190 196 PRINTF1("in INIT *** ERR spacewire_configure_link code %d\n", status_spw )
191 197 }
192 198 }
193 199
194 200 if ( status_spw == RTEMS_SUCCESSFUL) // (3) start the link
195 201 {
196 202 status_spw = spacewire_start_link( fdSPW );
197 203 if ( status_spw != RTEMS_SUCCESSFUL )
198 204 {
199 205 PRINTF1("in INIT *** ERR spacewire_start_link code %d\n", status_spw )
200 206 }
201 207 }
202 208 // </SPACEWIRE INITIALIZATION>
203 209 // ***************************
204 210
205 211 status = start_all_tasks(); // start all tasks
206 212 if (status != RTEMS_SUCCESSFUL)
207 213 {
208 214 PRINTF1("in INIT *** ERR in start_all_tasks, code %d", status)
209 215 }
210 216
211 217 // start RECV and SEND *AFTER* SpaceWire Initialization, due to the timeout of the start call during the initialization
212 218 status = start_recv_send_tasks();
213 219 if ( status != RTEMS_SUCCESSFUL )
214 220 {
215 221 PRINTF1("in INIT *** ERR start_recv_send_tasks code %d\n", status )
216 222 }
217 223
218 224 // suspend science tasks, they will be restarted later depending on the mode
219 225 status = suspend_science_tasks(); // suspend science tasks (not done in stop_current_mode if current mode = STANDBY)
220 226 if (status != RTEMS_SUCCESSFUL)
221 227 {
222 228 PRINTF1("in INIT *** in suspend_science_tasks *** ERR code: %d\n", status)
223 229 }
224 230
225 231 // configure IRQ handling for the waveform picker unit
226 232 status = rtems_interrupt_catch( waveforms_isr,
227 233 IRQ_SPARC_WAVEFORM_PICKER,
228 234 &old_isr_handler) ;
229 235 // configure IRQ handling for the spectral matrices unit
230 236 status = rtems_interrupt_catch( spectral_matrices_isr,
231 237 IRQ_SPARC_SPECTRAL_MATRIX,
232 238 &old_isr_handler) ;
233 239
234 240 // if the spacewire link is not up then send an event to the SPIQ task for link recovery
235 241 if ( status_spw != RTEMS_SUCCESSFUL )
236 242 {
237 243 status = rtems_event_send( Task_id[TASKID_SPIQ], SPW_LINKERR_EVENT );
238 244 if ( status != RTEMS_SUCCESSFUL ) {
239 245 PRINTF1("in INIT *** ERR rtems_event_send to SPIQ code %d\n", status )
240 246 }
241 247 }
242 248
243 249 BOOT_PRINTF("delete INIT\n")
244 250
245 251 set_hk_lfr_sc_potential_flag( true );
246 252
247 253 status = rtems_task_delete(RTEMS_SELF);
248 254
249 255 }
250 256
251 257 void init_local_mode_parameters( void )
252 258 {
253 259 /** This function initialize the param_local global variable with default values.
254 260 *
255 261 */
256 262
257 263 unsigned int i;
258 264
259 265 // LOCAL PARAMETERS
260 266
261 267 BOOT_PRINTF1("local_sbm1_nb_cwf_max %d \n", param_local.local_sbm1_nb_cwf_max)
262 268 BOOT_PRINTF1("local_sbm2_nb_cwf_max %d \n", param_local.local_sbm2_nb_cwf_max)
263 269 BOOT_PRINTF1("nb_interrupt_f0_MAX = %d\n", param_local.local_nb_interrupt_f0_MAX)
264 270
265 271 // init sequence counters
266 272
267 273 for(i = 0; i<SEQ_CNT_NB_DEST_ID; i++)
268 274 {
269 275 sequenceCounters_TC_EXE[i] = 0x00;
270 276 sequenceCounters_TM_DUMP[i] = 0x00;
271 277 }
272 278 sequenceCounters_SCIENCE_NORMAL_BURST = 0x00;
273 279 sequenceCounters_SCIENCE_SBM1_SBM2 = 0x00;
274 280 sequenceCounterHK = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
275 281 }
276 282
277 283 void reset_local_time( void )
278 284 {
279 285 time_management_regs->ctrl = time_management_regs->ctrl | 0x02; // [0010] software reset, coarse time = 0x80000000
280 286 }
281 287
282 288 void create_names( void ) // create all names for tasks and queues
283 289 {
284 290 /** This function creates all RTEMS names used in the software for tasks and queues.
285 291 *
286 292 * @return RTEMS directive status codes:
287 293 * - RTEMS_SUCCESSFUL - successful completion
288 294 *
289 295 */
290 296
291 297 // task names
292 298 Task_name[TASKID_RECV] = rtems_build_name( 'R', 'E', 'C', 'V' );
293 299 Task_name[TASKID_ACTN] = rtems_build_name( 'A', 'C', 'T', 'N' );
294 300 Task_name[TASKID_SPIQ] = rtems_build_name( 'S', 'P', 'I', 'Q' );
295 301 Task_name[TASKID_LOAD] = rtems_build_name( 'L', 'O', 'A', 'D' );
296 302 Task_name[TASKID_AVF0] = rtems_build_name( 'A', 'V', 'F', '0' );
297 303 Task_name[TASKID_SWBD] = rtems_build_name( 'S', 'W', 'B', 'D' );
298 304 Task_name[TASKID_WFRM] = rtems_build_name( 'W', 'F', 'R', 'M' );
299 305 Task_name[TASKID_DUMB] = rtems_build_name( 'D', 'U', 'M', 'B' );
300 306 Task_name[TASKID_HOUS] = rtems_build_name( 'H', 'O', 'U', 'S' );
301 307 Task_name[TASKID_PRC0] = rtems_build_name( 'P', 'R', 'C', '0' );
302 308 Task_name[TASKID_CWF3] = rtems_build_name( 'C', 'W', 'F', '3' );
303 309 Task_name[TASKID_CWF2] = rtems_build_name( 'C', 'W', 'F', '2' );
304 310 Task_name[TASKID_CWF1] = rtems_build_name( 'C', 'W', 'F', '1' );
305 311 Task_name[TASKID_SEND] = rtems_build_name( 'S', 'E', 'N', 'D' );
306 312 Task_name[TASKID_WTDG] = rtems_build_name( 'W', 'T', 'D', 'G' );
307 313 Task_name[TASKID_AVF1] = rtems_build_name( 'A', 'V', 'F', '1' );
308 314 Task_name[TASKID_PRC1] = rtems_build_name( 'P', 'R', 'C', '1' );
309 315 Task_name[TASKID_AVF2] = rtems_build_name( 'A', 'V', 'F', '2' );
310 316 Task_name[TASKID_PRC2] = rtems_build_name( 'P', 'R', 'C', '2' );
311 317
312 318 // rate monotonic period names
313 319 name_hk_rate_monotonic = rtems_build_name( 'H', 'O', 'U', 'S' );
314 320
315 321 misc_name[QUEUE_RECV] = rtems_build_name( 'Q', '_', 'R', 'V' );
316 322 misc_name[QUEUE_SEND] = rtems_build_name( 'Q', '_', 'S', 'D' );
317 323 misc_name[QUEUE_PRC0] = rtems_build_name( 'Q', '_', 'P', '0' );
318 324 misc_name[QUEUE_PRC1] = rtems_build_name( 'Q', '_', 'P', '1' );
319 325 misc_name[QUEUE_PRC2] = rtems_build_name( 'Q', '_', 'P', '2' );
326
327 timecode_timer_name = rtems_build_name( 'S', 'P', 'T', 'C' );
320 328 }
321 329
322 330 int create_all_tasks( void ) // create all tasks which run in the software
323 331 {
324 332 /** This function creates all RTEMS tasks used in the software.
325 333 *
326 334 * @return RTEMS directive status codes:
327 335 * - RTEMS_SUCCESSFUL - task created successfully
328 336 * - RTEMS_INVALID_ADDRESS - id is NULL
329 337 * - RTEMS_INVALID_NAME - invalid task name
330 338 * - RTEMS_INVALID_PRIORITY - invalid task priority
331 339 * - RTEMS_MP_NOT_CONFIGURED - multiprocessing not configured
332 340 * - RTEMS_TOO_MANY - too many tasks created
333 341 * - RTEMS_UNSATISFIED - not enough memory for stack/FP context
334 342 * - RTEMS_TOO_MANY - too many global objects
335 343 *
336 344 */
337 345
338 346 rtems_status_code status;
339 347
340 348 //**********
341 349 // SPACEWIRE
342 350 // RECV
343 351 status = rtems_task_create(
344 352 Task_name[TASKID_RECV], TASK_PRIORITY_RECV, RTEMS_MINIMUM_STACK_SIZE,
345 353 RTEMS_DEFAULT_MODES,
346 354 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_RECV]
347 355 );
348 356 if (status == RTEMS_SUCCESSFUL) // SEND
349 357 {
350 358 status = rtems_task_create(
351 359 Task_name[TASKID_SEND], TASK_PRIORITY_SEND, RTEMS_MINIMUM_STACK_SIZE * 2,
352 360 RTEMS_DEFAULT_MODES,
353 361 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SEND]
354 362 );
355 363 }
356 364 if (status == RTEMS_SUCCESSFUL) // WTDG
357 365 {
358 366 status = rtems_task_create(
359 367 Task_name[TASKID_WTDG], TASK_PRIORITY_WTDG, RTEMS_MINIMUM_STACK_SIZE,
360 368 RTEMS_DEFAULT_MODES,
361 369 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_WTDG]
362 370 );
363 371 }
364 372 if (status == RTEMS_SUCCESSFUL) // ACTN
365 373 {
366 374 status = rtems_task_create(
367 375 Task_name[TASKID_ACTN], TASK_PRIORITY_ACTN, RTEMS_MINIMUM_STACK_SIZE,
368 376 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
369 377 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_ACTN]
370 378 );
371 379 }
372 380 if (status == RTEMS_SUCCESSFUL) // SPIQ
373 381 {
374 382 status = rtems_task_create(
375 383 Task_name[TASKID_SPIQ], TASK_PRIORITY_SPIQ, RTEMS_MINIMUM_STACK_SIZE,
376 384 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
377 385 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SPIQ]
378 386 );
379 387 }
380 388
381 389 //******************
382 390 // SPECTRAL MATRICES
383 391 if (status == RTEMS_SUCCESSFUL) // AVF0
384 392 {
385 393 status = rtems_task_create(
386 394 Task_name[TASKID_AVF0], TASK_PRIORITY_AVF0, RTEMS_MINIMUM_STACK_SIZE,
387 395 RTEMS_DEFAULT_MODES,
388 396 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF0]
389 397 );
390 398 }
391 399 if (status == RTEMS_SUCCESSFUL) // PRC0
392 400 {
393 401 status = rtems_task_create(
394 402 Task_name[TASKID_PRC0], TASK_PRIORITY_PRC0, RTEMS_MINIMUM_STACK_SIZE * 2,
395 403 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
396 404 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC0]
397 405 );
398 406 }
399 407 if (status == RTEMS_SUCCESSFUL) // AVF1
400 408 {
401 409 status = rtems_task_create(
402 410 Task_name[TASKID_AVF1], TASK_PRIORITY_AVF1, RTEMS_MINIMUM_STACK_SIZE,
403 411 RTEMS_DEFAULT_MODES,
404 412 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF1]
405 413 );
406 414 }
407 415 if (status == RTEMS_SUCCESSFUL) // PRC1
408 416 {
409 417 status = rtems_task_create(
410 418 Task_name[TASKID_PRC1], TASK_PRIORITY_PRC1, RTEMS_MINIMUM_STACK_SIZE * 2,
411 419 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
412 420 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC1]
413 421 );
414 422 }
415 423 if (status == RTEMS_SUCCESSFUL) // AVF2
416 424 {
417 425 status = rtems_task_create(
418 426 Task_name[TASKID_AVF2], TASK_PRIORITY_AVF2, RTEMS_MINIMUM_STACK_SIZE,
419 427 RTEMS_DEFAULT_MODES,
420 428 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF2]
421 429 );
422 430 }
423 431 if (status == RTEMS_SUCCESSFUL) // PRC2
424 432 {
425 433 status = rtems_task_create(
426 434 Task_name[TASKID_PRC2], TASK_PRIORITY_PRC2, RTEMS_MINIMUM_STACK_SIZE * 2,
427 435 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
428 436 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC2]
429 437 );
430 438 }
431 439
432 440 //****************
433 441 // WAVEFORM PICKER
434 442 if (status == RTEMS_SUCCESSFUL) // WFRM
435 443 {
436 444 status = rtems_task_create(
437 445 Task_name[TASKID_WFRM], TASK_PRIORITY_WFRM, RTEMS_MINIMUM_STACK_SIZE,
438 446 RTEMS_DEFAULT_MODES,
439 447 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_WFRM]
440 448 );
441 449 }
442 450 if (status == RTEMS_SUCCESSFUL) // CWF3
443 451 {
444 452 status = rtems_task_create(
445 453 Task_name[TASKID_CWF3], TASK_PRIORITY_CWF3, RTEMS_MINIMUM_STACK_SIZE,
446 454 RTEMS_DEFAULT_MODES,
447 455 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF3]
448 456 );
449 457 }
450 458 if (status == RTEMS_SUCCESSFUL) // CWF2
451 459 {
452 460 status = rtems_task_create(
453 461 Task_name[TASKID_CWF2], TASK_PRIORITY_CWF2, RTEMS_MINIMUM_STACK_SIZE,
454 462 RTEMS_DEFAULT_MODES,
455 463 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF2]
456 464 );
457 465 }
458 466 if (status == RTEMS_SUCCESSFUL) // CWF1
459 467 {
460 468 status = rtems_task_create(
461 469 Task_name[TASKID_CWF1], TASK_PRIORITY_CWF1, RTEMS_MINIMUM_STACK_SIZE,
462 470 RTEMS_DEFAULT_MODES,
463 471 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF1]
464 472 );
465 473 }
466 474 if (status == RTEMS_SUCCESSFUL) // SWBD
467 475 {
468 476 status = rtems_task_create(
469 477 Task_name[TASKID_SWBD], TASK_PRIORITY_SWBD, RTEMS_MINIMUM_STACK_SIZE,
470 478 RTEMS_DEFAULT_MODES,
471 479 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SWBD]
472 480 );
473 481 }
474 482
475 483 //*****
476 484 // MISC
477 485 if (status == RTEMS_SUCCESSFUL) // LOAD
478 486 {
479 487 status = rtems_task_create(
480 488 Task_name[TASKID_LOAD], TASK_PRIORITY_LOAD, RTEMS_MINIMUM_STACK_SIZE,
481 489 RTEMS_DEFAULT_MODES,
482 490 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_LOAD]
483 491 );
484 492 }
485 493 if (status == RTEMS_SUCCESSFUL) // DUMB
486 494 {
487 495 status = rtems_task_create(
488 496 Task_name[TASKID_DUMB], TASK_PRIORITY_DUMB, RTEMS_MINIMUM_STACK_SIZE,
489 497 RTEMS_DEFAULT_MODES,
490 498 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_DUMB]
491 499 );
492 500 }
493 501 if (status == RTEMS_SUCCESSFUL) // HOUS
494 502 {
495 503 status = rtems_task_create(
496 504 Task_name[TASKID_HOUS], TASK_PRIORITY_HOUS, RTEMS_MINIMUM_STACK_SIZE,
497 505 RTEMS_DEFAULT_MODES,
498 506 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_HOUS]
499 507 );
500 508 }
501 509
502 510 return status;
503 511 }
504 512
505 513 int start_recv_send_tasks( void )
506 514 {
507 515 rtems_status_code status;
508 516
509 517 status = rtems_task_start( Task_id[TASKID_RECV], recv_task, 1 );
510 518 if (status!=RTEMS_SUCCESSFUL) {
511 519 BOOT_PRINTF("in INIT *** Error starting TASK_RECV\n")
512 520 }
513 521
514 522 if (status == RTEMS_SUCCESSFUL) // SEND
515 523 {
516 524 status = rtems_task_start( Task_id[TASKID_SEND], send_task, 1 );
517 525 if (status!=RTEMS_SUCCESSFUL) {
518 526 BOOT_PRINTF("in INIT *** Error starting TASK_SEND\n")
519 527 }
520 528 }
521 529
522 530 return status;
523 531 }
524 532
525 533 int start_all_tasks( void ) // start all tasks except SEND RECV and HOUS
526 534 {
527 535 /** This function starts all RTEMS tasks used in the software.
528 536 *
529 537 * @return RTEMS directive status codes:
530 538 * - RTEMS_SUCCESSFUL - ask started successfully
531 539 * - RTEMS_INVALID_ADDRESS - invalid task entry point
532 540 * - RTEMS_INVALID_ID - invalid task id
533 541 * - RTEMS_INCORRECT_STATE - task not in the dormant state
534 542 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task
535 543 *
536 544 */
537 545 // starts all the tasks fot eh flight software
538 546
539 547 rtems_status_code status;
540 548
541 549 //**********
542 550 // SPACEWIRE
543 551 status = rtems_task_start( Task_id[TASKID_SPIQ], spiq_task, 1 );
544 552 if (status!=RTEMS_SUCCESSFUL) {
545 553 BOOT_PRINTF("in INIT *** Error starting TASK_SPIQ\n")
546 554 }
547 555
548 556 if (status == RTEMS_SUCCESSFUL) // WTDG
549 557 {
550 558 status = rtems_task_start( Task_id[TASKID_WTDG], wtdg_task, 1 );
551 559 if (status!=RTEMS_SUCCESSFUL) {
552 560 BOOT_PRINTF("in INIT *** Error starting TASK_WTDG\n")
553 561 }
554 562 }
555 563
556 564 if (status == RTEMS_SUCCESSFUL) // ACTN
557 565 {
558 566 status = rtems_task_start( Task_id[TASKID_ACTN], actn_task, 1 );
559 567 if (status!=RTEMS_SUCCESSFUL) {
560 568 BOOT_PRINTF("in INIT *** Error starting TASK_ACTN\n")
561 569 }
562 570 }
563 571
564 572 //******************
565 573 // SPECTRAL MATRICES
566 574 if (status == RTEMS_SUCCESSFUL) // AVF0
567 575 {
568 576 status = rtems_task_start( Task_id[TASKID_AVF0], avf0_task, LFR_MODE_STANDBY );
569 577 if (status!=RTEMS_SUCCESSFUL) {
570 578 BOOT_PRINTF("in INIT *** Error starting TASK_AVF0\n")
571 579 }
572 580 }
573 581 if (status == RTEMS_SUCCESSFUL) // PRC0
574 582 {
575 583 status = rtems_task_start( Task_id[TASKID_PRC0], prc0_task, LFR_MODE_STANDBY );
576 584 if (status!=RTEMS_SUCCESSFUL) {
577 585 BOOT_PRINTF("in INIT *** Error starting TASK_PRC0\n")
578 586 }
579 587 }
580 588 if (status == RTEMS_SUCCESSFUL) // AVF1
581 589 {
582 590 status = rtems_task_start( Task_id[TASKID_AVF1], avf1_task, LFR_MODE_STANDBY );
583 591 if (status!=RTEMS_SUCCESSFUL) {
584 592 BOOT_PRINTF("in INIT *** Error starting TASK_AVF1\n")
585 593 }
586 594 }
587 595 if (status == RTEMS_SUCCESSFUL) // PRC1
588 596 {
589 597 status = rtems_task_start( Task_id[TASKID_PRC1], prc1_task, LFR_MODE_STANDBY );
590 598 if (status!=RTEMS_SUCCESSFUL) {
591 599 BOOT_PRINTF("in INIT *** Error starting TASK_PRC1\n")
592 600 }
593 601 }
594 602 if (status == RTEMS_SUCCESSFUL) // AVF2
595 603 {
596 604 status = rtems_task_start( Task_id[TASKID_AVF2], avf2_task, 1 );
597 605 if (status!=RTEMS_SUCCESSFUL) {
598 606 BOOT_PRINTF("in INIT *** Error starting TASK_AVF2\n")
599 607 }
600 608 }
601 609 if (status == RTEMS_SUCCESSFUL) // PRC2
602 610 {
603 611 status = rtems_task_start( Task_id[TASKID_PRC2], prc2_task, 1 );
604 612 if (status!=RTEMS_SUCCESSFUL) {
605 613 BOOT_PRINTF("in INIT *** Error starting TASK_PRC2\n")
606 614 }
607 615 }
608 616
609 617 //****************
610 618 // WAVEFORM PICKER
611 619 if (status == RTEMS_SUCCESSFUL) // WFRM
612 620 {
613 621 status = rtems_task_start( Task_id[TASKID_WFRM], wfrm_task, 1 );
614 622 if (status!=RTEMS_SUCCESSFUL) {
615 623 BOOT_PRINTF("in INIT *** Error starting TASK_WFRM\n")
616 624 }
617 625 }
618 626 if (status == RTEMS_SUCCESSFUL) // CWF3
619 627 {
620 628 status = rtems_task_start( Task_id[TASKID_CWF3], cwf3_task, 1 );
621 629 if (status!=RTEMS_SUCCESSFUL) {
622 630 BOOT_PRINTF("in INIT *** Error starting TASK_CWF3\n")
623 631 }
624 632 }
625 633 if (status == RTEMS_SUCCESSFUL) // CWF2
626 634 {
627 635 status = rtems_task_start( Task_id[TASKID_CWF2], cwf2_task, 1 );
628 636 if (status!=RTEMS_SUCCESSFUL) {
629 637 BOOT_PRINTF("in INIT *** Error starting TASK_CWF2\n")
630 638 }
631 639 }
632 640 if (status == RTEMS_SUCCESSFUL) // CWF1
633 641 {
634 642 status = rtems_task_start( Task_id[TASKID_CWF1], cwf1_task, 1 );
635 643 if (status!=RTEMS_SUCCESSFUL) {
636 644 BOOT_PRINTF("in INIT *** Error starting TASK_CWF1\n")
637 645 }
638 646 }
639 647 if (status == RTEMS_SUCCESSFUL) // SWBD
640 648 {
641 649 status = rtems_task_start( Task_id[TASKID_SWBD], swbd_task, 1 );
642 650 if (status!=RTEMS_SUCCESSFUL) {
643 651 BOOT_PRINTF("in INIT *** Error starting TASK_SWBD\n")
644 652 }
645 653 }
646 654
647 655 //*****
648 656 // MISC
649 657 if (status == RTEMS_SUCCESSFUL) // HOUS
650 658 {
651 659 status = rtems_task_start( Task_id[TASKID_HOUS], hous_task, 1 );
652 660 if (status!=RTEMS_SUCCESSFUL) {
653 661 BOOT_PRINTF("in INIT *** Error starting TASK_HOUS\n")
654 662 }
655 663 }
656 664 if (status == RTEMS_SUCCESSFUL) // DUMB
657 665 {
658 666 status = rtems_task_start( Task_id[TASKID_DUMB], dumb_task, 1 );
659 667 if (status!=RTEMS_SUCCESSFUL) {
660 668 BOOT_PRINTF("in INIT *** Error starting TASK_DUMB\n")
661 669 }
662 670 }
663 671 if (status == RTEMS_SUCCESSFUL) // LOAD
664 672 {
665 673 status = rtems_task_start( Task_id[TASKID_LOAD], load_task, 1 );
666 674 if (status!=RTEMS_SUCCESSFUL) {
667 675 BOOT_PRINTF("in INIT *** Error starting TASK_LOAD\n")
668 676 }
669 677 }
670 678
671 679 return status;
672 680 }
673 681
674 682 rtems_status_code create_message_queues( void ) // create the two message queues used in the software
675 683 {
676 684 rtems_status_code status_recv;
677 685 rtems_status_code status_send;
678 686 rtems_status_code status_q_p0;
679 687 rtems_status_code status_q_p1;
680 688 rtems_status_code status_q_p2;
681 689 rtems_status_code ret;
682 690 rtems_id queue_id;
683 691
684 692 //****************************************
685 693 // create the queue for handling valid TCs
686 694 status_recv = rtems_message_queue_create( misc_name[QUEUE_RECV],
687 695 MSG_QUEUE_COUNT_RECV, CCSDS_TC_PKT_MAX_SIZE,
688 696 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
689 697 if ( status_recv != RTEMS_SUCCESSFUL ) {
690 698 PRINTF1("in create_message_queues *** ERR creating QUEU queue, %d\n", status_recv)
691 699 }
692 700
693 701 //************************************************
694 702 // create the queue for handling TM packet sending
695 703 status_send = rtems_message_queue_create( misc_name[QUEUE_SEND],
696 704 MSG_QUEUE_COUNT_SEND, MSG_QUEUE_SIZE_SEND,
697 705 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
698 706 if ( status_send != RTEMS_SUCCESSFUL ) {
699 707 PRINTF1("in create_message_queues *** ERR creating PKTS queue, %d\n", status_send)
700 708 }
701 709
702 710 //*****************************************************************************
703 711 // create the queue for handling averaged spectral matrices for processing @ f0
704 712 status_q_p0 = rtems_message_queue_create( misc_name[QUEUE_PRC0],
705 713 MSG_QUEUE_COUNT_PRC0, MSG_QUEUE_SIZE_PRC0,
706 714 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
707 715 if ( status_q_p0 != RTEMS_SUCCESSFUL ) {
708 716 PRINTF1("in create_message_queues *** ERR creating Q_P0 queue, %d\n", status_q_p0)
709 717 }
710 718
711 719 //*****************************************************************************
712 720 // create the queue for handling averaged spectral matrices for processing @ f1
713 721 status_q_p1 = rtems_message_queue_create( misc_name[QUEUE_PRC1],
714 722 MSG_QUEUE_COUNT_PRC1, MSG_QUEUE_SIZE_PRC1,
715 723 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
716 724 if ( status_q_p1 != RTEMS_SUCCESSFUL ) {
717 725 PRINTF1("in create_message_queues *** ERR creating Q_P1 queue, %d\n", status_q_p1)
718 726 }
719 727
720 728 //*****************************************************************************
721 729 // create the queue for handling averaged spectral matrices for processing @ f2
722 730 status_q_p2 = rtems_message_queue_create( misc_name[QUEUE_PRC2],
723 731 MSG_QUEUE_COUNT_PRC2, MSG_QUEUE_SIZE_PRC2,
724 732 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
725 733 if ( status_q_p2 != RTEMS_SUCCESSFUL ) {
726 734 PRINTF1("in create_message_queues *** ERR creating Q_P2 queue, %d\n", status_q_p2)
727 735 }
728 736
729 737 if ( status_recv != RTEMS_SUCCESSFUL )
730 738 {
731 739 ret = status_recv;
732 740 }
733 741 else if( status_send != RTEMS_SUCCESSFUL )
734 742 {
735 743 ret = status_send;
736 744 }
737 745 else if( status_q_p0 != RTEMS_SUCCESSFUL )
738 746 {
739 747 ret = status_q_p0;
740 748 }
741 749 else if( status_q_p1 != RTEMS_SUCCESSFUL )
742 750 {
743 751 ret = status_q_p1;
744 752 }
745 753 else
746 754 {
747 755 ret = status_q_p2;
748 756 }
749 757
750 758 return ret;
751 759 }
752 760
761 rtems_status_code create_timecode_timer( void )
762 {
763 rtems_status_code status;
764
765 status = rtems_timer_create( timecode_timer_name, &timecode_timer_id );
766
767 if ( status != RTEMS_SUCCESSFUL )
768 {
769 PRINTF1("in create_timer_timecode *** ERR creating SPTC timer, %d\n", status)
770 }
771 else
772 {
773 PRINTF("in create_timer_timecode *** OK creating SPTC timer\n")
774 }
775
776 return status;
777 }
778
753 779 rtems_status_code get_message_queue_id_send( rtems_id *queue_id )
754 780 {
755 781 rtems_status_code status;
756 782 rtems_name queue_name;
757 783
758 784 queue_name = rtems_build_name( 'Q', '_', 'S', 'D' );
759 785
760 786 status = rtems_message_queue_ident( queue_name, 0, queue_id );
761 787
762 788 return status;
763 789 }
764 790
765 791 rtems_status_code get_message_queue_id_recv( rtems_id *queue_id )
766 792 {
767 793 rtems_status_code status;
768 794 rtems_name queue_name;
769 795
770 796 queue_name = rtems_build_name( 'Q', '_', 'R', 'V' );
771 797
772 798 status = rtems_message_queue_ident( queue_name, 0, queue_id );
773 799
774 800 return status;
775 801 }
776 802
777 803 rtems_status_code get_message_queue_id_prc0( rtems_id *queue_id )
778 804 {
779 805 rtems_status_code status;
780 806 rtems_name queue_name;
781 807
782 808 queue_name = rtems_build_name( 'Q', '_', 'P', '0' );
783 809
784 810 status = rtems_message_queue_ident( queue_name, 0, queue_id );
785 811
786 812 return status;
787 813 }
788 814
789 815 rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id )
790 816 {
791 817 rtems_status_code status;
792 818 rtems_name queue_name;
793 819
794 820 queue_name = rtems_build_name( 'Q', '_', 'P', '1' );
795 821
796 822 status = rtems_message_queue_ident( queue_name, 0, queue_id );
797 823
798 824 return status;
799 825 }
800 826
801 827 rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id )
802 828 {
803 829 rtems_status_code status;
804 830 rtems_name queue_name;
805 831
806 832 queue_name = rtems_build_name( 'Q', '_', 'P', '2' );
807 833
808 834 status = rtems_message_queue_ident( queue_name, 0, queue_id );
809 835
810 836 return status;
811 837 }
812 838
813 839 void update_queue_max_count( rtems_id queue_id, unsigned char*fifo_size_max )
814 840 {
815 841 u_int32_t count;
816 842 rtems_status_code status;
817 843
818 844 status = rtems_message_queue_get_number_pending( queue_id, &count );
819 845
820 846 count = count + 1;
821 847
822 848 if (status != RTEMS_SUCCESSFUL)
823 849 {
824 850 PRINTF1("in update_queue_max_count *** ERR = %d\n", status)
825 851 }
826 852 else
827 853 {
828 854 if (count > *fifo_size_max)
829 855 {
830 856 *fifo_size_max = count;
831 857 }
832 858 }
833 859 }
834 860
835 861 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize )
836 862 {
837 863 unsigned char i;
838 864
839 865 //***************
840 866 // BUFFER ADDRESS
841 867 for(i=0; i<nbNodes; i++)
842 868 {
843 869 ring[i].coarseTime = 0xffffffff;
844 870 ring[i].fineTime = 0xffffffff;
845 871 ring[i].sid = 0x00;
846 872 ring[i].status = 0x00;
847 873 ring[i].buffer_address = (int) &buffer[ i * bufferSize ];
848 874 }
849 875
850 876 //*****
851 877 // NEXT
852 878 ring[ nbNodes - 1 ].next = (ring_node*) &ring[ 0 ];
853 879 for(i=0; i<nbNodes-1; i++)
854 880 {
855 881 ring[i].next = (ring_node*) &ring[ i + 1 ];
856 882 }
857 883
858 884 //*********
859 885 // PREVIOUS
860 886 ring[ 0 ].previous = (ring_node*) &ring[ nbNodes - 1 ];
861 887 for(i=1; i<nbNodes; i++)
862 888 {
863 889 ring[i].previous = (ring_node*) &ring[ i - 1 ];
864 890 }
865 891 }
@@ -1,700 +1,705
1 1 /** General usage functions and RTEMS tasks.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 */
7 7
8 8 #include "fsw_misc.h"
9 9
10 10 void timer_configure(unsigned char timer, unsigned int clock_divider,
11 11 unsigned char interrupt_level, rtems_isr (*timer_isr)() )
12 12 {
13 13 /** This function configures a GPTIMER timer instantiated in the VHDL design.
14 14 *
15 15 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
16 16 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
17 17 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
18 18 * @param interrupt_level is the interrupt level that the timer drives.
19 19 * @param timer_isr is the interrupt subroutine that will be attached to the IRQ driven by the timer.
20 20 *
21 21 * Interrupt levels are described in the SPARC documentation sparcv8.pdf p.76
22 22 *
23 23 */
24 24
25 25 rtems_status_code status;
26 26 rtems_isr_entry old_isr_handler;
27 27
28 28 gptimer_regs->timer[timer].ctrl = 0x00; // reset the control register
29 29
30 30 status = rtems_interrupt_catch( timer_isr, interrupt_level, &old_isr_handler) ; // see sparcv8.pdf p.76 for interrupt levels
31 31 if (status!=RTEMS_SUCCESSFUL)
32 32 {
33 33 PRINTF("in configure_timer *** ERR rtems_interrupt_catch\n")
34 34 }
35 35
36 36 timer_set_clock_divider( timer, clock_divider);
37 37 }
38 38
39 39 void timer_start(unsigned char timer)
40 40 {
41 41 /** This function starts a GPTIMER timer.
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 *
46 46 */
47 47
48 48 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
49 49 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000004; // LD load value from the reload register
50 50 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000001; // EN enable the timer
51 51 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000002; // RS restart
52 52 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000008; // IE interrupt enable
53 53 }
54 54
55 55 void timer_stop(unsigned char timer)
56 56 {
57 57 /** This function stops a GPTIMER timer.
58 58 *
59 59 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
60 60 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
61 61 *
62 62 */
63 63
64 64 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xfffffffe; // EN enable the timer
65 65 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl & 0xffffffef; // IE interrupt enable
66 66 gptimer_regs->timer[timer].ctrl = gptimer_regs->timer[timer].ctrl | 0x00000010; // clear pending IRQ if any
67 67 }
68 68
69 69 void timer_set_clock_divider(unsigned char timer, unsigned int clock_divider)
70 70 {
71 71 /** This function sets the clock divider of a GPTIMER timer.
72 72 *
73 73 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
74 74 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
75 75 * @param clock_divider is the divider of the 1 MHz clock that will be configured.
76 76 *
77 77 */
78 78
79 79 gptimer_regs->timer[timer].reload = clock_divider; // base clock frequency is 1 MHz
80 80 }
81 81
82 82 // WATCHDOG
83 83
84 84 rtems_isr watchdog_isr( rtems_vector_number vector )
85 85 {
86 86 rtems_status_code status_code;
87 87
88 88 status_code = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_12 );
89 89 }
90 90
91 91 void watchdog_configure(void)
92 92 {
93 93 /** This function configure the watchdog.
94 94 *
95 95 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
96 96 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
97 97 *
98 98 * The watchdog is a timer provided by the GPTIMER IP core of the GRLIB.
99 99 *
100 100 */
101 101
102 102 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt during configuration
103 103
104 104 timer_configure( TIMER_WATCHDOG, CLKDIV_WATCHDOG, IRQ_SPARC_GPTIMER_WATCHDOG, watchdog_isr );
105 105
106 106 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
107 107 }
108 108
109 109 void watchdog_stop(void)
110 110 {
111 111 LEON_Mask_interrupt( IRQ_GPTIMER_WATCHDOG ); // mask gptimer/watchdog interrupt line
112 112 timer_stop( TIMER_WATCHDOG );
113 113 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG ); // clear gptimer/watchdog interrupt
114 114 }
115 115
116 116 void watchdog_reload(void)
117 117 {
118 118 /** This function reloads the watchdog timer counter with the timer reload value.
119 119 *
120 120 *
121 121 */
122 122
123 123 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
124 124 }
125 125
126 126 void watchdog_start(void)
127 127 {
128 128 /** This function starts the watchdog timer.
129 129 *
130 130 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
131 131 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
132 132 *
133 133 */
134 134
135 135 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
136 136
137 137 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000010; // clear pending IRQ if any
138 138 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
139 139 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000001; // EN enable the timer
140 140 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000008; // IE interrupt enable
141 141
142 142 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
143 143
144 144 }
145 145
146 146 int send_console_outputs_on_apbuart_port( void ) // Send the console outputs on the apbuart port
147 147 {
148 148 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
149 149
150 150 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
151 151
152 152 return 0;
153 153 }
154 154
155 155 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
156 156 {
157 157 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
158 158
159 159 apbuart_regs->ctrl = apbuart_regs->ctrl | APBUART_CTRL_REG_MASK_TE;
160 160
161 161 return 0;
162 162 }
163 163
164 164 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
165 165 {
166 166 /** This function sets the scaler reload register of the apbuart module
167 167 *
168 168 * @param regs is the address of the apbuart registers in memory
169 169 * @param value is the value that will be stored in the scaler register
170 170 *
171 171 * The value shall be set by the software to get data on the serial interface.
172 172 *
173 173 */
174 174
175 175 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
176 176
177 177 apbuart_regs->scaler = value;
178 178 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
179 179 }
180 180
181 181 //************
182 182 // RTEMS TASKS
183 183
184 184 rtems_task load_task(rtems_task_argument argument)
185 185 {
186 186 BOOT_PRINTF("in LOAD *** \n")
187 187
188 188 rtems_status_code status;
189 189 unsigned int i;
190 190 unsigned int j;
191 191 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
192 192 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
193 193
194 194 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
195 195
196 196 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
197 197 if( status != RTEMS_SUCCESSFUL ) {
198 198 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
199 199 }
200 200
201 201 i = 0;
202 202 j = 0;
203 203
204 204 watchdog_configure();
205 205
206 206 watchdog_start();
207 207
208 208 while(1){
209 209 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
210 210 watchdog_reload();
211 211 i = i + 1;
212 212 if ( i == 10 )
213 213 {
214 214 i = 0;
215 215 j = j + 1;
216 216 PRINTF1("%d\n", j)
217 217 }
218 218 #ifdef DEBUG_WATCHDOG
219 219 if (j == 3 )
220 220 {
221 221 status = rtems_task_delete(RTEMS_SELF);
222 222 }
223 223 #endif
224 224 }
225 225 }
226 226
227 227 rtems_task hous_task(rtems_task_argument argument)
228 228 {
229 229 rtems_status_code status;
230 230 rtems_status_code spare_status;
231 231 rtems_id queue_id;
232 232 rtems_rate_monotonic_period_status period_status;
233 233
234 234 status = get_message_queue_id_send( &queue_id );
235 235 if (status != RTEMS_SUCCESSFUL)
236 236 {
237 237 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
238 238 }
239 239
240 240 BOOT_PRINTF("in HOUS ***\n")
241 241
242 242 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
243 243 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
244 244 if( status != RTEMS_SUCCESSFUL ) {
245 245 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status )
246 246 }
247 247 }
248 248
249 249 status = rtems_rate_monotonic_cancel(HK_id);
250 250 if( status != RTEMS_SUCCESSFUL ) {
251 251 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status )
252 252 }
253 253 else {
254 254 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n")
255 255 }
256 256
257 257 // startup phase
258 258 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
259 259 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
260 260 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
261 261 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
262 262 {
263 263 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
264 264 {
265 265 break; // break if LFR is synchronized
266 266 }
267 267 else
268 268 {
269 269 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
270 270 // sched_yield();
271 271 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
272 272 }
273 273 }
274 274 status = rtems_rate_monotonic_cancel(HK_id);
275 275 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
276 276
277 277 set_hk_lfr_reset_cause( POWER_ON );
278 278
279 279 while(1){ // launch the rate monotonic task
280 280 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
281 281 if ( status != RTEMS_SUCCESSFUL ) {
282 282 PRINTF1( "in HOUS *** ERR period: %d\n", status);
283 283 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
284 284 }
285 285 else {
286 286 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
287 287 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
288 288 increment_seq_counter( &sequenceCounterHK );
289 289
290 290 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
291 291 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
292 292 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
293 293 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
294 294 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
295 295 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
296 296
297 297 spacewire_update_statistics();
298 298
299 299 hk_lfr_le_me_he_update();
300 300
301 301 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
302 302 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
303 303 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
304 304 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
305 305 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
306 306
307 307 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
308 308 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
309 309 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
310 310 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
311 311 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
312 312
313 313 // SEND PACKET
314 314 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
315 315 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
316 316 if (status != RTEMS_SUCCESSFUL) {
317 317 PRINTF1("in HOUS *** ERR send: %d\n", status)
318 318 }
319 319 }
320 320 }
321 321
322 322 PRINTF("in HOUS *** deleting task\n")
323 323
324 324 status = rtems_task_delete( RTEMS_SELF ); // should not return
325 325
326 326 return;
327 327 }
328 328
329 329 rtems_task dumb_task( rtems_task_argument unused )
330 330 {
331 331 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
332 332 *
333 333 * @param unused is the starting argument of the RTEMS task
334 334 *
335 335 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
336 336 *
337 337 */
338 338
339 339 unsigned int i;
340 340 unsigned int intEventOut;
341 341 unsigned int coarse_time = 0;
342 342 unsigned int fine_time = 0;
343 343 rtems_event_set event_out;
344 344
345 char *DumbMessages[13] = {"in DUMB *** default", // RTEMS_EVENT_0
345 char *DumbMessages[14] = {"in DUMB *** default", // RTEMS_EVENT_0
346 346 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
347 347 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
348 348 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
349 349 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
350 350 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
351 351 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
352 352 "ready for dump", // RTEMS_EVENT_7
353 353 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
354 354 "tick", // RTEMS_EVENT_9
355 355 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
356 356 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11
357 "WATCHDOG timer" // RTEMS_EVENT_12
357 "WATCHDOG timer", // RTEMS_EVENT_12
358 "TIMECODE timer" // RTEMS_EVENT_13
358 359 };
359 360
360 361 BOOT_PRINTF("in DUMB *** \n")
361 362
362 363 while(1){
363 364 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
364 365 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
365 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12,
366 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13,
366 367 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
367 368 intEventOut = (unsigned int) event_out;
368 369 for ( i=0; i<32; i++)
369 370 {
370 371 if ( ((intEventOut >> i) & 0x0001) != 0)
371 372 {
372 373 coarse_time = time_management_regs->coarse_time;
373 374 fine_time = time_management_regs->fine_time;
374 375 if (i==12)
375 376 {
376 377 PRINTF1("%s\n", DumbMessages[12])
377 378 }
379 if (i==13)
380 {
381 PRINTF1("%s\n", DumbMessages[13])
382 }
378 383 }
379 384 }
380 385 }
381 386 }
382 387
383 388 //*****************************
384 389 // init housekeeping parameters
385 390
386 391 void init_housekeeping_parameters( void )
387 392 {
388 393 /** This function initialize the housekeeping_packet global variable with default values.
389 394 *
390 395 */
391 396
392 397 unsigned int i = 0;
393 398 unsigned char *parameters;
394 399 unsigned char sizeOfHK;
395 400
396 401 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
397 402
398 403 parameters = (unsigned char*) &housekeeping_packet;
399 404
400 405 for(i = 0; i< sizeOfHK; i++)
401 406 {
402 407 parameters[i] = 0x00;
403 408 }
404 409
405 410 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
406 411 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
407 412 housekeeping_packet.reserved = DEFAULT_RESERVED;
408 413 housekeeping_packet.userApplication = CCSDS_USER_APP;
409 414 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
410 415 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
411 416 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
412 417 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
413 418 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
414 419 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
415 420 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
416 421 housekeeping_packet.serviceType = TM_TYPE_HK;
417 422 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
418 423 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
419 424 housekeeping_packet.sid = SID_HK;
420 425
421 426 // init status word
422 427 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
423 428 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
424 429 // init software version
425 430 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
426 431 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
427 432 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
428 433 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
429 434 // init fpga version
430 435 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
431 436 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
432 437 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
433 438 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
434 439
435 440 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
436 441 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
437 442 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
438 443 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
439 444 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
440 445 }
441 446
442 447 void increment_seq_counter( unsigned short *packetSequenceControl )
443 448 {
444 449 /** This function increment the sequence counter passes in argument.
445 450 *
446 451 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
447 452 *
448 453 */
449 454
450 455 unsigned short segmentation_grouping_flag;
451 456 unsigned short sequence_cnt;
452 457
453 458 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
454 459 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
455 460
456 461 if ( sequence_cnt < SEQ_CNT_MAX)
457 462 {
458 463 sequence_cnt = sequence_cnt + 1;
459 464 }
460 465 else
461 466 {
462 467 sequence_cnt = 0;
463 468 }
464 469
465 470 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
466 471 }
467 472
468 473 void getTime( unsigned char *time)
469 474 {
470 475 /** This function write the current local time in the time buffer passed in argument.
471 476 *
472 477 */
473 478
474 479 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
475 480 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
476 481 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
477 482 time[3] = (unsigned char) (time_management_regs->coarse_time);
478 483 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
479 484 time[5] = (unsigned char) (time_management_regs->fine_time);
480 485 }
481 486
482 487 unsigned long long int getTimeAsUnsignedLongLongInt( )
483 488 {
484 489 /** This function write the current local time in the time buffer passed in argument.
485 490 *
486 491 */
487 492 unsigned long long int time;
488 493
489 494 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
490 495 + time_management_regs->fine_time;
491 496
492 497 return time;
493 498 }
494 499
495 500 void send_dumb_hk( void )
496 501 {
497 502 Packet_TM_LFR_HK_t dummy_hk_packet;
498 503 unsigned char *parameters;
499 504 unsigned int i;
500 505 rtems_id queue_id;
501 506
502 507 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
503 508 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
504 509 dummy_hk_packet.reserved = DEFAULT_RESERVED;
505 510 dummy_hk_packet.userApplication = CCSDS_USER_APP;
506 511 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
507 512 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
508 513 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
509 514 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
510 515 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
511 516 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
512 517 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
513 518 dummy_hk_packet.serviceType = TM_TYPE_HK;
514 519 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
515 520 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
516 521 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
517 522 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
518 523 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
519 524 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
520 525 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
521 526 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
522 527 dummy_hk_packet.sid = SID_HK;
523 528
524 529 // init status word
525 530 dummy_hk_packet.lfr_status_word[0] = 0xff;
526 531 dummy_hk_packet.lfr_status_word[1] = 0xff;
527 532 // init software version
528 533 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
529 534 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
530 535 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
531 536 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
532 537 // init fpga version
533 538 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
534 539 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
535 540 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
536 541 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
537 542
538 543 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
539 544
540 545 for (i=0; i<100; i++)
541 546 {
542 547 parameters[i] = 0xff;
543 548 }
544 549
545 550 get_message_queue_id_send( &queue_id );
546 551
547 552 rtems_message_queue_send( queue_id, &dummy_hk_packet,
548 553 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
549 554 }
550 555
551 556 void get_temperatures( unsigned char *temperatures )
552 557 {
553 558 unsigned char* temp_scm_ptr;
554 559 unsigned char* temp_pcb_ptr;
555 560 unsigned char* temp_fpga_ptr;
556 561
557 562 // SEL1 SEL0
558 563 // 0 0 => PCB
559 564 // 0 1 => FPGA
560 565 // 1 0 => SCM
561 566
562 567 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
563 568 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
564 569 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
565 570
566 571 temperatures[0] = temp_scm_ptr[2];
567 572 temperatures[1] = temp_scm_ptr[3];
568 573 temperatures[2] = temp_pcb_ptr[2];
569 574 temperatures[3] = temp_pcb_ptr[3];
570 575 temperatures[4] = temp_fpga_ptr[2];
571 576 temperatures[5] = temp_fpga_ptr[3];
572 577 }
573 578
574 579 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
575 580 {
576 581 unsigned char* v_ptr;
577 582 unsigned char* e1_ptr;
578 583 unsigned char* e2_ptr;
579 584
580 585 v_ptr = (unsigned char *) &waveform_picker_regs->v;
581 586 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
582 587 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
583 588
584 589 spacecraft_potential[0] = v_ptr[2];
585 590 spacecraft_potential[1] = v_ptr[3];
586 591 spacecraft_potential[2] = e1_ptr[2];
587 592 spacecraft_potential[3] = e1_ptr[3];
588 593 spacecraft_potential[4] = e2_ptr[2];
589 594 spacecraft_potential[5] = e2_ptr[3];
590 595 }
591 596
592 597 void get_cpu_load( unsigned char *resource_statistics )
593 598 {
594 599 unsigned char cpu_load;
595 600
596 601 cpu_load = lfr_rtems_cpu_usage_report();
597 602
598 603 // HK_LFR_CPU_LOAD
599 604 resource_statistics[0] = cpu_load;
600 605
601 606 // HK_LFR_CPU_LOAD_MAX
602 607 if (cpu_load > resource_statistics[1])
603 608 {
604 609 resource_statistics[1] = cpu_load;
605 610 }
606 611
607 612 // CPU_LOAD_AVE
608 613 resource_statistics[2] = 0;
609 614
610 615 #ifndef PRINT_TASK_STATISTICS
611 616 rtems_cpu_usage_reset();
612 617 #endif
613 618
614 619 }
615 620
616 621 void set_hk_lfr_sc_potential_flag( bool state )
617 622 {
618 623 if (state == true)
619 624 {
620 625 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x40; // [0100 0000]
621 626 }
622 627 else
623 628 {
624 629 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xbf; // [1011 1111]
625 630 }
626 631 }
627 632
628 633 void set_hk_lfr_mag_fields_flag( bool state )
629 634 {
630 635 if (state == true)
631 636 {
632 637 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x20; // [0010 0000]
633 638 }
634 639 else
635 640 {
636 641 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xd7; // [1101 1111]
637 642 }
638 643 }
639 644
640 645 void set_hk_lfr_calib_enable( bool state )
641 646 {
642 647 if (state == true)
643 648 {
644 649 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x08; // [0000 1000]
645 650 }
646 651 else
647 652 {
648 653 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xf7; // [1111 0111]
649 654 }
650 655 }
651 656
652 657 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
653 658 {
654 659 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
655 660 | (lfr_reset_cause & 0x07 ); // [0000 0111]
656 661 }
657 662
658 663 void hk_lfr_le_me_he_update()
659 664 {
660 665 unsigned int hk_lfr_le_cnt;
661 666 unsigned int hk_lfr_me_cnt;
662 667 unsigned int hk_lfr_he_cnt;
663 668
664 669 hk_lfr_le_cnt = 0;
665 670 hk_lfr_me_cnt = 0;
666 671 hk_lfr_he_cnt = 0;
667 672
668 673 //update the low severity error counter
669 674 hk_lfr_le_cnt =
670 675 housekeeping_packet.hk_lfr_dpu_spw_parity
671 676 + housekeeping_packet.hk_lfr_dpu_spw_disconnect
672 677 + housekeeping_packet.hk_lfr_dpu_spw_escape
673 678 + housekeeping_packet.hk_lfr_dpu_spw_credit
674 679 + housekeeping_packet.hk_lfr_dpu_spw_write_sync
675 680 + housekeeping_packet.hk_lfr_dpu_spw_rx_ahb
676 681 + housekeeping_packet.hk_lfr_dpu_spw_tx_ahb
677 682 + housekeeping_packet.hk_lfr_time_timecode_ctr;
678 683
679 684 //update the medium severity error counter
680 685 hk_lfr_me_cnt =
681 686 housekeeping_packet.hk_lfr_dpu_spw_early_eop
682 687 + housekeeping_packet.hk_lfr_dpu_spw_invalid_addr
683 688 + housekeeping_packet.hk_lfr_dpu_spw_eep
684 689 + housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
685 690
686 691 //update the high severity error counter
687 692 hk_lfr_he_cnt = 0;
688 693
689 694 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
690 695 // LE
691 696 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((hk_lfr_le_cnt & 0xff00) >> 8);
692 697 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (hk_lfr_le_cnt & 0x00ff);
693 698 // ME
694 699 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((hk_lfr_me_cnt & 0xff00) >> 8);
695 700 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (hk_lfr_me_cnt & 0x00ff);
696 701 // HE
697 702 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & 0xff00) >> 8);
698 703 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & 0x00ff);
699 704
700 705 }
@@ -1,1295 +1,1403
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;
17 17 rtems_id semq_id;
18 18
19 19 //*****************
20 20 // waveform headers
21 21 Header_TM_LFR_SCIENCE_CWF_t headerCWF;
22 22 Header_TM_LFR_SCIENCE_SWF_t headerSWF;
23 23 Header_TM_LFR_SCIENCE_ASM_t headerASM;
24 24
25 unsigned char previousTimecodeCtr = 0;
26 unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
27
25 28 //***********
26 29 // RTEMS TASK
27 30 rtems_task spiq_task(rtems_task_argument unused)
28 31 {
29 32 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
30 33 *
31 34 * @param unused is the starting argument of the RTEMS task
32 35 *
33 36 */
34 37
35 38 rtems_event_set event_out;
36 39 rtems_status_code status;
37 40 int linkStatus;
38 41
39 42 BOOT_PRINTF("in SPIQ *** \n")
40 43
41 44 while(true){
42 45 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
43 46 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
44 47
45 48 // [0] SUSPEND RECV AND SEND TASKS
46 49 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
47 50 if ( status != RTEMS_SUCCESSFUL ) {
48 51 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
49 52 }
50 53 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
51 54 if ( status != RTEMS_SUCCESSFUL ) {
52 55 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
53 56 }
54 57
55 58 // [1] CHECK THE LINK
56 59 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
57 60 if ( linkStatus != 5) {
58 61 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
59 62 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
60 63 }
61 64
62 65 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
63 66 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
64 67 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
65 68 {
66 69 spacewire_compute_stats_offsets();
67 70 status = spacewire_reset_link( );
68 71 }
69 72 else // [2.b] in run state, start the link
70 73 {
71 74 status = spacewire_stop_and_start_link( fdSPW ); // start the link
72 75 if ( status != RTEMS_SUCCESSFUL)
73 76 {
74 77 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
75 78 }
76 79 }
77 80
78 81 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
79 82 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
80 83 {
81 84 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
82 85 if ( status != RTEMS_SUCCESSFUL ) {
83 86 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
84 87 }
85 88 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
86 89 if ( status != RTEMS_SUCCESSFUL ) {
87 90 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
88 91 }
89 92 }
90 93 else // [3.b] the link is not in run state, go in STANDBY mode
91 94 {
92 95 status = enter_mode_standby();
93 96 if ( status != RTEMS_SUCCESSFUL ) {
94 97 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
95 98 }
96 99 // wake the WTDG task up to wait for the link recovery
97 100 status = rtems_event_send ( Task_id[TASKID_WTDG], RTEMS_EVENT_0 );
98 101 status = rtems_task_suspend( RTEMS_SELF );
99 102 }
100 103 }
101 104 }
102 105
103 106 rtems_task recv_task( rtems_task_argument unused )
104 107 {
105 108 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
106 109 *
107 110 * @param unused is the starting argument of the RTEMS task
108 111 *
109 112 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
110 113 * 1. It reads the incoming data.
111 114 * 2. Launches the acceptance procedure.
112 115 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
113 116 *
114 117 */
115 118
116 119 int len;
117 120 ccsdsTelecommandPacket_t currentTC;
118 121 unsigned char computed_CRC[ 2 ];
119 122 unsigned char currentTC_LEN_RCV[ 2 ];
120 123 unsigned char destinationID;
121 124 unsigned int estimatedPacketLength;
122 125 unsigned int parserCode;
123 126 rtems_status_code status;
124 127 rtems_id queue_recv_id;
125 128 rtems_id queue_send_id;
126 129
127 130 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
128 131
129 132 status = get_message_queue_id_recv( &queue_recv_id );
130 133 if (status != RTEMS_SUCCESSFUL)
131 134 {
132 135 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
133 136 }
134 137
135 138 status = get_message_queue_id_send( &queue_send_id );
136 139 if (status != RTEMS_SUCCESSFUL)
137 140 {
138 141 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
139 142 }
140 143
141 144 BOOT_PRINTF("in RECV *** \n")
142 145
143 146 while(1)
144 147 {
145 148 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
146 149 if (len == -1){ // error during the read call
147 150 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
148 151 }
149 152 else {
150 153 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
151 154 PRINTF("in RECV *** packet lenght too short\n")
152 155 }
153 156 else {
154 157 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
155 158 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
156 159 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
157 160 // CHECK THE TC
158 161 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
159 162 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
160 163 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
161 164 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
162 165 || (parserCode == WRONG_SRC_ID) )
163 166 { // send TM_LFR_TC_EXE_CORRUPTED
164 167 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
165 168 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
166 169 &&
167 170 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
168 171 )
169 172 {
170 173 if ( parserCode == WRONG_SRC_ID )
171 174 {
172 175 destinationID = SID_TC_GROUND;
173 176 }
174 177 else
175 178 {
176 179 destinationID = currentTC.sourceID;
177 180 }
178 181 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
179 182 computed_CRC, currentTC_LEN_RCV,
180 183 destinationID );
181 184 }
182 185 }
183 186 else
184 187 { // send valid TC to the action launcher
185 188 status = rtems_message_queue_send( queue_recv_id, &currentTC,
186 189 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
187 190 }
188 191 }
189 192 }
190 193
191 194 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
192 195
193 196 }
194 197 }
195 198
196 199 rtems_task send_task( rtems_task_argument argument)
197 200 {
198 201 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
199 202 *
200 203 * @param unused is the starting argument of the RTEMS task
201 204 *
202 205 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
203 206 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
204 207 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
205 208 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
206 209 * data it contains.
207 210 *
208 211 */
209 212
210 213 rtems_status_code status; // RTEMS status code
211 214 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
212 215 ring_node *incomingRingNodePtr;
213 216 int ring_node_address;
214 217 char *charPtr;
215 218 spw_ioctl_pkt_send *spw_ioctl_send;
216 219 size_t size; // size of the incoming TC packet
217 220 rtems_id queue_send_id;
218 221 unsigned int sid;
219 222 unsigned char sidAsUnsignedChar;
220 223 unsigned char type;
221 224
222 225 incomingRingNodePtr = NULL;
223 226 ring_node_address = 0;
224 227 charPtr = (char *) &ring_node_address;
225 228 sid = 0;
226 229 sidAsUnsignedChar = 0;
227 230
228 231 init_header_cwf( &headerCWF );
229 232 init_header_swf( &headerSWF );
230 233 init_header_asm( &headerASM );
231 234
232 235 status = get_message_queue_id_send( &queue_send_id );
233 236 if (status != RTEMS_SUCCESSFUL)
234 237 {
235 238 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
236 239 }
237 240
238 241 BOOT_PRINTF("in SEND *** \n")
239 242
240 243 while(1)
241 244 {
242 245 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
243 246 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
244 247
245 248 if (status!=RTEMS_SUCCESSFUL)
246 249 {
247 250 PRINTF1("in SEND *** (1) ERR = %d\n", status)
248 251 }
249 252 else
250 253 {
251 254 if ( size == sizeof(ring_node*) )
252 255 {
253 256 charPtr[0] = incomingData[0];
254 257 charPtr[1] = incomingData[1];
255 258 charPtr[2] = incomingData[2];
256 259 charPtr[3] = incomingData[3];
257 260 incomingRingNodePtr = (ring_node*) ring_node_address;
258 261 sid = incomingRingNodePtr->sid;
259 262 if ( (sid==SID_NORM_CWF_LONG_F3)
260 263 || (sid==SID_BURST_CWF_F2 )
261 264 || (sid==SID_SBM1_CWF_F1 )
262 265 || (sid==SID_SBM2_CWF_F2 ))
263 266 {
264 267 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
265 268 }
266 269 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
267 270 {
268 271 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
269 272 }
270 273 else if ( (sid==SID_NORM_CWF_F3) )
271 274 {
272 275 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
273 276 }
274 277 else if (sid==SID_NORM_ASM_F0)
275 278 {
276 279 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
277 280 }
278 281 else if (sid==SID_NORM_ASM_F1)
279 282 {
280 283 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
281 284 }
282 285 else if (sid==SID_NORM_ASM_F2)
283 286 {
284 287 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
285 288 }
286 289 else if ( sid==TM_CODE_K_DUMP )
287 290 {
288 291 spw_send_k_dump( incomingRingNodePtr );
289 292 }
290 293 else
291 294 {
292 295 PRINTF1("unexpected sid = %d\n", sid);
293 296 }
294 297 }
295 298 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
296 299 {
297 300 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
298 301 sid = sidAsUnsignedChar;
299 302 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
300 303 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
301 304 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
302 305 {
303 306 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
304 307 }
305 308
306 309 status = write( fdSPW, incomingData, size );
307 310 if (status == -1){
308 311 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
309 312 }
310 313 }
311 314 else // the incoming message is a spw_ioctl_pkt_send structure
312 315 {
313 316 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
314 317 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
315 318 if (status == -1){
316 319 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
317 320 }
318 321 }
319 322 }
320 323
321 324 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
322 325
323 326 }
324 327 }
325 328
326 329 rtems_task wtdg_task( rtems_task_argument argument )
327 330 {
328 331 rtems_event_set event_out;
329 332 rtems_status_code status;
330 333 int linkStatus;
331 334
332 335 BOOT_PRINTF("in WTDG ***\n")
333 336
334 337 while(1)
335 338 {
336 339 // wait for an RTEMS_EVENT
337 340 rtems_event_receive( RTEMS_EVENT_0,
338 341 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
339 342 PRINTF("in WTDG *** wait for the link\n")
340 343 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
341 344 while( linkStatus != 5) // wait for the link
342 345 {
343 346 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
344 347 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
345 348 }
346 349
347 350 status = spacewire_stop_and_start_link( fdSPW );
348 351
349 352 if (status != RTEMS_SUCCESSFUL)
350 353 {
351 354 PRINTF1("in WTDG *** ERR link not started %d\n", status)
352 355 }
353 356 else
354 357 {
355 358 PRINTF("in WTDG *** OK link started\n")
356 359 }
357 360
358 361 // restart the SPIQ task
359 362 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
360 363 if ( status != RTEMS_SUCCESSFUL ) {
361 364 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
362 365 }
363 366
364 367 // restart RECV and SEND
365 368 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
366 369 if ( status != RTEMS_SUCCESSFUL ) {
367 370 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
368 371 }
369 372 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
370 373 if ( status != RTEMS_SUCCESSFUL ) {
371 374 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
372 375 }
373 376 }
374 377 }
375 378
376 379 //****************
377 380 // OTHER FUNCTIONS
378 381 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
379 382 {
380 383 /** This function opens the SpaceWire link.
381 384 *
382 385 * @return a valid file descriptor in case of success, -1 in case of a failure
383 386 *
384 387 */
385 388 rtems_status_code status;
386 389
387 390 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
388 391 if ( fdSPW < 0 ) {
389 392 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
390 393 }
391 394 else
392 395 {
393 396 status = RTEMS_SUCCESSFUL;
394 397 }
395 398
396 399 return status;
397 400 }
398 401
399 402 int spacewire_start_link( int fd )
400 403 {
401 404 rtems_status_code status;
402 405
403 406 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
404 407 // -1 default hardcoded driver timeout
405 408
406 409 return status;
407 410 }
408 411
409 412 int spacewire_stop_and_start_link( int fd )
410 413 {
411 414 rtems_status_code status;
412 415
413 416 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
414 417 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
415 418 // -1 default hardcoded driver timeout
416 419
417 420 return status;
418 421 }
419 422
420 423 int spacewire_configure_link( int fd )
421 424 {
422 425 /** This function configures the SpaceWire link.
423 426 *
424 427 * @return GR-RTEMS-DRIVER directive status codes:
425 428 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
426 429 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
427 430 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
428 431 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
429 432 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
430 433 * - 5 EIO - Error when writing to grswp hardware registers.
431 434 * - 2 ENOENT - No such file or directory
432 435 */
433 436
434 437 rtems_status_code status;
435 438
436 439 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
437 440 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
438 441
439 442 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
440 443 if (status!=RTEMS_SUCCESSFUL) {
441 444 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
442 445 }
443 446 //
444 447 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
445 448 if (status!=RTEMS_SUCCESSFUL) {
446 449 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
447 450 }
448 451 //
449 452 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
450 453 if (status!=RTEMS_SUCCESSFUL) {
451 454 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
452 455 }
453 456 //
454 457 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
455 458 if (status!=RTEMS_SUCCESSFUL) {
456 459 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
457 460 }
458 461 //
459 462 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
460 463 if (status!=RTEMS_SUCCESSFUL) {
461 464 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
462 465 }
463 466 //
464 467 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
465 468 if (status!=RTEMS_SUCCESSFUL) {
466 469 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
467 470 }
468 471 //
469 472 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
470 473 if (status!=RTEMS_SUCCESSFUL) {
471 474 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
472 475 }
473 476
474 477 return status;
475 478 }
476 479
477 480 int spacewire_reset_link( void )
478 481 {
479 482 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
480 483 *
481 484 * @return RTEMS directive status code:
482 485 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
483 486 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
484 487 *
485 488 */
486 489
487 490 rtems_status_code status_spw;
488 491 rtems_status_code status;
489 492 int i;
490 493
491 494 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
492 495 {
493 496 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
494 497
495 498 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
496 499
497 500 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
498 501
499 502 status_spw = spacewire_stop_and_start_link( fdSPW );
500 503 if ( status_spw != RTEMS_SUCCESSFUL )
501 504 {
502 505 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
503 506 }
504 507
505 508 if ( status_spw == RTEMS_SUCCESSFUL)
506 509 {
507 510 break;
508 511 }
509 512 }
510 513
511 514 return status_spw;
512 515 }
513 516
514 517 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
515 518 {
516 519 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
517 520 *
518 521 * @param val is the value, 0 or 1, used to set the value of the NP bit.
519 522 * @param regAddr is the address of the GRSPW control register.
520 523 *
521 524 * NP is the bit 20 of the GRSPW control register.
522 525 *
523 526 */
524 527
525 528 unsigned int *spwptr = (unsigned int*) regAddr;
526 529
527 530 if (val == 1) {
528 531 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
529 532 }
530 533 if (val== 0) {
531 534 *spwptr = *spwptr & 0xffdfffff;
532 535 }
533 536 }
534 537
535 538 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
536 539 {
537 540 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
538 541 *
539 542 * @param val is the value, 0 or 1, used to set the value of the RE bit.
540 543 * @param regAddr is the address of the GRSPW control register.
541 544 *
542 545 * RE is the bit 16 of the GRSPW control register.
543 546 *
544 547 */
545 548
546 549 unsigned int *spwptr = (unsigned int*) regAddr;
547 550
548 551 if (val == 1)
549 552 {
550 553 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
551 554 }
552 555 if (val== 0)
553 556 {
554 557 *spwptr = *spwptr & 0xfffdffff;
555 558 }
556 559 }
557 560
558 561 void spacewire_compute_stats_offsets( void )
559 562 {
560 563 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
561 564 *
562 565 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
563 566 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
564 567 * during the open systel call).
565 568 *
566 569 */
567 570
568 571 spw_stats spacewire_stats_grspw;
569 572 rtems_status_code status;
570 573
571 574 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
572 575
573 576 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
574 577 + spacewire_stats.packets_received;
575 578 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
576 579 + spacewire_stats.packets_sent;
577 580 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
578 581 + spacewire_stats.parity_err;
579 582 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
580 583 + spacewire_stats.disconnect_err;
581 584 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
582 585 + spacewire_stats.escape_err;
583 586 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
584 587 + spacewire_stats.credit_err;
585 588 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
586 589 + spacewire_stats.write_sync_err;
587 590 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
588 591 + spacewire_stats.rx_rmap_header_crc_err;
589 592 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
590 593 + spacewire_stats.rx_rmap_data_crc_err;
591 594 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
592 595 + spacewire_stats.early_ep;
593 596 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
594 597 + spacewire_stats.invalid_address;
595 598 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
596 599 + spacewire_stats.rx_eep_err;
597 600 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
598 601 + spacewire_stats.rx_truncated;
599 602 }
600 603
601 604 void spacewire_update_statistics( void )
602 605 {
603 606 rtems_status_code status;
604 607 spw_stats spacewire_stats_grspw;
605 608
606 609 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
607 610
608 611 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
609 612 + spacewire_stats_grspw.packets_received;
610 613 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
611 614 + spacewire_stats_grspw.packets_sent;
612 615 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
613 616 + spacewire_stats_grspw.parity_err;
614 617 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
615 618 + spacewire_stats_grspw.disconnect_err;
616 619 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
617 620 + spacewire_stats_grspw.escape_err;
618 621 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
619 622 + spacewire_stats_grspw.credit_err;
620 623 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
621 624 + spacewire_stats_grspw.write_sync_err;
622 625 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
623 626 + spacewire_stats_grspw.rx_rmap_header_crc_err;
624 627 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
625 628 + spacewire_stats_grspw.rx_rmap_data_crc_err;
626 629 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
627 630 + spacewire_stats_grspw.early_ep;
628 631 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
629 632 + spacewire_stats_grspw.invalid_address;
630 633 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
631 634 + spacewire_stats_grspw.rx_eep_err;
632 635 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
633 636 + spacewire_stats_grspw.rx_truncated;
634 637 //spacewire_stats.tx_link_err;
635 638
636 639 //****************************
637 640 // DPU_SPACEWIRE_IF_STATISTICS
638 641 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
639 642 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
640 643 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
641 644 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
642 645 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
643 646 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
644 647
645 648 //******************************************
646 649 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
647 650 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
648 651 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
649 652 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
650 653 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
651 654 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
652 655
653 656 //*********************************************
654 657 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
655 658 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
656 659 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
657 660 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
658 661 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
659 662 }
660 663
661 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
664 void increase_unsigned_char_counter( unsigned char *counter )
665 {
666 // update the number of valid timecodes that have been received
667 if (*counter == 255)
668 {
669 *counter = 0;
670 }
671 else
662 672 {
663 // a valid timecode has been received, write it in the HK report
664 unsigned int *grspwPtr;
665 unsigned char timecodeCtr;
666 unsigned char updateTimeCtr;
673 *counter = *counter + 1;
674 }
675 }
667 676
668 grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
677 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
678 {
679
680 unsigned char currentTimecodeCtr;
681
682 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
669 683
670 housekeeping_packet.hk_lfr_dpu_spw_last_timc = (unsigned char) (grspwPtr[0] & 0xff); // [1111 1111]
671 timecodeCtr = (unsigned char) (grspwPtr[0] & 0x3f); // [0011 1111]
672 updateTimeCtr = time_management_regs->coarse_time_load & 0x3f; // [0011 1111]
684 if (currentTimecodeCtr == previousTimecodeCtr)
685 {
686 //************************
687 // HK_LFR_TIMECODE_MISSING
688 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
689 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
690 }
691 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
692 {
693 // the timecode value has changed and the value is valid, this is unexpected because
694 // the timer should not have fired, the timecode_irq_handler should have been raised
695 }
696 else
697 {
698 //************************
699 // HK_LFR_TIMECODE_INVALID
700 // the timecode value has changed and the value is not valid, no tickout has been generated
701 // this is why the timer has fired
702 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
703 }
673 704
674 // update the number of valid timecodes that have been received
675 if (housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt == 255)
705 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
706 }
707
708 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
709 {
710 unsigned char ret;
711
712 ret = LFR_DEFAULT;
713
714 if (currentTimecodeCtr == 0)
715 {
716 if (previousTimecodeCtr == 63)
676 717 {
677 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = 0;
718 ret = LFR_SUCCESSFUL;
719 }
720 else
721 {
722 ret = LFR_DEFAULT;
723 }
724 }
725 else
726 {
727 if (currentTimecodeCtr == (previousTimecodeCtr +1))
728 {
729 ret = LFR_SUCCESSFUL;
678 730 }
679 731 else
680 732 {
681 housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt = housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt + 1;
733 ret = LFR_DEFAULT;
734 }
735 }
736
737 return ret;
682 738 }
683 739
684 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
685 if (timecodeCtr != updateTimeCtr)
740 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
686 741 {
687 if (housekeeping_packet.hk_lfr_time_timecode_ctr == 255)
742 unsigned int ret;
743
744 ret = LFR_DEFAULT;
745
746 if (timecode == internalTime)
688 747 {
689 housekeeping_packet.hk_lfr_time_timecode_ctr = 0;
748 ret = LFR_SUCCESSFUL;
690 749 }
691 750 else
692 751 {
693 housekeeping_packet.hk_lfr_time_timecode_ctr = housekeeping_packet.hk_lfr_time_timecode_ctr + 1;
752 ret = LFR_DEFAULT;
753 }
754
755 return ret;
694 756 }
757
758 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
759 {
760 // a tickout has been emitted, perform actions on the incoming timecode
761
762 unsigned char incomingTimecode;
763 unsigned char updateTime;
764 unsigned char internalTime;
765 rtems_status_code status;
766
767 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
768 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
769 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
770
771 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
772
773 // update the number of tickout that have been generated
774 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
775
776 //**************************
777 // HK_LFR_TIMECODE_ERRONEOUS
778 // MISSING and INVALID are handled by the timecode_timer_routine service routine
779 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
780 {
781 // this is unexpected but a tickout has been raised and the timecode is erroneous
782 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
695 783 }
784
785 //************************
786 // HK_LFR_TIME_TIMECODE_IT
787 // check the coherency between the SpaceWire timecode and the Internal Time
788 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
789 {
790 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
791 }
792
793 //********************
794 // HK_LFR_TIMECODE_CTR
795 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
796 if (incomingTimecode != updateTime)
797 {
798 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
799 }
800
801 // launch the timecode timer to detect missing or invalid timecodes
802 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
803 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
696 804 }
697 805
698 806 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
699 807 {
700 808 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
701 809 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
702 810 header->reserved = DEFAULT_RESERVED;
703 811 header->userApplication = CCSDS_USER_APP;
704 812 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
705 813 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
706 814 header->packetLength[0] = 0x00;
707 815 header->packetLength[1] = 0x00;
708 816 // DATA FIELD HEADER
709 817 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
710 818 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
711 819 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
712 820 header->destinationID = TM_DESTINATION_ID_GROUND;
713 821 header->time[0] = 0x00;
714 822 header->time[0] = 0x00;
715 823 header->time[0] = 0x00;
716 824 header->time[0] = 0x00;
717 825 header->time[0] = 0x00;
718 826 header->time[0] = 0x00;
719 827 // AUXILIARY DATA HEADER
720 828 header->sid = 0x00;
721 829 header->hkBIA = DEFAULT_HKBIA;
722 830 header->blkNr[0] = 0x00;
723 831 header->blkNr[1] = 0x00;
724 832 }
725 833
726 834 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
727 835 {
728 836 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
729 837 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
730 838 header->reserved = DEFAULT_RESERVED;
731 839 header->userApplication = CCSDS_USER_APP;
732 840 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
733 841 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
734 842 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
735 843 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
736 844 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
737 845 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
738 846 // DATA FIELD HEADER
739 847 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
740 848 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
741 849 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
742 850 header->destinationID = TM_DESTINATION_ID_GROUND;
743 851 header->time[0] = 0x00;
744 852 header->time[0] = 0x00;
745 853 header->time[0] = 0x00;
746 854 header->time[0] = 0x00;
747 855 header->time[0] = 0x00;
748 856 header->time[0] = 0x00;
749 857 // AUXILIARY DATA HEADER
750 858 header->sid = 0x00;
751 859 header->hkBIA = DEFAULT_HKBIA;
752 860 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
753 861 header->pktNr = 0x00;
754 862 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
755 863 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
756 864 }
757 865
758 866 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
759 867 {
760 868 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
761 869 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
762 870 header->reserved = DEFAULT_RESERVED;
763 871 header->userApplication = CCSDS_USER_APP;
764 872 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
765 873 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
766 874 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
767 875 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
768 876 header->packetLength[0] = 0x00;
769 877 header->packetLength[1] = 0x00;
770 878 // DATA FIELD HEADER
771 879 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
772 880 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
773 881 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
774 882 header->destinationID = TM_DESTINATION_ID_GROUND;
775 883 header->time[0] = 0x00;
776 884 header->time[0] = 0x00;
777 885 header->time[0] = 0x00;
778 886 header->time[0] = 0x00;
779 887 header->time[0] = 0x00;
780 888 header->time[0] = 0x00;
781 889 // AUXILIARY DATA HEADER
782 890 header->sid = 0x00;
783 891 header->biaStatusInfo = 0x00;
784 892 header->pa_lfr_pkt_cnt_asm = 0x00;
785 893 header->pa_lfr_pkt_nr_asm = 0x00;
786 894 header->pa_lfr_asm_blk_nr[0] = 0x00;
787 895 header->pa_lfr_asm_blk_nr[1] = 0x00;
788 896 }
789 897
790 898 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
791 899 Header_TM_LFR_SCIENCE_CWF_t *header )
792 900 {
793 901 /** This function sends CWF CCSDS packets (F2, F1 or F0).
794 902 *
795 903 * @param waveform points to the buffer containing the data that will be send.
796 904 * @param sid is the source identifier of the data that will be sent.
797 905 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
798 906 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
799 907 * contain information to setup the transmission of the data packets.
800 908 *
801 909 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
802 910 *
803 911 */
804 912
805 913 unsigned int i;
806 914 int ret;
807 915 unsigned int coarseTime;
808 916 unsigned int fineTime;
809 917 rtems_status_code status;
810 918 spw_ioctl_pkt_send spw_ioctl_send_CWF;
811 919 int *dataPtr;
812 920 unsigned char sid;
813 921
814 922 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
815 923 spw_ioctl_send_CWF.options = 0;
816 924
817 925 ret = LFR_DEFAULT;
818 926 sid = (unsigned char) ring_node_to_send->sid;
819 927
820 928 coarseTime = ring_node_to_send->coarseTime;
821 929 fineTime = ring_node_to_send->fineTime;
822 930 dataPtr = (int*) ring_node_to_send->buffer_address;
823 931
824 932 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
825 933 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
826 934 header->hkBIA = pa_bia_status_info;
827 935 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
828 936 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
829 937 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
830 938
831 939 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
832 940 {
833 941 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
834 942 spw_ioctl_send_CWF.hdr = (char*) header;
835 943 // BUILD THE DATA
836 944 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
837 945
838 946 // SET PACKET SEQUENCE CONTROL
839 947 increment_seq_counter_source_id( header->packetSequenceControl, sid );
840 948
841 949 // SET SID
842 950 header->sid = sid;
843 951
844 952 // SET PACKET TIME
845 953 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
846 954 //
847 955 header->time[0] = header->acquisitionTime[0];
848 956 header->time[1] = header->acquisitionTime[1];
849 957 header->time[2] = header->acquisitionTime[2];
850 958 header->time[3] = header->acquisitionTime[3];
851 959 header->time[4] = header->acquisitionTime[4];
852 960 header->time[5] = header->acquisitionTime[5];
853 961
854 962 // SET PACKET ID
855 963 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
856 964 {
857 965 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
858 966 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
859 967 }
860 968 else
861 969 {
862 970 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
863 971 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
864 972 }
865 973
866 974 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
867 975 if (status != RTEMS_SUCCESSFUL) {
868 976 ret = LFR_DEFAULT;
869 977 }
870 978 }
871 979
872 980 return ret;
873 981 }
874 982
875 983 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
876 984 Header_TM_LFR_SCIENCE_SWF_t *header )
877 985 {
878 986 /** This function sends SWF CCSDS packets (F2, F1 or F0).
879 987 *
880 988 * @param waveform points to the buffer containing the data that will be send.
881 989 * @param sid is the source identifier of the data that will be sent.
882 990 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
883 991 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
884 992 * contain information to setup the transmission of the data packets.
885 993 *
886 994 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
887 995 *
888 996 */
889 997
890 998 unsigned int i;
891 999 int ret;
892 1000 unsigned int coarseTime;
893 1001 unsigned int fineTime;
894 1002 rtems_status_code status;
895 1003 spw_ioctl_pkt_send spw_ioctl_send_SWF;
896 1004 int *dataPtr;
897 1005 unsigned char sid;
898 1006
899 1007 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
900 1008 spw_ioctl_send_SWF.options = 0;
901 1009
902 1010 ret = LFR_DEFAULT;
903 1011
904 1012 coarseTime = ring_node_to_send->coarseTime;
905 1013 fineTime = ring_node_to_send->fineTime;
906 1014 dataPtr = (int*) ring_node_to_send->buffer_address;
907 1015 sid = ring_node_to_send->sid;
908 1016
909 1017 header->hkBIA = pa_bia_status_info;
910 1018 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
911 1019
912 1020 for (i=0; i<7; i++) // send waveform
913 1021 {
914 1022 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
915 1023 spw_ioctl_send_SWF.hdr = (char*) header;
916 1024
917 1025 // SET PACKET SEQUENCE CONTROL
918 1026 increment_seq_counter_source_id( header->packetSequenceControl, sid );
919 1027
920 1028 // SET PACKET LENGTH AND BLKNR
921 1029 if (i == 6)
922 1030 {
923 1031 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
924 1032 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
925 1033 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
926 1034 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
927 1035 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
928 1036 }
929 1037 else
930 1038 {
931 1039 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
932 1040 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
933 1041 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
934 1042 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
935 1043 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
936 1044 }
937 1045
938 1046 // SET PACKET TIME
939 1047 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
940 1048 //
941 1049 header->time[0] = header->acquisitionTime[0];
942 1050 header->time[1] = header->acquisitionTime[1];
943 1051 header->time[2] = header->acquisitionTime[2];
944 1052 header->time[3] = header->acquisitionTime[3];
945 1053 header->time[4] = header->acquisitionTime[4];
946 1054 header->time[5] = header->acquisitionTime[5];
947 1055
948 1056 // SET SID
949 1057 header->sid = sid;
950 1058
951 1059 // SET PKTNR
952 1060 header->pktNr = i+1; // PKT_NR
953 1061
954 1062 // SEND PACKET
955 1063 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
956 1064 if (status != RTEMS_SUCCESSFUL) {
957 1065 ret = LFR_DEFAULT;
958 1066 }
959 1067 }
960 1068
961 1069 return ret;
962 1070 }
963 1071
964 1072 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
965 1073 Header_TM_LFR_SCIENCE_CWF_t *header )
966 1074 {
967 1075 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
968 1076 *
969 1077 * @param waveform points to the buffer containing the data that will be send.
970 1078 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
971 1079 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
972 1080 * contain information to setup the transmission of the data packets.
973 1081 *
974 1082 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
975 1083 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
976 1084 *
977 1085 */
978 1086
979 1087 unsigned int i;
980 1088 int ret;
981 1089 unsigned int coarseTime;
982 1090 unsigned int fineTime;
983 1091 rtems_status_code status;
984 1092 spw_ioctl_pkt_send spw_ioctl_send_CWF;
985 1093 char *dataPtr;
986 1094 unsigned char sid;
987 1095
988 1096 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
989 1097 spw_ioctl_send_CWF.options = 0;
990 1098
991 1099 ret = LFR_DEFAULT;
992 1100 sid = ring_node_to_send->sid;
993 1101
994 1102 coarseTime = ring_node_to_send->coarseTime;
995 1103 fineTime = ring_node_to_send->fineTime;
996 1104 dataPtr = (char*) ring_node_to_send->buffer_address;
997 1105
998 1106 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
999 1107 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1000 1108 header->hkBIA = pa_bia_status_info;
1001 1109 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1002 1110 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1003 1111 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1004 1112
1005 1113 //*********************
1006 1114 // SEND CWF3_light DATA
1007 1115 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1008 1116 {
1009 1117 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1010 1118 spw_ioctl_send_CWF.hdr = (char*) header;
1011 1119 // BUILD THE DATA
1012 1120 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1013 1121
1014 1122 // SET PACKET SEQUENCE COUNTER
1015 1123 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1016 1124
1017 1125 // SET SID
1018 1126 header->sid = sid;
1019 1127
1020 1128 // SET PACKET TIME
1021 1129 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1022 1130 //
1023 1131 header->time[0] = header->acquisitionTime[0];
1024 1132 header->time[1] = header->acquisitionTime[1];
1025 1133 header->time[2] = header->acquisitionTime[2];
1026 1134 header->time[3] = header->acquisitionTime[3];
1027 1135 header->time[4] = header->acquisitionTime[4];
1028 1136 header->time[5] = header->acquisitionTime[5];
1029 1137
1030 1138 // SET PACKET ID
1031 1139 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1032 1140 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1033 1141
1034 1142 // SEND PACKET
1035 1143 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1036 1144 if (status != RTEMS_SUCCESSFUL) {
1037 1145 ret = LFR_DEFAULT;
1038 1146 }
1039 1147 }
1040 1148
1041 1149 return ret;
1042 1150 }
1043 1151
1044 1152 void spw_send_asm_f0( ring_node *ring_node_to_send,
1045 1153 Header_TM_LFR_SCIENCE_ASM_t *header )
1046 1154 {
1047 1155 unsigned int i;
1048 1156 unsigned int length = 0;
1049 1157 rtems_status_code status;
1050 1158 unsigned int sid;
1051 1159 float *spectral_matrix;
1052 1160 int coarseTime;
1053 1161 int fineTime;
1054 1162 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1055 1163
1056 1164 sid = ring_node_to_send->sid;
1057 1165 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1058 1166 coarseTime = ring_node_to_send->coarseTime;
1059 1167 fineTime = ring_node_to_send->fineTime;
1060 1168
1061 1169 header->biaStatusInfo = pa_bia_status_info;
1062 1170 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1063 1171
1064 1172 for (i=0; i<3; i++)
1065 1173 {
1066 1174 if ((i==0) || (i==1))
1067 1175 {
1068 1176 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1069 1177 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1070 1178 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1071 1179 ];
1072 1180 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1073 1181 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1074 1182 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1075 1183 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1076 1184 }
1077 1185 else
1078 1186 {
1079 1187 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1080 1188 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1081 1189 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1082 1190 ];
1083 1191 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1084 1192 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1085 1193 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1086 1194 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1087 1195 }
1088 1196
1089 1197 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1090 1198 spw_ioctl_send_ASM.hdr = (char *) header;
1091 1199 spw_ioctl_send_ASM.options = 0;
1092 1200
1093 1201 // (2) BUILD THE HEADER
1094 1202 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1095 1203 header->packetLength[0] = (unsigned char) (length>>8);
1096 1204 header->packetLength[1] = (unsigned char) (length);
1097 1205 header->sid = (unsigned char) sid; // SID
1098 1206 header->pa_lfr_pkt_cnt_asm = 3;
1099 1207 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1100 1208
1101 1209 // (3) SET PACKET TIME
1102 1210 header->time[0] = (unsigned char) (coarseTime>>24);
1103 1211 header->time[1] = (unsigned char) (coarseTime>>16);
1104 1212 header->time[2] = (unsigned char) (coarseTime>>8);
1105 1213 header->time[3] = (unsigned char) (coarseTime);
1106 1214 header->time[4] = (unsigned char) (fineTime>>8);
1107 1215 header->time[5] = (unsigned char) (fineTime);
1108 1216 //
1109 1217 header->acquisitionTime[0] = header->time[0];
1110 1218 header->acquisitionTime[1] = header->time[1];
1111 1219 header->acquisitionTime[2] = header->time[2];
1112 1220 header->acquisitionTime[3] = header->time[3];
1113 1221 header->acquisitionTime[4] = header->time[4];
1114 1222 header->acquisitionTime[5] = header->time[5];
1115 1223
1116 1224 // (4) SEND PACKET
1117 1225 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1118 1226 if (status != RTEMS_SUCCESSFUL) {
1119 1227 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1120 1228 }
1121 1229 }
1122 1230 }
1123 1231
1124 1232 void spw_send_asm_f1( ring_node *ring_node_to_send,
1125 1233 Header_TM_LFR_SCIENCE_ASM_t *header )
1126 1234 {
1127 1235 unsigned int i;
1128 1236 unsigned int length = 0;
1129 1237 rtems_status_code status;
1130 1238 unsigned int sid;
1131 1239 float *spectral_matrix;
1132 1240 int coarseTime;
1133 1241 int fineTime;
1134 1242 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1135 1243
1136 1244 sid = ring_node_to_send->sid;
1137 1245 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1138 1246 coarseTime = ring_node_to_send->coarseTime;
1139 1247 fineTime = ring_node_to_send->fineTime;
1140 1248
1141 1249 header->biaStatusInfo = pa_bia_status_info;
1142 1250 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1143 1251
1144 1252 for (i=0; i<3; i++)
1145 1253 {
1146 1254 if ((i==0) || (i==1))
1147 1255 {
1148 1256 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1149 1257 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1150 1258 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1151 1259 ];
1152 1260 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1153 1261 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1154 1262 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1155 1263 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1156 1264 }
1157 1265 else
1158 1266 {
1159 1267 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1160 1268 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1161 1269 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1162 1270 ];
1163 1271 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1164 1272 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1165 1273 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1166 1274 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1167 1275 }
1168 1276
1169 1277 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1170 1278 spw_ioctl_send_ASM.hdr = (char *) header;
1171 1279 spw_ioctl_send_ASM.options = 0;
1172 1280
1173 1281 // (2) BUILD THE HEADER
1174 1282 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1175 1283 header->packetLength[0] = (unsigned char) (length>>8);
1176 1284 header->packetLength[1] = (unsigned char) (length);
1177 1285 header->sid = (unsigned char) sid; // SID
1178 1286 header->pa_lfr_pkt_cnt_asm = 3;
1179 1287 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1180 1288
1181 1289 // (3) SET PACKET TIME
1182 1290 header->time[0] = (unsigned char) (coarseTime>>24);
1183 1291 header->time[1] = (unsigned char) (coarseTime>>16);
1184 1292 header->time[2] = (unsigned char) (coarseTime>>8);
1185 1293 header->time[3] = (unsigned char) (coarseTime);
1186 1294 header->time[4] = (unsigned char) (fineTime>>8);
1187 1295 header->time[5] = (unsigned char) (fineTime);
1188 1296 //
1189 1297 header->acquisitionTime[0] = header->time[0];
1190 1298 header->acquisitionTime[1] = header->time[1];
1191 1299 header->acquisitionTime[2] = header->time[2];
1192 1300 header->acquisitionTime[3] = header->time[3];
1193 1301 header->acquisitionTime[4] = header->time[4];
1194 1302 header->acquisitionTime[5] = header->time[5];
1195 1303
1196 1304 // (4) SEND PACKET
1197 1305 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1198 1306 if (status != RTEMS_SUCCESSFUL) {
1199 1307 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1200 1308 }
1201 1309 }
1202 1310 }
1203 1311
1204 1312 void spw_send_asm_f2( ring_node *ring_node_to_send,
1205 1313 Header_TM_LFR_SCIENCE_ASM_t *header )
1206 1314 {
1207 1315 unsigned int i;
1208 1316 unsigned int length = 0;
1209 1317 rtems_status_code status;
1210 1318 unsigned int sid;
1211 1319 float *spectral_matrix;
1212 1320 int coarseTime;
1213 1321 int fineTime;
1214 1322 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1215 1323
1216 1324 sid = ring_node_to_send->sid;
1217 1325 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1218 1326 coarseTime = ring_node_to_send->coarseTime;
1219 1327 fineTime = ring_node_to_send->fineTime;
1220 1328
1221 1329 header->biaStatusInfo = pa_bia_status_info;
1222 1330 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1223 1331
1224 1332 for (i=0; i<3; i++)
1225 1333 {
1226 1334
1227 1335 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1228 1336 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1229 1337 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1230 1338 ];
1231 1339 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1232 1340 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1233 1341 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1234 1342 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1235 1343
1236 1344 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1237 1345 spw_ioctl_send_ASM.hdr = (char *) header;
1238 1346 spw_ioctl_send_ASM.options = 0;
1239 1347
1240 1348 // (2) BUILD THE HEADER
1241 1349 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1242 1350 header->packetLength[0] = (unsigned char) (length>>8);
1243 1351 header->packetLength[1] = (unsigned char) (length);
1244 1352 header->sid = (unsigned char) sid; // SID
1245 1353 header->pa_lfr_pkt_cnt_asm = 3;
1246 1354 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1247 1355
1248 1356 // (3) SET PACKET TIME
1249 1357 header->time[0] = (unsigned char) (coarseTime>>24);
1250 1358 header->time[1] = (unsigned char) (coarseTime>>16);
1251 1359 header->time[2] = (unsigned char) (coarseTime>>8);
1252 1360 header->time[3] = (unsigned char) (coarseTime);
1253 1361 header->time[4] = (unsigned char) (fineTime>>8);
1254 1362 header->time[5] = (unsigned char) (fineTime);
1255 1363 //
1256 1364 header->acquisitionTime[0] = header->time[0];
1257 1365 header->acquisitionTime[1] = header->time[1];
1258 1366 header->acquisitionTime[2] = header->time[2];
1259 1367 header->acquisitionTime[3] = header->time[3];
1260 1368 header->acquisitionTime[4] = header->time[4];
1261 1369 header->acquisitionTime[5] = header->time[5];
1262 1370
1263 1371 // (4) SEND PACKET
1264 1372 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1265 1373 if (status != RTEMS_SUCCESSFUL) {
1266 1374 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1267 1375 }
1268 1376 }
1269 1377 }
1270 1378
1271 1379 void spw_send_k_dump( ring_node *ring_node_to_send )
1272 1380 {
1273 1381 rtems_status_code status;
1274 1382 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1275 1383 unsigned int packetLength;
1276 1384 unsigned int size;
1277 1385
1278 1386 PRINTF("spw_send_k_dump\n")
1279 1387
1280 1388 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1281 1389
1282 1390 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1283 1391
1284 1392 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1285 1393
1286 1394 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1287 1395
1288 1396 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1289 1397
1290 1398 if (status == -1){
1291 1399 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1292 1400 }
1293 1401
1294 1402 ring_node_to_send->status = 0x00;
1295 1403 }
General Comments 0
You need to be logged in to leave comments. Login now