##// END OF EJS Templates
Snapshot resynchro rewritten, drift is measured one snapshot in two...
paul -
r253:cc5f75e74b54 R3a
parent child
Show More
@@ -1,192 +1,192
1 1 #ifndef GSCMEMORY_HPP_
2 2 #define GSCMEMORY_HPP_
3 3
4 4 #ifndef LEON3
5 5 #define LEON3
6 6 #endif
7 7
8 8 #define REGS_ADDR_PLUGANDPLAY 0xFFFFF000
9 9 #define ASR16_REG_ADDRESS 0x90400040 // Ancillary State Register 16 = Register protection control register (FT only)
10 10
11 11 #define DEVICEID_LEON3 0x003
12 12 #define DEVICEID_LEON3FT 0x053
13 13 #define VENDORID_GAISLER 0x01
14 14
15 15 // CCR
16 16 #define POS_ITE 12
17 17 #define COUNTER_FIELD_ITE 0x00003000 // 0000 0000 0000 0000 0011 0000 0000 0000
18 18 #define COUNTER_MASK_ITE 0xffffcfff // 1111 1111 1111 1111 1100 1111 1111 1111
19 19 #define POS_IDE 10
20 20 #define COUNTER_FIELD_IDE 0x00000c00 // 0000 0000 0000 0000 0000 1100 0000 0000
21 21 #define COUNTER_MASK_IDE 0xfffff3ff // 1111 1111 1111 1111 1111 0011 1111 1111
22 22 //
23 23 #define POS_DTE 8
24 24 #define COUNTER_FIELD_DTE 0x00000300 // 0000 0000 0000 0000 0000 0011 0000 0000
25 25 #define COUNTER_MASK_DTE 0xfffffcff // 1111 1111 1111 1111 1111 1100 1111 1111
26 26 #define POS_DDE 6
27 27 #define COUNTER_FIELD_DDE 0x000000c0 // 0000 0000 0000 0000 0000 0000 1100 0000
28 28 #define COUNTER_MASK_DDE 0xffffff3f // 1111 1111 1111 1111 1111 1111 0011 1111
29 29
30 30 // ASR16
31 31 #define POS_FPRF 27
32 32 #define COUNTER_FIELD_FPRF 0x38000000 // 0011 1000 0000 0000 0000 0000 0000 0000
33 33 #define COUNTER_MASK_FPRF 0xc7ffffff // 1100 0111 1111 1111 1111 1111 1111 1111
34 34 #define POS_IURF 11
35 35 #define COUNTER_FIELD_IURF 0x00003800 // 0000 0000 0000 0000 0011 1000 0000 0000
36 36 #define COUNTER_MASK_IURF 0xffffc7ff // 1111 1111 1111 1111 1100 0111 1111 1111
37 37
38 38 volatile unsigned int *asr16Ptr = (volatile unsigned int *) ASR16_REG_ADDRESS;
39 39
40 40 static inline void flushCache()
41 41 {
42 42 /**
43 43 * Flush the data cache and the instruction cache.
44 44 *
45 45 * @param void
46 46 *
47 47 * @return void
48 48 */
49 49
50 50 asm("flush");
51 51 }
52 52
53 53 //***************************
54 54 // CCR Cache control register
55 55
56 56 static unsigned int CCR_getValue()
57 57 {
58 58 unsigned int cacheControlRegister = 0;
59 59 __asm__ __volatile__("lda [%%g0] 2, %0" : "=r"(cacheControlRegister) : );
60 60 return cacheControlRegister;
61 61 }
62 62
63 63 static void CCR_setValue(unsigned int cacheControlRegister)
64 64 {
65 65 __asm__ __volatile__("sta %0, [%%g0] 2" : : "r"(cacheControlRegister));
66 66 }
67 67
68 68 static void CCR_resetCacheControlRegister()
69 69 {
70 70 unsigned int cacheControlRegister;
71 71 cacheControlRegister = 0x00;
72 72 CCR_setValue(cacheControlRegister);
73 73 }
74 74
75 75 static void CCR_enableInstructionCache()
76 76 {
77 77 // [1:0] Instruction Cache state (ICS)
78 78 // Indicates the current data cache state according to the following: X0 = disabled, 01 = frozen, 11 = enabled.
79 79 unsigned int cacheControlRegister;
80 80 cacheControlRegister = CCR_getValue();
81 81 cacheControlRegister = (cacheControlRegister | 0x3);
82 82 CCR_setValue(cacheControlRegister);
83 83 }
84 84
85 85 static void CCR_enableDataCache()
86 86 {
87 87 // [3:2] Data Cache state (DCS)
88 88 // Indicates the current data cache state according to the following: X0 = disabled, 01 = frozen, 11 = enabled.
89 89 unsigned int cacheControlRegister;
90 90 cacheControlRegister = CCR_getValue();
91 91 cacheControlRegister = (cacheControlRegister | 0xc);
92 92 CCR_setValue(cacheControlRegister);
93 93 }
94 94
95 95 static void CCR_faultTolerantScheme()
96 96 {
97 97 // [20:19] FT scheme (FT) - β€œ00” = no FT, β€œ01” = 4-bit checking implemented
98 98 unsigned int cacheControlRegister;
99 99 unsigned int *plugAndPlayRegister;
100 100 unsigned int vendorId;
101 101 unsigned int deviceId;
102 102
103 103 plugAndPlayRegister = (unsigned int*) REGS_ADDR_PLUGANDPLAY;
104 104 vendorId = ( (*plugAndPlayRegister) & 0xff000000 ) >> 24;
105 105 deviceId = ( (*plugAndPlayRegister) & 0x00fff000 ) >> 12;
106 106
107 107 if( (vendorId == VENDORID_GAISLER) & (deviceId ==DEVICEID_LEON3FT) )
108 108 {
109 PRINTF("in faultTolerantScheme *** Leon3FT detected, configure the CCR FT bits");
109 PRINTF("in faultTolerantScheme *** Leon3FT detected, configure the CCR FT bits\n");
110 110 cacheControlRegister = CCR_getValue();
111 111 cacheControlRegister = (cacheControlRegister | 0xc);
112 112 CCR_setValue(cacheControlRegister);
113 113 }
114 114 else
115 115 {
116 116 PRINTF("in faultTolerantScheme *** not a Leon3FT, no need to configure the CCR FT bits\n");
117 117 PRINTF2(" *** vendorID = 0x%x, deviceId = 0x%x\n", vendorId, deviceId);
118 118 }
119 119 }
120 120
121 121 static void CCR_enableInstructionBurstFetch()
122 122 {
123 123 // [16] Instruction burst fetch (IB). This bit enables burst fill during instruction fetch.
124 124 unsigned int cacheControlRegister;
125 125 cacheControlRegister = CCR_getValue();
126 126 // set the bit IB to 1
127 127 cacheControlRegister = (cacheControlRegister | 0x10000);
128 128 CCR_setValue(cacheControlRegister);
129 129 }
130 130
131 131 static void CCR_getInstructionAndDataErrorCounters( unsigned int* instructionErrorCounter, unsigned int* dataErrorCounter )
132 132 {
133 133 // [13:12] Instruction Tag Errors (ITE) - Number of detected parity errors in the instruction tag cache.
134 134 // Only available if fault-tolerance is enabled (FT field in this register is non-zero).
135 135 // [11:10] Instruction Data Errors (IDE) - Number of detected parity errors in the instruction data cache.
136 136 // Only available if fault-tolerance is enabled (FT field in this register is non-zero).
137 137
138 138 unsigned int cacheControlRegister;
139 139 unsigned int iTE;
140 140 unsigned int iDE;
141 141 unsigned int dTE;
142 142 unsigned int dDE;
143 143
144 144 cacheControlRegister = CCR_getValue();
145 145 iTE = (cacheControlRegister & COUNTER_FIELD_ITE) >> POS_ITE;
146 146 iDE = (cacheControlRegister & COUNTER_FIELD_IDE) >> POS_IDE;
147 147 dTE = (cacheControlRegister & COUNTER_FIELD_DTE) >> POS_DTE;
148 148 dDE = (cacheControlRegister & COUNTER_FIELD_DDE) >> POS_DDE;
149 149
150 150 *instructionErrorCounter = iTE + iDE;
151 151 *dataErrorCounter = dTE + dDE;
152 152
153 153 // reset counters
154 154 cacheControlRegister = cacheControlRegister
155 155 & COUNTER_FIELD_ITE
156 156 & COUNTER_FIELD_IDE
157 157 & COUNTER_FIELD_DTE
158 158 & COUNTER_FIELD_DDE;
159 159
160 160 CCR_setValue(cacheControlRegister);
161 161 }
162 162
163 163 //*******************************************
164 164 // ASR16 Register protection control register
165 165
166 static unsigned int ASR16_get_FPRF_IURF_ErrorCounters( unsigned int* fprfErrorCounter, unsigned int* iurfErrorCounter)
166 static void ASR16_get_FPRF_IURF_ErrorCounters( unsigned int* fprfErrorCounter, unsigned int* iurfErrorCounter)
167 167 {
168 168 /** This function is used to retrieve the integer unit register file error counter and the floating point unit
169 169 * register file error counter
170 170 *
171 171 * @return void
172 172 *
173 173 * [29:27] FP RF error counter - Number of detected parity errors in the FP register file.
174 174 * [13:11] IU RF error counter - Number of detected parity errors in the IU register file.
175 175 *
176 176 */
177 177
178 178 unsigned int asr16;
179 179
180 180 asr16 = *asr16Ptr;
181 181 *fprfErrorCounter = ( asr16 & COUNTER_FIELD_FPRF ) >> POS_FPRF;
182 182 *iurfErrorCounter = ( asr16 & COUNTER_FIELD_IURF ) >> POS_IURF;
183 183
184 184 // reset the counter to 0
185 asr16 = asr16Ptr
185 asr16 = asr16
186 186 & COUNTER_MASK_FPRF
187 187 & COUNTER_FIELD_IURF;
188 188
189 189 *asr16Ptr = asr16;
190 190 }
191 191
192 192 #endif /* GSCMEMORY_HPP_ */
@@ -1,56 +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 18 extern rtems_name timecode_timer_name;
19 19 extern rtems_id timecode_timer_id;
20 20
21 21 // RTEMS TASK
22 22 rtems_task spiq_task( rtems_task_argument argument );
23 23 rtems_task recv_task( rtems_task_argument unused );
24 24 rtems_task send_task( rtems_task_argument argument );
25 25 rtems_task wtdg_task( rtems_task_argument argument );
26 26
27 27 int spacewire_open_link( void );
28 28 int spacewire_start_link( int fd );
29 29 int spacewire_stop_and_start_link( int fd );
30 30 int spacewire_configure_link(int fd );
31 int spacewire_reset_link( void );
31 int spacewire_several_connect_attemps( void );
32 32 void spacewire_set_NP( unsigned char val, unsigned int regAddr ); // No Port force
33 33 void spacewire_set_RE( unsigned char val, unsigned int regAddr ); // RMAP Enable
34 34 void spacewire_compute_stats_offsets( void );
35 35 void spacewire_update_statistics( void );
36 36 void increase_unsigned_char_counter( unsigned char *counter );
37 37
38 38 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header );
39 39 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header );
40 40 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header );
41 41 int spw_send_waveform_CWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
42 42 int spw_send_waveform_SWF( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_SWF_t *header );
43 43 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_CWF_t *header );
44 44 void spw_send_asm_f0( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
45 45 void spw_send_asm_f1( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
46 46 void spw_send_asm_f2( ring_node *ring_node_to_send, Header_TM_LFR_SCIENCE_ASM_t *header );
47 47 void spw_send_k_dump( ring_node *ring_node_to_send );
48 48
49 49 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data );
50 50 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr);
51 51 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime);
52 52 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc );
53 53
54 54 void (*grspw_timecode_callback) ( void *pDev, void *regs, int minor, unsigned int tc );
55 55
56 56 #endif // FSW_SPACEWIRE_H_INCLUDED
@@ -1,14 +1,14
1 1 # LOAD FSW USING LINK 1
2 2 SpwPlugin0.StarDundeeSelectLinkNumber( 1 )
3 3
4 4 dsu3plugin0.openFile("/opt/DEV_PLE/FSW-qt/bin/fsw")
5 5 #dsu3plugin0.openFile("/opt/LFR/LFR-FSW/2.0.2.3/fsw")
6 6 dsu3plugin0.loadFile()
7 7
8 8 dsu3plugin0.run()
9 9
10 10 # START SENDING TIMECODES AT 1 Hz
11 SpwPlugin0.StarDundeeStartTimecodes( 1 )
11 #SpwPlugin0.StarDundeeStartTimecodes( 1 )
12 12
13 13 # it is possible to change the time code frequency
14 14 #RMAPPlugin0.changeTimecodeFrequency(2)
@@ -1,910 +1,909
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 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 // ASI 2 contains a few control registers that have not been assigned as ancillary state registers.
68 68 // These should only be read and written using 32-bit LDA/STA instructions.
69 69 // All cache registers are accessed through load/store operations to the alternate address space (LDA/STA), using ASI = 2.
70 70 // The table below shows the register addresses:
71 71 // 0x00 Cache control register
72 72 // 0x04 Reserved
73 73 // 0x08 Instruction cache configuration register
74 74 // 0x0C Data cache configuration register
75 75
76 76 // Cache Control Register Leon3 / Leon3FT
77 77 // 31..30 29 28 27..24 23 22 21 20..19 18 17 16
78 78 // RFT PS TB DS FD FI FT ST IB
79 79 // 15 14 13..12 11..10 9..8 7..6 5 4 3..2 1..0
80 80 // IP DP ITE IDE DTE DDE DF IF DCS ICS
81 81
82 82 unsigned int cacheControlRegister;
83 83
84 84 cacheControlRegister = CCR_getValue();
85 85 PRINTF1("(0) cacheControlRegister = %x\n", cacheControlRegister);
86 86
87 87 CCR_resetCacheControlRegister();
88 88
89 89 CCR_enableInstructionCache(); // ICS bits
90 90 CCR_enableDataCache(); // DCS bits
91 91 CCR_enableInstructionBurstFetch(); // IB bit
92 92
93 93 cacheControlRegister = CCR_getValue();
94 94 PRINTF1("(1) cacheControlRegister = %x\n", cacheControlRegister);
95 95
96 96 CCR_faultTolerantScheme();
97 97
98 // FT activation
98 PRINTF("\n");
99 99 }
100 100
101 101 rtems_task Init( rtems_task_argument ignored )
102 102 {
103 103 /** This is the RTEMS INIT taks, it is the first task launched by the system.
104 104 *
105 105 * @param unused is the starting argument of the RTEMS task
106 106 *
107 107 * The INIT task create and run all other RTEMS tasks.
108 108 *
109 109 */
110 110
111 111 //***********
112 112 // INIT CACHE
113 113
114 114 unsigned char *vhdlVersion;
115 115
116 116 reset_lfr();
117 117
118 118 reset_local_time();
119 119
120 120 rtems_cpu_usage_reset();
121 121
122 122 rtems_status_code status;
123 123 rtems_status_code status_spw;
124 124 rtems_isr_entry old_isr_handler;
125 125
126 126 // UART settings
127 send_console_outputs_on_apbuart_port();
127 enable_apbuart_transmitter();
128 128 set_apbuart_scaler_reload_register(REGS_ADDR_APBUART, APBUART_SCALER_RELOAD_VALUE);
129 enable_apbuart_transmitter();
130 129
131 130 DEBUG_PRINTF("\n\n\n\n\nIn INIT *** Now the console is on port COM1\n")
132 131
133 132
134 133 PRINTF("\n\n\n\n\n")
135 134
136 135 initCache();
137 136
138 137 PRINTF("*************************\n")
139 138 PRINTF("** LFR Flight Software **\n")
140 139 PRINTF1("** %d.", SW_VERSION_N1)
141 140 PRINTF1("%d." , SW_VERSION_N2)
142 141 PRINTF1("%d." , SW_VERSION_N3)
143 142 PRINTF1("%d **\n", SW_VERSION_N4)
144 143
145 144 vhdlVersion = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
146 145 PRINTF("** VHDL **\n")
147 146 PRINTF1("** %d.", vhdlVersion[1])
148 147 PRINTF1("%d." , vhdlVersion[2])
149 148 PRINTF1("%d **\n", vhdlVersion[3])
150 149 PRINTF("*************************\n")
151 150 PRINTF("\n\n")
152 151
153 152 init_parameter_dump();
154 153 init_kcoefficients_dump();
155 154 init_local_mode_parameters();
156 155 init_housekeeping_parameters();
157 156 init_k_coefficients_prc0();
158 157 init_k_coefficients_prc1();
159 158 init_k_coefficients_prc2();
160 159 pa_bia_status_info = 0x00;
161 160 update_last_valid_transition_date( DEFAULT_LAST_VALID_TRANSITION_DATE );
162 161
163 162 // waveform picker initialization
164 163 WFP_init_rings(); LEON_Clear_interrupt( IRQ_SPARC_GPTIMER_WATCHDOG ); // initialize the waveform rings
165 164 WFP_reset_current_ring_nodes();
166 165 reset_waveform_picker_regs();
167 166
168 167 // spectral matrices initialization
169 168 SM_init_rings(); // initialize spectral matrices rings
170 169 SM_reset_current_ring_nodes();
171 170 reset_spectral_matrix_regs();
172 171
173 172 // configure calibration
174 173 configureCalibration( false ); // true means interleaved mode, false is for normal mode
175 174
176 175 updateLFRCurrentMode();
177 176
178 177 BOOT_PRINTF1("in INIT *** lfrCurrentMode is %d\n", lfrCurrentMode)
179 178
180 179 create_names(); // create all names
181 180
182 181 status = create_timecode_timer(); // create the timer used by timecode_irq_handler
183 182 if (status != RTEMS_SUCCESSFUL)
184 183 {
185 184 PRINTF1("in INIT *** ERR in create_timer_timecode, code %d", status)
186 185 }
187 186
188 187 status = create_message_queues(); // create message queues
189 188 if (status != RTEMS_SUCCESSFUL)
190 189 {
191 190 PRINTF1("in INIT *** ERR in create_message_queues, code %d", status)
192 191 }
193 192
194 193 status = create_all_tasks(); // create all tasks
195 194 if (status != RTEMS_SUCCESSFUL)
196 195 {
197 196 PRINTF1("in INIT *** ERR in create_all_tasks, code %d\n", status)
198 197 }
199 198
200 199 // **************************
201 200 // <SPACEWIRE INITIALIZATION>
202 201 grspw_timecode_callback = &timecode_irq_handler;
203 202
204 203 status_spw = spacewire_open_link(); // (1) open the link
205 204 if ( status_spw != RTEMS_SUCCESSFUL )
206 205 {
207 206 PRINTF1("in INIT *** ERR spacewire_open_link code %d\n", status_spw )
208 207 }
209 208
210 209 if ( status_spw == RTEMS_SUCCESSFUL ) // (2) configure the link
211 210 {
212 211 status_spw = spacewire_configure_link( fdSPW );
213 212 if ( status_spw != RTEMS_SUCCESSFUL )
214 213 {
215 214 PRINTF1("in INIT *** ERR spacewire_configure_link code %d\n", status_spw )
216 215 }
217 216 }
218 217
219 218 if ( status_spw == RTEMS_SUCCESSFUL) // (3) start the link
220 219 {
221 220 status_spw = spacewire_start_link( fdSPW );
222 221 if ( status_spw != RTEMS_SUCCESSFUL )
223 222 {
224 223 PRINTF1("in INIT *** ERR spacewire_start_link code %d\n", status_spw )
225 224 }
226 225 }
227 226 // </SPACEWIRE INITIALIZATION>
228 227 // ***************************
229 228
230 229 status = start_all_tasks(); // start all tasks
231 230 if (status != RTEMS_SUCCESSFUL)
232 231 {
233 232 PRINTF1("in INIT *** ERR in start_all_tasks, code %d", status)
234 233 }
235 234
236 235 // start RECV and SEND *AFTER* SpaceWire Initialization, due to the timeout of the start call during the initialization
237 236 status = start_recv_send_tasks();
238 237 if ( status != RTEMS_SUCCESSFUL )
239 238 {
240 239 PRINTF1("in INIT *** ERR start_recv_send_tasks code %d\n", status )
241 240 }
242 241
243 242 // suspend science tasks, they will be restarted later depending on the mode
244 243 status = suspend_science_tasks(); // suspend science tasks (not done in stop_current_mode if current mode = STANDBY)
245 244 if (status != RTEMS_SUCCESSFUL)
246 245 {
247 246 PRINTF1("in INIT *** in suspend_science_tasks *** ERR code: %d\n", status)
248 247 }
249 248
250 249 // configure IRQ handling for the waveform picker unit
251 250 status = rtems_interrupt_catch( waveforms_isr,
252 251 IRQ_SPARC_WAVEFORM_PICKER,
253 252 &old_isr_handler) ;
254 253 // configure IRQ handling for the spectral matrices unit
255 254 status = rtems_interrupt_catch( spectral_matrices_isr,
256 255 IRQ_SPARC_SPECTRAL_MATRIX,
257 256 &old_isr_handler) ;
258 257
259 258 // if the spacewire link is not up then send an event to the SPIQ task for link recovery
260 259 if ( status_spw != RTEMS_SUCCESSFUL )
261 260 {
262 261 status = rtems_event_send( Task_id[TASKID_SPIQ], SPW_LINKERR_EVENT );
263 262 if ( status != RTEMS_SUCCESSFUL ) {
264 263 PRINTF1("in INIT *** ERR rtems_event_send to SPIQ code %d\n", status )
265 264 }
266 265 }
267 266
268 267 BOOT_PRINTF("delete INIT\n")
269 268
270 269 set_hk_lfr_sc_potential_flag( true );
271 270
272 271 status = rtems_task_delete(RTEMS_SELF);
273 272
274 273 }
275 274
276 275 void init_local_mode_parameters( void )
277 276 {
278 277 /** This function initialize the param_local global variable with default values.
279 278 *
280 279 */
281 280
282 281 unsigned int i;
283 282
284 283 // LOCAL PARAMETERS
285 284
286 285 BOOT_PRINTF1("local_sbm1_nb_cwf_max %d \n", param_local.local_sbm1_nb_cwf_max)
287 286 BOOT_PRINTF1("local_sbm2_nb_cwf_max %d \n", param_local.local_sbm2_nb_cwf_max)
288 287 BOOT_PRINTF1("nb_interrupt_f0_MAX = %d\n", param_local.local_nb_interrupt_f0_MAX)
289 288
290 289 // init sequence counters
291 290
292 291 for(i = 0; i<SEQ_CNT_NB_DEST_ID; i++)
293 292 {
294 293 sequenceCounters_TC_EXE[i] = 0x00;
295 294 sequenceCounters_TM_DUMP[i] = 0x00;
296 295 }
297 296 sequenceCounters_SCIENCE_NORMAL_BURST = 0x00;
298 297 sequenceCounters_SCIENCE_SBM1_SBM2 = 0x00;
299 298 sequenceCounterHK = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
300 299 }
301 300
302 301 void reset_local_time( void )
303 302 {
304 303 time_management_regs->ctrl = time_management_regs->ctrl | 0x02; // [0010] software reset, coarse time = 0x80000000
305 304 }
306 305
307 306 void create_names( void ) // create all names for tasks and queues
308 307 {
309 308 /** This function creates all RTEMS names used in the software for tasks and queues.
310 309 *
311 310 * @return RTEMS directive status codes:
312 311 * - RTEMS_SUCCESSFUL - successful completion
313 312 *
314 313 */
315 314
316 315 // task names
317 316 Task_name[TASKID_RECV] = rtems_build_name( 'R', 'E', 'C', 'V' );
318 317 Task_name[TASKID_ACTN] = rtems_build_name( 'A', 'C', 'T', 'N' );
319 318 Task_name[TASKID_SPIQ] = rtems_build_name( 'S', 'P', 'I', 'Q' );
320 319 Task_name[TASKID_LOAD] = rtems_build_name( 'L', 'O', 'A', 'D' );
321 320 Task_name[TASKID_AVF0] = rtems_build_name( 'A', 'V', 'F', '0' );
322 321 Task_name[TASKID_SWBD] = rtems_build_name( 'S', 'W', 'B', 'D' );
323 322 Task_name[TASKID_WFRM] = rtems_build_name( 'W', 'F', 'R', 'M' );
324 323 Task_name[TASKID_DUMB] = rtems_build_name( 'D', 'U', 'M', 'B' );
325 324 Task_name[TASKID_HOUS] = rtems_build_name( 'H', 'O', 'U', 'S' );
326 325 Task_name[TASKID_PRC0] = rtems_build_name( 'P', 'R', 'C', '0' );
327 326 Task_name[TASKID_CWF3] = rtems_build_name( 'C', 'W', 'F', '3' );
328 327 Task_name[TASKID_CWF2] = rtems_build_name( 'C', 'W', 'F', '2' );
329 328 Task_name[TASKID_CWF1] = rtems_build_name( 'C', 'W', 'F', '1' );
330 329 Task_name[TASKID_SEND] = rtems_build_name( 'S', 'E', 'N', 'D' );
331 330 Task_name[TASKID_WTDG] = rtems_build_name( 'W', 'T', 'D', 'G' );
332 331 Task_name[TASKID_AVF1] = rtems_build_name( 'A', 'V', 'F', '1' );
333 332 Task_name[TASKID_PRC1] = rtems_build_name( 'P', 'R', 'C', '1' );
334 333 Task_name[TASKID_AVF2] = rtems_build_name( 'A', 'V', 'F', '2' );
335 334 Task_name[TASKID_PRC2] = rtems_build_name( 'P', 'R', 'C', '2' );
336 335
337 336 // rate monotonic period names
338 337 name_hk_rate_monotonic = rtems_build_name( 'H', 'O', 'U', 'S' );
339 338
340 339 misc_name[QUEUE_RECV] = rtems_build_name( 'Q', '_', 'R', 'V' );
341 340 misc_name[QUEUE_SEND] = rtems_build_name( 'Q', '_', 'S', 'D' );
342 341 misc_name[QUEUE_PRC0] = rtems_build_name( 'Q', '_', 'P', '0' );
343 342 misc_name[QUEUE_PRC1] = rtems_build_name( 'Q', '_', 'P', '1' );
344 343 misc_name[QUEUE_PRC2] = rtems_build_name( 'Q', '_', 'P', '2' );
345 344
346 345 timecode_timer_name = rtems_build_name( 'S', 'P', 'T', 'C' );
347 346 }
348 347
349 348 int create_all_tasks( void ) // create all tasks which run in the software
350 349 {
351 350 /** This function creates all RTEMS tasks used in the software.
352 351 *
353 352 * @return RTEMS directive status codes:
354 353 * - RTEMS_SUCCESSFUL - task created successfully
355 354 * - RTEMS_INVALID_ADDRESS - id is NULL
356 355 * - RTEMS_INVALID_NAME - invalid task name
357 356 * - RTEMS_INVALID_PRIORITY - invalid task priority
358 357 * - RTEMS_MP_NOT_CONFIGURED - multiprocessing not configured
359 358 * - RTEMS_TOO_MANY - too many tasks created
360 359 * - RTEMS_UNSATISFIED - not enough memory for stack/FP context
361 360 * - RTEMS_TOO_MANY - too many global objects
362 361 *
363 362 */
364 363
365 364 rtems_status_code status;
366 365
367 366 //**********
368 367 // SPACEWIRE
369 368 // RECV
370 369 status = rtems_task_create(
371 370 Task_name[TASKID_RECV], TASK_PRIORITY_RECV, RTEMS_MINIMUM_STACK_SIZE,
372 371 RTEMS_DEFAULT_MODES,
373 372 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_RECV]
374 373 );
375 374 if (status == RTEMS_SUCCESSFUL) // SEND
376 375 {
377 376 status = rtems_task_create(
378 377 Task_name[TASKID_SEND], TASK_PRIORITY_SEND, RTEMS_MINIMUM_STACK_SIZE * 2,
379 378 RTEMS_DEFAULT_MODES,
380 379 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SEND]
381 380 );
382 381 }
383 382 if (status == RTEMS_SUCCESSFUL) // WTDG
384 383 {
385 384 status = rtems_task_create(
386 385 Task_name[TASKID_WTDG], TASK_PRIORITY_WTDG, RTEMS_MINIMUM_STACK_SIZE,
387 386 RTEMS_DEFAULT_MODES,
388 387 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_WTDG]
389 388 );
390 389 }
391 390 if (status == RTEMS_SUCCESSFUL) // ACTN
392 391 {
393 392 status = rtems_task_create(
394 393 Task_name[TASKID_ACTN], TASK_PRIORITY_ACTN, RTEMS_MINIMUM_STACK_SIZE,
395 394 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
396 395 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_ACTN]
397 396 );
398 397 }
399 398 if (status == RTEMS_SUCCESSFUL) // SPIQ
400 399 {
401 400 status = rtems_task_create(
402 401 Task_name[TASKID_SPIQ], TASK_PRIORITY_SPIQ, RTEMS_MINIMUM_STACK_SIZE,
403 402 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
404 403 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_SPIQ]
405 404 );
406 405 }
407 406
408 407 //******************
409 408 // SPECTRAL MATRICES
410 409 if (status == RTEMS_SUCCESSFUL) // AVF0
411 410 {
412 411 status = rtems_task_create(
413 412 Task_name[TASKID_AVF0], TASK_PRIORITY_AVF0, RTEMS_MINIMUM_STACK_SIZE,
414 413 RTEMS_DEFAULT_MODES,
415 414 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF0]
416 415 );
417 416 }
418 417 if (status == RTEMS_SUCCESSFUL) // PRC0
419 418 {
420 419 status = rtems_task_create(
421 420 Task_name[TASKID_PRC0], TASK_PRIORITY_PRC0, RTEMS_MINIMUM_STACK_SIZE * 2,
422 421 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
423 422 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC0]
424 423 );
425 424 }
426 425 if (status == RTEMS_SUCCESSFUL) // AVF1
427 426 {
428 427 status = rtems_task_create(
429 428 Task_name[TASKID_AVF1], TASK_PRIORITY_AVF1, RTEMS_MINIMUM_STACK_SIZE,
430 429 RTEMS_DEFAULT_MODES,
431 430 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF1]
432 431 );
433 432 }
434 433 if (status == RTEMS_SUCCESSFUL) // PRC1
435 434 {
436 435 status = rtems_task_create(
437 436 Task_name[TASKID_PRC1], TASK_PRIORITY_PRC1, RTEMS_MINIMUM_STACK_SIZE * 2,
438 437 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
439 438 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC1]
440 439 );
441 440 }
442 441 if (status == RTEMS_SUCCESSFUL) // AVF2
443 442 {
444 443 status = rtems_task_create(
445 444 Task_name[TASKID_AVF2], TASK_PRIORITY_AVF2, RTEMS_MINIMUM_STACK_SIZE,
446 445 RTEMS_DEFAULT_MODES,
447 446 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_AVF2]
448 447 );
449 448 }
450 449 if (status == RTEMS_SUCCESSFUL) // PRC2
451 450 {
452 451 status = rtems_task_create(
453 452 Task_name[TASKID_PRC2], TASK_PRIORITY_PRC2, RTEMS_MINIMUM_STACK_SIZE * 2,
454 453 RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
455 454 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_PRC2]
456 455 );
457 456 }
458 457
459 458 //****************
460 459 // WAVEFORM PICKER
461 460 if (status == RTEMS_SUCCESSFUL) // WFRM
462 461 {
463 462 status = rtems_task_create(
464 463 Task_name[TASKID_WFRM], TASK_PRIORITY_WFRM, RTEMS_MINIMUM_STACK_SIZE,
465 464 RTEMS_DEFAULT_MODES,
466 465 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_WFRM]
467 466 );
468 467 }
469 468 if (status == RTEMS_SUCCESSFUL) // CWF3
470 469 {
471 470 status = rtems_task_create(
472 471 Task_name[TASKID_CWF3], TASK_PRIORITY_CWF3, RTEMS_MINIMUM_STACK_SIZE,
473 472 RTEMS_DEFAULT_MODES,
474 473 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF3]
475 474 );
476 475 }
477 476 if (status == RTEMS_SUCCESSFUL) // CWF2
478 477 {
479 478 status = rtems_task_create(
480 479 Task_name[TASKID_CWF2], TASK_PRIORITY_CWF2, RTEMS_MINIMUM_STACK_SIZE,
481 480 RTEMS_DEFAULT_MODES,
482 481 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF2]
483 482 );
484 483 }
485 484 if (status == RTEMS_SUCCESSFUL) // CWF1
486 485 {
487 486 status = rtems_task_create(
488 487 Task_name[TASKID_CWF1], TASK_PRIORITY_CWF1, RTEMS_MINIMUM_STACK_SIZE,
489 488 RTEMS_DEFAULT_MODES,
490 489 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_CWF1]
491 490 );
492 491 }
493 492 if (status == RTEMS_SUCCESSFUL) // SWBD
494 493 {
495 494 status = rtems_task_create(
496 495 Task_name[TASKID_SWBD], TASK_PRIORITY_SWBD, RTEMS_MINIMUM_STACK_SIZE,
497 496 RTEMS_DEFAULT_MODES,
498 497 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_SWBD]
499 498 );
500 499 }
501 500
502 501 //*****
503 502 // MISC
504 503 if (status == RTEMS_SUCCESSFUL) // LOAD
505 504 {
506 505 status = rtems_task_create(
507 506 Task_name[TASKID_LOAD], TASK_PRIORITY_LOAD, RTEMS_MINIMUM_STACK_SIZE,
508 507 RTEMS_DEFAULT_MODES,
509 508 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_LOAD]
510 509 );
511 510 }
512 511 if (status == RTEMS_SUCCESSFUL) // DUMB
513 512 {
514 513 status = rtems_task_create(
515 514 Task_name[TASKID_DUMB], TASK_PRIORITY_DUMB, RTEMS_MINIMUM_STACK_SIZE,
516 515 RTEMS_DEFAULT_MODES,
517 516 RTEMS_DEFAULT_ATTRIBUTES, &Task_id[TASKID_DUMB]
518 517 );
519 518 }
520 519 if (status == RTEMS_SUCCESSFUL) // HOUS
521 520 {
522 521 status = rtems_task_create(
523 522 Task_name[TASKID_HOUS], TASK_PRIORITY_HOUS, RTEMS_MINIMUM_STACK_SIZE,
524 523 RTEMS_DEFAULT_MODES,
525 524 RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT, &Task_id[TASKID_HOUS]
526 525 );
527 526 }
528 527
529 528 return status;
530 529 }
531 530
532 531 int start_recv_send_tasks( void )
533 532 {
534 533 rtems_status_code status;
535 534
536 535 status = rtems_task_start( Task_id[TASKID_RECV], recv_task, 1 );
537 536 if (status!=RTEMS_SUCCESSFUL) {
538 537 BOOT_PRINTF("in INIT *** Error starting TASK_RECV\n")
539 538 }
540 539
541 540 if (status == RTEMS_SUCCESSFUL) // SEND
542 541 {
543 542 status = rtems_task_start( Task_id[TASKID_SEND], send_task, 1 );
544 543 if (status!=RTEMS_SUCCESSFUL) {
545 544 BOOT_PRINTF("in INIT *** Error starting TASK_SEND\n")
546 545 }
547 546 }
548 547
549 548 return status;
550 549 }
551 550
552 551 int start_all_tasks( void ) // start all tasks except SEND RECV and HOUS
553 552 {
554 553 /** This function starts all RTEMS tasks used in the software.
555 554 *
556 555 * @return RTEMS directive status codes:
557 556 * - RTEMS_SUCCESSFUL - ask started successfully
558 557 * - RTEMS_INVALID_ADDRESS - invalid task entry point
559 558 * - RTEMS_INVALID_ID - invalid task id
560 559 * - RTEMS_INCORRECT_STATE - task not in the dormant state
561 560 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task
562 561 *
563 562 */
564 563 // starts all the tasks fot eh flight software
565 564
566 565 rtems_status_code status;
567 566
568 567 //**********
569 568 // SPACEWIRE
570 569 status = rtems_task_start( Task_id[TASKID_SPIQ], spiq_task, 1 );
571 570 if (status!=RTEMS_SUCCESSFUL) {
572 571 BOOT_PRINTF("in INIT *** Error starting TASK_SPIQ\n")
573 572 }
574 573
575 574 if (status == RTEMS_SUCCESSFUL) // WTDG
576 575 {
577 576 status = rtems_task_start( Task_id[TASKID_WTDG], wtdg_task, 1 );
578 577 if (status!=RTEMS_SUCCESSFUL) {
579 578 BOOT_PRINTF("in INIT *** Error starting TASK_WTDG\n")
580 579 }
581 580 }
582 581
583 582 if (status == RTEMS_SUCCESSFUL) // ACTN
584 583 {
585 584 status = rtems_task_start( Task_id[TASKID_ACTN], actn_task, 1 );
586 585 if (status!=RTEMS_SUCCESSFUL) {
587 586 BOOT_PRINTF("in INIT *** Error starting TASK_ACTN\n")
588 587 }
589 588 }
590 589
591 590 //******************
592 591 // SPECTRAL MATRICES
593 592 if (status == RTEMS_SUCCESSFUL) // AVF0
594 593 {
595 594 status = rtems_task_start( Task_id[TASKID_AVF0], avf0_task, LFR_MODE_STANDBY );
596 595 if (status!=RTEMS_SUCCESSFUL) {
597 596 BOOT_PRINTF("in INIT *** Error starting TASK_AVF0\n")
598 597 }
599 598 }
600 599 if (status == RTEMS_SUCCESSFUL) // PRC0
601 600 {
602 601 status = rtems_task_start( Task_id[TASKID_PRC0], prc0_task, LFR_MODE_STANDBY );
603 602 if (status!=RTEMS_SUCCESSFUL) {
604 603 BOOT_PRINTF("in INIT *** Error starting TASK_PRC0\n")
605 604 }
606 605 }
607 606 if (status == RTEMS_SUCCESSFUL) // AVF1
608 607 {
609 608 status = rtems_task_start( Task_id[TASKID_AVF1], avf1_task, LFR_MODE_STANDBY );
610 609 if (status!=RTEMS_SUCCESSFUL) {
611 610 BOOT_PRINTF("in INIT *** Error starting TASK_AVF1\n")
612 611 }
613 612 }
614 613 if (status == RTEMS_SUCCESSFUL) // PRC1
615 614 {
616 615 status = rtems_task_start( Task_id[TASKID_PRC1], prc1_task, LFR_MODE_STANDBY );
617 616 if (status!=RTEMS_SUCCESSFUL) {
618 617 BOOT_PRINTF("in INIT *** Error starting TASK_PRC1\n")
619 618 }
620 619 }
621 620 if (status == RTEMS_SUCCESSFUL) // AVF2
622 621 {
623 622 status = rtems_task_start( Task_id[TASKID_AVF2], avf2_task, 1 );
624 623 if (status!=RTEMS_SUCCESSFUL) {
625 624 BOOT_PRINTF("in INIT *** Error starting TASK_AVF2\n")
626 625 }
627 626 }
628 627 if (status == RTEMS_SUCCESSFUL) // PRC2
629 628 {
630 629 status = rtems_task_start( Task_id[TASKID_PRC2], prc2_task, 1 );
631 630 if (status!=RTEMS_SUCCESSFUL) {
632 631 BOOT_PRINTF("in INIT *** Error starting TASK_PRC2\n")
633 632 }
634 633 }
635 634
636 635 //****************
637 636 // WAVEFORM PICKER
638 637 if (status == RTEMS_SUCCESSFUL) // WFRM
639 638 {
640 639 status = rtems_task_start( Task_id[TASKID_WFRM], wfrm_task, 1 );
641 640 if (status!=RTEMS_SUCCESSFUL) {
642 641 BOOT_PRINTF("in INIT *** Error starting TASK_WFRM\n")
643 642 }
644 643 }
645 644 if (status == RTEMS_SUCCESSFUL) // CWF3
646 645 {
647 646 status = rtems_task_start( Task_id[TASKID_CWF3], cwf3_task, 1 );
648 647 if (status!=RTEMS_SUCCESSFUL) {
649 648 BOOT_PRINTF("in INIT *** Error starting TASK_CWF3\n")
650 649 }
651 650 }
652 651 if (status == RTEMS_SUCCESSFUL) // CWF2
653 652 {
654 653 status = rtems_task_start( Task_id[TASKID_CWF2], cwf2_task, 1 );
655 654 if (status!=RTEMS_SUCCESSFUL) {
656 655 BOOT_PRINTF("in INIT *** Error starting TASK_CWF2\n")
657 656 }
658 657 }
659 658 if (status == RTEMS_SUCCESSFUL) // CWF1
660 659 {
661 660 status = rtems_task_start( Task_id[TASKID_CWF1], cwf1_task, 1 );
662 661 if (status!=RTEMS_SUCCESSFUL) {
663 662 BOOT_PRINTF("in INIT *** Error starting TASK_CWF1\n")
664 663 }
665 664 }
666 665 if (status == RTEMS_SUCCESSFUL) // SWBD
667 666 {
668 667 status = rtems_task_start( Task_id[TASKID_SWBD], swbd_task, 1 );
669 668 if (status!=RTEMS_SUCCESSFUL) {
670 669 BOOT_PRINTF("in INIT *** Error starting TASK_SWBD\n")
671 670 }
672 671 }
673 672
674 673 //*****
675 674 // MISC
676 675 if (status == RTEMS_SUCCESSFUL) // HOUS
677 676 {
678 677 status = rtems_task_start( Task_id[TASKID_HOUS], hous_task, 1 );
679 678 if (status!=RTEMS_SUCCESSFUL) {
680 679 BOOT_PRINTF("in INIT *** Error starting TASK_HOUS\n")
681 680 }
682 681 }
683 682 if (status == RTEMS_SUCCESSFUL) // DUMB
684 683 {
685 684 status = rtems_task_start( Task_id[TASKID_DUMB], dumb_task, 1 );
686 685 if (status!=RTEMS_SUCCESSFUL) {
687 686 BOOT_PRINTF("in INIT *** Error starting TASK_DUMB\n")
688 687 }
689 688 }
690 689 if (status == RTEMS_SUCCESSFUL) // LOAD
691 690 {
692 691 status = rtems_task_start( Task_id[TASKID_LOAD], load_task, 1 );
693 692 if (status!=RTEMS_SUCCESSFUL) {
694 693 BOOT_PRINTF("in INIT *** Error starting TASK_LOAD\n")
695 694 }
696 695 }
697 696
698 697 return status;
699 698 }
700 699
701 700 rtems_status_code create_message_queues( void ) // create the two message queues used in the software
702 701 {
703 702 rtems_status_code status_recv;
704 703 rtems_status_code status_send;
705 704 rtems_status_code status_q_p0;
706 705 rtems_status_code status_q_p1;
707 706 rtems_status_code status_q_p2;
708 707 rtems_status_code ret;
709 708 rtems_id queue_id;
710 709
711 710 //****************************************
712 711 // create the queue for handling valid TCs
713 712 status_recv = rtems_message_queue_create( misc_name[QUEUE_RECV],
714 713 MSG_QUEUE_COUNT_RECV, CCSDS_TC_PKT_MAX_SIZE,
715 714 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
716 715 if ( status_recv != RTEMS_SUCCESSFUL ) {
717 716 PRINTF1("in create_message_queues *** ERR creating QUEU queue, %d\n", status_recv)
718 717 }
719 718
720 719 //************************************************
721 720 // create the queue for handling TM packet sending
722 721 status_send = rtems_message_queue_create( misc_name[QUEUE_SEND],
723 722 MSG_QUEUE_COUNT_SEND, MSG_QUEUE_SIZE_SEND,
724 723 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
725 724 if ( status_send != RTEMS_SUCCESSFUL ) {
726 725 PRINTF1("in create_message_queues *** ERR creating PKTS queue, %d\n", status_send)
727 726 }
728 727
729 728 //*****************************************************************************
730 729 // create the queue for handling averaged spectral matrices for processing @ f0
731 730 status_q_p0 = rtems_message_queue_create( misc_name[QUEUE_PRC0],
732 731 MSG_QUEUE_COUNT_PRC0, MSG_QUEUE_SIZE_PRC0,
733 732 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
734 733 if ( status_q_p0 != RTEMS_SUCCESSFUL ) {
735 734 PRINTF1("in create_message_queues *** ERR creating Q_P0 queue, %d\n", status_q_p0)
736 735 }
737 736
738 737 //*****************************************************************************
739 738 // create the queue for handling averaged spectral matrices for processing @ f1
740 739 status_q_p1 = rtems_message_queue_create( misc_name[QUEUE_PRC1],
741 740 MSG_QUEUE_COUNT_PRC1, MSG_QUEUE_SIZE_PRC1,
742 741 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
743 742 if ( status_q_p1 != RTEMS_SUCCESSFUL ) {
744 743 PRINTF1("in create_message_queues *** ERR creating Q_P1 queue, %d\n", status_q_p1)
745 744 }
746 745
747 746 //*****************************************************************************
748 747 // create the queue for handling averaged spectral matrices for processing @ f2
749 748 status_q_p2 = rtems_message_queue_create( misc_name[QUEUE_PRC2],
750 749 MSG_QUEUE_COUNT_PRC2, MSG_QUEUE_SIZE_PRC2,
751 750 RTEMS_FIFO | RTEMS_LOCAL, &queue_id );
752 751 if ( status_q_p2 != RTEMS_SUCCESSFUL ) {
753 752 PRINTF1("in create_message_queues *** ERR creating Q_P2 queue, %d\n", status_q_p2)
754 753 }
755 754
756 755 if ( status_recv != RTEMS_SUCCESSFUL )
757 756 {
758 757 ret = status_recv;
759 758 }
760 759 else if( status_send != RTEMS_SUCCESSFUL )
761 760 {
762 761 ret = status_send;
763 762 }
764 763 else if( status_q_p0 != RTEMS_SUCCESSFUL )
765 764 {
766 765 ret = status_q_p0;
767 766 }
768 767 else if( status_q_p1 != RTEMS_SUCCESSFUL )
769 768 {
770 769 ret = status_q_p1;
771 770 }
772 771 else
773 772 {
774 773 ret = status_q_p2;
775 774 }
776 775
777 776 return ret;
778 777 }
779 778
780 779 rtems_status_code create_timecode_timer( void )
781 780 {
782 781 rtems_status_code status;
783 782
784 783 status = rtems_timer_create( timecode_timer_name, &timecode_timer_id );
785 784
786 785 if ( status != RTEMS_SUCCESSFUL )
787 786 {
788 787 PRINTF1("in create_timer_timecode *** ERR creating SPTC timer, %d\n", status)
789 788 }
790 789 else
791 790 {
792 791 PRINTF("in create_timer_timecode *** OK creating SPTC timer\n")
793 792 }
794 793
795 794 return status;
796 795 }
797 796
798 797 rtems_status_code get_message_queue_id_send( rtems_id *queue_id )
799 798 {
800 799 rtems_status_code status;
801 800 rtems_name queue_name;
802 801
803 802 queue_name = rtems_build_name( 'Q', '_', 'S', 'D' );
804 803
805 804 status = rtems_message_queue_ident( queue_name, 0, queue_id );
806 805
807 806 return status;
808 807 }
809 808
810 809 rtems_status_code get_message_queue_id_recv( rtems_id *queue_id )
811 810 {
812 811 rtems_status_code status;
813 812 rtems_name queue_name;
814 813
815 814 queue_name = rtems_build_name( 'Q', '_', 'R', 'V' );
816 815
817 816 status = rtems_message_queue_ident( queue_name, 0, queue_id );
818 817
819 818 return status;
820 819 }
821 820
822 821 rtems_status_code get_message_queue_id_prc0( rtems_id *queue_id )
823 822 {
824 823 rtems_status_code status;
825 824 rtems_name queue_name;
826 825
827 826 queue_name = rtems_build_name( 'Q', '_', 'P', '0' );
828 827
829 828 status = rtems_message_queue_ident( queue_name, 0, queue_id );
830 829
831 830 return status;
832 831 }
833 832
834 833 rtems_status_code get_message_queue_id_prc1( rtems_id *queue_id )
835 834 {
836 835 rtems_status_code status;
837 836 rtems_name queue_name;
838 837
839 838 queue_name = rtems_build_name( 'Q', '_', 'P', '1' );
840 839
841 840 status = rtems_message_queue_ident( queue_name, 0, queue_id );
842 841
843 842 return status;
844 843 }
845 844
846 845 rtems_status_code get_message_queue_id_prc2( rtems_id *queue_id )
847 846 {
848 847 rtems_status_code status;
849 848 rtems_name queue_name;
850 849
851 850 queue_name = rtems_build_name( 'Q', '_', 'P', '2' );
852 851
853 852 status = rtems_message_queue_ident( queue_name, 0, queue_id );
854 853
855 854 return status;
856 855 }
857 856
858 857 void update_queue_max_count( rtems_id queue_id, unsigned char*fifo_size_max )
859 858 {
860 859 u_int32_t count;
861 860 rtems_status_code status;
862 861
863 862 status = rtems_message_queue_get_number_pending( queue_id, &count );
864 863
865 864 count = count + 1;
866 865
867 866 if (status != RTEMS_SUCCESSFUL)
868 867 {
869 868 PRINTF1("in update_queue_max_count *** ERR = %d\n", status)
870 869 }
871 870 else
872 871 {
873 872 if (count > *fifo_size_max)
874 873 {
875 874 *fifo_size_max = count;
876 875 }
877 876 }
878 877 }
879 878
880 879 void init_ring(ring_node ring[], unsigned char nbNodes, volatile int buffer[], unsigned int bufferSize )
881 880 {
882 881 unsigned char i;
883 882
884 883 //***************
885 884 // BUFFER ADDRESS
886 885 for(i=0; i<nbNodes; i++)
887 886 {
888 887 ring[i].coarseTime = 0xffffffff;
889 888 ring[i].fineTime = 0xffffffff;
890 889 ring[i].sid = 0x00;
891 890 ring[i].status = 0x00;
892 891 ring[i].buffer_address = (int) &buffer[ i * bufferSize ];
893 892 }
894 893
895 894 //*****
896 895 // NEXT
897 896 ring[ nbNodes - 1 ].next = (ring_node*) &ring[ 0 ];
898 897 for(i=0; i<nbNodes-1; i++)
899 898 {
900 899 ring[i].next = (ring_node*) &ring[ i + 1 ];
901 900 }
902 901
903 902 //*********
904 903 // PREVIOUS
905 904 ring[ 0 ].previous = (ring_node*) &ring[ nbNodes - 1 ];
906 905 for(i=1; i<nbNodes; i++)
907 906 {
908 907 ring[i].previous = (ring_node*) &ring[ i - 1 ];
909 908 }
910 909 }
@@ -1,745 +1,737
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 * @param void
121 121 *
122 122 * @return void
123 123 *
124 124 */
125 125
126 126 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
127 127 }
128 128
129 129 void watchdog_start(void)
130 130 {
131 131 /** This function starts the watchdog timer.
132 132 *
133 133 * @param gptimer_regs points to the APB registers of the GPTIMER IP core.
134 134 * @param timer is the number of the timer in the IP core (several timers can be instantiated).
135 135 *
136 136 */
137 137
138 138 LEON_Clear_interrupt( IRQ_GPTIMER_WATCHDOG );
139 139
140 140 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000010; // clear pending IRQ if any
141 141 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000004; // LD load value from the reload register
142 142 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000001; // EN enable the timer
143 143 gptimer_regs->timer[TIMER_WATCHDOG].ctrl = gptimer_regs->timer[TIMER_WATCHDOG].ctrl | 0x00000008; // IE interrupt enable
144 144
145 145 LEON_Unmask_interrupt( IRQ_GPTIMER_WATCHDOG );
146 146
147 147 }
148 148
149 int send_console_outputs_on_apbuart_port( void ) // Send the console outputs on the apbuart port
149 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
150 150 {
151 151 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
152 152
153 153 apbuart_regs->ctrl = APBUART_CTRL_REG_MASK_TE;
154 154
155 155 return 0;
156 156 }
157 157
158 int enable_apbuart_transmitter( void ) // set the bit 1, TE Transmitter Enable to 1 in the APBUART control register
159 {
160 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) REGS_ADDR_APBUART;
161
162 apbuart_regs->ctrl = apbuart_regs->ctrl | APBUART_CTRL_REG_MASK_TE;
163
164 return 0;
165 }
166
167 158 void set_apbuart_scaler_reload_register(unsigned int regs, unsigned int value)
168 159 {
169 160 /** This function sets the scaler reload register of the apbuart module
170 161 *
171 162 * @param regs is the address of the apbuart registers in memory
172 163 * @param value is the value that will be stored in the scaler register
173 164 *
174 165 * The value shall be set by the software to get data on the serial interface.
175 166 *
176 167 */
177 168
178 169 struct apbuart_regs_str *apbuart_regs = (struct apbuart_regs_str *) regs;
179 170
180 171 apbuart_regs->scaler = value;
172
181 173 BOOT_PRINTF1("OK *** apbuart port scaler reload register set to 0x%x\n", value)
182 174 }
183 175
184 176 //************
185 177 // RTEMS TASKS
186 178
187 179 rtems_task load_task(rtems_task_argument argument)
188 180 {
189 181 BOOT_PRINTF("in LOAD *** \n")
190 182
191 183 rtems_status_code status;
192 184 unsigned int i;
193 185 unsigned int j;
194 186 rtems_name name_watchdog_rate_monotonic; // name of the watchdog rate monotonic
195 187 rtems_id watchdog_period_id; // id of the watchdog rate monotonic period
196 188
197 189 name_watchdog_rate_monotonic = rtems_build_name( 'L', 'O', 'A', 'D' );
198 190
199 191 status = rtems_rate_monotonic_create( name_watchdog_rate_monotonic, &watchdog_period_id );
200 192 if( status != RTEMS_SUCCESSFUL ) {
201 193 PRINTF1( "in LOAD *** rtems_rate_monotonic_create failed with status of %d\n", status )
202 194 }
203 195
204 196 i = 0;
205 197 j = 0;
206 198
207 199 watchdog_configure();
208 200
209 201 watchdog_start();
210 202
211 203 while(1){
212 204 status = rtems_rate_monotonic_period( watchdog_period_id, WATCHDOG_PERIOD );
213 205 watchdog_reload();
214 206 i = i + 1;
215 207 if ( i == 10 )
216 208 {
217 209 i = 0;
218 210 j = j + 1;
219 211 PRINTF1("%d\n", j)
220 212 }
221 213 #ifdef DEBUG_WATCHDOG
222 214 if (j == 3 )
223 215 {
224 216 status = rtems_task_delete(RTEMS_SELF);
225 217 }
226 218 #endif
227 219 }
228 220 }
229 221
230 222 rtems_task hous_task(rtems_task_argument argument)
231 223 {
232 224 rtems_status_code status;
233 225 rtems_status_code spare_status;
234 226 rtems_id queue_id;
235 227 rtems_rate_monotonic_period_status period_status;
236 228
237 229 status = get_message_queue_id_send( &queue_id );
238 230 if (status != RTEMS_SUCCESSFUL)
239 231 {
240 232 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
241 233 }
242 234
243 235 BOOT_PRINTF("in HOUS ***\n")
244 236
245 237 if (rtems_rate_monotonic_ident( name_hk_rate_monotonic, &HK_id) != RTEMS_SUCCESSFUL) {
246 238 status = rtems_rate_monotonic_create( name_hk_rate_monotonic, &HK_id );
247 239 if( status != RTEMS_SUCCESSFUL ) {
248 240 PRINTF1( "rtems_rate_monotonic_create failed with status of %d\n", status )
249 241 }
250 242 }
251 243
252 244 status = rtems_rate_monotonic_cancel(HK_id);
253 245 if( status != RTEMS_SUCCESSFUL ) {
254 246 PRINTF1( "ERR *** in HOUS *** rtems_rate_monotonic_cancel(HK_id) ***code: %d\n", status )
255 247 }
256 248 else {
257 249 DEBUG_PRINTF("OK *** in HOUS *** rtems_rate_monotonic_cancel(HK_id)\n")
258 250 }
259 251
260 252 // startup phase
261 253 status = rtems_rate_monotonic_period( HK_id, SY_LFR_TIME_SYN_TIMEOUT_in_ticks );
262 254 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
263 255 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
264 256 while(period_status.state != RATE_MONOTONIC_EXPIRED ) // after SY_LFR_TIME_SYN_TIMEOUT ms, starts HK anyway
265 257 {
266 258 if ((time_management_regs->coarse_time & 0x80000000) == 0x00000000) // check time synchronization
267 259 {
268 260 break; // break if LFR is synchronized
269 261 }
270 262 else
271 263 {
272 264 status = rtems_rate_monotonic_get_status( HK_id, &period_status );
273 265 // sched_yield();
274 266 status = rtems_task_wake_after( 10 ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 100 ms = 10 * 10 ms
275 267 }
276 268 }
277 269 status = rtems_rate_monotonic_cancel(HK_id);
278 270 DEBUG_PRINTF1("startup HK, HK_id status = %d\n", period_status.state)
279 271
280 272 set_hk_lfr_reset_cause( POWER_ON );
281 273
282 274 while(1){ // launch the rate monotonic task
283 275 status = rtems_rate_monotonic_period( HK_id, HK_PERIOD );
284 276 if ( status != RTEMS_SUCCESSFUL ) {
285 277 PRINTF1( "in HOUS *** ERR period: %d\n", status);
286 278 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_6 );
287 279 }
288 280 else {
289 281 housekeeping_packet.packetSequenceControl[0] = (unsigned char) (sequenceCounterHK >> 8);
290 282 housekeeping_packet.packetSequenceControl[1] = (unsigned char) (sequenceCounterHK );
291 283 increment_seq_counter( &sequenceCounterHK );
292 284
293 285 housekeeping_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
294 286 housekeeping_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
295 287 housekeeping_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
296 288 housekeeping_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
297 289 housekeeping_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
298 290 housekeeping_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
299 291
300 292 spacewire_update_statistics();
301 293
302 294 hk_lfr_le_me_he_update();
303 295
304 296 set_hk_lfr_time_not_synchro();
305 297
306 298 housekeeping_packet.hk_lfr_q_sd_fifo_size_max = hk_lfr_q_sd_fifo_size_max;
307 299 housekeeping_packet.hk_lfr_q_rv_fifo_size_max = hk_lfr_q_rv_fifo_size_max;
308 300 housekeeping_packet.hk_lfr_q_p0_fifo_size_max = hk_lfr_q_p0_fifo_size_max;
309 301 housekeeping_packet.hk_lfr_q_p1_fifo_size_max = hk_lfr_q_p1_fifo_size_max;
310 302 housekeeping_packet.hk_lfr_q_p2_fifo_size_max = hk_lfr_q_p2_fifo_size_max;
311 303
312 304 housekeeping_packet.sy_lfr_common_parameters_spare = parameter_dump_packet.sy_lfr_common_parameters_spare;
313 305 housekeeping_packet.sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
314 306 get_temperatures( housekeeping_packet.hk_lfr_temp_scm );
315 307 get_v_e1_e2_f3( housekeeping_packet.hk_lfr_sc_v_f3 );
316 308 get_cpu_load( (unsigned char *) &housekeeping_packet.hk_lfr_cpu_load );
317 309
318 310 // SEND PACKET
319 311 status = rtems_message_queue_send( queue_id, &housekeeping_packet,
320 312 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
321 313 if (status != RTEMS_SUCCESSFUL) {
322 314 PRINTF1("in HOUS *** ERR send: %d\n", status)
323 315 }
324 316 }
325 317 }
326 318
327 319 PRINTF("in HOUS *** deleting task\n")
328 320
329 321 status = rtems_task_delete( RTEMS_SELF ); // should not return
330 322
331 323 return;
332 324 }
333 325
334 326 rtems_task dumb_task( rtems_task_argument unused )
335 327 {
336 328 /** This RTEMS taks is used to print messages without affecting the general behaviour of the software.
337 329 *
338 330 * @param unused is the starting argument of the RTEMS task
339 331 *
340 332 * The DUMB taks waits for RTEMS events and print messages depending on the incoming events.
341 333 *
342 334 */
343 335
344 336 unsigned int i;
345 337 unsigned int intEventOut;
346 338 unsigned int coarse_time = 0;
347 339 unsigned int fine_time = 0;
348 340 rtems_event_set event_out;
349 341
350 342 char *DumbMessages[14] = {"in DUMB *** default", // RTEMS_EVENT_0
351 343 "in DUMB *** timecode_irq_handler", // RTEMS_EVENT_1
352 344 "in DUMB *** f3 buffer changed", // RTEMS_EVENT_2
353 345 "in DUMB *** in SMIQ *** Error sending event to AVF0", // RTEMS_EVENT_3
354 346 "in DUMB *** spectral_matrices_isr *** Error sending event to SMIQ", // RTEMS_EVENT_4
355 347 "in DUMB *** waveforms_simulator_isr", // RTEMS_EVENT_5
356 348 "VHDL SM *** two buffers f0 ready", // RTEMS_EVENT_6
357 349 "ready for dump", // RTEMS_EVENT_7
358 350 "VHDL ERR *** spectral matrix", // RTEMS_EVENT_8
359 351 "tick", // RTEMS_EVENT_9
360 352 "VHDL ERR *** waveform picker", // RTEMS_EVENT_10
361 353 "VHDL ERR *** unexpected ready matrix values", // RTEMS_EVENT_11
362 354 "WATCHDOG timer", // RTEMS_EVENT_12
363 355 "TIMECODE timer" // RTEMS_EVENT_13
364 356 };
365 357
366 358 BOOT_PRINTF("in DUMB *** \n")
367 359
368 360 while(1){
369 361 rtems_event_receive(RTEMS_EVENT_0 | RTEMS_EVENT_1 | RTEMS_EVENT_2 | RTEMS_EVENT_3
370 362 | RTEMS_EVENT_4 | RTEMS_EVENT_5 | RTEMS_EVENT_6 | RTEMS_EVENT_7
371 363 | RTEMS_EVENT_8 | RTEMS_EVENT_9 | RTEMS_EVENT_12 | RTEMS_EVENT_13,
372 364 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out); // wait for an RTEMS_EVENT
373 365 intEventOut = (unsigned int) event_out;
374 366 for ( i=0; i<32; i++)
375 367 {
376 368 if ( ((intEventOut >> i) & 0x0001) != 0)
377 369 {
378 370 coarse_time = time_management_regs->coarse_time;
379 371 fine_time = time_management_regs->fine_time;
380 372 if (i==12)
381 373 {
382 374 PRINTF1("%s\n", DumbMessages[12])
383 375 }
384 376 if (i==13)
385 377 {
386 378 PRINTF1("%s\n", DumbMessages[13])
387 379 }
388 380 }
389 381 }
390 382 }
391 383 }
392 384
393 385 //*****************************
394 386 // init housekeeping parameters
395 387
396 388 void init_housekeeping_parameters( void )
397 389 {
398 390 /** This function initialize the housekeeping_packet global variable with default values.
399 391 *
400 392 */
401 393
402 394 unsigned int i = 0;
403 395 unsigned char *parameters;
404 396 unsigned char sizeOfHK;
405 397
406 398 sizeOfHK = sizeof( Packet_TM_LFR_HK_t );
407 399
408 400 parameters = (unsigned char*) &housekeeping_packet;
409 401
410 402 for(i = 0; i< sizeOfHK; i++)
411 403 {
412 404 parameters[i] = 0x00;
413 405 }
414 406
415 407 housekeeping_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
416 408 housekeeping_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
417 409 housekeeping_packet.reserved = DEFAULT_RESERVED;
418 410 housekeeping_packet.userApplication = CCSDS_USER_APP;
419 411 housekeeping_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
420 412 housekeeping_packet.packetID[1] = (unsigned char) (APID_TM_HK);
421 413 housekeeping_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
422 414 housekeeping_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
423 415 housekeeping_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
424 416 housekeeping_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
425 417 housekeeping_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
426 418 housekeeping_packet.serviceType = TM_TYPE_HK;
427 419 housekeeping_packet.serviceSubType = TM_SUBTYPE_HK;
428 420 housekeeping_packet.destinationID = TM_DESTINATION_ID_GROUND;
429 421 housekeeping_packet.sid = SID_HK;
430 422
431 423 // init status word
432 424 housekeeping_packet.lfr_status_word[0] = DEFAULT_STATUS_WORD_BYTE0;
433 425 housekeeping_packet.lfr_status_word[1] = DEFAULT_STATUS_WORD_BYTE1;
434 426 // init software version
435 427 housekeeping_packet.lfr_sw_version[0] = SW_VERSION_N1;
436 428 housekeeping_packet.lfr_sw_version[1] = SW_VERSION_N2;
437 429 housekeeping_packet.lfr_sw_version[2] = SW_VERSION_N3;
438 430 housekeeping_packet.lfr_sw_version[3] = SW_VERSION_N4;
439 431 // init fpga version
440 432 parameters = (unsigned char *) (REGS_ADDR_VHDL_VERSION);
441 433 housekeeping_packet.lfr_fpga_version[0] = parameters[1]; // n1
442 434 housekeeping_packet.lfr_fpga_version[1] = parameters[2]; // n2
443 435 housekeeping_packet.lfr_fpga_version[2] = parameters[3]; // n3
444 436
445 437 housekeeping_packet.hk_lfr_q_sd_fifo_size = MSG_QUEUE_COUNT_SEND;
446 438 housekeeping_packet.hk_lfr_q_rv_fifo_size = MSG_QUEUE_COUNT_RECV;
447 439 housekeeping_packet.hk_lfr_q_p0_fifo_size = MSG_QUEUE_COUNT_PRC0;
448 440 housekeeping_packet.hk_lfr_q_p1_fifo_size = MSG_QUEUE_COUNT_PRC1;
449 441 housekeeping_packet.hk_lfr_q_p2_fifo_size = MSG_QUEUE_COUNT_PRC2;
450 442 }
451 443
452 444 void increment_seq_counter( unsigned short *packetSequenceControl )
453 445 {
454 446 /** This function increment the sequence counter passes in argument.
455 447 *
456 448 * The increment does not affect the grouping flag. In case of an overflow, the counter is reset to 0.
457 449 *
458 450 */
459 451
460 452 unsigned short segmentation_grouping_flag;
461 453 unsigned short sequence_cnt;
462 454
463 455 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8; // keep bits 7 downto 6
464 456 sequence_cnt = (*packetSequenceControl) & 0x3fff; // [0011 1111 1111 1111]
465 457
466 458 if ( sequence_cnt < SEQ_CNT_MAX)
467 459 {
468 460 sequence_cnt = sequence_cnt + 1;
469 461 }
470 462 else
471 463 {
472 464 sequence_cnt = 0;
473 465 }
474 466
475 467 *packetSequenceControl = segmentation_grouping_flag | sequence_cnt ;
476 468 }
477 469
478 470 void getTime( unsigned char *time)
479 471 {
480 472 /** This function write the current local time in the time buffer passed in argument.
481 473 *
482 474 */
483 475
484 476 time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
485 477 time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
486 478 time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
487 479 time[3] = (unsigned char) (time_management_regs->coarse_time);
488 480 time[4] = (unsigned char) (time_management_regs->fine_time>>8);
489 481 time[5] = (unsigned char) (time_management_regs->fine_time);
490 482 }
491 483
492 484 unsigned long long int getTimeAsUnsignedLongLongInt( )
493 485 {
494 486 /** This function write the current local time in the time buffer passed in argument.
495 487 *
496 488 */
497 489 unsigned long long int time;
498 490
499 491 time = ( (unsigned long long int) (time_management_regs->coarse_time & 0x7fffffff) << 16 )
500 492 + time_management_regs->fine_time;
501 493
502 494 return time;
503 495 }
504 496
505 497 void send_dumb_hk( void )
506 498 {
507 499 Packet_TM_LFR_HK_t dummy_hk_packet;
508 500 unsigned char *parameters;
509 501 unsigned int i;
510 502 rtems_id queue_id;
511 503
512 504 dummy_hk_packet.targetLogicalAddress = CCSDS_DESTINATION_ID;
513 505 dummy_hk_packet.protocolIdentifier = CCSDS_PROTOCOLE_ID;
514 506 dummy_hk_packet.reserved = DEFAULT_RESERVED;
515 507 dummy_hk_packet.userApplication = CCSDS_USER_APP;
516 508 dummy_hk_packet.packetID[0] = (unsigned char) (APID_TM_HK >> 8);
517 509 dummy_hk_packet.packetID[1] = (unsigned char) (APID_TM_HK);
518 510 dummy_hk_packet.packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
519 511 dummy_hk_packet.packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
520 512 dummy_hk_packet.packetLength[0] = (unsigned char) (PACKET_LENGTH_HK >> 8);
521 513 dummy_hk_packet.packetLength[1] = (unsigned char) (PACKET_LENGTH_HK );
522 514 dummy_hk_packet.spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
523 515 dummy_hk_packet.serviceType = TM_TYPE_HK;
524 516 dummy_hk_packet.serviceSubType = TM_SUBTYPE_HK;
525 517 dummy_hk_packet.destinationID = TM_DESTINATION_ID_GROUND;
526 518 dummy_hk_packet.time[0] = (unsigned char) (time_management_regs->coarse_time>>24);
527 519 dummy_hk_packet.time[1] = (unsigned char) (time_management_regs->coarse_time>>16);
528 520 dummy_hk_packet.time[2] = (unsigned char) (time_management_regs->coarse_time>>8);
529 521 dummy_hk_packet.time[3] = (unsigned char) (time_management_regs->coarse_time);
530 522 dummy_hk_packet.time[4] = (unsigned char) (time_management_regs->fine_time>>8);
531 523 dummy_hk_packet.time[5] = (unsigned char) (time_management_regs->fine_time);
532 524 dummy_hk_packet.sid = SID_HK;
533 525
534 526 // init status word
535 527 dummy_hk_packet.lfr_status_word[0] = 0xff;
536 528 dummy_hk_packet.lfr_status_word[1] = 0xff;
537 529 // init software version
538 530 dummy_hk_packet.lfr_sw_version[0] = SW_VERSION_N1;
539 531 dummy_hk_packet.lfr_sw_version[1] = SW_VERSION_N2;
540 532 dummy_hk_packet.lfr_sw_version[2] = SW_VERSION_N3;
541 533 dummy_hk_packet.lfr_sw_version[3] = SW_VERSION_N4;
542 534 // init fpga version
543 535 parameters = (unsigned char *) (REGS_ADDR_WAVEFORM_PICKER + 0xb0);
544 536 dummy_hk_packet.lfr_fpga_version[0] = parameters[1]; // n1
545 537 dummy_hk_packet.lfr_fpga_version[1] = parameters[2]; // n2
546 538 dummy_hk_packet.lfr_fpga_version[2] = parameters[3]; // n3
547 539
548 540 parameters = (unsigned char *) &dummy_hk_packet.hk_lfr_cpu_load;
549 541
550 542 for (i=0; i<100; i++)
551 543 {
552 544 parameters[i] = 0xff;
553 545 }
554 546
555 547 get_message_queue_id_send( &queue_id );
556 548
557 549 rtems_message_queue_send( queue_id, &dummy_hk_packet,
558 550 PACKET_LENGTH_HK + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES);
559 551 }
560 552
561 553 void get_temperatures( unsigned char *temperatures )
562 554 {
563 555 unsigned char* temp_scm_ptr;
564 556 unsigned char* temp_pcb_ptr;
565 557 unsigned char* temp_fpga_ptr;
566 558
567 559 // SEL1 SEL0
568 560 // 0 0 => PCB
569 561 // 0 1 => FPGA
570 562 // 1 0 => SCM
571 563
572 564 temp_scm_ptr = (unsigned char *) &time_management_regs->temp_scm;
573 565 temp_pcb_ptr = (unsigned char *) &time_management_regs->temp_pcb;
574 566 temp_fpga_ptr = (unsigned char *) &time_management_regs->temp_fpga;
575 567
576 568 temperatures[0] = temp_scm_ptr[2];
577 569 temperatures[1] = temp_scm_ptr[3];
578 570 temperatures[2] = temp_pcb_ptr[2];
579 571 temperatures[3] = temp_pcb_ptr[3];
580 572 temperatures[4] = temp_fpga_ptr[2];
581 573 temperatures[5] = temp_fpga_ptr[3];
582 574 }
583 575
584 576 void get_v_e1_e2_f3( unsigned char *spacecraft_potential )
585 577 {
586 578 unsigned char* v_ptr;
587 579 unsigned char* e1_ptr;
588 580 unsigned char* e2_ptr;
589 581
590 582 v_ptr = (unsigned char *) &waveform_picker_regs->v;
591 583 e1_ptr = (unsigned char *) &waveform_picker_regs->e1;
592 584 e2_ptr = (unsigned char *) &waveform_picker_regs->e2;
593 585
594 586 spacecraft_potential[0] = v_ptr[2];
595 587 spacecraft_potential[1] = v_ptr[3];
596 588 spacecraft_potential[2] = e1_ptr[2];
597 589 spacecraft_potential[3] = e1_ptr[3];
598 590 spacecraft_potential[4] = e2_ptr[2];
599 591 spacecraft_potential[5] = e2_ptr[3];
600 592 }
601 593
602 594 void get_cpu_load( unsigned char *resource_statistics )
603 595 {
604 596 unsigned char cpu_load;
605 597
606 598 cpu_load = lfr_rtems_cpu_usage_report();
607 599
608 600 // HK_LFR_CPU_LOAD
609 601 resource_statistics[0] = cpu_load;
610 602
611 603 // HK_LFR_CPU_LOAD_MAX
612 604 if (cpu_load > resource_statistics[1])
613 605 {
614 606 resource_statistics[1] = cpu_load;
615 607 }
616 608
617 609 // CPU_LOAD_AVE
618 610 resource_statistics[2] = 0;
619 611
620 612 #ifndef PRINT_TASK_STATISTICS
621 613 rtems_cpu_usage_reset();
622 614 #endif
623 615
624 616 }
625 617
626 618 void set_hk_lfr_sc_potential_flag( bool state )
627 619 {
628 620 if (state == true)
629 621 {
630 622 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x40; // [0100 0000]
631 623 }
632 624 else
633 625 {
634 626 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xbf; // [1011 1111]
635 627 }
636 628 }
637 629
638 630 void set_hk_lfr_mag_fields_flag( bool state )
639 631 {
640 632 if (state == true)
641 633 {
642 634 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x20; // [0010 0000]
643 635 }
644 636 else
645 637 {
646 638 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xd7; // [1101 1111]
647 639 }
648 640 }
649 641
650 642 void set_hk_lfr_calib_enable( bool state )
651 643 {
652 644 if (state == true)
653 645 {
654 646 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] | 0x08; // [0000 1000]
655 647 }
656 648 else
657 649 {
658 650 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1] & 0xf7; // [1111 0111]
659 651 }
660 652 }
661 653
662 654 void set_hk_lfr_reset_cause( enum lfr_reset_cause_t lfr_reset_cause )
663 655 {
664 656 housekeeping_packet.lfr_status_word[1] = housekeeping_packet.lfr_status_word[1]
665 657 | (lfr_reset_cause & 0x07 ); // [0000 0111]
666 658 }
667 659
668 660 void hk_lfr_le_me_he_update()
669 661 {
670 662 unsigned int hk_lfr_le_cnt;
671 663 unsigned int hk_lfr_me_cnt;
672 664 unsigned int hk_lfr_he_cnt;
673 665
674 666 hk_lfr_le_cnt = 0;
675 667 hk_lfr_me_cnt = 0;
676 668 hk_lfr_he_cnt = 0;
677 669
678 670 //update the low severity error counter
679 671 hk_lfr_le_cnt =
680 672 housekeeping_packet.hk_lfr_dpu_spw_parity
681 673 + housekeeping_packet.hk_lfr_dpu_spw_disconnect
682 674 + housekeeping_packet.hk_lfr_dpu_spw_escape
683 675 + housekeeping_packet.hk_lfr_dpu_spw_credit
684 676 + housekeeping_packet.hk_lfr_dpu_spw_write_sync
685 677 + housekeeping_packet.hk_lfr_dpu_spw_rx_ahb
686 678 + housekeeping_packet.hk_lfr_dpu_spw_tx_ahb
687 679 + housekeeping_packet.hk_lfr_timecode_erroneous
688 680 + housekeeping_packet.hk_lfr_timecode_missing
689 681 + housekeeping_packet.hk_lfr_timecode_invalid
690 682 + housekeeping_packet.hk_lfr_time_timecode_it
691 683 + housekeeping_packet.hk_lfr_time_not_synchro
692 684 + housekeeping_packet.hk_lfr_time_timecode_ctr;
693 685
694 686 //update the medium severity error counter
695 687 hk_lfr_me_cnt =
696 688 housekeeping_packet.hk_lfr_dpu_spw_early_eop
697 689 + housekeeping_packet.hk_lfr_dpu_spw_invalid_addr
698 690 + housekeeping_packet.hk_lfr_dpu_spw_eep
699 691 + housekeeping_packet.hk_lfr_dpu_spw_rx_too_big;
700 692
701 693 //update the high severity error counter
702 694 hk_lfr_he_cnt = 0;
703 695
704 696 // update housekeeping packet counters, convert unsigned int numbers in 2 bytes numbers
705 697 // LE
706 698 housekeeping_packet.hk_lfr_le_cnt[0] = (unsigned char) ((hk_lfr_le_cnt & 0xff00) >> 8);
707 699 housekeeping_packet.hk_lfr_le_cnt[1] = (unsigned char) (hk_lfr_le_cnt & 0x00ff);
708 700 // ME
709 701 housekeeping_packet.hk_lfr_me_cnt[0] = (unsigned char) ((hk_lfr_me_cnt & 0xff00) >> 8);
710 702 housekeeping_packet.hk_lfr_me_cnt[1] = (unsigned char) (hk_lfr_me_cnt & 0x00ff);
711 703 // HE
712 704 housekeeping_packet.hk_lfr_he_cnt[0] = (unsigned char) ((hk_lfr_he_cnt & 0xff00) >> 8);
713 705 housekeeping_packet.hk_lfr_he_cnt[1] = (unsigned char) (hk_lfr_he_cnt & 0x00ff);
714 706
715 707 }
716 708
717 709 void set_hk_lfr_time_not_synchro()
718 710 {
719 711 static unsigned char synchroLost = 1;
720 712 int synchronizationBit;
721 713
722 714 // get the synchronization bit
723 715 synchronizationBit = (time_management_regs->coarse_time & 0x80000000) >> 31; // 1000 0000 0000 0000
724 716
725 717 switch (synchronizationBit)
726 718 {
727 719 case 0:
728 720 if (synchroLost == 1)
729 721 {
730 722 synchroLost = 0;
731 723 }
732 724 break;
733 725 case 1:
734 726 if (synchroLost == 0 )
735 727 {
736 728 synchroLost = 1;
737 729 increase_unsigned_char_counter(&housekeeping_packet.hk_lfr_time_not_synchro);
738 730 }
739 731 break;
740 732 default:
741 733 PRINTF1("in hk_lfr_time_not_synchro *** unexpected value for synchronizationBit = %d\n", synchronizationBit);
742 734 break;
743 735 }
744 736
745 737 }
@@ -1,1422 +1,1423
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 25 unsigned char previousTimecodeCtr = 0;
26 26 unsigned int *grspwPtr = (unsigned int *) (REGS_ADDR_GRSPW + APB_OFFSET_GRSPW_TIME_REGISTER);
27 27
28 28 //***********
29 29 // RTEMS TASK
30 30 rtems_task spiq_task(rtems_task_argument unused)
31 31 {
32 32 /** This RTEMS task is awaken by an rtems_event sent by the interruption subroutine of the SpaceWire driver.
33 33 *
34 34 * @param unused is the starting argument of the RTEMS task
35 35 *
36 36 */
37 37
38 38 rtems_event_set event_out;
39 39 rtems_status_code status;
40 40 int linkStatus;
41 41
42 42 BOOT_PRINTF("in SPIQ *** \n")
43 43
44 44 while(true){
45 45 rtems_event_receive(SPW_LINKERR_EVENT, RTEMS_WAIT, RTEMS_NO_TIMEOUT, &event_out); // wait for an SPW_LINKERR_EVENT
46 46 PRINTF("in SPIQ *** got SPW_LINKERR_EVENT\n")
47 47
48 48 // [0] SUSPEND RECV AND SEND TASKS
49 49 status = rtems_task_suspend( Task_id[ TASKID_RECV ] );
50 50 if ( status != RTEMS_SUCCESSFUL ) {
51 51 PRINTF("in SPIQ *** ERR suspending RECV Task\n")
52 52 }
53 53 status = rtems_task_suspend( Task_id[ TASKID_SEND ] );
54 54 if ( status != RTEMS_SUCCESSFUL ) {
55 55 PRINTF("in SPIQ *** ERR suspending SEND Task\n")
56 56 }
57 57
58 58 // [1] CHECK THE LINK
59 59 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (1)
60 60 if ( linkStatus != 5) {
61 61 PRINTF1("in SPIQ *** linkStatus %d, wait...\n", linkStatus)
62 62 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
63 63 }
64 64
65 65 // [2] RECHECK THE LINK AFTER SY_LFR_DPU_CONNECT_TIMEOUT
66 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
66 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status (2)
67 67 if ( linkStatus != 5 ) // [2.a] not in run state, reset the link
68 68 {
69 69 spacewire_compute_stats_offsets();
70 status = spacewire_reset_link( );
70 status = spacewire_several_connect_attemps( );
71 71 }
72 72 else // [2.b] in run state, start the link
73 73 {
74 74 status = spacewire_stop_and_start_link( fdSPW ); // start the link
75 75 if ( status != RTEMS_SUCCESSFUL)
76 76 {
77 77 PRINTF1("in SPIQ *** ERR spacewire_stop_and_start_link %d\n", status)
78 78 }
79 79 }
80 80
81 81 // [3] COMPLETE RECOVERY ACTION AFTER SY_LFR_DPU_CONNECT_ATTEMPTS
82 82 if ( status == RTEMS_SUCCESSFUL ) // [3.a] the link is in run state and has been started successfully
83 83 {
84 84 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
85 85 if ( status != RTEMS_SUCCESSFUL ) {
86 86 PRINTF("in SPIQ *** ERR resuming SEND Task\n")
87 87 }
88 88 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
89 89 if ( status != RTEMS_SUCCESSFUL ) {
90 90 PRINTF("in SPIQ *** ERR resuming RECV Task\n")
91 91 }
92 92 }
93 93 else // [3.b] the link is not in run state, go in STANDBY mode
94 94 {
95 95 status = enter_mode_standby();
96 if ( status != RTEMS_SUCCESSFUL ) {
96 if ( status != RTEMS_SUCCESSFUL )
97 {
97 98 PRINTF1("in SPIQ *** ERR enter_standby_mode *** code %d\n", status)
98 99 }
99 100 // wake the WTDG task up to wait for the link recovery
100 101 status = rtems_event_send ( Task_id[TASKID_WTDG], RTEMS_EVENT_0 );
101 102 status = rtems_task_suspend( RTEMS_SELF );
102 103 }
103 104 }
104 105 }
105 106
106 107 rtems_task recv_task( rtems_task_argument unused )
107 108 {
108 109 /** This RTEMS task is dedicated to the reception of incoming TeleCommands.
109 110 *
110 111 * @param unused is the starting argument of the RTEMS task
111 112 *
112 113 * The RECV task blocks on a call to the read system call, waiting for incoming SpaceWire data. When unblocked:
113 114 * 1. It reads the incoming data.
114 115 * 2. Launches the acceptance procedure.
115 116 * 3. If the Telecommand is valid, sends it to a dedicated RTEMS message queue.
116 117 *
117 118 */
118 119
119 120 int len;
120 121 ccsdsTelecommandPacket_t currentTC;
121 122 unsigned char computed_CRC[ 2 ];
122 123 unsigned char currentTC_LEN_RCV[ 2 ];
123 124 unsigned char destinationID;
124 125 unsigned int estimatedPacketLength;
125 126 unsigned int parserCode;
126 127 rtems_status_code status;
127 128 rtems_id queue_recv_id;
128 129 rtems_id queue_send_id;
129 130
130 131 initLookUpTableForCRC(); // the table is used to compute Cyclic Redundancy Codes
131 132
132 133 status = get_message_queue_id_recv( &queue_recv_id );
133 134 if (status != RTEMS_SUCCESSFUL)
134 135 {
135 136 PRINTF1("in RECV *** ERR get_message_queue_id_recv %d\n", status)
136 137 }
137 138
138 139 status = get_message_queue_id_send( &queue_send_id );
139 140 if (status != RTEMS_SUCCESSFUL)
140 141 {
141 142 PRINTF1("in RECV *** ERR get_message_queue_id_send %d\n", status)
142 143 }
143 144
144 145 BOOT_PRINTF("in RECV *** \n")
145 146
146 147 while(1)
147 148 {
148 149 len = read( fdSPW, (char*) &currentTC, CCSDS_TC_PKT_MAX_SIZE ); // the call to read is blocking
149 150 if (len == -1){ // error during the read call
150 151 PRINTF1("in RECV *** last read call returned -1, ERRNO %d\n", errno)
151 152 }
152 153 else {
153 154 if ( (len+1) < CCSDS_TC_PKT_MIN_SIZE ) {
154 155 PRINTF("in RECV *** packet lenght too short\n")
155 156 }
156 157 else {
157 158 estimatedPacketLength = (unsigned int) (len - CCSDS_TC_TM_PACKET_OFFSET - 3); // => -3 is for Prot ID, Reserved and User App bytes
158 159 currentTC_LEN_RCV[ 0 ] = (unsigned char) (estimatedPacketLength >> 8);
159 160 currentTC_LEN_RCV[ 1 ] = (unsigned char) (estimatedPacketLength );
160 161 // CHECK THE TC
161 162 parserCode = tc_parser( &currentTC, estimatedPacketLength, computed_CRC ) ;
162 163 if ( (parserCode == ILLEGAL_APID) || (parserCode == WRONG_LEN_PKT)
163 164 || (parserCode == INCOR_CHECKSUM) || (parserCode == ILL_TYPE)
164 165 || (parserCode == ILL_SUBTYPE) || (parserCode == WRONG_APP_DATA)
165 166 || (parserCode == WRONG_SRC_ID) )
166 167 { // send TM_LFR_TC_EXE_CORRUPTED
167 168 PRINTF1("TC corrupted received, with code: %d\n", parserCode)
168 169 if ( !( (currentTC.serviceType==TC_TYPE_TIME) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_TIME) )
169 170 &&
170 171 !( (currentTC.serviceType==TC_TYPE_GEN) && (currentTC.serviceSubType==TC_SUBTYPE_UPDT_INFO))
171 172 )
172 173 {
173 174 if ( parserCode == WRONG_SRC_ID )
174 175 {
175 176 destinationID = SID_TC_GROUND;
176 177 }
177 178 else
178 179 {
179 180 destinationID = currentTC.sourceID;
180 181 }
181 182 send_tm_lfr_tc_exe_corrupted( &currentTC, queue_send_id,
182 183 computed_CRC, currentTC_LEN_RCV,
183 184 destinationID );
184 185 }
185 186 }
186 187 else
187 188 { // send valid TC to the action launcher
188 189 status = rtems_message_queue_send( queue_recv_id, &currentTC,
189 190 estimatedPacketLength + CCSDS_TC_TM_PACKET_OFFSET + 3);
190 191 }
191 192 }
192 193 }
193 194
194 195 update_queue_max_count( queue_recv_id, &hk_lfr_q_rv_fifo_size_max );
195 196
196 197 }
197 198 }
198 199
199 200 rtems_task send_task( rtems_task_argument argument)
200 201 {
201 202 /** This RTEMS task is dedicated to the transmission of TeleMetry packets.
202 203 *
203 204 * @param unused is the starting argument of the RTEMS task
204 205 *
205 206 * The SEND task waits for a message to become available in the dedicated RTEMS queue. When a message arrives:
206 207 * - if the first byte is equal to CCSDS_DESTINATION_ID, the message is sent as is using the write system call.
207 208 * - if the first byte is not equal to CCSDS_DESTINATION_ID, the message is handled as a spw_ioctl_pkt_send. After
208 209 * analyzis, the packet is sent either using the write system call or using the ioctl call SPACEWIRE_IOCTRL_SEND, depending on the
209 210 * data it contains.
210 211 *
211 212 */
212 213
213 214 rtems_status_code status; // RTEMS status code
214 215 char incomingData[MSG_QUEUE_SIZE_SEND]; // incoming data buffer
215 216 ring_node *incomingRingNodePtr;
216 217 int ring_node_address;
217 218 char *charPtr;
218 219 spw_ioctl_pkt_send *spw_ioctl_send;
219 220 size_t size; // size of the incoming TC packet
220 221 rtems_id queue_send_id;
221 222 unsigned int sid;
222 223 unsigned char sidAsUnsignedChar;
223 224 unsigned char type;
224 225
225 226 incomingRingNodePtr = NULL;
226 227 ring_node_address = 0;
227 228 charPtr = (char *) &ring_node_address;
228 229 sid = 0;
229 230 sidAsUnsignedChar = 0;
230 231
231 232 init_header_cwf( &headerCWF );
232 233 init_header_swf( &headerSWF );
233 234 init_header_asm( &headerASM );
234 235
235 236 status = get_message_queue_id_send( &queue_send_id );
236 237 if (status != RTEMS_SUCCESSFUL)
237 238 {
238 239 PRINTF1("in HOUS *** ERR get_message_queue_id_send %d\n", status)
239 240 }
240 241
241 242 BOOT_PRINTF("in SEND *** \n")
242 243
243 244 while(1)
244 245 {
245 246 status = rtems_message_queue_receive( queue_send_id, incomingData, &size,
246 247 RTEMS_WAIT, RTEMS_NO_TIMEOUT );
247 248
248 249 if (status!=RTEMS_SUCCESSFUL)
249 250 {
250 251 PRINTF1("in SEND *** (1) ERR = %d\n", status)
251 252 }
252 253 else
253 254 {
254 255 if ( size == sizeof(ring_node*) )
255 256 {
256 257 charPtr[0] = incomingData[0];
257 258 charPtr[1] = incomingData[1];
258 259 charPtr[2] = incomingData[2];
259 260 charPtr[3] = incomingData[3];
260 261 incomingRingNodePtr = (ring_node*) ring_node_address;
261 262 sid = incomingRingNodePtr->sid;
262 263 if ( (sid==SID_NORM_CWF_LONG_F3)
263 264 || (sid==SID_BURST_CWF_F2 )
264 265 || (sid==SID_SBM1_CWF_F1 )
265 266 || (sid==SID_SBM2_CWF_F2 ))
266 267 {
267 268 spw_send_waveform_CWF( incomingRingNodePtr, &headerCWF );
268 269 }
269 270 else if ( (sid==SID_NORM_SWF_F0) || (sid== SID_NORM_SWF_F1) || (sid==SID_NORM_SWF_F2) )
270 271 {
271 272 spw_send_waveform_SWF( incomingRingNodePtr, &headerSWF );
272 273 }
273 274 else if ( (sid==SID_NORM_CWF_F3) )
274 275 {
275 276 spw_send_waveform_CWF3_light( incomingRingNodePtr, &headerCWF );
276 277 }
277 278 else if (sid==SID_NORM_ASM_F0)
278 279 {
279 280 spw_send_asm_f0( incomingRingNodePtr, &headerASM );
280 281 }
281 282 else if (sid==SID_NORM_ASM_F1)
282 283 {
283 284 spw_send_asm_f1( incomingRingNodePtr, &headerASM );
284 285 }
285 286 else if (sid==SID_NORM_ASM_F2)
286 287 {
287 288 spw_send_asm_f2( incomingRingNodePtr, &headerASM );
288 289 }
289 290 else if ( sid==TM_CODE_K_DUMP )
290 291 {
291 292 spw_send_k_dump( incomingRingNodePtr );
292 293 }
293 294 else
294 295 {
295 296 PRINTF1("unexpected sid = %d\n", sid);
296 297 }
297 298 }
298 299 else if ( incomingData[0] == CCSDS_DESTINATION_ID ) // the incoming message is a ccsds packet
299 300 {
300 301 sidAsUnsignedChar = (unsigned char) incomingData[ PACKET_POS_PA_LFR_SID_PKT ];
301 302 sid = sidAsUnsignedChar;
302 303 type = (unsigned char) incomingData[ PACKET_POS_SERVICE_TYPE ];
303 304 if (type == TM_TYPE_LFR_SCIENCE) // this is a BP packet, all other types are handled differently
304 305 // SET THE SEQUENCE_CNT PARAMETER IN CASE OF BP0 OR BP1 PACKETS
305 306 {
306 307 increment_seq_counter_source_id( (unsigned char*) &incomingData[ PACKET_POS_SEQUENCE_CNT ], sid );
307 308 }
308 309
309 310 status = write( fdSPW, incomingData, size );
310 311 if (status == -1){
311 312 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
312 313 }
313 314 }
314 315 else // the incoming message is a spw_ioctl_pkt_send structure
315 316 {
316 317 spw_ioctl_send = (spw_ioctl_pkt_send*) incomingData;
317 318 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, spw_ioctl_send );
318 319 if (status == -1){
319 320 PRINTF2("in SEND *** (2.b) ERRNO = %d, RTEMS = %d\n", errno, status)
320 321 }
321 322 }
322 323 }
323 324
324 325 update_queue_max_count( queue_send_id, &hk_lfr_q_sd_fifo_size_max );
325 326
326 327 }
327 328 }
328 329
329 330 rtems_task wtdg_task( rtems_task_argument argument )
330 331 {
331 332 rtems_event_set event_out;
332 333 rtems_status_code status;
333 334 int linkStatus;
334 335
335 336 BOOT_PRINTF("in WTDG ***\n")
336 337
337 338 while(1)
338 339 {
339 340 // wait for an RTEMS_EVENT
340 341 rtems_event_receive( RTEMS_EVENT_0,
341 342 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
342 343 PRINTF("in WTDG *** wait for the link\n")
343 344 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
344 345 while( linkStatus != 5) // wait for the link
345 346 {
346 347 status = rtems_task_wake_after( 10 ); // monitor the link each 100ms
347 348 status = ioctl(fdSPW, SPACEWIRE_IOCTRL_GET_LINK_STATUS, &linkStatus); // get the link status
348 349 }
349 350
350 351 status = spacewire_stop_and_start_link( fdSPW );
351 352
352 353 if (status != RTEMS_SUCCESSFUL)
353 354 {
354 355 PRINTF1("in WTDG *** ERR link not started %d\n", status)
355 356 }
356 357 else
357 358 {
358 359 PRINTF("in WTDG *** OK link started\n")
359 360 }
360 361
361 362 // restart the SPIQ task
362 363 status = rtems_task_restart( Task_id[TASKID_SPIQ], 1 );
363 364 if ( status != RTEMS_SUCCESSFUL ) {
364 365 PRINTF("in SPIQ *** ERR restarting SPIQ Task\n")
365 366 }
366 367
367 368 // restart RECV and SEND
368 369 status = rtems_task_restart( Task_id[ TASKID_SEND ], 1 );
369 370 if ( status != RTEMS_SUCCESSFUL ) {
370 371 PRINTF("in SPIQ *** ERR restarting SEND Task\n")
371 372 }
372 373 status = rtems_task_restart( Task_id[ TASKID_RECV ], 1 );
373 374 if ( status != RTEMS_SUCCESSFUL ) {
374 375 PRINTF("in SPIQ *** ERR restarting RECV Task\n")
375 376 }
376 377 }
377 378 }
378 379
379 380 //****************
380 381 // OTHER FUNCTIONS
381 382 int spacewire_open_link( void ) // by default, the driver resets the core: [SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET);]
382 383 {
383 384 /** This function opens the SpaceWire link.
384 385 *
385 386 * @return a valid file descriptor in case of success, -1 in case of a failure
386 387 *
387 388 */
388 389 rtems_status_code status;
389 390
390 391 fdSPW = open(GRSPW_DEVICE_NAME, O_RDWR); // open the device. the open call resets the hardware
391 392 if ( fdSPW < 0 ) {
392 393 PRINTF1("ERR *** in configure_spw_link *** error opening "GRSPW_DEVICE_NAME" with ERR %d\n", errno)
393 394 }
394 395 else
395 396 {
396 397 status = RTEMS_SUCCESSFUL;
397 398 }
398 399
399 400 return status;
400 401 }
401 402
402 403 int spacewire_start_link( int fd )
403 404 {
404 405 rtems_status_code status;
405 406
406 407 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
407 408 // -1 default hardcoded driver timeout
408 409
409 410 return status;
410 411 }
411 412
412 413 int spacewire_stop_and_start_link( int fd )
413 414 {
414 415 rtems_status_code status;
415 416
416 417 status = ioctl( fd, SPACEWIRE_IOCTRL_STOP); // start fails if link pDev->running != 0
417 418 status = ioctl( fd, SPACEWIRE_IOCTRL_START, -1); // returns successfuly if the link is started
418 419 // -1 default hardcoded driver timeout
419 420
420 421 return status;
421 422 }
422 423
423 424 int spacewire_configure_link( int fd )
424 425 {
425 426 /** This function configures the SpaceWire link.
426 427 *
427 428 * @return GR-RTEMS-DRIVER directive status codes:
428 429 * - 22 EINVAL - Null pointer or an out of range value was given as the argument.
429 430 * - 16 EBUSY - Only used for SEND. Returned when no descriptors are avialble in non-blocking mode.
430 431 * - 88 ENOSYS - Returned for SET_DESTKEY if RMAP command handler is not available or if a non-implemented call is used.
431 432 * - 116 ETIMEDOUT - REturned for SET_PACKET_SIZE and START if the link could not be brought up.
432 433 * - 12 ENOMEM - Returned for SET_PACKETSIZE if it was unable to allocate the new buffers.
433 434 * - 5 EIO - Error when writing to grswp hardware registers.
434 435 * - 2 ENOENT - No such file or directory
435 436 */
436 437
437 438 rtems_status_code status;
438 439
439 440 spacewire_set_NP(1, REGS_ADDR_GRSPW); // [N]o [P]ort force
440 441 spacewire_set_RE(1, REGS_ADDR_GRSPW); // [R]MAP [E]nable, the dedicated call seems to break the no port force configuration
441 442
442 443 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_RXBLOCK, 1); // sets the blocking mode for reception
443 444 if (status!=RTEMS_SUCCESSFUL) {
444 445 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_RXBLOCK\n")
445 446 }
446 447 //
447 448 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_EVENT_ID, Task_id[TASKID_SPIQ]); // sets the task ID to which an event is sent when a
448 449 if (status!=RTEMS_SUCCESSFUL) {
449 450 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_EVENT_ID\n") // link-error interrupt occurs
450 451 }
451 452 //
452 453 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_DISABLE_ERR, 0); // automatic link-disabling due to link-error interrupts
453 454 if (status!=RTEMS_SUCCESSFUL) {
454 455 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_DISABLE_ERR\n")
455 456 }
456 457 //
457 458 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ, 1); // sets the link-error interrupt bit
458 459 if (status!=RTEMS_SUCCESSFUL) {
459 460 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ\n")
460 461 }
461 462 //
462 463 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK, 1); // transmission blocks
463 464 if (status!=RTEMS_SUCCESSFUL) {
464 465 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK\n")
465 466 }
466 467 //
467 468 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL, 1); // transmission blocks when no transmission descriptor is available
468 469 if (status!=RTEMS_SUCCESSFUL) {
469 470 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL\n")
470 471 }
471 472 //
472 473 status = ioctl(fd, SPACEWIRE_IOCTRL_SET_TCODE_CTRL, 0x0909); // [Time Rx : Time Tx : Link error : Tick-out IRQ]
473 474 if (status!=RTEMS_SUCCESSFUL) {
474 475 PRINTF("in SPIQ *** Error SPACEWIRE_IOCTRL_SET_TCODE_CTRL,\n")
475 476 }
476 477
477 478 return status;
478 479 }
479 480
480 int spacewire_reset_link( void )
481 int spacewire_several_connect_attemps( void )
481 482 {
482 483 /** This function is executed by the SPIQ rtems_task wehn it has been awaken by an interruption raised by the SpaceWire driver.
483 484 *
484 485 * @return RTEMS directive status code:
485 486 * - RTEMS_UNSATISFIED is returned is the link is not in the running state after 10 s.
486 487 * - RTEMS_SUCCESSFUL is returned if the link is up before the timeout.
487 488 *
488 489 */
489 490
490 491 rtems_status_code status_spw;
491 492 rtems_status_code status;
492 493 int i;
493 494
494 495 for ( i=0; i<SY_LFR_DPU_CONNECT_ATTEMPT; i++ )
495 496 {
496 497 PRINTF1("in spacewire_reset_link *** link recovery, try %d\n", i);
497 498
498 499 // CLOSING THE DRIVER AT THIS POINT WILL MAKE THE SEND TASK BLOCK THE SYSTEM
499 500
500 501 status = rtems_task_wake_after( SY_LFR_DPU_CONNECT_TIMEOUT ); // wait SY_LFR_DPU_CONNECT_TIMEOUT 1000 ms
501 502
502 503 status_spw = spacewire_stop_and_start_link( fdSPW );
503 504 if ( status_spw != RTEMS_SUCCESSFUL )
504 505 {
505 506 PRINTF1("in spacewire_reset_link *** ERR spacewire_start_link code %d\n", status_spw)
506 507 }
507 508
508 509 if ( status_spw == RTEMS_SUCCESSFUL)
509 510 {
510 511 break;
511 512 }
512 513 }
513 514
514 515 return status_spw;
515 516 }
516 517
517 518 void spacewire_set_NP( unsigned char val, unsigned int regAddr ) // [N]o [P]ort force
518 519 {
519 520 /** This function sets the [N]o [P]ort force bit of the GRSPW control register.
520 521 *
521 522 * @param val is the value, 0 or 1, used to set the value of the NP bit.
522 523 * @param regAddr is the address of the GRSPW control register.
523 524 *
524 525 * NP is the bit 20 of the GRSPW control register.
525 526 *
526 527 */
527 528
528 529 unsigned int *spwptr = (unsigned int*) regAddr;
529 530
530 531 if (val == 1) {
531 532 *spwptr = *spwptr | 0x00100000; // [NP] set the No port force bit
532 533 }
533 534 if (val== 0) {
534 535 *spwptr = *spwptr & 0xffdfffff;
535 536 }
536 537 }
537 538
538 539 void spacewire_set_RE( unsigned char val, unsigned int regAddr ) // [R]MAP [E]nable
539 540 {
540 541 /** This function sets the [R]MAP [E]nable bit of the GRSPW control register.
541 542 *
542 543 * @param val is the value, 0 or 1, used to set the value of the RE bit.
543 544 * @param regAddr is the address of the GRSPW control register.
544 545 *
545 546 * RE is the bit 16 of the GRSPW control register.
546 547 *
547 548 */
548 549
549 550 unsigned int *spwptr = (unsigned int*) regAddr;
550 551
551 552 if (val == 1)
552 553 {
553 554 *spwptr = *spwptr | 0x00010000; // [RE] set the RMAP Enable bit
554 555 }
555 556 if (val== 0)
556 557 {
557 558 *spwptr = *spwptr & 0xfffdffff;
558 559 }
559 560 }
560 561
561 562 void spacewire_compute_stats_offsets( void )
562 563 {
563 564 /** This function computes the SpaceWire statistics offsets in case of a SpaceWire related interruption raising.
564 565 *
565 566 * The offsets keep a record of the statistics in case of a reset of the statistics. They are added to the current statistics
566 567 * to keep the counters consistent even after a reset of the SpaceWire driver (the counter are set to zero by the driver when it
567 568 * during the open systel call).
568 569 *
569 570 */
570 571
571 572 spw_stats spacewire_stats_grspw;
572 573 rtems_status_code status;
573 574
574 575 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
575 576
576 577 spacewire_stats_backup.packets_received = spacewire_stats_grspw.packets_received
577 578 + spacewire_stats.packets_received;
578 579 spacewire_stats_backup.packets_sent = spacewire_stats_grspw.packets_sent
579 580 + spacewire_stats.packets_sent;
580 581 spacewire_stats_backup.parity_err = spacewire_stats_grspw.parity_err
581 582 + spacewire_stats.parity_err;
582 583 spacewire_stats_backup.disconnect_err = spacewire_stats_grspw.disconnect_err
583 584 + spacewire_stats.disconnect_err;
584 585 spacewire_stats_backup.escape_err = spacewire_stats_grspw.escape_err
585 586 + spacewire_stats.escape_err;
586 587 spacewire_stats_backup.credit_err = spacewire_stats_grspw.credit_err
587 588 + spacewire_stats.credit_err;
588 589 spacewire_stats_backup.write_sync_err = spacewire_stats_grspw.write_sync_err
589 590 + spacewire_stats.write_sync_err;
590 591 spacewire_stats_backup.rx_rmap_header_crc_err = spacewire_stats_grspw.rx_rmap_header_crc_err
591 592 + spacewire_stats.rx_rmap_header_crc_err;
592 593 spacewire_stats_backup.rx_rmap_data_crc_err = spacewire_stats_grspw.rx_rmap_data_crc_err
593 594 + spacewire_stats.rx_rmap_data_crc_err;
594 595 spacewire_stats_backup.early_ep = spacewire_stats_grspw.early_ep
595 596 + spacewire_stats.early_ep;
596 597 spacewire_stats_backup.invalid_address = spacewire_stats_grspw.invalid_address
597 598 + spacewire_stats.invalid_address;
598 599 spacewire_stats_backup.rx_eep_err = spacewire_stats_grspw.rx_eep_err
599 600 + spacewire_stats.rx_eep_err;
600 601 spacewire_stats_backup.rx_truncated = spacewire_stats_grspw.rx_truncated
601 602 + spacewire_stats.rx_truncated;
602 603 }
603 604
604 605 void spacewire_update_statistics( void )
605 606 {
606 607 rtems_status_code status;
607 608 spw_stats spacewire_stats_grspw;
608 609
609 610 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_GET_STATISTICS, &spacewire_stats_grspw );
610 611
611 612 spacewire_stats.packets_received = spacewire_stats_backup.packets_received
612 613 + spacewire_stats_grspw.packets_received;
613 614 spacewire_stats.packets_sent = spacewire_stats_backup.packets_sent
614 615 + spacewire_stats_grspw.packets_sent;
615 616 spacewire_stats.parity_err = spacewire_stats_backup.parity_err
616 617 + spacewire_stats_grspw.parity_err;
617 618 spacewire_stats.disconnect_err = spacewire_stats_backup.disconnect_err
618 619 + spacewire_stats_grspw.disconnect_err;
619 620 spacewire_stats.escape_err = spacewire_stats_backup.escape_err
620 621 + spacewire_stats_grspw.escape_err;
621 622 spacewire_stats.credit_err = spacewire_stats_backup.credit_err
622 623 + spacewire_stats_grspw.credit_err;
623 624 spacewire_stats.write_sync_err = spacewire_stats_backup.write_sync_err
624 625 + spacewire_stats_grspw.write_sync_err;
625 626 spacewire_stats.rx_rmap_header_crc_err = spacewire_stats_backup.rx_rmap_header_crc_err
626 627 + spacewire_stats_grspw.rx_rmap_header_crc_err;
627 628 spacewire_stats.rx_rmap_data_crc_err = spacewire_stats_backup.rx_rmap_data_crc_err
628 629 + spacewire_stats_grspw.rx_rmap_data_crc_err;
629 630 spacewire_stats.early_ep = spacewire_stats_backup.early_ep
630 631 + spacewire_stats_grspw.early_ep;
631 632 spacewire_stats.invalid_address = spacewire_stats_backup.invalid_address
632 633 + spacewire_stats_grspw.invalid_address;
633 634 spacewire_stats.rx_eep_err = spacewire_stats_backup.rx_eep_err
634 635 + spacewire_stats_grspw.rx_eep_err;
635 636 spacewire_stats.rx_truncated = spacewire_stats_backup.rx_truncated
636 637 + spacewire_stats_grspw.rx_truncated;
637 638 //spacewire_stats.tx_link_err;
638 639
639 640 //****************************
640 641 // DPU_SPACEWIRE_IF_STATISTICS
641 642 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[0] = (unsigned char) (spacewire_stats.packets_received >> 8);
642 643 housekeeping_packet.hk_lfr_dpu_spw_pkt_rcv_cnt[1] = (unsigned char) (spacewire_stats.packets_received);
643 644 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[0] = (unsigned char) (spacewire_stats.packets_sent >> 8);
644 645 housekeeping_packet.hk_lfr_dpu_spw_pkt_sent_cnt[1] = (unsigned char) (spacewire_stats.packets_sent);
645 646 //housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt;
646 647 //housekeeping_packet.hk_lfr_dpu_spw_last_timc;
647 648
648 649 //******************************************
649 650 // ERROR COUNTERS / SPACEWIRE / LOW SEVERITY
650 651 housekeeping_packet.hk_lfr_dpu_spw_parity = (unsigned char) spacewire_stats.parity_err;
651 652 housekeeping_packet.hk_lfr_dpu_spw_disconnect = (unsigned char) spacewire_stats.disconnect_err;
652 653 housekeeping_packet.hk_lfr_dpu_spw_escape = (unsigned char) spacewire_stats.escape_err;
653 654 housekeeping_packet.hk_lfr_dpu_spw_credit = (unsigned char) spacewire_stats.credit_err;
654 655 housekeeping_packet.hk_lfr_dpu_spw_write_sync = (unsigned char) spacewire_stats.write_sync_err;
655 656
656 657 //*********************************************
657 658 // ERROR COUNTERS / SPACEWIRE / MEDIUM SEVERITY
658 659 housekeeping_packet.hk_lfr_dpu_spw_early_eop = (unsigned char) spacewire_stats.early_ep;
659 660 housekeeping_packet.hk_lfr_dpu_spw_invalid_addr = (unsigned char) spacewire_stats.invalid_address;
660 661 housekeeping_packet.hk_lfr_dpu_spw_eep = (unsigned char) spacewire_stats.rx_eep_err;
661 662 housekeeping_packet.hk_lfr_dpu_spw_rx_too_big = (unsigned char) spacewire_stats.rx_truncated;
662 663 }
663 664
664 665 void increase_unsigned_char_counter( unsigned char *counter )
665 666 {
666 667 // update the number of valid timecodes that have been received
667 668 if (*counter == 255)
668 669 {
669 670 *counter = 0;
670 671 }
671 672 else
672 673 {
673 674 *counter = *counter + 1;
674 675 }
675 676 }
676 677
677 678 rtems_timer_service_routine timecode_timer_routine( rtems_id timer_id, void *user_data )
678 679 {
679 680
680 681 unsigned char currentTimecodeCtr;
681 682
682 683 currentTimecodeCtr = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
683 684
684 685 if (currentTimecodeCtr == previousTimecodeCtr)
685 686 {
686 687 //************************
687 688 // HK_LFR_TIMECODE_MISSING
688 689 // the timecode value has not changed, no valid timecode has been received, the timecode is MISSING
689 690 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_missing );
690 691 }
691 692 else if (currentTimecodeCtr == (previousTimecodeCtr+1))
692 693 {
693 694 // the timecode value has changed and the value is valid, this is unexpected because
694 695 // the timer should not have fired, the timecode_irq_handler should have been raised
695 696 }
696 697 else
697 698 {
698 699 //************************
699 700 // HK_LFR_TIMECODE_INVALID
700 701 // the timecode value has changed and the value is not valid, no tickout has been generated
701 702 // this is why the timer has fired
702 703 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_invalid );
703 704 }
704 705
705 706 rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_13 );
706 707 }
707 708
708 709 unsigned int check_timecode_and_previous_timecode_coherency(unsigned char currentTimecodeCtr)
709 710 {
710 711 /** This function checks the coherency between the incoming timecode and the last valid timecode.
711 712 *
712 713 * @param currentTimecodeCtr is the incoming timecode
713 714 *
714 715 * @return returned codes::
715 716 * - LFR_DEFAULT
716 717 * - LFR_SUCCESSFUL
717 718 *
718 719 */
719 720
720 721 static unsigned char firstTickout = 1;
721 722 unsigned char ret;
722 723
723 724 ret = LFR_DEFAULT;
724 725
725 726 if (firstTickout == 0)
726 727 {
727 728 if (currentTimecodeCtr == 0)
728 729 {
729 730 if (previousTimecodeCtr == 63)
730 731 {
731 732 ret = LFR_SUCCESSFUL;
732 733 }
733 734 else
734 735 {
735 736 ret = LFR_DEFAULT;
736 737 }
737 738 }
738 739 else
739 740 {
740 741 if (currentTimecodeCtr == (previousTimecodeCtr +1))
741 742 {
742 743 ret = LFR_SUCCESSFUL;
743 744 }
744 745 else
745 746 {
746 747 ret = LFR_DEFAULT;
747 748 }
748 749 }
749 750 }
750 751 else
751 752 {
752 753 firstTickout = 0;
753 754 ret = LFR_SUCCESSFUL;
754 755 }
755 756
756 757 return ret;
757 758 }
758 759
759 760 unsigned int check_timecode_and_internal_time_coherency(unsigned char timecode, unsigned char internalTime)
760 761 {
761 762 unsigned int ret;
762 763
763 764 ret = LFR_DEFAULT;
764 765
765 766 if (timecode == internalTime)
766 767 {
767 768 ret = LFR_SUCCESSFUL;
768 769 }
769 770 else
770 771 {
771 772 ret = LFR_DEFAULT;
772 773 }
773 774
774 775 return ret;
775 776 }
776 777
777 778 void timecode_irq_handler( void *pDev, void *regs, int minor, unsigned int tc )
778 779 {
779 780 // a tickout has been emitted, perform actions on the incoming timecode
780 781
781 782 unsigned char incomingTimecode;
782 783 unsigned char updateTime;
783 784 unsigned char internalTime;
784 785 rtems_status_code status;
785 786
786 787 incomingTimecode = (unsigned char) (grspwPtr[0] & TIMECODE_MASK);
787 788 updateTime = time_management_regs->coarse_time_load & TIMECODE_MASK;
788 789 internalTime = time_management_regs->coarse_time & TIMECODE_MASK;
789 790
790 791 housekeeping_packet.hk_lfr_dpu_spw_last_timc = incomingTimecode;
791 792
792 793 // update the number of tickout that have been generated
793 794 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_dpu_spw_tick_out_cnt );
794 795
795 796 //**************************
796 797 // HK_LFR_TIMECODE_ERRONEOUS
797 798 // MISSING and INVALID are handled by the timecode_timer_routine service routine
798 799 if (check_timecode_and_previous_timecode_coherency( incomingTimecode ) == LFR_DEFAULT)
799 800 {
800 801 // this is unexpected but a tickout could have been raised despite of the timecode being erroneous
801 802 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_timecode_erroneous );
802 803 }
803 804
804 805 //************************
805 806 // HK_LFR_TIME_TIMECODE_IT
806 807 // check the coherency between the SpaceWire timecode and the Internal Time
807 808 if (check_timecode_and_internal_time_coherency( incomingTimecode, internalTime ) == LFR_DEFAULT)
808 809 {
809 810 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_it );
810 811 }
811 812
812 813 //********************
813 814 // HK_LFR_TIMECODE_CTR
814 815 // check the value of the timecode with respect to the last TC_LFR_UPDATE_TIME => SSS-CP-FS-370
815 816 if (incomingTimecode != updateTime)
816 817 {
817 818 increase_unsigned_char_counter( &housekeeping_packet.hk_lfr_time_timecode_ctr );
818 819 }
819 820
820 821 // launch the timecode timer to detect missing or invalid timecodes
821 822 previousTimecodeCtr = incomingTimecode; // update the previousTimecodeCtr value
822 823 status = rtems_timer_fire_after( timecode_timer_id, TIMECODE_TIMER_TIMEOUT, timecode_timer_routine, NULL );
823 824 }
824 825
825 826 void init_header_cwf( Header_TM_LFR_SCIENCE_CWF_t *header )
826 827 {
827 828 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
828 829 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
829 830 header->reserved = DEFAULT_RESERVED;
830 831 header->userApplication = CCSDS_USER_APP;
831 832 header->packetSequenceControl[0]= TM_PACKET_SEQ_CTRL_STANDALONE;
832 833 header->packetSequenceControl[1]= TM_PACKET_SEQ_CNT_DEFAULT;
833 834 header->packetLength[0] = 0x00;
834 835 header->packetLength[1] = 0x00;
835 836 // DATA FIELD HEADER
836 837 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
837 838 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
838 839 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
839 840 header->destinationID = TM_DESTINATION_ID_GROUND;
840 841 header->time[0] = 0x00;
841 842 header->time[0] = 0x00;
842 843 header->time[0] = 0x00;
843 844 header->time[0] = 0x00;
844 845 header->time[0] = 0x00;
845 846 header->time[0] = 0x00;
846 847 // AUXILIARY DATA HEADER
847 848 header->sid = 0x00;
848 849 header->hkBIA = DEFAULT_HKBIA;
849 850 header->blkNr[0] = 0x00;
850 851 header->blkNr[1] = 0x00;
851 852 }
852 853
853 854 void init_header_swf( Header_TM_LFR_SCIENCE_SWF_t *header )
854 855 {
855 856 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
856 857 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
857 858 header->reserved = DEFAULT_RESERVED;
858 859 header->userApplication = CCSDS_USER_APP;
859 860 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
860 861 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
861 862 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
862 863 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
863 864 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
864 865 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
865 866 // DATA FIELD HEADER
866 867 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
867 868 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
868 869 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6; // service subtype
869 870 header->destinationID = TM_DESTINATION_ID_GROUND;
870 871 header->time[0] = 0x00;
871 872 header->time[0] = 0x00;
872 873 header->time[0] = 0x00;
873 874 header->time[0] = 0x00;
874 875 header->time[0] = 0x00;
875 876 header->time[0] = 0x00;
876 877 // AUXILIARY DATA HEADER
877 878 header->sid = 0x00;
878 879 header->hkBIA = DEFAULT_HKBIA;
879 880 header->pktCnt = DEFAULT_PKTCNT; // PKT_CNT
880 881 header->pktNr = 0x00;
881 882 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
882 883 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
883 884 }
884 885
885 886 void init_header_asm( Header_TM_LFR_SCIENCE_ASM_t *header )
886 887 {
887 888 header->targetLogicalAddress = CCSDS_DESTINATION_ID;
888 889 header->protocolIdentifier = CCSDS_PROTOCOLE_ID;
889 890 header->reserved = DEFAULT_RESERVED;
890 891 header->userApplication = CCSDS_USER_APP;
891 892 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
892 893 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
893 894 header->packetSequenceControl[0] = TM_PACKET_SEQ_CTRL_STANDALONE;
894 895 header->packetSequenceControl[1] = TM_PACKET_SEQ_CNT_DEFAULT;
895 896 header->packetLength[0] = 0x00;
896 897 header->packetLength[1] = 0x00;
897 898 // DATA FIELD HEADER
898 899 header->spare1_pusVersion_spare2 = DEFAULT_SPARE1_PUSVERSION_SPARE2;
899 900 header->serviceType = TM_TYPE_LFR_SCIENCE; // service type
900 901 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3; // service subtype
901 902 header->destinationID = TM_DESTINATION_ID_GROUND;
902 903 header->time[0] = 0x00;
903 904 header->time[0] = 0x00;
904 905 header->time[0] = 0x00;
905 906 header->time[0] = 0x00;
906 907 header->time[0] = 0x00;
907 908 header->time[0] = 0x00;
908 909 // AUXILIARY DATA HEADER
909 910 header->sid = 0x00;
910 911 header->biaStatusInfo = 0x00;
911 912 header->pa_lfr_pkt_cnt_asm = 0x00;
912 913 header->pa_lfr_pkt_nr_asm = 0x00;
913 914 header->pa_lfr_asm_blk_nr[0] = 0x00;
914 915 header->pa_lfr_asm_blk_nr[1] = 0x00;
915 916 }
916 917
917 918 int spw_send_waveform_CWF( ring_node *ring_node_to_send,
918 919 Header_TM_LFR_SCIENCE_CWF_t *header )
919 920 {
920 921 /** This function sends CWF CCSDS packets (F2, F1 or F0).
921 922 *
922 923 * @param waveform points to the buffer containing the data that will be send.
923 924 * @param sid is the source identifier of the data that will be sent.
924 925 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
925 926 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
926 927 * contain information to setup the transmission of the data packets.
927 928 *
928 929 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
929 930 *
930 931 */
931 932
932 933 unsigned int i;
933 934 int ret;
934 935 unsigned int coarseTime;
935 936 unsigned int fineTime;
936 937 rtems_status_code status;
937 938 spw_ioctl_pkt_send spw_ioctl_send_CWF;
938 939 int *dataPtr;
939 940 unsigned char sid;
940 941
941 942 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
942 943 spw_ioctl_send_CWF.options = 0;
943 944
944 945 ret = LFR_DEFAULT;
945 946 sid = (unsigned char) ring_node_to_send->sid;
946 947
947 948 coarseTime = ring_node_to_send->coarseTime;
948 949 fineTime = ring_node_to_send->fineTime;
949 950 dataPtr = (int*) ring_node_to_send->buffer_address;
950 951
951 952 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_336 >> 8);
952 953 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_336 );
953 954 header->hkBIA = pa_bia_status_info;
954 955 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
955 956 header->blkNr[0] = (unsigned char) (BLK_NR_CWF >> 8);
956 957 header->blkNr[1] = (unsigned char) (BLK_NR_CWF );
957 958
958 959 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF; i++) // send waveform
959 960 {
960 961 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF * NB_WORDS_SWF_BLK) ];
961 962 spw_ioctl_send_CWF.hdr = (char*) header;
962 963 // BUILD THE DATA
963 964 spw_ioctl_send_CWF.dlen = BLK_NR_CWF * NB_BYTES_SWF_BLK;
964 965
965 966 // SET PACKET SEQUENCE CONTROL
966 967 increment_seq_counter_source_id( header->packetSequenceControl, sid );
967 968
968 969 // SET SID
969 970 header->sid = sid;
970 971
971 972 // SET PACKET TIME
972 973 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime);
973 974 //
974 975 header->time[0] = header->acquisitionTime[0];
975 976 header->time[1] = header->acquisitionTime[1];
976 977 header->time[2] = header->acquisitionTime[2];
977 978 header->time[3] = header->acquisitionTime[3];
978 979 header->time[4] = header->acquisitionTime[4];
979 980 header->time[5] = header->acquisitionTime[5];
980 981
981 982 // SET PACKET ID
982 983 if ( (sid == SID_SBM1_CWF_F1) || (sid == SID_SBM2_CWF_F2) )
983 984 {
984 985 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2 >> 8);
985 986 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_SBM1_SBM2);
986 987 }
987 988 else
988 989 {
989 990 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
990 991 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
991 992 }
992 993
993 994 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
994 995 if (status != RTEMS_SUCCESSFUL) {
995 996 ret = LFR_DEFAULT;
996 997 }
997 998 }
998 999
999 1000 return ret;
1000 1001 }
1001 1002
1002 1003 int spw_send_waveform_SWF( ring_node *ring_node_to_send,
1003 1004 Header_TM_LFR_SCIENCE_SWF_t *header )
1004 1005 {
1005 1006 /** This function sends SWF CCSDS packets (F2, F1 or F0).
1006 1007 *
1007 1008 * @param waveform points to the buffer containing the data that will be send.
1008 1009 * @param sid is the source identifier of the data that will be sent.
1009 1010 * @param headerSWF points to a table of headers that have been prepared for the data transmission.
1010 1011 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1011 1012 * contain information to setup the transmission of the data packets.
1012 1013 *
1013 1014 * One group of 2048 samples is sent as 7 consecutive packets, 6 packets containing 340 blocks and 8 packets containing 8 blocks.
1014 1015 *
1015 1016 */
1016 1017
1017 1018 unsigned int i;
1018 1019 int ret;
1019 1020 unsigned int coarseTime;
1020 1021 unsigned int fineTime;
1021 1022 rtems_status_code status;
1022 1023 spw_ioctl_pkt_send spw_ioctl_send_SWF;
1023 1024 int *dataPtr;
1024 1025 unsigned char sid;
1025 1026
1026 1027 spw_ioctl_send_SWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_SWF;
1027 1028 spw_ioctl_send_SWF.options = 0;
1028 1029
1029 1030 ret = LFR_DEFAULT;
1030 1031
1031 1032 coarseTime = ring_node_to_send->coarseTime;
1032 1033 fineTime = ring_node_to_send->fineTime;
1033 1034 dataPtr = (int*) ring_node_to_send->buffer_address;
1034 1035 sid = ring_node_to_send->sid;
1035 1036
1036 1037 header->hkBIA = pa_bia_status_info;
1037 1038 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1038 1039
1039 1040 for (i=0; i<7; i++) // send waveform
1040 1041 {
1041 1042 spw_ioctl_send_SWF.data = (char*) &dataPtr[ (i * BLK_NR_304 * NB_WORDS_SWF_BLK) ];
1042 1043 spw_ioctl_send_SWF.hdr = (char*) header;
1043 1044
1044 1045 // SET PACKET SEQUENCE CONTROL
1045 1046 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1046 1047
1047 1048 // SET PACKET LENGTH AND BLKNR
1048 1049 if (i == 6)
1049 1050 {
1050 1051 spw_ioctl_send_SWF.dlen = BLK_NR_224 * NB_BYTES_SWF_BLK;
1051 1052 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_224 >> 8);
1052 1053 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_224 );
1053 1054 header->blkNr[0] = (unsigned char) (BLK_NR_224 >> 8);
1054 1055 header->blkNr[1] = (unsigned char) (BLK_NR_224 );
1055 1056 }
1056 1057 else
1057 1058 {
1058 1059 spw_ioctl_send_SWF.dlen = BLK_NR_304 * NB_BYTES_SWF_BLK;
1059 1060 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_SWF_304 >> 8);
1060 1061 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_SWF_304 );
1061 1062 header->blkNr[0] = (unsigned char) (BLK_NR_304 >> 8);
1062 1063 header->blkNr[1] = (unsigned char) (BLK_NR_304 );
1063 1064 }
1064 1065
1065 1066 // SET PACKET TIME
1066 1067 compute_acquisition_time( coarseTime, fineTime, sid, i, header->acquisitionTime );
1067 1068 //
1068 1069 header->time[0] = header->acquisitionTime[0];
1069 1070 header->time[1] = header->acquisitionTime[1];
1070 1071 header->time[2] = header->acquisitionTime[2];
1071 1072 header->time[3] = header->acquisitionTime[3];
1072 1073 header->time[4] = header->acquisitionTime[4];
1073 1074 header->time[5] = header->acquisitionTime[5];
1074 1075
1075 1076 // SET SID
1076 1077 header->sid = sid;
1077 1078
1078 1079 // SET PKTNR
1079 1080 header->pktNr = i+1; // PKT_NR
1080 1081
1081 1082 // SEND PACKET
1082 1083 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_SWF );
1083 1084 if (status != RTEMS_SUCCESSFUL) {
1084 1085 ret = LFR_DEFAULT;
1085 1086 }
1086 1087 }
1087 1088
1088 1089 return ret;
1089 1090 }
1090 1091
1091 1092 int spw_send_waveform_CWF3_light( ring_node *ring_node_to_send,
1092 1093 Header_TM_LFR_SCIENCE_CWF_t *header )
1093 1094 {
1094 1095 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
1095 1096 *
1096 1097 * @param waveform points to the buffer containing the data that will be send.
1097 1098 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
1098 1099 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
1099 1100 * contain information to setup the transmission of the data packets.
1100 1101 *
1101 1102 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
1102 1103 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
1103 1104 *
1104 1105 */
1105 1106
1106 1107 unsigned int i;
1107 1108 int ret;
1108 1109 unsigned int coarseTime;
1109 1110 unsigned int fineTime;
1110 1111 rtems_status_code status;
1111 1112 spw_ioctl_pkt_send spw_ioctl_send_CWF;
1112 1113 char *dataPtr;
1113 1114 unsigned char sid;
1114 1115
1115 1116 spw_ioctl_send_CWF.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_CWF;
1116 1117 spw_ioctl_send_CWF.options = 0;
1117 1118
1118 1119 ret = LFR_DEFAULT;
1119 1120 sid = ring_node_to_send->sid;
1120 1121
1121 1122 coarseTime = ring_node_to_send->coarseTime;
1122 1123 fineTime = ring_node_to_send->fineTime;
1123 1124 dataPtr = (char*) ring_node_to_send->buffer_address;
1124 1125
1125 1126 header->packetLength[0] = (unsigned char) (TM_LEN_SCI_CWF_672 >> 8);
1126 1127 header->packetLength[1] = (unsigned char) (TM_LEN_SCI_CWF_672 );
1127 1128 header->hkBIA = pa_bia_status_info;
1128 1129 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1129 1130 header->blkNr[0] = (unsigned char) (BLK_NR_CWF_SHORT_F3 >> 8);
1130 1131 header->blkNr[1] = (unsigned char) (BLK_NR_CWF_SHORT_F3 );
1131 1132
1132 1133 //*********************
1133 1134 // SEND CWF3_light DATA
1134 1135 for (i=0; i<NB_PACKETS_PER_GROUP_OF_CWF_LIGHT; i++) // send waveform
1135 1136 {
1136 1137 spw_ioctl_send_CWF.data = (char*) &dataPtr[ (i * BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK) ];
1137 1138 spw_ioctl_send_CWF.hdr = (char*) header;
1138 1139 // BUILD THE DATA
1139 1140 spw_ioctl_send_CWF.dlen = BLK_NR_CWF_SHORT_F3 * NB_BYTES_CWF3_LIGHT_BLK;
1140 1141
1141 1142 // SET PACKET SEQUENCE COUNTER
1142 1143 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1143 1144
1144 1145 // SET SID
1145 1146 header->sid = sid;
1146 1147
1147 1148 // SET PACKET TIME
1148 1149 compute_acquisition_time( coarseTime, fineTime, SID_NORM_CWF_F3, i, header->acquisitionTime );
1149 1150 //
1150 1151 header->time[0] = header->acquisitionTime[0];
1151 1152 header->time[1] = header->acquisitionTime[1];
1152 1153 header->time[2] = header->acquisitionTime[2];
1153 1154 header->time[3] = header->acquisitionTime[3];
1154 1155 header->time[4] = header->acquisitionTime[4];
1155 1156 header->time[5] = header->acquisitionTime[5];
1156 1157
1157 1158 // SET PACKET ID
1158 1159 header->packetID[0] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST >> 8);
1159 1160 header->packetID[1] = (unsigned char) (APID_TM_SCIENCE_NORMAL_BURST);
1160 1161
1161 1162 // SEND PACKET
1162 1163 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_CWF );
1163 1164 if (status != RTEMS_SUCCESSFUL) {
1164 1165 ret = LFR_DEFAULT;
1165 1166 }
1166 1167 }
1167 1168
1168 1169 return ret;
1169 1170 }
1170 1171
1171 1172 void spw_send_asm_f0( ring_node *ring_node_to_send,
1172 1173 Header_TM_LFR_SCIENCE_ASM_t *header )
1173 1174 {
1174 1175 unsigned int i;
1175 1176 unsigned int length = 0;
1176 1177 rtems_status_code status;
1177 1178 unsigned int sid;
1178 1179 float *spectral_matrix;
1179 1180 int coarseTime;
1180 1181 int fineTime;
1181 1182 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1182 1183
1183 1184 sid = ring_node_to_send->sid;
1184 1185 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1185 1186 coarseTime = ring_node_to_send->coarseTime;
1186 1187 fineTime = ring_node_to_send->fineTime;
1187 1188
1188 1189 header->biaStatusInfo = pa_bia_status_info;
1189 1190 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1190 1191
1191 1192 for (i=0; i<3; i++)
1192 1193 {
1193 1194 if ((i==0) || (i==1))
1194 1195 {
1195 1196 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_1;
1196 1197 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1197 1198 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1198 1199 ];
1199 1200 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_1;
1200 1201 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1201 1202 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_1) >> 8 ); // BLK_NR MSB
1202 1203 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_1); // BLK_NR LSB
1203 1204 }
1204 1205 else
1205 1206 {
1206 1207 spw_ioctl_send_ASM.dlen = DLEN_ASM_F0_PKT_2;
1207 1208 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1208 1209 ( (ASM_F0_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F0_1) ) * NB_VALUES_PER_SM )
1209 1210 ];
1210 1211 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F0_2;
1211 1212 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1212 1213 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F0_2) >> 8 ); // BLK_NR MSB
1213 1214 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F0_2); // BLK_NR LSB
1214 1215 }
1215 1216
1216 1217 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1217 1218 spw_ioctl_send_ASM.hdr = (char *) header;
1218 1219 spw_ioctl_send_ASM.options = 0;
1219 1220
1220 1221 // (2) BUILD THE HEADER
1221 1222 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1222 1223 header->packetLength[0] = (unsigned char) (length>>8);
1223 1224 header->packetLength[1] = (unsigned char) (length);
1224 1225 header->sid = (unsigned char) sid; // SID
1225 1226 header->pa_lfr_pkt_cnt_asm = 3;
1226 1227 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1227 1228
1228 1229 // (3) SET PACKET TIME
1229 1230 header->time[0] = (unsigned char) (coarseTime>>24);
1230 1231 header->time[1] = (unsigned char) (coarseTime>>16);
1231 1232 header->time[2] = (unsigned char) (coarseTime>>8);
1232 1233 header->time[3] = (unsigned char) (coarseTime);
1233 1234 header->time[4] = (unsigned char) (fineTime>>8);
1234 1235 header->time[5] = (unsigned char) (fineTime);
1235 1236 //
1236 1237 header->acquisitionTime[0] = header->time[0];
1237 1238 header->acquisitionTime[1] = header->time[1];
1238 1239 header->acquisitionTime[2] = header->time[2];
1239 1240 header->acquisitionTime[3] = header->time[3];
1240 1241 header->acquisitionTime[4] = header->time[4];
1241 1242 header->acquisitionTime[5] = header->time[5];
1242 1243
1243 1244 // (4) SEND PACKET
1244 1245 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1245 1246 if (status != RTEMS_SUCCESSFUL) {
1246 1247 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1247 1248 }
1248 1249 }
1249 1250 }
1250 1251
1251 1252 void spw_send_asm_f1( ring_node *ring_node_to_send,
1252 1253 Header_TM_LFR_SCIENCE_ASM_t *header )
1253 1254 {
1254 1255 unsigned int i;
1255 1256 unsigned int length = 0;
1256 1257 rtems_status_code status;
1257 1258 unsigned int sid;
1258 1259 float *spectral_matrix;
1259 1260 int coarseTime;
1260 1261 int fineTime;
1261 1262 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1262 1263
1263 1264 sid = ring_node_to_send->sid;
1264 1265 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1265 1266 coarseTime = ring_node_to_send->coarseTime;
1266 1267 fineTime = ring_node_to_send->fineTime;
1267 1268
1268 1269 header->biaStatusInfo = pa_bia_status_info;
1269 1270 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1270 1271
1271 1272 for (i=0; i<3; i++)
1272 1273 {
1273 1274 if ((i==0) || (i==1))
1274 1275 {
1275 1276 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_1;
1276 1277 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1277 1278 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1278 1279 ];
1279 1280 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_1;
1280 1281 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1281 1282 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_1) >> 8 ); // BLK_NR MSB
1282 1283 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_1); // BLK_NR LSB
1283 1284 }
1284 1285 else
1285 1286 {
1286 1287 spw_ioctl_send_ASM.dlen = DLEN_ASM_F1_PKT_2;
1287 1288 spw_ioctl_send_ASM.data = (char*) &spectral_matrix[
1288 1289 ( (ASM_F1_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F1_1) ) * NB_VALUES_PER_SM )
1289 1290 ];
1290 1291 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F1_2;
1291 1292 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_6;
1292 1293 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F1_2) >> 8 ); // BLK_NR MSB
1293 1294 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F1_2); // BLK_NR LSB
1294 1295 }
1295 1296
1296 1297 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1297 1298 spw_ioctl_send_ASM.hdr = (char *) header;
1298 1299 spw_ioctl_send_ASM.options = 0;
1299 1300
1300 1301 // (2) BUILD THE HEADER
1301 1302 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1302 1303 header->packetLength[0] = (unsigned char) (length>>8);
1303 1304 header->packetLength[1] = (unsigned char) (length);
1304 1305 header->sid = (unsigned char) sid; // SID
1305 1306 header->pa_lfr_pkt_cnt_asm = 3;
1306 1307 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1307 1308
1308 1309 // (3) SET PACKET TIME
1309 1310 header->time[0] = (unsigned char) (coarseTime>>24);
1310 1311 header->time[1] = (unsigned char) (coarseTime>>16);
1311 1312 header->time[2] = (unsigned char) (coarseTime>>8);
1312 1313 header->time[3] = (unsigned char) (coarseTime);
1313 1314 header->time[4] = (unsigned char) (fineTime>>8);
1314 1315 header->time[5] = (unsigned char) (fineTime);
1315 1316 //
1316 1317 header->acquisitionTime[0] = header->time[0];
1317 1318 header->acquisitionTime[1] = header->time[1];
1318 1319 header->acquisitionTime[2] = header->time[2];
1319 1320 header->acquisitionTime[3] = header->time[3];
1320 1321 header->acquisitionTime[4] = header->time[4];
1321 1322 header->acquisitionTime[5] = header->time[5];
1322 1323
1323 1324 // (4) SEND PACKET
1324 1325 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1325 1326 if (status != RTEMS_SUCCESSFUL) {
1326 1327 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1327 1328 }
1328 1329 }
1329 1330 }
1330 1331
1331 1332 void spw_send_asm_f2( ring_node *ring_node_to_send,
1332 1333 Header_TM_LFR_SCIENCE_ASM_t *header )
1333 1334 {
1334 1335 unsigned int i;
1335 1336 unsigned int length = 0;
1336 1337 rtems_status_code status;
1337 1338 unsigned int sid;
1338 1339 float *spectral_matrix;
1339 1340 int coarseTime;
1340 1341 int fineTime;
1341 1342 spw_ioctl_pkt_send spw_ioctl_send_ASM;
1342 1343
1343 1344 sid = ring_node_to_send->sid;
1344 1345 spectral_matrix = (float*) ring_node_to_send->buffer_address;
1345 1346 coarseTime = ring_node_to_send->coarseTime;
1346 1347 fineTime = ring_node_to_send->fineTime;
1347 1348
1348 1349 header->biaStatusInfo = pa_bia_status_info;
1349 1350 header->sy_lfr_common_parameters = parameter_dump_packet.sy_lfr_common_parameters;
1350 1351
1351 1352 for (i=0; i<3; i++)
1352 1353 {
1353 1354
1354 1355 spw_ioctl_send_ASM.dlen = DLEN_ASM_F2_PKT;
1355 1356 spw_ioctl_send_ASM.data = (char *) &spectral_matrix[
1356 1357 ( (ASM_F2_INDICE_START + (i*NB_BINS_PER_PKT_ASM_F2) ) * NB_VALUES_PER_SM )
1357 1358 ];
1358 1359 length = PACKET_LENGTH_TM_LFR_SCIENCE_ASM_F2;
1359 1360 header->serviceSubType = TM_SUBTYPE_LFR_SCIENCE_3;
1360 1361 header->pa_lfr_asm_blk_nr[0] = (unsigned char) ( (NB_BINS_PER_PKT_ASM_F2) >> 8 ); // BLK_NR MSB
1361 1362 header->pa_lfr_asm_blk_nr[1] = (unsigned char) (NB_BINS_PER_PKT_ASM_F2); // BLK_NR LSB
1362 1363
1363 1364 spw_ioctl_send_ASM.hlen = HEADER_LENGTH_TM_LFR_SCIENCE_ASM;
1364 1365 spw_ioctl_send_ASM.hdr = (char *) header;
1365 1366 spw_ioctl_send_ASM.options = 0;
1366 1367
1367 1368 // (2) BUILD THE HEADER
1368 1369 increment_seq_counter_source_id( header->packetSequenceControl, sid );
1369 1370 header->packetLength[0] = (unsigned char) (length>>8);
1370 1371 header->packetLength[1] = (unsigned char) (length);
1371 1372 header->sid = (unsigned char) sid; // SID
1372 1373 header->pa_lfr_pkt_cnt_asm = 3;
1373 1374 header->pa_lfr_pkt_nr_asm = (unsigned char) (i+1);
1374 1375
1375 1376 // (3) SET PACKET TIME
1376 1377 header->time[0] = (unsigned char) (coarseTime>>24);
1377 1378 header->time[1] = (unsigned char) (coarseTime>>16);
1378 1379 header->time[2] = (unsigned char) (coarseTime>>8);
1379 1380 header->time[3] = (unsigned char) (coarseTime);
1380 1381 header->time[4] = (unsigned char) (fineTime>>8);
1381 1382 header->time[5] = (unsigned char) (fineTime);
1382 1383 //
1383 1384 header->acquisitionTime[0] = header->time[0];
1384 1385 header->acquisitionTime[1] = header->time[1];
1385 1386 header->acquisitionTime[2] = header->time[2];
1386 1387 header->acquisitionTime[3] = header->time[3];
1387 1388 header->acquisitionTime[4] = header->time[4];
1388 1389 header->acquisitionTime[5] = header->time[5];
1389 1390
1390 1391 // (4) SEND PACKET
1391 1392 status = ioctl( fdSPW, SPACEWIRE_IOCTRL_SEND, &spw_ioctl_send_ASM );
1392 1393 if (status != RTEMS_SUCCESSFUL) {
1393 1394 PRINTF1("in ASM_send *** ERR %d\n", (int) status)
1394 1395 }
1395 1396 }
1396 1397 }
1397 1398
1398 1399 void spw_send_k_dump( ring_node *ring_node_to_send )
1399 1400 {
1400 1401 rtems_status_code status;
1401 1402 Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *kcoefficients_dump;
1402 1403 unsigned int packetLength;
1403 1404 unsigned int size;
1404 1405
1405 1406 PRINTF("spw_send_k_dump\n")
1406 1407
1407 1408 kcoefficients_dump = (Packet_TM_LFR_KCOEFFICIENTS_DUMP_t *) ring_node_to_send->buffer_address;
1408 1409
1409 1410 packetLength = kcoefficients_dump->packetLength[0] * 256 + kcoefficients_dump->packetLength[1];
1410 1411
1411 1412 size = packetLength + CCSDS_TC_TM_PACKET_OFFSET + CCSDS_PROTOCOLE_EXTRA_BYTES;
1412 1413
1413 1414 PRINTF2("packetLength %d, size %d\n", packetLength, size )
1414 1415
1415 1416 status = write( fdSPW, (char *) ring_node_to_send->buffer_address, size );
1416 1417
1417 1418 if (status == -1){
1418 1419 PRINTF2("in SEND *** (2.a) ERRNO = %d, size = %d\n", errno, size)
1419 1420 }
1420 1421
1421 1422 ring_node_to_send->status = 0x00;
1422 1423 }
@@ -1,1606 +1,1607
1 1 /** Functions and tasks related to TeleCommand handling.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle TeleCommands:\n
7 7 * action launching\n
8 8 * TC parsing\n
9 9 * ...
10 10 *
11 11 */
12 12
13 13 #include "tc_handler.h"
14 14 #include "math.h"
15 15
16 16 //***********
17 17 // RTEMS TASK
18 18
19 19 rtems_task actn_task( rtems_task_argument unused )
20 20 {
21 21 /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands.
22 22 *
23 23 * @param unused is the starting argument of the RTEMS task
24 24 *
25 25 * The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending
26 26 * on the incoming TeleCommand.
27 27 *
28 28 */
29 29
30 30 int result;
31 31 rtems_status_code status; // RTEMS status code
32 32 ccsdsTelecommandPacket_t TC; // TC sent to the ACTN task
33 33 size_t size; // size of the incoming TC packet
34 34 unsigned char subtype; // subtype of the current TC packet
35 35 unsigned char time[6];
36 36 rtems_id queue_rcv_id;
37 37 rtems_id queue_snd_id;
38 38
39 39 status = get_message_queue_id_recv( &queue_rcv_id );
40 40 if (status != RTEMS_SUCCESSFUL)
41 41 {
42 42 PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status)
43 43 }
44 44
45 45 status = get_message_queue_id_send( &queue_snd_id );
46 46 if (status != RTEMS_SUCCESSFUL)
47 47 {
48 48 PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status)
49 49 }
50 50
51 51 result = LFR_SUCCESSFUL;
52 52 subtype = 0; // subtype of the current TC packet
53 53
54 54 BOOT_PRINTF("in ACTN *** \n")
55 55
56 56 while(1)
57 57 {
58 58 status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size,
59 59 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
60 60 getTime( time ); // set time to the current time
61 61 if (status!=RTEMS_SUCCESSFUL)
62 62 {
63 63 PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status)
64 64 }
65 65 else
66 66 {
67 67 subtype = TC.serviceSubType;
68 68 switch(subtype)
69 69 {
70 70 case TC_SUBTYPE_RESET:
71 71 result = action_reset( &TC, queue_snd_id, time );
72 72 close_action( &TC, result, queue_snd_id );
73 73 break;
74 74 case TC_SUBTYPE_LOAD_COMM:
75 75 result = action_load_common_par( &TC );
76 76 close_action( &TC, result, queue_snd_id );
77 77 break;
78 78 case TC_SUBTYPE_LOAD_NORM:
79 79 result = action_load_normal_par( &TC, queue_snd_id, time );
80 80 close_action( &TC, result, queue_snd_id );
81 81 break;
82 82 case TC_SUBTYPE_LOAD_BURST:
83 83 result = action_load_burst_par( &TC, queue_snd_id, time );
84 84 close_action( &TC, result, queue_snd_id );
85 85 break;
86 86 case TC_SUBTYPE_LOAD_SBM1:
87 87 result = action_load_sbm1_par( &TC, queue_snd_id, time );
88 88 close_action( &TC, result, queue_snd_id );
89 89 break;
90 90 case TC_SUBTYPE_LOAD_SBM2:
91 91 result = action_load_sbm2_par( &TC, queue_snd_id, time );
92 92 close_action( &TC, result, queue_snd_id );
93 93 break;
94 94 case TC_SUBTYPE_DUMP:
95 95 result = action_dump_par( &TC, queue_snd_id );
96 96 close_action( &TC, result, queue_snd_id );
97 97 break;
98 98 case TC_SUBTYPE_ENTER:
99 99 result = action_enter_mode( &TC, queue_snd_id );
100 100 close_action( &TC, result, queue_snd_id );
101 101 break;
102 102 case TC_SUBTYPE_UPDT_INFO:
103 103 result = action_update_info( &TC, queue_snd_id );
104 104 close_action( &TC, result, queue_snd_id );
105 105 break;
106 106 case TC_SUBTYPE_EN_CAL:
107 107 result = action_enable_calibration( &TC, queue_snd_id, time );
108 108 close_action( &TC, result, queue_snd_id );
109 109 break;
110 110 case TC_SUBTYPE_DIS_CAL:
111 111 result = action_disable_calibration( &TC, queue_snd_id, time );
112 112 close_action( &TC, result, queue_snd_id );
113 113 break;
114 114 case TC_SUBTYPE_LOAD_K:
115 115 result = action_load_kcoefficients( &TC, queue_snd_id, time );
116 116 close_action( &TC, result, queue_snd_id );
117 117 break;
118 118 case TC_SUBTYPE_DUMP_K:
119 119 result = action_dump_kcoefficients( &TC, queue_snd_id, time );
120 120 close_action( &TC, result, queue_snd_id );
121 121 break;
122 122 case TC_SUBTYPE_LOAD_FBINS:
123 123 result = action_load_fbins_mask( &TC, queue_snd_id, time );
124 124 close_action( &TC, result, queue_snd_id );
125 125 break;
126 126 case TC_SUBTYPE_UPDT_TIME:
127 127 result = action_update_time( &TC );
128 128 close_action( &TC, result, queue_snd_id );
129 129 break;
130 130 default:
131 131 break;
132 132 }
133 133 }
134 134 }
135 135 }
136 136
137 137 //***********
138 138 // TC ACTIONS
139 139
140 140 int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
141 141 {
142 142 /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received.
143 143 *
144 144 * @param TC points to the TeleCommand packet that is being processed
145 145 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
146 146 *
147 147 */
148 148
149 149 PRINTF("this is the end!!!\n")
150 150 exit(0);
151 151 send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time );
152 152 return LFR_DEFAULT;
153 153 }
154 154
155 155 int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id )
156 156 {
157 157 /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received.
158 158 *
159 159 * @param TC points to the TeleCommand packet that is being processed
160 160 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
161 161 *
162 162 */
163 163
164 164 rtems_status_code status;
165 165 unsigned char requestedMode;
166 166 unsigned int *transitionCoarseTime_ptr;
167 167 unsigned int transitionCoarseTime;
168 168 unsigned char * bytePosPtr;
169 169
170 170 bytePosPtr = (unsigned char *) &TC->packetID;
171 171
172 172 requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ];
173 173 transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] );
174 174 transitionCoarseTime = (*transitionCoarseTime_ptr) & 0x7fffffff;
175 175
176 176 status = check_mode_value( requestedMode );
177 177
178 178 if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent
179 179 {
180 180 send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode );
181 181 }
182 182
183 183 else // the mode value is valid, check the transition
184 184 {
185 185 status = check_mode_transition(requestedMode);
186 186 if (status != LFR_SUCCESSFUL)
187 187 {
188 188 PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n")
189 189 send_tm_lfr_tc_exe_not_executable( TC, queue_id );
190 190 }
191 191 }
192 192
193 193 if ( status == LFR_SUCCESSFUL ) // the transition is valid, check the date
194 194 {
195 195 status = check_transition_date( transitionCoarseTime );
196 196 if (status != LFR_SUCCESSFUL)
197 197 {
198 198 PRINTF("ERR *** in action_enter_mode *** check_transition_date\n")
199 199 send_tm_lfr_tc_exe_inconsistent( TC, queue_id,
200 200 BYTE_POS_CP_LFR_ENTER_MODE_TIME,
201 201 bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME + 3 ] );
202 202 }
203 203 }
204 204
205 205 if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode
206 206 {
207 207 PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode);
208 208
209 209 update_last_valid_transition_date( transitionCoarseTime );
210 210
211 211 switch(requestedMode)
212 212 {
213 213 case LFR_MODE_STANDBY:
214 214 status = enter_mode_standby();
215 215 break;
216 216 case LFR_MODE_NORMAL:
217 217 status = enter_mode_normal( transitionCoarseTime );
218 218 break;
219 219 case LFR_MODE_BURST:
220 220 status = enter_mode_burst( transitionCoarseTime );
221 221 break;
222 222 case LFR_MODE_SBM1:
223 223 status = enter_mode_sbm1( transitionCoarseTime );
224 224 break;
225 225 case LFR_MODE_SBM2:
226 226 status = enter_mode_sbm2( transitionCoarseTime );
227 227 break;
228 228 default:
229 229 break;
230 230 }
231 231 }
232 232
233 233 return status;
234 234 }
235 235
236 236 int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id)
237 237 {
238 238 /** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received.
239 239 *
240 240 * @param TC points to the TeleCommand packet that is being processed
241 241 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
242 242 *
243 243 * @return LFR directive status code:
244 244 * - LFR_DEFAULT
245 245 * - LFR_SUCCESSFUL
246 246 *
247 247 */
248 248
249 249 unsigned int val;
250 250 int result;
251 251 unsigned int status;
252 252 unsigned char mode;
253 253 unsigned char * bytePosPtr;
254 254
255 255 bytePosPtr = (unsigned char *) &TC->packetID;
256 256
257 257 // check LFR mode
258 258 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & 0x1e) >> 1;
259 259 status = check_update_info_hk_lfr_mode( mode );
260 260 if (status == LFR_SUCCESSFUL) // check TDS mode
261 261 {
262 262 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0xf0) >> 4;
263 263 status = check_update_info_hk_tds_mode( mode );
264 264 }
265 265 if (status == LFR_SUCCESSFUL) // check THR mode
266 266 {
267 267 mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0x0f);
268 268 status = check_update_info_hk_thr_mode( mode );
269 269 }
270 270 if (status == LFR_SUCCESSFUL) // if the parameter check is successful
271 271 {
272 272 val = housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * 256
273 273 + housekeeping_packet.hk_lfr_update_info_tc_cnt[1];
274 274 val++;
275 275 housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> 8);
276 276 housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val);
277 277 }
278 278
279 279 // pa_bia_status_info
280 280 // => pa_bia_mode_mux_set 3 bits
281 281 // => pa_bia_mode_hv_enabled 1 bit
282 282 // => pa_bia_mode_bias1_enabled 1 bit
283 283 // => pa_bia_mode_bias2_enabled 1 bit
284 284 // => pa_bia_mode_bias3_enabled 1 bit
285 285 // => pa_bia_on_off (cp_dpu_bias_on_off)
286 286 pa_bia_status_info = bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET2 ] & 0xfe; // [1111 1110]
287 287 pa_bia_status_info = pa_bia_status_info
288 288 | (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET1 ] & 0x1);
289 289
290 290 result = status;
291 291
292 292 return result;
293 293 }
294 294
295 295 int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
296 296 {
297 297 /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received.
298 298 *
299 299 * @param TC points to the TeleCommand packet that is being processed
300 300 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
301 301 *
302 302 */
303 303
304 304 int result;
305 305
306 306 result = LFR_DEFAULT;
307 307
308 308 setCalibration( true );
309 309
310 310 result = LFR_SUCCESSFUL;
311 311
312 312 return result;
313 313 }
314 314
315 315 int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time)
316 316 {
317 317 /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received.
318 318 *
319 319 * @param TC points to the TeleCommand packet that is being processed
320 320 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
321 321 *
322 322 */
323 323
324 324 int result;
325 325
326 326 result = LFR_DEFAULT;
327 327
328 328 setCalibration( false );
329 329
330 330 result = LFR_SUCCESSFUL;
331 331
332 332 return result;
333 333 }
334 334
335 335 int action_update_time(ccsdsTelecommandPacket_t *TC)
336 336 {
337 337 /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received.
338 338 *
339 339 * @param TC points to the TeleCommand packet that is being processed
340 340 * @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver
341 341 *
342 342 * @return LFR_SUCCESSFUL
343 343 *
344 344 */
345 345
346 346 unsigned int val;
347 347
348 348 time_management_regs->coarse_time_load = (TC->dataAndCRC[0] << 24)
349 349 + (TC->dataAndCRC[1] << 16)
350 350 + (TC->dataAndCRC[2] << 8)
351 351 + TC->dataAndCRC[3];
352 352
353 353 val = housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * 256
354 354 + housekeeping_packet.hk_lfr_update_time_tc_cnt[1];
355 355 val++;
356 356 housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> 8);
357 357 housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val);
358 358
359 359 return LFR_SUCCESSFUL;
360 360 }
361 361
362 362 //*******************
363 363 // ENTERING THE MODES
364 364 int check_mode_value( unsigned char requestedMode )
365 365 {
366 366 int status;
367 367
368 368 if ( (requestedMode != LFR_MODE_STANDBY)
369 369 && (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST)
370 370 && (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) )
371 371 {
372 372 status = LFR_DEFAULT;
373 373 }
374 374 else
375 375 {
376 376 status = LFR_SUCCESSFUL;
377 377 }
378 378
379 379 return status;
380 380 }
381 381
382 382 int check_mode_transition( unsigned char requestedMode )
383 383 {
384 384 /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE.
385 385 *
386 386 * @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE
387 387 *
388 388 * @return LFR directive status codes:
389 389 * - LFR_SUCCESSFUL - the transition is authorized
390 390 * - LFR_DEFAULT - the transition is not authorized
391 391 *
392 392 */
393 393
394 394 int status;
395 395
396 396 switch (requestedMode)
397 397 {
398 398 case LFR_MODE_STANDBY:
399 399 if ( lfrCurrentMode == LFR_MODE_STANDBY ) {
400 400 status = LFR_DEFAULT;
401 401 }
402 402 else
403 403 {
404 404 status = LFR_SUCCESSFUL;
405 405 }
406 406 break;
407 407 case LFR_MODE_NORMAL:
408 408 if ( lfrCurrentMode == LFR_MODE_NORMAL ) {
409 409 status = LFR_DEFAULT;
410 410 }
411 411 else {
412 412 status = LFR_SUCCESSFUL;
413 413 }
414 414 break;
415 415 case LFR_MODE_BURST:
416 416 if ( lfrCurrentMode == LFR_MODE_BURST ) {
417 417 status = LFR_DEFAULT;
418 418 }
419 419 else {
420 420 status = LFR_SUCCESSFUL;
421 421 }
422 422 break;
423 423 case LFR_MODE_SBM1:
424 424 if ( lfrCurrentMode == LFR_MODE_SBM1 ) {
425 425 status = LFR_DEFAULT;
426 426 }
427 427 else {
428 428 status = LFR_SUCCESSFUL;
429 429 }
430 430 break;
431 431 case LFR_MODE_SBM2:
432 432 if ( lfrCurrentMode == LFR_MODE_SBM2 ) {
433 433 status = LFR_DEFAULT;
434 434 }
435 435 else {
436 436 status = LFR_SUCCESSFUL;
437 437 }
438 438 break;
439 439 default:
440 440 status = LFR_DEFAULT;
441 441 break;
442 442 }
443 443
444 444 return status;
445 445 }
446 446
447 447 void update_last_valid_transition_date( unsigned int transitionCoarseTime )
448 448 {
449 449 lastValidEnterModeTime = transitionCoarseTime;
450 PRINTF1("lastValidEnterModeTime = %x\n", transitionCoarseTime);
450 451 }
451 452
452 453 int check_transition_date( unsigned int transitionCoarseTime )
453 454 {
454 455 int status;
455 456 unsigned int localCoarseTime;
456 457 unsigned int deltaCoarseTime;
457 458
458 459 status = LFR_SUCCESSFUL;
459 460
460 461 if (transitionCoarseTime == 0) // transition time = 0 means an instant transition
461 462 {
462 463 status = LFR_SUCCESSFUL;
463 464 }
464 465 else
465 466 {
466 467 localCoarseTime = time_management_regs->coarse_time & 0x7fffffff;
467 468
468 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime)
469 PRINTF2("localTime = %x, transitionTime = %x\n", localCoarseTime, transitionCoarseTime);
469 470
470 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
471 if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322
471 472 {
472 473 status = LFR_DEFAULT;
473 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n")
474 PRINTF("ERR *** in check_transition_date *** transitionCoarseTime <= localCoarseTime\n");
474 475 }
475 476
476 477 if (status == LFR_SUCCESSFUL)
477 478 {
478 479 deltaCoarseTime = transitionCoarseTime - localCoarseTime;
479 480 if ( deltaCoarseTime > 3 ) // SSS-CP-EQS-323
480 481 {
481 482 status = LFR_DEFAULT;
482 483 PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime)
483 484 }
484 485 }
485 486 }
486 487
487 488 return status;
488 489 }
489 490
490 491 int restart_asm_activities( unsigned char lfrRequestedMode )
491 492 {
492 493 rtems_status_code status;
493 494
494 495 status = stop_spectral_matrices();
495 496
496 497 status = restart_asm_tasks( lfrRequestedMode );
497 498
498 499 launch_spectral_matrix();
499 500
500 501 return status;
501 502 }
502 503
503 504 int stop_spectral_matrices( void )
504 505 {
505 506 /** This function stops and restarts the current mode average spectral matrices activities.
506 507 *
507 508 * @return RTEMS directive status codes:
508 509 * - RTEMS_SUCCESSFUL - task restarted successfully
509 510 * - RTEMS_INVALID_ID - task id invalid
510 511 * - RTEMS_ALREADY_SUSPENDED - task already suspended
511 512 *
512 513 */
513 514
514 515 rtems_status_code status;
515 516
516 517 status = RTEMS_SUCCESSFUL;
517 518
518 519 // (1) mask interruptions
519 520 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
520 521
521 522 // (2) reset spectral matrices registers
522 523 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
523 524 reset_sm_status();
524 525
525 526 // (3) clear interruptions
526 527 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
527 528
528 529 // suspend several tasks
529 530 if (lfrCurrentMode != LFR_MODE_STANDBY) {
530 531 status = suspend_asm_tasks();
531 532 }
532 533
533 534 if (status != RTEMS_SUCCESSFUL)
534 535 {
535 536 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
536 537 }
537 538
538 539 return status;
539 540 }
540 541
541 542 int stop_current_mode( void )
542 543 {
543 544 /** This function stops the current mode by masking interrupt lines and suspending science tasks.
544 545 *
545 546 * @return RTEMS directive status codes:
546 547 * - RTEMS_SUCCESSFUL - task restarted successfully
547 548 * - RTEMS_INVALID_ID - task id invalid
548 549 * - RTEMS_ALREADY_SUSPENDED - task already suspended
549 550 *
550 551 */
551 552
552 553 rtems_status_code status;
553 554
554 555 status = RTEMS_SUCCESSFUL;
555 556
556 557 // (1) mask interruptions
557 558 LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt
558 559 LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
559 560
560 561 // (2) reset waveform picker registers
561 562 reset_wfp_burst_enable(); // reset burst and enable bits
562 563 reset_wfp_status(); // reset all the status bits
563 564
564 565 // (3) reset spectral matrices registers
565 566 set_sm_irq_onNewMatrix( 0 ); // stop the spectral matrices
566 567 reset_sm_status();
567 568
568 569 // reset lfr VHDL module
569 570 reset_lfr();
570 571
571 572 reset_extractSWF(); // reset the extractSWF flag to false
572 573
573 574 // (4) clear interruptions
574 575 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt
575 576 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt
576 577
577 578 // suspend several tasks
578 579 if (lfrCurrentMode != LFR_MODE_STANDBY) {
579 580 status = suspend_science_tasks();
580 581 }
581 582
582 583 if (status != RTEMS_SUCCESSFUL)
583 584 {
584 585 PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status)
585 586 }
586 587
587 588 return status;
588 589 }
589 590
590 591 int enter_mode_standby()
591 592 {
592 593 /** This function is used to put LFR in the STANDBY mode.
593 594 *
594 595 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
595 596 *
596 597 * @return RTEMS directive status codes:
597 598 * - RTEMS_SUCCESSFUL - task restarted successfully
598 599 * - RTEMS_INVALID_ID - task id invalid
599 600 * - RTEMS_INCORRECT_STATE - task never started
600 601 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
601 602 *
602 603 * The STANDBY mode does not depends on a specific transition date, the effect of the TC_LFR_ENTER_MODE
603 604 * is immediate.
604 605 *
605 606 */
606 607
607 608 int status;
608 609
609 610 status = stop_current_mode(); // STOP THE CURRENT MODE
610 611
611 612 #ifdef PRINT_TASK_STATISTICS
612 613 rtems_cpu_usage_report();
613 614 #endif
614 615
615 616 #ifdef PRINT_STACK_REPORT
616 617 PRINTF("stack report selected\n")
617 618 rtems_stack_checker_report_usage();
618 619 #endif
619 620
620 621 return status;
621 622 }
622 623
623 624 int enter_mode_normal( unsigned int transitionCoarseTime )
624 625 {
625 626 /** This function is used to start the NORMAL mode.
626 627 *
627 628 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
628 629 *
629 630 * @return RTEMS directive status codes:
630 631 * - RTEMS_SUCCESSFUL - task restarted successfully
631 632 * - RTEMS_INVALID_ID - task id invalid
632 633 * - RTEMS_INCORRECT_STATE - task never started
633 634 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
634 635 *
635 636 * The way the NORMAL mode is started depends on the LFR current mode. If LFR is in SBM1 or SBM2,
636 637 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected.
637 638 *
638 639 */
639 640
640 641 int status;
641 642
642 643 #ifdef PRINT_TASK_STATISTICS
643 644 rtems_cpu_usage_reset();
644 645 #endif
645 646
646 647 status = RTEMS_UNSATISFIED;
647 648
648 649 switch( lfrCurrentMode )
649 650 {
650 651 case LFR_MODE_STANDBY:
651 652 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart science tasks
652 653 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
653 654 {
654 655 launch_spectral_matrix( );
655 656 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
656 657 }
657 658 break;
658 659 case LFR_MODE_BURST:
659 660 status = stop_current_mode(); // stop the current mode
660 661 status = restart_science_tasks( LFR_MODE_NORMAL ); // restart the science tasks
661 662 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
662 663 {
663 664 launch_spectral_matrix( );
664 665 launch_waveform_picker( LFR_MODE_NORMAL, transitionCoarseTime );
665 666 }
666 667 break;
667 668 case LFR_MODE_SBM1:
668 669 restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
669 670 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
670 671 break;
671 672 case LFR_MODE_SBM2:
672 673 restart_asm_activities( LFR_MODE_NORMAL ); // this is necessary to restart ASM tasks to update the parameters
673 674 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
674 675 break;
675 676 default:
676 677 break;
677 678 }
678 679
679 680 if (status != RTEMS_SUCCESSFUL)
680 681 {
681 682 PRINTF1("ERR *** in enter_mode_normal *** status = %d\n", status)
682 683 status = RTEMS_UNSATISFIED;
683 684 }
684 685
685 686 return status;
686 687 }
687 688
688 689 int enter_mode_burst( unsigned int transitionCoarseTime )
689 690 {
690 691 /** This function is used to start the BURST mode.
691 692 *
692 693 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
693 694 *
694 695 * @return RTEMS directive status codes:
695 696 * - RTEMS_SUCCESSFUL - task restarted successfully
696 697 * - RTEMS_INVALID_ID - task id invalid
697 698 * - RTEMS_INCORRECT_STATE - task never started
698 699 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
699 700 *
700 701 * The way the BURST mode is started does not depend on the LFR current mode.
701 702 *
702 703 */
703 704
704 705
705 706 int status;
706 707
707 708 #ifdef PRINT_TASK_STATISTICS
708 709 rtems_cpu_usage_reset();
709 710 #endif
710 711
711 712 status = stop_current_mode(); // stop the current mode
712 713 status = restart_science_tasks( LFR_MODE_BURST ); // restart the science tasks
713 714 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
714 715 {
715 716 launch_spectral_matrix( );
716 717 launch_waveform_picker( LFR_MODE_BURST, transitionCoarseTime );
717 718 }
718 719
719 720 if (status != RTEMS_SUCCESSFUL)
720 721 {
721 722 PRINTF1("ERR *** in enter_mode_burst *** status = %d\n", status)
722 723 status = RTEMS_UNSATISFIED;
723 724 }
724 725
725 726 return status;
726 727 }
727 728
728 729 int enter_mode_sbm1( unsigned int transitionCoarseTime )
729 730 {
730 731 /** This function is used to start the SBM1 mode.
731 732 *
732 733 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
733 734 *
734 735 * @return RTEMS directive status codes:
735 736 * - RTEMS_SUCCESSFUL - task restarted successfully
736 737 * - RTEMS_INVALID_ID - task id invalid
737 738 * - RTEMS_INCORRECT_STATE - task never started
738 739 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
739 740 *
740 741 * The way the SBM1 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM2,
741 742 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
742 743 * cases, the acquisition is completely restarted.
743 744 *
744 745 */
745 746
746 747 int status;
747 748
748 749 #ifdef PRINT_TASK_STATISTICS
749 750 rtems_cpu_usage_reset();
750 751 #endif
751 752
752 753 status = RTEMS_UNSATISFIED;
753 754
754 755 switch( lfrCurrentMode )
755 756 {
756 757 case LFR_MODE_STANDBY:
757 758 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart science tasks
758 759 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
759 760 {
760 761 launch_spectral_matrix( );
761 762 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
762 763 }
763 764 break;
764 765 case LFR_MODE_NORMAL: // lfrCurrentMode will be updated after the execution of close_action
765 766 restart_asm_activities( LFR_MODE_SBM1 );
766 767 status = LFR_SUCCESSFUL;
767 768 break;
768 769 case LFR_MODE_BURST:
769 770 status = stop_current_mode(); // stop the current mode
770 771 status = restart_science_tasks( LFR_MODE_SBM1 ); // restart the science tasks
771 772 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
772 773 {
773 774 launch_spectral_matrix( );
774 775 launch_waveform_picker( LFR_MODE_SBM1, transitionCoarseTime );
775 776 }
776 777 break;
777 778 case LFR_MODE_SBM2:
778 779 restart_asm_activities( LFR_MODE_SBM1 );
779 780 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
780 781 break;
781 782 default:
782 783 break;
783 784 }
784 785
785 786 if (status != RTEMS_SUCCESSFUL)
786 787 {
787 788 PRINTF1("ERR *** in enter_mode_sbm1 *** status = %d\n", status)
788 789 status = RTEMS_UNSATISFIED;
789 790 }
790 791
791 792 return status;
792 793 }
793 794
794 795 int enter_mode_sbm2( unsigned int transitionCoarseTime )
795 796 {
796 797 /** This function is used to start the SBM2 mode.
797 798 *
798 799 * @param transitionCoarseTime is the requested transition time contained in the TC_LFR_ENTER_MODE
799 800 *
800 801 * @return RTEMS directive status codes:
801 802 * - RTEMS_SUCCESSFUL - task restarted successfully
802 803 * - RTEMS_INVALID_ID - task id invalid
803 804 * - RTEMS_INCORRECT_STATE - task never started
804 805 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
805 806 *
806 807 * The way the SBM2 mode is started depends on the LFR current mode. If LFR is in NORMAL or SBM1,
807 808 * the snapshots are not restarted, only ASM, BP and CWF data generation are affected. In other
808 809 * cases, the acquisition is completely restarted.
809 810 *
810 811 */
811 812
812 813 int status;
813 814
814 815 #ifdef PRINT_TASK_STATISTICS
815 816 rtems_cpu_usage_reset();
816 817 #endif
817 818
818 819 status = RTEMS_UNSATISFIED;
819 820
820 821 switch( lfrCurrentMode )
821 822 {
822 823 case LFR_MODE_STANDBY:
823 824 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart science tasks
824 825 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
825 826 {
826 827 launch_spectral_matrix( );
827 828 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
828 829 }
829 830 break;
830 831 case LFR_MODE_NORMAL:
831 832 restart_asm_activities( LFR_MODE_SBM2 );
832 833 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
833 834 break;
834 835 case LFR_MODE_BURST:
835 836 status = stop_current_mode(); // stop the current mode
836 837 status = restart_science_tasks( LFR_MODE_SBM2 ); // restart the science tasks
837 838 if (status == RTEMS_SUCCESSFUL) // relaunch spectral_matrix and waveform_picker modules
838 839 {
839 840 launch_spectral_matrix( );
840 841 launch_waveform_picker( LFR_MODE_SBM2, transitionCoarseTime );
841 842 }
842 843 break;
843 844 case LFR_MODE_SBM1:
844 845 restart_asm_activities( LFR_MODE_SBM2 );
845 846 status = LFR_SUCCESSFUL; // lfrCurrentMode will be updated after the execution of close_action
846 847 break;
847 848 default:
848 849 break;
849 850 }
850 851
851 852 if (status != RTEMS_SUCCESSFUL)
852 853 {
853 854 PRINTF1("ERR *** in enter_mode_sbm2 *** status = %d\n", status)
854 855 status = RTEMS_UNSATISFIED;
855 856 }
856 857
857 858 return status;
858 859 }
859 860
860 861 int restart_science_tasks( unsigned char lfrRequestedMode )
861 862 {
862 863 /** This function is used to restart all science tasks.
863 864 *
864 865 * @return RTEMS directive status codes:
865 866 * - RTEMS_SUCCESSFUL - task restarted successfully
866 867 * - RTEMS_INVALID_ID - task id invalid
867 868 * - RTEMS_INCORRECT_STATE - task never started
868 869 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
869 870 *
870 871 * Science tasks are AVF0, PRC0, WFRM, CWF3, CW2, CWF1
871 872 *
872 873 */
873 874
874 875 rtems_status_code status[10];
875 876 rtems_status_code ret;
876 877
877 878 ret = RTEMS_SUCCESSFUL;
878 879
879 880 status[0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
880 881 if (status[0] != RTEMS_SUCCESSFUL)
881 882 {
882 883 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[0])
883 884 }
884 885
885 886 status[1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
886 887 if (status[1] != RTEMS_SUCCESSFUL)
887 888 {
888 889 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[1])
889 890 }
890 891
891 892 status[2] = rtems_task_restart( Task_id[TASKID_WFRM],1 );
892 893 if (status[2] != RTEMS_SUCCESSFUL)
893 894 {
894 895 PRINTF1("in restart_science_task *** WFRM ERR %d\n", status[2])
895 896 }
896 897
897 898 status[3] = rtems_task_restart( Task_id[TASKID_CWF3],1 );
898 899 if (status[3] != RTEMS_SUCCESSFUL)
899 900 {
900 901 PRINTF1("in restart_science_task *** CWF3 ERR %d\n", status[3])
901 902 }
902 903
903 904 status[4] = rtems_task_restart( Task_id[TASKID_CWF2],1 );
904 905 if (status[4] != RTEMS_SUCCESSFUL)
905 906 {
906 907 PRINTF1("in restart_science_task *** CWF2 ERR %d\n", status[4])
907 908 }
908 909
909 910 status[5] = rtems_task_restart( Task_id[TASKID_CWF1],1 );
910 911 if (status[5] != RTEMS_SUCCESSFUL)
911 912 {
912 913 PRINTF1("in restart_science_task *** CWF1 ERR %d\n", status[5])
913 914 }
914 915
915 916 status[6] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
916 917 if (status[6] != RTEMS_SUCCESSFUL)
917 918 {
918 919 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[6])
919 920 }
920 921
921 922 status[7] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
922 923 if (status[7] != RTEMS_SUCCESSFUL)
923 924 {
924 925 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[7])
925 926 }
926 927
927 928 status[8] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
928 929 if (status[8] != RTEMS_SUCCESSFUL)
929 930 {
930 931 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[8])
931 932 }
932 933
933 934 status[9] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
934 935 if (status[9] != RTEMS_SUCCESSFUL)
935 936 {
936 937 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[9])
937 938 }
938 939
939 940 if ( (status[0] != RTEMS_SUCCESSFUL) || (status[1] != RTEMS_SUCCESSFUL) ||
940 941 (status[2] != RTEMS_SUCCESSFUL) || (status[3] != RTEMS_SUCCESSFUL) ||
941 942 (status[4] != RTEMS_SUCCESSFUL) || (status[5] != RTEMS_SUCCESSFUL) ||
942 943 (status[6] != RTEMS_SUCCESSFUL) || (status[7] != RTEMS_SUCCESSFUL) ||
943 944 (status[8] != RTEMS_SUCCESSFUL) || (status[9] != RTEMS_SUCCESSFUL) )
944 945 {
945 946 ret = RTEMS_UNSATISFIED;
946 947 }
947 948
948 949 return ret;
949 950 }
950 951
951 952 int restart_asm_tasks( unsigned char lfrRequestedMode )
952 953 {
953 954 /** This function is used to restart average spectral matrices tasks.
954 955 *
955 956 * @return RTEMS directive status codes:
956 957 * - RTEMS_SUCCESSFUL - task restarted successfully
957 958 * - RTEMS_INVALID_ID - task id invalid
958 959 * - RTEMS_INCORRECT_STATE - task never started
959 960 * - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot restart remote task
960 961 *
961 962 * ASM tasks are AVF0, PRC0, AVF1, PRC1, AVF2 and PRC2
962 963 *
963 964 */
964 965
965 966 rtems_status_code status[6];
966 967 rtems_status_code ret;
967 968
968 969 ret = RTEMS_SUCCESSFUL;
969 970
970 971 status[0] = rtems_task_restart( Task_id[TASKID_AVF0], lfrRequestedMode );
971 972 if (status[0] != RTEMS_SUCCESSFUL)
972 973 {
973 974 PRINTF1("in restart_science_task *** AVF0 ERR %d\n", status[0])
974 975 }
975 976
976 977 status[1] = rtems_task_restart( Task_id[TASKID_PRC0], lfrRequestedMode );
977 978 if (status[1] != RTEMS_SUCCESSFUL)
978 979 {
979 980 PRINTF1("in restart_science_task *** PRC0 ERR %d\n", status[1])
980 981 }
981 982
982 983 status[2] = rtems_task_restart( Task_id[TASKID_AVF1], lfrRequestedMode );
983 984 if (status[2] != RTEMS_SUCCESSFUL)
984 985 {
985 986 PRINTF1("in restart_science_task *** AVF1 ERR %d\n", status[2])
986 987 }
987 988
988 989 status[3] = rtems_task_restart( Task_id[TASKID_PRC1],lfrRequestedMode );
989 990 if (status[3] != RTEMS_SUCCESSFUL)
990 991 {
991 992 PRINTF1("in restart_science_task *** PRC1 ERR %d\n", status[3])
992 993 }
993 994
994 995 status[4] = rtems_task_restart( Task_id[TASKID_AVF2], 1 );
995 996 if (status[4] != RTEMS_SUCCESSFUL)
996 997 {
997 998 PRINTF1("in restart_science_task *** AVF2 ERR %d\n", status[4])
998 999 }
999 1000
1000 1001 status[5] = rtems_task_restart( Task_id[TASKID_PRC2], 1 );
1001 1002 if (status[5] != RTEMS_SUCCESSFUL)
1002 1003 {
1003 1004 PRINTF1("in restart_science_task *** PRC2 ERR %d\n", status[5])
1004 1005 }
1005 1006
1006 1007 if ( (status[0] != RTEMS_SUCCESSFUL) || (status[1] != RTEMS_SUCCESSFUL) ||
1007 1008 (status[2] != RTEMS_SUCCESSFUL) || (status[3] != RTEMS_SUCCESSFUL) ||
1008 1009 (status[4] != RTEMS_SUCCESSFUL) || (status[5] != RTEMS_SUCCESSFUL) )
1009 1010 {
1010 1011 ret = RTEMS_UNSATISFIED;
1011 1012 }
1012 1013
1013 1014 return ret;
1014 1015 }
1015 1016
1016 1017 int suspend_science_tasks( void )
1017 1018 {
1018 1019 /** This function suspends the science tasks.
1019 1020 *
1020 1021 * @return RTEMS directive status codes:
1021 1022 * - RTEMS_SUCCESSFUL - task restarted successfully
1022 1023 * - RTEMS_INVALID_ID - task id invalid
1023 1024 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1024 1025 *
1025 1026 */
1026 1027
1027 1028 rtems_status_code status;
1028 1029
1029 1030 PRINTF("in suspend_science_tasks\n")
1030 1031
1031 1032 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1032 1033 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1033 1034 {
1034 1035 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1035 1036 }
1036 1037 else
1037 1038 {
1038 1039 status = RTEMS_SUCCESSFUL;
1039 1040 }
1040 1041 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1041 1042 {
1042 1043 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1043 1044 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1044 1045 {
1045 1046 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1046 1047 }
1047 1048 else
1048 1049 {
1049 1050 status = RTEMS_SUCCESSFUL;
1050 1051 }
1051 1052 }
1052 1053 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1053 1054 {
1054 1055 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1055 1056 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1056 1057 {
1057 1058 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1058 1059 }
1059 1060 else
1060 1061 {
1061 1062 status = RTEMS_SUCCESSFUL;
1062 1063 }
1063 1064 }
1064 1065 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1065 1066 {
1066 1067 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1067 1068 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1068 1069 {
1069 1070 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1070 1071 }
1071 1072 else
1072 1073 {
1073 1074 status = RTEMS_SUCCESSFUL;
1074 1075 }
1075 1076 }
1076 1077 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1077 1078 {
1078 1079 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1079 1080 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1080 1081 {
1081 1082 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1082 1083 }
1083 1084 else
1084 1085 {
1085 1086 status = RTEMS_SUCCESSFUL;
1086 1087 }
1087 1088 }
1088 1089 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1089 1090 {
1090 1091 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1091 1092 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1092 1093 {
1093 1094 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1094 1095 }
1095 1096 else
1096 1097 {
1097 1098 status = RTEMS_SUCCESSFUL;
1098 1099 }
1099 1100 }
1100 1101 if (status == RTEMS_SUCCESSFUL) // suspend WFRM
1101 1102 {
1102 1103 status = rtems_task_suspend( Task_id[TASKID_WFRM] );
1103 1104 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1104 1105 {
1105 1106 PRINTF1("in suspend_science_task *** WFRM ERR %d\n", status)
1106 1107 }
1107 1108 else
1108 1109 {
1109 1110 status = RTEMS_SUCCESSFUL;
1110 1111 }
1111 1112 }
1112 1113 if (status == RTEMS_SUCCESSFUL) // suspend CWF3
1113 1114 {
1114 1115 status = rtems_task_suspend( Task_id[TASKID_CWF3] );
1115 1116 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1116 1117 {
1117 1118 PRINTF1("in suspend_science_task *** CWF3 ERR %d\n", status)
1118 1119 }
1119 1120 else
1120 1121 {
1121 1122 status = RTEMS_SUCCESSFUL;
1122 1123 }
1123 1124 }
1124 1125 if (status == RTEMS_SUCCESSFUL) // suspend CWF2
1125 1126 {
1126 1127 status = rtems_task_suspend( Task_id[TASKID_CWF2] );
1127 1128 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1128 1129 {
1129 1130 PRINTF1("in suspend_science_task *** CWF2 ERR %d\n", status)
1130 1131 }
1131 1132 else
1132 1133 {
1133 1134 status = RTEMS_SUCCESSFUL;
1134 1135 }
1135 1136 }
1136 1137 if (status == RTEMS_SUCCESSFUL) // suspend CWF1
1137 1138 {
1138 1139 status = rtems_task_suspend( Task_id[TASKID_CWF1] );
1139 1140 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1140 1141 {
1141 1142 PRINTF1("in suspend_science_task *** CWF1 ERR %d\n", status)
1142 1143 }
1143 1144 else
1144 1145 {
1145 1146 status = RTEMS_SUCCESSFUL;
1146 1147 }
1147 1148 }
1148 1149
1149 1150 return status;
1150 1151 }
1151 1152
1152 1153 int suspend_asm_tasks( void )
1153 1154 {
1154 1155 /** This function suspends the science tasks.
1155 1156 *
1156 1157 * @return RTEMS directive status codes:
1157 1158 * - RTEMS_SUCCESSFUL - task restarted successfully
1158 1159 * - RTEMS_INVALID_ID - task id invalid
1159 1160 * - RTEMS_ALREADY_SUSPENDED - task already suspended
1160 1161 *
1161 1162 */
1162 1163
1163 1164 rtems_status_code status;
1164 1165
1165 1166 PRINTF("in suspend_science_tasks\n")
1166 1167
1167 1168 status = rtems_task_suspend( Task_id[TASKID_AVF0] ); // suspend AVF0
1168 1169 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1169 1170 {
1170 1171 PRINTF1("in suspend_science_task *** AVF0 ERR %d\n", status)
1171 1172 }
1172 1173 else
1173 1174 {
1174 1175 status = RTEMS_SUCCESSFUL;
1175 1176 }
1176 1177
1177 1178 if (status == RTEMS_SUCCESSFUL) // suspend PRC0
1178 1179 {
1179 1180 status = rtems_task_suspend( Task_id[TASKID_PRC0] );
1180 1181 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1181 1182 {
1182 1183 PRINTF1("in suspend_science_task *** PRC0 ERR %d\n", status)
1183 1184 }
1184 1185 else
1185 1186 {
1186 1187 status = RTEMS_SUCCESSFUL;
1187 1188 }
1188 1189 }
1189 1190
1190 1191 if (status == RTEMS_SUCCESSFUL) // suspend AVF1
1191 1192 {
1192 1193 status = rtems_task_suspend( Task_id[TASKID_AVF1] );
1193 1194 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1194 1195 {
1195 1196 PRINTF1("in suspend_science_task *** AVF1 ERR %d\n", status)
1196 1197 }
1197 1198 else
1198 1199 {
1199 1200 status = RTEMS_SUCCESSFUL;
1200 1201 }
1201 1202 }
1202 1203
1203 1204 if (status == RTEMS_SUCCESSFUL) // suspend PRC1
1204 1205 {
1205 1206 status = rtems_task_suspend( Task_id[TASKID_PRC1] );
1206 1207 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1207 1208 {
1208 1209 PRINTF1("in suspend_science_task *** PRC1 ERR %d\n", status)
1209 1210 }
1210 1211 else
1211 1212 {
1212 1213 status = RTEMS_SUCCESSFUL;
1213 1214 }
1214 1215 }
1215 1216
1216 1217 if (status == RTEMS_SUCCESSFUL) // suspend AVF2
1217 1218 {
1218 1219 status = rtems_task_suspend( Task_id[TASKID_AVF2] );
1219 1220 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1220 1221 {
1221 1222 PRINTF1("in suspend_science_task *** AVF2 ERR %d\n", status)
1222 1223 }
1223 1224 else
1224 1225 {
1225 1226 status = RTEMS_SUCCESSFUL;
1226 1227 }
1227 1228 }
1228 1229
1229 1230 if (status == RTEMS_SUCCESSFUL) // suspend PRC2
1230 1231 {
1231 1232 status = rtems_task_suspend( Task_id[TASKID_PRC2] );
1232 1233 if ((status != RTEMS_SUCCESSFUL) && (status != RTEMS_ALREADY_SUSPENDED))
1233 1234 {
1234 1235 PRINTF1("in suspend_science_task *** PRC2 ERR %d\n", status)
1235 1236 }
1236 1237 else
1237 1238 {
1238 1239 status = RTEMS_SUCCESSFUL;
1239 1240 }
1240 1241 }
1241 1242
1242 1243 return status;
1243 1244 }
1244 1245
1245 1246 void launch_waveform_picker( unsigned char mode, unsigned int transitionCoarseTime )
1246 1247 {
1247 1248 WFP_reset_current_ring_nodes();
1248 1249
1249 1250 reset_waveform_picker_regs();
1250 1251
1251 1252 set_wfp_burst_enable_register( mode );
1252 1253
1253 1254 LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER );
1254 1255 LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER );
1255 1256
1256 1257 if (transitionCoarseTime == 0)
1257 1258 {
1258 1259 // instant transition means transition on the next valid date
1259 1260 // this is mandatory to have a good snapshot period a a good correction of the snapshot period
1260 1261 waveform_picker_regs->start_date = time_management_regs->coarse_time + 1;
1261 1262 }
1262 1263 else
1263 1264 {
1264 1265 waveform_picker_regs->start_date = transitionCoarseTime;
1265 1266 }
1266 1267
1267 1268 }
1268 1269
1269 1270 void launch_spectral_matrix( void )
1270 1271 {
1271 1272 SM_reset_current_ring_nodes();
1272 1273
1273 1274 reset_spectral_matrix_regs();
1274 1275
1275 1276 reset_nb_sm();
1276 1277
1277 1278 set_sm_irq_onNewMatrix( 1 );
1278 1279
1279 1280 LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX );
1280 1281 LEON_Unmask_interrupt( IRQ_SPECTRAL_MATRIX );
1281 1282
1282 1283 }
1283 1284
1284 1285 void set_sm_irq_onNewMatrix( unsigned char value )
1285 1286 {
1286 1287 if (value == 1)
1287 1288 {
1288 1289 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x01;
1289 1290 }
1290 1291 else
1291 1292 {
1292 1293 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffe; // 1110
1293 1294 }
1294 1295 }
1295 1296
1296 1297 void set_sm_irq_onError( unsigned char value )
1297 1298 {
1298 1299 if (value == 1)
1299 1300 {
1300 1301 spectral_matrix_regs->config = spectral_matrix_regs->config | 0x02;
1301 1302 }
1302 1303 else
1303 1304 {
1304 1305 spectral_matrix_regs->config = spectral_matrix_regs->config & 0xfffffffd; // 1101
1305 1306 }
1306 1307 }
1307 1308
1308 1309 //*****************************
1309 1310 // CONFIGURE CALIBRATION SIGNAL
1310 1311 void setCalibrationPrescaler( unsigned int prescaler )
1311 1312 {
1312 1313 // prescaling of the master clock (25 MHz)
1313 1314 // master clock is divided by 2^prescaler
1314 1315 time_management_regs->calPrescaler = prescaler;
1315 1316 }
1316 1317
1317 1318 void setCalibrationDivisor( unsigned int divisionFactor )
1318 1319 {
1319 1320 // division of the prescaled clock by the division factor
1320 1321 time_management_regs->calDivisor = divisionFactor;
1321 1322 }
1322 1323
1323 1324 void setCalibrationData( void ){
1324 1325 unsigned int k;
1325 1326 unsigned short data;
1326 1327 float val;
1327 1328 float f0;
1328 1329 float f1;
1329 1330 float fs;
1330 1331 float Ts;
1331 1332 float scaleFactor;
1332 1333
1333 1334 f0 = 625;
1334 1335 f1 = 10000;
1335 1336 fs = 160256.410;
1336 1337 Ts = 1. / fs;
1337 1338 scaleFactor = 0.250 / 0.000654; // 191, 500 mVpp, 2 sinus waves => 500 mVpp each, amplitude = 250 mV
1338 1339
1339 1340 time_management_regs->calDataPtr = 0x00;
1340 1341
1341 1342 // build the signal for the SCM calibration
1342 1343 for (k=0; k<256; k++)
1343 1344 {
1344 1345 val = sin( 2 * pi * f0 * k * Ts )
1345 1346 + sin( 2 * pi * f1 * k * Ts );
1346 1347 data = (unsigned short) ((val * scaleFactor) + 2048);
1347 1348 time_management_regs->calData = data & 0xfff;
1348 1349 }
1349 1350 }
1350 1351
1351 1352 void setCalibrationDataInterleaved( void ){
1352 1353 unsigned int k;
1353 1354 float val;
1354 1355 float f0;
1355 1356 float f1;
1356 1357 float fs;
1357 1358 float Ts;
1358 1359 unsigned short data[384];
1359 1360 unsigned char *dataPtr;
1360 1361
1361 1362 f0 = 625;
1362 1363 f1 = 10000;
1363 1364 fs = 240384.615;
1364 1365 Ts = 1. / fs;
1365 1366
1366 1367 time_management_regs->calDataPtr = 0x00;
1367 1368
1368 1369 // build the signal for the SCM calibration
1369 1370 for (k=0; k<384; k++)
1370 1371 {
1371 1372 val = sin( 2 * pi * f0 * k * Ts )
1372 1373 + sin( 2 * pi * f1 * k * Ts );
1373 1374 data[k] = (unsigned short) (val * 512 + 2048);
1374 1375 }
1375 1376
1376 1377 // write the signal in interleaved mode
1377 1378 for (k=0; k<128; k++)
1378 1379 {
1379 1380 dataPtr = (unsigned char*) &data[k*3 + 2];
1380 1381 time_management_regs->calData = (data[k*3] & 0xfff)
1381 1382 + ( (dataPtr[0] & 0x3f) << 12);
1382 1383 time_management_regs->calData = (data[k*3 + 1] & 0xfff)
1383 1384 + ( (dataPtr[1] & 0x3f) << 12);
1384 1385 }
1385 1386 }
1386 1387
1387 1388 void setCalibrationReload( bool state)
1388 1389 {
1389 1390 if (state == true)
1390 1391 {
1391 1392 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000010; // [0001 0000]
1392 1393 }
1393 1394 else
1394 1395 {
1395 1396 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffef; // [1110 1111]
1396 1397 }
1397 1398 }
1398 1399
1399 1400 void setCalibrationEnable( bool state )
1400 1401 {
1401 1402 // this bit drives the multiplexer
1402 1403 if (state == true)
1403 1404 {
1404 1405 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000040; // [0100 0000]
1405 1406 }
1406 1407 else
1407 1408 {
1408 1409 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffbf; // [1011 1111]
1409 1410 }
1410 1411 }
1411 1412
1412 1413 void setCalibrationInterleaved( bool state )
1413 1414 {
1414 1415 // this bit drives the multiplexer
1415 1416 if (state == true)
1416 1417 {
1417 1418 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl | 0x00000020; // [0010 0000]
1418 1419 }
1419 1420 else
1420 1421 {
1421 1422 time_management_regs->calDACCtrl = time_management_regs->calDACCtrl & 0xffffffdf; // [1101 1111]
1422 1423 }
1423 1424 }
1424 1425
1425 1426 void setCalibration( bool state )
1426 1427 {
1427 1428 if (state == true)
1428 1429 {
1429 1430 setCalibrationEnable( true );
1430 1431 setCalibrationReload( false );
1431 1432 set_hk_lfr_calib_enable( true );
1432 1433 }
1433 1434 else
1434 1435 {
1435 1436 setCalibrationEnable( false );
1436 1437 setCalibrationReload( true );
1437 1438 set_hk_lfr_calib_enable( false );
1438 1439 }
1439 1440 }
1440 1441
1441 1442 void configureCalibration( bool interleaved )
1442 1443 {
1443 1444 setCalibration( false );
1444 1445 if ( interleaved == true )
1445 1446 {
1446 1447 setCalibrationInterleaved( true );
1447 1448 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1448 1449 setCalibrationDivisor( 26 ); // => 240 384
1449 1450 setCalibrationDataInterleaved();
1450 1451 }
1451 1452 else
1452 1453 {
1453 1454 setCalibrationPrescaler( 0 ); // 25 MHz => 25 000 000
1454 1455 setCalibrationDivisor( 38 ); // => 160 256 (39 - 1)
1455 1456 setCalibrationData();
1456 1457 }
1457 1458 }
1458 1459
1459 1460 //****************
1460 1461 // CLOSING ACTIONS
1461 1462 void update_last_TC_exe( ccsdsTelecommandPacket_t *TC, unsigned char * time )
1462 1463 {
1463 1464 /** This function is used to update the HK packets statistics after a successful TC execution.
1464 1465 *
1465 1466 * @param TC points to the TC being processed
1466 1467 * @param time is the time used to date the TC execution
1467 1468 *
1468 1469 */
1469 1470
1470 1471 unsigned int val;
1471 1472
1472 1473 housekeeping_packet.hk_lfr_last_exe_tc_id[0] = TC->packetID[0];
1473 1474 housekeeping_packet.hk_lfr_last_exe_tc_id[1] = TC->packetID[1];
1474 1475 housekeeping_packet.hk_lfr_last_exe_tc_type[0] = 0x00;
1475 1476 housekeeping_packet.hk_lfr_last_exe_tc_type[1] = TC->serviceType;
1476 1477 housekeeping_packet.hk_lfr_last_exe_tc_subtype[0] = 0x00;
1477 1478 housekeeping_packet.hk_lfr_last_exe_tc_subtype[1] = TC->serviceSubType;
1478 1479 housekeeping_packet.hk_lfr_last_exe_tc_time[0] = time[0];
1479 1480 housekeeping_packet.hk_lfr_last_exe_tc_time[1] = time[1];
1480 1481 housekeeping_packet.hk_lfr_last_exe_tc_time[2] = time[2];
1481 1482 housekeeping_packet.hk_lfr_last_exe_tc_time[3] = time[3];
1482 1483 housekeeping_packet.hk_lfr_last_exe_tc_time[4] = time[4];
1483 1484 housekeeping_packet.hk_lfr_last_exe_tc_time[5] = time[5];
1484 1485
1485 1486 val = housekeeping_packet.hk_lfr_exe_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_exe_tc_cnt[1];
1486 1487 val++;
1487 1488 housekeeping_packet.hk_lfr_exe_tc_cnt[0] = (unsigned char) (val >> 8);
1488 1489 housekeeping_packet.hk_lfr_exe_tc_cnt[1] = (unsigned char) (val);
1489 1490 }
1490 1491
1491 1492 void update_last_TC_rej(ccsdsTelecommandPacket_t *TC, unsigned char * time )
1492 1493 {
1493 1494 /** This function is used to update the HK packets statistics after a TC rejection.
1494 1495 *
1495 1496 * @param TC points to the TC being processed
1496 1497 * @param time is the time used to date the TC rejection
1497 1498 *
1498 1499 */
1499 1500
1500 1501 unsigned int val;
1501 1502
1502 1503 housekeeping_packet.hk_lfr_last_rej_tc_id[0] = TC->packetID[0];
1503 1504 housekeeping_packet.hk_lfr_last_rej_tc_id[1] = TC->packetID[1];
1504 1505 housekeeping_packet.hk_lfr_last_rej_tc_type[0] = 0x00;
1505 1506 housekeeping_packet.hk_lfr_last_rej_tc_type[1] = TC->serviceType;
1506 1507 housekeeping_packet.hk_lfr_last_rej_tc_subtype[0] = 0x00;
1507 1508 housekeeping_packet.hk_lfr_last_rej_tc_subtype[1] = TC->serviceSubType;
1508 1509 housekeeping_packet.hk_lfr_last_rej_tc_time[0] = time[0];
1509 1510 housekeeping_packet.hk_lfr_last_rej_tc_time[1] = time[1];
1510 1511 housekeeping_packet.hk_lfr_last_rej_tc_time[2] = time[2];
1511 1512 housekeeping_packet.hk_lfr_last_rej_tc_time[3] = time[3];
1512 1513 housekeeping_packet.hk_lfr_last_rej_tc_time[4] = time[4];
1513 1514 housekeeping_packet.hk_lfr_last_rej_tc_time[5] = time[5];
1514 1515
1515 1516 val = housekeeping_packet.hk_lfr_rej_tc_cnt[0] * 256 + housekeeping_packet.hk_lfr_rej_tc_cnt[1];
1516 1517 val++;
1517 1518 housekeeping_packet.hk_lfr_rej_tc_cnt[0] = (unsigned char) (val >> 8);
1518 1519 housekeeping_packet.hk_lfr_rej_tc_cnt[1] = (unsigned char) (val);
1519 1520 }
1520 1521
1521 1522 void close_action(ccsdsTelecommandPacket_t *TC, int result, rtems_id queue_id )
1522 1523 {
1523 1524 /** This function is the last step of the TC execution workflow.
1524 1525 *
1525 1526 * @param TC points to the TC being processed
1526 1527 * @param result is the result of the TC execution (LFR_SUCCESSFUL / LFR_DEFAULT)
1527 1528 * @param queue_id is the id of the RTEMS message queue used to send TM packets
1528 1529 * @param time is the time used to date the TC execution
1529 1530 *
1530 1531 */
1531 1532
1532 1533 unsigned char requestedMode;
1533 1534
1534 1535 if (result == LFR_SUCCESSFUL)
1535 1536 {
1536 1537 if ( !( (TC->serviceType==TC_TYPE_TIME) & (TC->serviceSubType==TC_SUBTYPE_UPDT_TIME) )
1537 1538 &
1538 1539 !( (TC->serviceType==TC_TYPE_GEN) & (TC->serviceSubType==TC_SUBTYPE_UPDT_INFO))
1539 1540 )
1540 1541 {
1541 1542 send_tm_lfr_tc_exe_success( TC, queue_id );
1542 1543 }
1543 1544 if ( (TC->serviceType == TC_TYPE_GEN) & (TC->serviceSubType == TC_SUBTYPE_ENTER) )
1544 1545 {
1545 1546 //**********************************
1546 1547 // UPDATE THE LFRMODE LOCAL VARIABLE
1547 1548 requestedMode = TC->dataAndCRC[1];
1548 1549 housekeeping_packet.lfr_status_word[0] = (unsigned char) ((requestedMode << 4) + 0x0d);
1549 1550 updateLFRCurrentMode();
1550 1551 }
1551 1552 }
1552 1553 else if (result == LFR_EXE_ERROR)
1553 1554 {
1554 1555 send_tm_lfr_tc_exe_error( TC, queue_id );
1555 1556 }
1556 1557 }
1557 1558
1558 1559 //***************************
1559 1560 // Interrupt Service Routines
1560 1561 rtems_isr commutation_isr1( rtems_vector_number vector )
1561 1562 {
1562 1563 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1563 1564 PRINTF("In commutation_isr1 *** Error sending event to DUMB\n")
1564 1565 }
1565 1566 }
1566 1567
1567 1568 rtems_isr commutation_isr2( rtems_vector_number vector )
1568 1569 {
1569 1570 if (rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
1570 1571 PRINTF("In commutation_isr2 *** Error sending event to DUMB\n")
1571 1572 }
1572 1573 }
1573 1574
1574 1575 //****************
1575 1576 // OTHER FUNCTIONS
1576 1577 void updateLFRCurrentMode()
1577 1578 {
1578 1579 /** This function updates the value of the global variable lfrCurrentMode.
1579 1580 *
1580 1581 * lfrCurrentMode is a parameter used by several functions to know in which mode LFR is running.
1581 1582 *
1582 1583 */
1583 1584 // update the local value of lfrCurrentMode with the value contained in the housekeeping_packet structure
1584 1585 lfrCurrentMode = (housekeeping_packet.lfr_status_word[0] & 0xf0) >> 4;
1585 1586 }
1586 1587
1587 1588 void set_lfr_soft_reset( unsigned char value )
1588 1589 {
1589 1590 if (value == 1)
1590 1591 {
1591 1592 time_management_regs->ctrl = time_management_regs->ctrl | 0x00000004; // [0100]
1592 1593 }
1593 1594 else
1594 1595 {
1595 1596 time_management_regs->ctrl = time_management_regs->ctrl & 0xfffffffb; // [1011]
1596 1597 }
1597 1598 }
1598 1599
1599 1600 void reset_lfr( void )
1600 1601 {
1601 1602 set_lfr_soft_reset( 1 );
1602 1603
1603 1604 set_lfr_soft_reset( 0 );
1604 1605
1605 1606 set_hk_lfr_sc_potential_flag( true );
1606 1607 }
@@ -1,1196 +1,1214
1 1 /** Functions and tasks related to waveform packet generation.
2 2 *
3 3 * @file
4 4 * @author P. LEROY
5 5 *
6 6 * A group of functions to handle waveforms, in snapshot or continuous format.\n
7 7 *
8 8 */
9 9
10 10 #include "wf_handler.h"
11 11
12 12 //***************
13 13 // waveform rings
14 14 // F0
15 15 ring_node waveform_ring_f0[NB_RING_NODES_F0];
16 16 ring_node *current_ring_node_f0;
17 17 ring_node *ring_node_to_send_swf_f0;
18 18 // F1
19 19 ring_node waveform_ring_f1[NB_RING_NODES_F1];
20 20 ring_node *current_ring_node_f1;
21 21 ring_node *ring_node_to_send_swf_f1;
22 22 ring_node *ring_node_to_send_cwf_f1;
23 23 // F2
24 24 ring_node waveform_ring_f2[NB_RING_NODES_F2];
25 25 ring_node *current_ring_node_f2;
26 26 ring_node *ring_node_to_send_swf_f2;
27 27 ring_node *ring_node_to_send_cwf_f2;
28 28 // F3
29 29 ring_node waveform_ring_f3[NB_RING_NODES_F3];
30 30 ring_node *current_ring_node_f3;
31 31 ring_node *ring_node_to_send_cwf_f3;
32 32 char wf_cont_f3_light[ (NB_SAMPLES_PER_SNAPSHOT) * NB_BYTES_CWF3_LIGHT_BLK ];
33 33
34 34 bool extractSWF1 = false;
35 35 bool extractSWF2 = false;
36 36 bool swf0_ready_flag_f1 = false;
37 37 bool swf0_ready_flag_f2 = false;
38 38 bool swf1_ready = false;
39 39 bool swf2_ready = false;
40 40
41 41 int swf1_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
42 42 int swf2_extracted[ (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK) ];
43 43 ring_node ring_node_swf1_extracted;
44 44 ring_node ring_node_swf2_extracted;
45 45
46 46 //*********************
47 47 // Interrupt SubRoutine
48 48
49 49 ring_node * getRingNodeToSendCWF( unsigned char frequencyChannel)
50 50 {
51 51 ring_node *node;
52 52
53 53 node = NULL;
54 54 switch ( frequencyChannel ) {
55 55 case 1:
56 56 node = ring_node_to_send_cwf_f1;
57 57 break;
58 58 case 2:
59 59 node = ring_node_to_send_cwf_f2;
60 60 break;
61 61 case 3:
62 62 node = ring_node_to_send_cwf_f3;
63 63 break;
64 64 default:
65 65 break;
66 66 }
67 67
68 68 return node;
69 69 }
70 70
71 71 ring_node * getRingNodeToSendSWF( unsigned char frequencyChannel)
72 72 {
73 73 ring_node *node;
74 74
75 75 node = NULL;
76 76 switch ( frequencyChannel ) {
77 77 case 0:
78 78 node = ring_node_to_send_swf_f0;
79 79 break;
80 80 case 1:
81 81 node = ring_node_to_send_swf_f1;
82 82 break;
83 83 case 2:
84 84 node = ring_node_to_send_swf_f2;
85 85 break;
86 86 default:
87 87 break;
88 88 }
89 89
90 90 return node;
91 91 }
92 92
93 93 void reset_extractSWF( void )
94 94 {
95 95 extractSWF1 = false;
96 96 extractSWF2 = false;
97 97 swf0_ready_flag_f1 = false;
98 98 swf0_ready_flag_f2 = false;
99 99 swf1_ready = false;
100 100 swf2_ready = false;
101 101 }
102 102
103 103 inline void waveforms_isr_f3( void )
104 104 {
105 105 rtems_status_code spare_status;
106 106
107 107 if ( (lfrCurrentMode == LFR_MODE_NORMAL) || (lfrCurrentMode == LFR_MODE_BURST) // in BURST the data are used to place v, e1 and e2 in the HK packet
108 108 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode == LFR_MODE_SBM2) )
109 109 { // in modes other than STANDBY and BURST, send the CWF_F3 data
110 110 //***
111 111 // F3
112 112 if ( (waveform_picker_regs->status & 0xc0) != 0x00 ) { // [1100 0000] check the f3 full bits
113 113 ring_node_to_send_cwf_f3 = current_ring_node_f3->previous;
114 114 current_ring_node_f3 = current_ring_node_f3->next;
115 115 if ((waveform_picker_regs->status & 0x40) == 0x40){ // [0100 0000] f3 buffer 0 is full
116 116 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_0_coarse_time;
117 117 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_0_fine_time;
118 118 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->buffer_address;
119 119 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008840; // [1000 1000 0100 0000]
120 120 }
121 121 else if ((waveform_picker_regs->status & 0x80) == 0x80){ // [1000 0000] f3 buffer 1 is full
122 122 ring_node_to_send_cwf_f3->coarseTime = waveform_picker_regs->f3_1_coarse_time;
123 123 ring_node_to_send_cwf_f3->fineTime = waveform_picker_regs->f3_1_fine_time;
124 124 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address;
125 125 waveform_picker_regs->status = waveform_picker_regs->status & 0x00008880; // [1000 1000 1000 0000]
126 126 }
127 127 if (rtems_event_send( Task_id[TASKID_CWF3], RTEMS_EVENT_0 ) != RTEMS_SUCCESSFUL) {
128 128 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
129 129 }
130 130 }
131 131 }
132 132 }
133 133
134 134 inline void waveforms_isr_burst( void )
135 135 {
136 136 unsigned char status;
137 137 rtems_status_code spare_status;
138 138
139 139 status = (waveform_picker_regs->status & 0x30) >> 4; // [0011 0000] get the status bits for f2
140 140
141 141
142 142 switch(status)
143 143 {
144 144 case 1:
145 145 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
146 146 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
147 147 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
148 148 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
149 149 current_ring_node_f2 = current_ring_node_f2->next;
150 150 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
151 151 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
152 152 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
153 153 }
154 154 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
155 155 break;
156 156 case 2:
157 157 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
158 158 ring_node_to_send_cwf_f2->sid = SID_BURST_CWF_F2;
159 159 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
160 160 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
161 161 current_ring_node_f2 = current_ring_node_f2->next;
162 162 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
163 163 if (rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_BURST ) != RTEMS_SUCCESSFUL) {
164 164 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_0 );
165 165 }
166 166 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
167 167 break;
168 168 default:
169 169 break;
170 170 }
171 171 }
172 172
173 173 inline void waveform_isr_normal_sbm1_sbm2( void )
174 174 {
175 175 rtems_status_code status;
176 176
177 177 //***
178 178 // F0
179 179 if ( (waveform_picker_regs->status & 0x03) != 0x00 ) // [0000 0011] check the f0 full bits
180 180 {
181 181 swf0_ready_flag_f1 = true;
182 182 swf0_ready_flag_f2 = true;
183 183 ring_node_to_send_swf_f0 = current_ring_node_f0->previous;
184 184 current_ring_node_f0 = current_ring_node_f0->next;
185 185 if ( (waveform_picker_regs->status & 0x01) == 0x01)
186 186 {
187 187
188 188 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_0_coarse_time;
189 189 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_0_fine_time;
190 190 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->buffer_address;
191 191 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001101; // [0001 0001 0000 0001]
192 192 }
193 193 else if ( (waveform_picker_regs->status & 0x02) == 0x02)
194 194 {
195 195 ring_node_to_send_swf_f0->coarseTime = waveform_picker_regs->f0_1_coarse_time;
196 196 ring_node_to_send_swf_f0->fineTime = waveform_picker_regs->f0_1_fine_time;
197 197 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address;
198 198 waveform_picker_regs->status = waveform_picker_regs->status & 0x00001102; // [0001 0001 0000 0010]
199 199 }
200 200 }
201 201
202 202 //***
203 203 // F1
204 204 if ( (waveform_picker_regs->status & 0x0c) != 0x00 ) { // [0000 1100] check the f1 full bits
205 205 // (1) change the receiving buffer for the waveform picker
206 206 ring_node_to_send_cwf_f1 = current_ring_node_f1->previous;
207 207 current_ring_node_f1 = current_ring_node_f1->next;
208 208 if ( (waveform_picker_regs->status & 0x04) == 0x04)
209 209 {
210 210 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_0_coarse_time;
211 211 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_0_fine_time;
212 212 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->buffer_address;
213 213 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002204; // [0010 0010 0000 0100] f1 bits = 0
214 214 }
215 215 else if ( (waveform_picker_regs->status & 0x08) == 0x08)
216 216 {
217 217 ring_node_to_send_cwf_f1->coarseTime = waveform_picker_regs->f1_1_coarse_time;
218 218 ring_node_to_send_cwf_f1->fineTime = waveform_picker_regs->f1_1_fine_time;
219 219 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address;
220 220 waveform_picker_regs->status = waveform_picker_regs->status & 0x00002208; // [0010 0010 0000 1000] f1 bits = 0
221 221 }
222 222 // (2) send an event for the the CWF1 task for transmission (and snapshot extraction if needed)
223 223 status = rtems_event_send( Task_id[TASKID_CWF1], RTEMS_EVENT_MODE_NORM_S1_S2 );
224 224 }
225 225
226 226 //***
227 227 // F2
228 228 if ( (waveform_picker_regs->status & 0x30) != 0x00 ) { // [0011 0000] check the f2 full bit
229 229 // (1) change the receiving buffer for the waveform picker
230 230 ring_node_to_send_cwf_f2 = current_ring_node_f2->previous;
231 231 ring_node_to_send_cwf_f2->sid = SID_SBM2_CWF_F2;
232 232 current_ring_node_f2 = current_ring_node_f2->next;
233 233 if ( (waveform_picker_regs->status & 0x10) == 0x10)
234 234 {
235 235 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_0_coarse_time;
236 236 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_0_fine_time;
237 237 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->buffer_address;
238 238 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004410; // [0100 0100 0001 0000]
239 239 }
240 240 else if ( (waveform_picker_regs->status & 0x20) == 0x20)
241 241 {
242 242 ring_node_to_send_cwf_f2->coarseTime = waveform_picker_regs->f2_1_coarse_time;
243 243 ring_node_to_send_cwf_f2->fineTime = waveform_picker_regs->f2_1_fine_time;
244 244 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address;
245 245 waveform_picker_regs->status = waveform_picker_regs->status & 0x00004420; // [0100 0100 0010 0000]
246 246 }
247 247 // (2) send an event for the waveforms transmission
248 248 status = rtems_event_send( Task_id[TASKID_CWF2], RTEMS_EVENT_MODE_NORM_S1_S2 );
249 249 }
250 250 }
251 251
252 252 rtems_isr waveforms_isr( rtems_vector_number vector )
253 253 {
254 254 /** This is the interrupt sub routine called by the waveform picker core.
255 255 *
256 256 * This ISR launch different actions depending mainly on two pieces of information:
257 257 * 1. the values read in the registers of the waveform picker.
258 258 * 2. the current LFR mode.
259 259 *
260 260 */
261 261
262 262 // STATUS
263 263 // new error error buffer full
264 264 // 15 14 13 12 11 10 9 8
265 265 // f3 f2 f1 f0 f3 f2 f1 f0
266 266 //
267 267 // ready buffer
268 268 // 7 6 5 4 3 2 1 0
269 269 // f3_1 f3_0 f2_1 f2_0 f1_1 f1_0 f0_1 f0_0
270 270
271 271 rtems_status_code spare_status;
272 272
273 273 waveforms_isr_f3();
274 274
275 275 if ( (waveform_picker_regs->status & 0xff00) != 0x00) // [1111 1111 0000 0000] check the error bits
276 276 {
277 277 spare_status = rtems_event_send( Task_id[TASKID_DUMB], RTEMS_EVENT_10 );
278 278 }
279 279
280 280 switch(lfrCurrentMode)
281 281 {
282 282 //********
283 283 // STANDBY
284 284 case LFR_MODE_STANDBY:
285 285 break;
286 286 //**************************
287 287 // LFR NORMAL, SBM1 and SBM2
288 288 case LFR_MODE_NORMAL:
289 289 case LFR_MODE_SBM1:
290 290 case LFR_MODE_SBM2:
291 291 waveform_isr_normal_sbm1_sbm2();
292 292 break;
293 293 //******
294 294 // BURST
295 295 case LFR_MODE_BURST:
296 296 waveforms_isr_burst();
297 297 break;
298 298 //********
299 299 // DEFAULT
300 300 default:
301 301 break;
302 302 }
303 303 }
304 304
305 305 //************
306 306 // RTEMS TASKS
307 307
308 308 rtems_task wfrm_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
309 309 {
310 310 /** This RTEMS task is dedicated to the transmission of snapshots of the NORMAL mode.
311 311 *
312 312 * @param unused is the starting argument of the RTEMS task
313 313 *
314 314 * The following data packets are sent by this task:
315 315 * - TM_LFR_SCIENCE_NORMAL_SWF_F0
316 316 * - TM_LFR_SCIENCE_NORMAL_SWF_F1
317 317 * - TM_LFR_SCIENCE_NORMAL_SWF_F2
318 318 *
319 319 */
320 320
321 321 rtems_event_set event_out;
322 322 rtems_id queue_id;
323 323 rtems_status_code status;
324 324 ring_node *ring_node_swf1_extracted_ptr;
325 325 ring_node *ring_node_swf2_extracted_ptr;
326 326
327 327 ring_node_swf1_extracted_ptr = (ring_node *) &ring_node_swf1_extracted;
328 328 ring_node_swf2_extracted_ptr = (ring_node *) &ring_node_swf2_extracted;
329 329
330 330 status = get_message_queue_id_send( &queue_id );
331 331 if (status != RTEMS_SUCCESSFUL)
332 332 {
333 333 PRINTF1("in WFRM *** ERR get_message_queue_id_send %d\n", status);
334 334 }
335 335
336 336 BOOT_PRINTF("in WFRM ***\n");
337 337
338 338 while(1){
339 339 // wait for an RTEMS_EVENT
340 340 rtems_event_receive(RTEMS_EVENT_MODE_NORMAL,
341 341 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
342 342
343 343 snapshot_resynchronization( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
344 344
345 345 if (event_out == RTEMS_EVENT_MODE_NORMAL)
346 346 {
347 347 DEBUG_PRINTF("WFRM received RTEMS_EVENT_MODE_SBM2\n");
348 348 ring_node_to_send_swf_f0->sid = SID_NORM_SWF_F0;
349 349 ring_node_swf1_extracted_ptr->sid = SID_NORM_SWF_F1;
350 350 ring_node_swf2_extracted_ptr->sid = SID_NORM_SWF_F2;
351 351 status = rtems_message_queue_send( queue_id, &ring_node_to_send_swf_f0, sizeof( ring_node* ) );
352 352 status = rtems_message_queue_send( queue_id, &ring_node_swf1_extracted_ptr, sizeof( ring_node* ) );
353 353 status = rtems_message_queue_send( queue_id, &ring_node_swf2_extracted_ptr, sizeof( ring_node* ) );
354 354 }
355 355 }
356 356 }
357 357
358 358 rtems_task cwf3_task(rtems_task_argument argument) //used with the waveform picker VHDL IP
359 359 {
360 360 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f3.
361 361 *
362 362 * @param unused is the starting argument of the RTEMS task
363 363 *
364 364 * The following data packet is sent by this task:
365 365 * - TM_LFR_SCIENCE_NORMAL_CWF_F3
366 366 *
367 367 */
368 368
369 369 rtems_event_set event_out;
370 370 rtems_id queue_id;
371 371 rtems_status_code status;
372 372 ring_node ring_node_cwf3_light;
373 373 ring_node *ring_node_to_send_cwf;
374 374
375 375 status = get_message_queue_id_send( &queue_id );
376 376 if (status != RTEMS_SUCCESSFUL)
377 377 {
378 378 PRINTF1("in CWF3 *** ERR get_message_queue_id_send %d\n", status)
379 379 }
380 380
381 381 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
382 382
383 383 // init the ring_node_cwf3_light structure
384 384 ring_node_cwf3_light.buffer_address = (int) wf_cont_f3_light;
385 385 ring_node_cwf3_light.coarseTime = 0x00;
386 386 ring_node_cwf3_light.fineTime = 0x00;
387 387 ring_node_cwf3_light.next = NULL;
388 388 ring_node_cwf3_light.previous = NULL;
389 389 ring_node_cwf3_light.sid = SID_NORM_CWF_F3;
390 390 ring_node_cwf3_light.status = 0x00;
391 391
392 392 BOOT_PRINTF("in CWF3 ***\n")
393 393
394 394 while(1){
395 395 // wait for an RTEMS_EVENT
396 396 rtems_event_receive( RTEMS_EVENT_0,
397 397 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
398 398 if ( (lfrCurrentMode == LFR_MODE_NORMAL)
399 399 || (lfrCurrentMode == LFR_MODE_SBM1) || (lfrCurrentMode==LFR_MODE_SBM2) )
400 400 {
401 401 ring_node_to_send_cwf = getRingNodeToSendCWF( 3 );
402 402 if ( (parameter_dump_packet.sy_lfr_n_cwf_long_f3 & 0x01) == 0x01)
403 403 {
404 404 PRINTF("send CWF_LONG_F3\n")
405 405 ring_node_to_send_cwf_f3->sid = SID_NORM_CWF_LONG_F3;
406 406 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
407 407 }
408 408 else
409 409 {
410 410 PRINTF("send CWF_F3 (light)\n")
411 411 send_waveform_CWF3_light( ring_node_to_send_cwf, &ring_node_cwf3_light, queue_id );
412 412 }
413 413
414 414 }
415 415 else
416 416 {
417 417 PRINTF1("in CWF3 *** lfrCurrentMode is %d, no data will be sent\n", lfrCurrentMode)
418 418 }
419 419 }
420 420 }
421 421
422 422 rtems_task cwf2_task(rtems_task_argument argument) // ONLY USED IN BURST AND SBM2
423 423 {
424 424 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f2.
425 425 *
426 426 * @param unused is the starting argument of the RTEMS task
427 427 *
428 428 * The following data packet is sent by this function:
429 429 * - TM_LFR_SCIENCE_BURST_CWF_F2
430 430 * - TM_LFR_SCIENCE_SBM2_CWF_F2
431 431 *
432 432 */
433 433
434 434 rtems_event_set event_out;
435 435 rtems_id queue_id;
436 436 rtems_status_code status;
437 437 ring_node *ring_node_to_send;
438 438 unsigned long long int acquisitionTimeF0_asLong;
439 439
440 440 acquisitionTimeF0_asLong = 0x00;
441 441
442 442 status = get_message_queue_id_send( &queue_id );
443 443 if (status != RTEMS_SUCCESSFUL)
444 444 {
445 445 PRINTF1("in CWF2 *** ERR get_message_queue_id_send %d\n", status)
446 446 }
447 447
448 448 BOOT_PRINTF("in CWF2 ***\n")
449 449
450 450 while(1){
451 451 // wait for an RTEMS_EVENT
452 452 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2 | RTEMS_EVENT_MODE_BURST,
453 453 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
454 454 ring_node_to_send = getRingNodeToSendCWF( 2 );
455 455 if (event_out == RTEMS_EVENT_MODE_BURST)
456 456 {
457 457 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
458 458 }
459 459 else if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
460 460 {
461 461 if ( lfrCurrentMode == LFR_MODE_SBM2 )
462 462 {
463 463 status = rtems_message_queue_send( queue_id, &ring_node_to_send, sizeof( ring_node* ) );
464 464 }
465 465 // launch snapshot extraction if needed
466 466 if (extractSWF2 == true)
467 467 {
468 468 ring_node_to_send_swf_f2 = ring_node_to_send_cwf_f2;
469 469 // extract the snapshot
470 470 build_snapshot_from_ring( ring_node_to_send_swf_f2, 2, acquisitionTimeF0_asLong,
471 471 &ring_node_swf2_extracted, swf2_extracted );
472 472 // send the snapshot when built
473 473 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_SBM2 );
474 474 extractSWF2 = false;
475 475 swf2_ready = true;
476 476 }
477 477 if (swf0_ready_flag_f2 == true)
478 478 {
479 479 extractSWF2 = true;
480 480 // record the acquition time of the f0 snapshot to use to build the snapshot at f2
481 481 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
482 482 swf0_ready_flag_f2 = false;
483 483 }
484 484 }
485 485 }
486 486 }
487 487
488 488 rtems_task cwf1_task(rtems_task_argument argument) // ONLY USED IN SBM1
489 489 {
490 490 /** This RTEMS task is dedicated to the transmission of continuous waveforms at f1.
491 491 *
492 492 * @param unused is the starting argument of the RTEMS task
493 493 *
494 494 * The following data packet is sent by this function:
495 495 * - TM_LFR_SCIENCE_SBM1_CWF_F1
496 496 *
497 497 */
498 498
499 499 rtems_event_set event_out;
500 500 rtems_id queue_id;
501 501 rtems_status_code status;
502 502
503 503 ring_node *ring_node_to_send_cwf;
504 504
505 505 status = get_message_queue_id_send( &queue_id );
506 506 if (status != RTEMS_SUCCESSFUL)
507 507 {
508 508 PRINTF1("in CWF1 *** ERR get_message_queue_id_send %d\n", status)
509 509 }
510 510
511 511 BOOT_PRINTF("in CWF1 ***\n");
512 512
513 513 while(1){
514 514 // wait for an RTEMS_EVENT
515 515 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
516 516 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
517 517 ring_node_to_send_cwf = getRingNodeToSendCWF( 1 );
518 518 ring_node_to_send_cwf_f1->sid = SID_SBM1_CWF_F1;
519 519 if (lfrCurrentMode == LFR_MODE_SBM1)
520 520 {
521 521 status = rtems_message_queue_send( queue_id, &ring_node_to_send_cwf, sizeof( ring_node* ) );
522 522 if (status != 0)
523 523 {
524 524 PRINTF("cwf sending failed\n")
525 525 }
526 526 }
527 527 // launch snapshot extraction if needed
528 528 if (extractSWF1 == true)
529 529 {
530 530 ring_node_to_send_swf_f1 = ring_node_to_send_cwf;
531 531 // launch the snapshot extraction
532 532 status = rtems_event_send( Task_id[TASKID_SWBD], RTEMS_EVENT_MODE_NORM_S1_S2 );
533 533 extractSWF1 = false;
534 534 }
535 535 if (swf0_ready_flag_f1 == true)
536 536 {
537 537 extractSWF1 = true;
538 538 swf0_ready_flag_f1 = false; // this step shall be executed only one time
539 539 }
540 540 if ((swf1_ready == true) && (swf2_ready == true)) // swf_f1 is ready after the extraction
541 541 {
542 542 status = rtems_event_send( Task_id[TASKID_WFRM], RTEMS_EVENT_MODE_NORMAL );
543 543 swf1_ready = false;
544 544 swf2_ready = false;
545 545 }
546 546 }
547 547 }
548 548
549 549 rtems_task swbd_task(rtems_task_argument argument)
550 550 {
551 551 /** This RTEMS task is dedicated to the building of snapshots from different continuous waveforms buffers.
552 552 *
553 553 * @param unused is the starting argument of the RTEMS task
554 554 *
555 555 */
556 556
557 557 rtems_event_set event_out;
558 558 unsigned long long int acquisitionTimeF0_asLong;
559 559
560 560 acquisitionTimeF0_asLong = 0x00;
561 561
562 562 BOOT_PRINTF("in SWBD ***\n")
563 563
564 564 while(1){
565 565 // wait for an RTEMS_EVENT
566 566 rtems_event_receive( RTEMS_EVENT_MODE_NORM_S1_S2,
567 567 RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &event_out);
568 568 if (event_out == RTEMS_EVENT_MODE_NORM_S1_S2)
569 569 {
570 570 acquisitionTimeF0_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send_swf_f0->coarseTime );
571 571 build_snapshot_from_ring( ring_node_to_send_swf_f1, 1, acquisitionTimeF0_asLong,
572 572 &ring_node_swf1_extracted, swf1_extracted );
573 573 swf1_ready = true; // the snapshot has been extracted and is ready to be sent
574 574 }
575 575 else
576 576 {
577 577 PRINTF1("in SWBD *** unexpected rtems event received %x\n", (int) event_out)
578 578 }
579 579 }
580 580 }
581 581
582 582 //******************
583 583 // general functions
584 584
585 585 void WFP_init_rings( void )
586 586 {
587 587 // F0 RING
588 588 init_ring( waveform_ring_f0, NB_RING_NODES_F0, wf_buffer_f0, WFRM_BUFFER );
589 589 // F1 RING
590 590 init_ring( waveform_ring_f1, NB_RING_NODES_F1, wf_buffer_f1, WFRM_BUFFER );
591 591 // F2 RING
592 592 init_ring( waveform_ring_f2, NB_RING_NODES_F2, wf_buffer_f2, WFRM_BUFFER );
593 593 // F3 RING
594 594 init_ring( waveform_ring_f3, NB_RING_NODES_F3, wf_buffer_f3, WFRM_BUFFER );
595 595
596 596 ring_node_swf1_extracted.buffer_address = (int) swf1_extracted;
597 597 ring_node_swf2_extracted.buffer_address = (int) swf2_extracted;
598 598
599 599 DEBUG_PRINTF1("waveform_ring_f0 @%x\n", (unsigned int) waveform_ring_f0)
600 600 DEBUG_PRINTF1("waveform_ring_f1 @%x\n", (unsigned int) waveform_ring_f1)
601 601 DEBUG_PRINTF1("waveform_ring_f2 @%x\n", (unsigned int) waveform_ring_f2)
602 602 DEBUG_PRINTF1("waveform_ring_f3 @%x\n", (unsigned int) waveform_ring_f3)
603 603 DEBUG_PRINTF1("wf_buffer_f0 @%x\n", (unsigned int) wf_buffer_f0)
604 604 DEBUG_PRINTF1("wf_buffer_f1 @%x\n", (unsigned int) wf_buffer_f1)
605 605 DEBUG_PRINTF1("wf_buffer_f2 @%x\n", (unsigned int) wf_buffer_f2)
606 606 DEBUG_PRINTF1("wf_buffer_f3 @%x\n", (unsigned int) wf_buffer_f3)
607 607
608 608 }
609 609
610 610 void WFP_reset_current_ring_nodes( void )
611 611 {
612 612 current_ring_node_f0 = waveform_ring_f0[0].next;
613 613 current_ring_node_f1 = waveform_ring_f1[0].next;
614 614 current_ring_node_f2 = waveform_ring_f2[0].next;
615 615 current_ring_node_f3 = waveform_ring_f3[0].next;
616 616
617 617 ring_node_to_send_swf_f0 = waveform_ring_f0;
618 618 ring_node_to_send_swf_f1 = waveform_ring_f1;
619 619 ring_node_to_send_swf_f2 = waveform_ring_f2;
620 620
621 621 ring_node_to_send_cwf_f1 = waveform_ring_f1;
622 622 ring_node_to_send_cwf_f2 = waveform_ring_f2;
623 623 ring_node_to_send_cwf_f3 = waveform_ring_f3;
624 624 }
625 625
626 626 int send_waveform_CWF3_light( ring_node *ring_node_to_send, ring_node *ring_node_cwf3_light, rtems_id queue_id )
627 627 {
628 628 /** This function sends CWF_F3 CCSDS packets without the b1, b2 and b3 data.
629 629 *
630 630 * @param waveform points to the buffer containing the data that will be send.
631 631 * @param headerCWF points to a table of headers that have been prepared for the data transmission.
632 632 * @param queue_id is the id of the rtems queue to which spw_ioctl_pkt_send structures will be send. The structures
633 633 * contain information to setup the transmission of the data packets.
634 634 *
635 635 * By default, CWF_F3 packet are send without the b1, b2 and b3 data. This function rebuilds a data buffer
636 636 * from the incoming data and sends it in 7 packets, 6 containing 340 blocks and 1 one containing 8 blocks.
637 637 *
638 638 */
639 639
640 640 unsigned int i;
641 641 int ret;
642 642 rtems_status_code status;
643 643
644 644 char *sample;
645 645 int *dataPtr;
646 646
647 647 ret = LFR_DEFAULT;
648 648
649 649 dataPtr = (int*) ring_node_to_send->buffer_address;
650 650
651 651 ring_node_cwf3_light->coarseTime = ring_node_to_send->coarseTime;
652 652 ring_node_cwf3_light->fineTime = ring_node_to_send->fineTime;
653 653
654 654 //**********************
655 655 // BUILD CWF3_light DATA
656 656 for ( i=0; i< NB_SAMPLES_PER_SNAPSHOT; i++)
657 657 {
658 658 sample = (char*) &dataPtr[ (i * NB_WORDS_SWF_BLK) ];
659 659 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) ] = sample[ 0 ];
660 660 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 1 ] = sample[ 1 ];
661 661 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 2 ] = sample[ 2 ];
662 662 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 3 ] = sample[ 3 ];
663 663 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 4 ] = sample[ 4 ];
664 664 wf_cont_f3_light[ (i * NB_BYTES_CWF3_LIGHT_BLK) + 5 ] = sample[ 5 ];
665 665 }
666 666
667 667 // SEND PACKET
668 668 status = rtems_message_queue_send( queue_id, &ring_node_cwf3_light, sizeof( ring_node* ) );
669 669 if (status != RTEMS_SUCCESSFUL) {
670 670 ret = LFR_DEFAULT;
671 671 }
672 672
673 673 return ret;
674 674 }
675 675
676 676 void compute_acquisition_time( unsigned int coarseTime, unsigned int fineTime,
677 677 unsigned int sid, unsigned char pa_lfr_pkt_nr, unsigned char * acquisitionTime )
678 678 {
679 679 unsigned long long int acquisitionTimeAsLong;
680 680 unsigned char localAcquisitionTime[6];
681 681 double deltaT;
682 682
683 683 deltaT = 0.;
684 684
685 685 localAcquisitionTime[0] = (unsigned char) ( coarseTime >> 24 );
686 686 localAcquisitionTime[1] = (unsigned char) ( coarseTime >> 16 );
687 687 localAcquisitionTime[2] = (unsigned char) ( coarseTime >> 8 );
688 688 localAcquisitionTime[3] = (unsigned char) ( coarseTime );
689 689 localAcquisitionTime[4] = (unsigned char) ( fineTime >> 8 );
690 690 localAcquisitionTime[5] = (unsigned char) ( fineTime );
691 691
692 692 acquisitionTimeAsLong = ( (unsigned long long int) localAcquisitionTime[0] << 40 )
693 693 + ( (unsigned long long int) localAcquisitionTime[1] << 32 )
694 694 + ( (unsigned long long int) localAcquisitionTime[2] << 24 )
695 695 + ( (unsigned long long int) localAcquisitionTime[3] << 16 )
696 696 + ( (unsigned long long int) localAcquisitionTime[4] << 8 )
697 697 + ( (unsigned long long int) localAcquisitionTime[5] );
698 698
699 699 switch( sid )
700 700 {
701 701 case SID_NORM_SWF_F0:
702 702 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 24576. ;
703 703 break;
704 704
705 705 case SID_NORM_SWF_F1:
706 706 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 4096. ;
707 707 break;
708 708
709 709 case SID_NORM_SWF_F2:
710 710 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_304 * 65536. / 256. ;
711 711 break;
712 712
713 713 case SID_SBM1_CWF_F1:
714 714 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 4096. ;
715 715 break;
716 716
717 717 case SID_SBM2_CWF_F2:
718 718 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
719 719 break;
720 720
721 721 case SID_BURST_CWF_F2:
722 722 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 256. ;
723 723 break;
724 724
725 725 case SID_NORM_CWF_F3:
726 726 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF_SHORT_F3 * 65536. / 16. ;
727 727 break;
728 728
729 729 case SID_NORM_CWF_LONG_F3:
730 730 deltaT = ( (double ) (pa_lfr_pkt_nr) ) * BLK_NR_CWF * 65536. / 16. ;
731 731 break;
732 732
733 733 default:
734 734 PRINTF1("in compute_acquisition_time *** ERR unexpected sid %d\n", sid)
735 735 deltaT = 0.;
736 736 break;
737 737 }
738 738
739 739 acquisitionTimeAsLong = acquisitionTimeAsLong + (unsigned long long int) deltaT;
740 740 //
741 741 acquisitionTime[0] = (unsigned char) (acquisitionTimeAsLong >> 40);
742 742 acquisitionTime[1] = (unsigned char) (acquisitionTimeAsLong >> 32);
743 743 acquisitionTime[2] = (unsigned char) (acquisitionTimeAsLong >> 24);
744 744 acquisitionTime[3] = (unsigned char) (acquisitionTimeAsLong >> 16);
745 745 acquisitionTime[4] = (unsigned char) (acquisitionTimeAsLong >> 8 );
746 746 acquisitionTime[5] = (unsigned char) (acquisitionTimeAsLong );
747 747
748 748 }
749 749
750 750 void build_snapshot_from_ring( ring_node *ring_node_to_send,
751 751 unsigned char frequencyChannel,
752 752 unsigned long long int acquisitionTimeF0_asLong,
753 753 ring_node *ring_node_swf_extracted,
754 754 int *swf_extracted)
755 755 {
756 756 unsigned int i;
757 757 unsigned long long int centerTime_asLong;
758 758 unsigned long long int acquisitionTime_asLong;
759 759 unsigned long long int bufferAcquisitionTime_asLong;
760 760 unsigned char *ptr1;
761 761 unsigned char *ptr2;
762 762 unsigned char *timeCharPtr;
763 763 unsigned char nb_ring_nodes;
764 764 unsigned long long int frequency_asLong;
765 765 unsigned long long int nbTicksPerSample_asLong;
766 766 unsigned long long int nbSamplesPart1_asLong;
767 767 unsigned long long int sampleOffset_asLong;
768 768
769 769 unsigned int deltaT_F0;
770 770 unsigned int deltaT_F1;
771 771 unsigned long long int deltaT_F2;
772 772
773 773 deltaT_F0 = 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
774 774 deltaT_F1 = 16384; // (2048. / 4096. / 2.) * 65536. = 16384;
775 775 deltaT_F2 = 262144; // (2048. / 256. / 2.) * 65536. = 262144;
776 776 sampleOffset_asLong = 0x00;
777 777
778 778 // (1) get the f0 acquisition time => the value is passed in argument
779 779
780 780 // (2) compute the central reference time
781 781 centerTime_asLong = acquisitionTimeF0_asLong + deltaT_F0;
782 782
783 783 // (3) compute the acquisition time of the current snapshot
784 784 switch(frequencyChannel)
785 785 {
786 786 case 1: // 1 is for F1 = 4096 Hz
787 787 acquisitionTime_asLong = centerTime_asLong - deltaT_F1;
788 788 nb_ring_nodes = NB_RING_NODES_F1;
789 789 frequency_asLong = 4096;
790 790 nbTicksPerSample_asLong = 16; // 65536 / 4096;
791 791 break;
792 792 case 2: // 2 is for F2 = 256 Hz
793 793 acquisitionTime_asLong = centerTime_asLong - deltaT_F2;
794 794 nb_ring_nodes = NB_RING_NODES_F2;
795 795 frequency_asLong = 256;
796 796 nbTicksPerSample_asLong = 256; // 65536 / 256;
797 797 break;
798 798 default:
799 799 acquisitionTime_asLong = centerTime_asLong;
800 800 frequency_asLong = 256;
801 801 nbTicksPerSample_asLong = 256;
802 802 break;
803 803 }
804 804
805 805 //****************************************************************************
806 806 // (4) search the ring_node with the acquisition time <= acquisitionTime_asLong
807 807 for (i=0; i<nb_ring_nodes; i++)
808 808 {
809 809 //PRINTF1("%d ... ", i);
810 810 bufferAcquisitionTime_asLong = get_acquisition_time( (unsigned char *) &ring_node_to_send->coarseTime );
811 811 if (bufferAcquisitionTime_asLong <= acquisitionTime_asLong)
812 812 {
813 813 //PRINTF1("buffer found with acquisition time = %llx\n", bufferAcquisitionTime_asLong);
814 814 break;
815 815 }
816 816 ring_node_to_send = ring_node_to_send->previous;
817 817 }
818 818
819 819 // (5) compute the number of samples to take in the current buffer
820 820 sampleOffset_asLong = ((acquisitionTime_asLong - bufferAcquisitionTime_asLong) * frequency_asLong ) >> 16;
821 821 nbSamplesPart1_asLong = NB_SAMPLES_PER_SNAPSHOT - sampleOffset_asLong;
822 822 //PRINTF2("sampleOffset_asLong = %lld, nbSamplesPart1_asLong = %lld\n", sampleOffset_asLong, nbSamplesPart1_asLong);
823 823
824 824 // (6) compute the final acquisition time
825 825 acquisitionTime_asLong = bufferAcquisitionTime_asLong +
826 826 sampleOffset_asLong * nbTicksPerSample_asLong;
827 827
828 828 // (7) copy the acquisition time at the beginning of the extrated snapshot
829 829 ptr1 = (unsigned char*) &acquisitionTime_asLong;
830 830 // fine time
831 831 ptr2 = (unsigned char*) &ring_node_swf_extracted->fineTime;
832 832 ptr2[2] = ptr1[ 4 + 2 ];
833 833 ptr2[3] = ptr1[ 5 + 2 ];
834 834 // coarse time
835 835 ptr2 = (unsigned char*) &ring_node_swf_extracted->coarseTime;
836 836 ptr2[0] = ptr1[ 0 + 2 ];
837 837 ptr2[1] = ptr1[ 1 + 2 ];
838 838 ptr2[2] = ptr1[ 2 + 2 ];
839 839 ptr2[3] = ptr1[ 3 + 2 ];
840 840
841 841 // re set the synchronization bit
842 842 timeCharPtr = (unsigned char*) &ring_node_to_send->coarseTime;
843 843 ptr2[0] = ptr2[0] | (timeCharPtr[0] & 0x80); // [1000 0000]
844 844
845 845 if ( (nbSamplesPart1_asLong >= NB_SAMPLES_PER_SNAPSHOT) | (nbSamplesPart1_asLong < 0) )
846 846 {
847 847 nbSamplesPart1_asLong = 0;
848 848 }
849 849 // copy the part 1 of the snapshot in the extracted buffer
850 850 for ( i = 0; i < (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i++ )
851 851 {
852 852 swf_extracted[i] =
853 853 ((int*) ring_node_to_send->buffer_address)[ i + (sampleOffset_asLong * NB_WORDS_SWF_BLK) ];
854 854 }
855 855 // copy the part 2 of the snapshot in the extracted buffer
856 856 ring_node_to_send = ring_node_to_send->next;
857 857 for ( i = (nbSamplesPart1_asLong * NB_WORDS_SWF_BLK); i < (NB_SAMPLES_PER_SNAPSHOT * NB_WORDS_SWF_BLK); i++ )
858 858 {
859 859 swf_extracted[i] =
860 860 ((int*) ring_node_to_send->buffer_address)[ (i-(nbSamplesPart1_asLong * NB_WORDS_SWF_BLK)) ];
861 861 }
862 862 }
863 863
864 864 void snapshot_resynchronization( unsigned char *timePtr )
865 865 {
866 866 unsigned long long int acquisitionTime;
867 867 unsigned long long int centerTime;
868 868 unsigned long long int previousTick;
869 869 unsigned long long int nextTick;
870 870 unsigned long long int deltaPreviousTick;
871 871 unsigned long long int deltaNextTick;
872 unsigned int deltaTickInF2;
872 int deltaTickInF2;
873 873 double deltaPrevious_ms;
874 874 double deltaNext_ms;
875 double correctionInF2;
876 static unsigned char resynchroEngaged = 0;
875 877
876 // get acquisition time in fine time ticks
877 acquisitionTime = get_acquisition_time( timePtr );
878 if (resynchroEngaged == 0)
879 {
880 resynchroEngaged = 1;
881 // get acquisition time in fine time ticks
882 acquisitionTime = get_acquisition_time( timePtr );
878 883
879 // compute center time
880 centerTime = acquisitionTime + 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
881 previousTick = centerTime - (centerTime & 0xffff);
882 nextTick = previousTick + 65536;
884 // compute center time
885 centerTime = acquisitionTime + 2731; // (2048. / 24576. / 2.) * 65536. = 2730.667;
886 previousTick = centerTime - (centerTime & 0xffff);
887 nextTick = previousTick + 65536;
883 888
884 deltaPreviousTick = centerTime - previousTick;
885 deltaNextTick = nextTick - centerTime;
889 deltaPreviousTick = centerTime - previousTick;
890 deltaNextTick = nextTick - centerTime;
891
892 deltaPrevious_ms = ((double) deltaPreviousTick) / 65536. * 1000.;
893 deltaNext_ms = ((double) deltaNextTick) / 65536. * 1000.;
894
895 PRINTF2("delta previous = %f ms, delta next = %f ms\n", deltaPrevious_ms, deltaNext_ms);
896 PRINTF2("delta previous = %llu fine time ticks, delta next = %llu fine time ticks\n", deltaPreviousTick, deltaNextTick);
886 897
887 deltaPrevious_ms = ((double) deltaPreviousTick) / 65536. * 1000.;
888 deltaNext_ms = ((double) deltaNextTick) / 65536. * 1000.;
889
890 PRINTF2("delta previous = %f ms, delta next = %f ms\n", deltaPrevious_ms, deltaNext_ms);
891 PRINTF2("delta previous = %llu fine time ticks, delta next = %llu fine time ticks\n", deltaPreviousTick, deltaNextTick);
898 // which tick is the closest?
899 if (deltaPreviousTick > deltaNextTick)
900 {
901 // the snapshot center is just before the second => increase delta_snapshot
902 correctionInF2 = + (deltaNext_ms * 256. / 1000. );
903 }
904 else
905 {
906 // the snapshot center is just after the second => decrease delta_snapshot
907 correctionInF2 = - (deltaPrevious_ms * 256. / 1000. );
908 }
892 909
893 // which tick is the closest
894 if (deltaPreviousTick > deltaNextTick)
895 {
896 // the snapshot center is just before the second => increase delta_snapshot
897 deltaTickInF2 = ceil( (deltaNext_ms * 256. / 1000.) );
898 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + 1 * deltaTickInF2;
899 PRINTF2("correction of = + %u, delta_snapshot = %d\n", deltaTickInF2, waveform_picker_regs->delta_snapshot);
910 if (correctionInF2 >=0 )
911 {
912 deltaTickInF2 = floor( correctionInF2 );
913 }
914 else
915 {
916 deltaTickInF2 = ceil( correctionInF2 );
917 }
918 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot + deltaTickInF2;
919 PRINTF2("Correction of = %d, delta_snapshot = %d\n\n", deltaTickInF2, waveform_picker_regs->delta_snapshot);
900 920 }
901 921 else
902 922 {
903 // the snapshot center is just after the second => decrease delat_snapshot
904 deltaTickInF2 = ceil( (deltaPrevious_ms * 256. / 1000.) );
905 waveform_picker_regs->delta_snapshot = waveform_picker_regs->delta_snapshot - 1 * deltaTickInF2;
906 PRINTF2("correction of = - %u, delta_snapshot = %d\n", deltaTickInF2, waveform_picker_regs->delta_snapshot);
923 PRINTF1("No resynchro, delta_snapshot = %d\n\n", waveform_picker_regs->delta_snapshot);
924 resynchroEngaged = 0;
907 925 }
908 926 }
909 927
910 928 //**************
911 929 // wfp registers
912 930 void reset_wfp_burst_enable( void )
913 931 {
914 932 /** This function resets the waveform picker burst_enable register.
915 933 *
916 934 * The burst bits [f2 f1 f0] and the enable bits [f3 f2 f1 f0] are set to 0.
917 935 *
918 936 */
919 937
920 938 // [1000 000] burst f2, f1, f0 enable f3, f2, f1, f0
921 939 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable & 0x80;
922 940 }
923 941
924 942 void reset_wfp_status( void )
925 943 {
926 944 /** This function resets the waveform picker status register.
927 945 *
928 946 * All status bits are set to 0 [new_err full_err full].
929 947 *
930 948 */
931 949
932 950 waveform_picker_regs->status = 0xffff;
933 951 }
934 952
935 953 void reset_wfp_buffer_addresses( void )
936 954 {
937 955 // F0
938 956 waveform_picker_regs->addr_data_f0_0 = current_ring_node_f0->previous->buffer_address; // 0x08
939 957 waveform_picker_regs->addr_data_f0_1 = current_ring_node_f0->buffer_address; // 0x0c
940 958 // F1
941 959 waveform_picker_regs->addr_data_f1_0 = current_ring_node_f1->previous->buffer_address; // 0x10
942 960 waveform_picker_regs->addr_data_f1_1 = current_ring_node_f1->buffer_address; // 0x14
943 961 // F2
944 962 waveform_picker_regs->addr_data_f2_0 = current_ring_node_f2->previous->buffer_address; // 0x18
945 963 waveform_picker_regs->addr_data_f2_1 = current_ring_node_f2->buffer_address; // 0x1c
946 964 // F3
947 965 waveform_picker_regs->addr_data_f3_0 = current_ring_node_f3->previous->buffer_address; // 0x20
948 966 waveform_picker_regs->addr_data_f3_1 = current_ring_node_f3->buffer_address; // 0x24
949 967 }
950 968
951 969 void reset_waveform_picker_regs( void )
952 970 {
953 971 /** This function resets the waveform picker module registers.
954 972 *
955 973 * The registers affected by this function are located at the following offset addresses:
956 974 * - 0x00 data_shaping
957 975 * - 0x04 run_burst_enable
958 976 * - 0x08 addr_data_f0
959 977 * - 0x0C addr_data_f1
960 978 * - 0x10 addr_data_f2
961 979 * - 0x14 addr_data_f3
962 980 * - 0x18 status
963 981 * - 0x1C delta_snapshot
964 982 * - 0x20 delta_f0
965 983 * - 0x24 delta_f0_2
966 984 * - 0x28 delta_f1
967 985 * - 0x2c delta_f2
968 986 * - 0x30 nb_data_by_buffer
969 987 * - 0x34 nb_snapshot_param
970 988 * - 0x38 start_date
971 989 * - 0x3c nb_word_in_buffer
972 990 *
973 991 */
974 992
975 993 set_wfp_data_shaping(); // 0x00 *** R1 R0 SP1 SP0 BW
976 994
977 995 reset_wfp_burst_enable(); // 0x04 *** [run *** burst f2, f1, f0 *** enable f3, f2, f1, f0 ]
978 996
979 997 reset_wfp_buffer_addresses();
980 998
981 999 reset_wfp_status(); // 0x18
982 1000
983 1001 set_wfp_delta_snapshot(); // 0x1c *** 300 s => 0x12bff
984 1002
985 1003 set_wfp_delta_f0_f0_2(); // 0x20, 0x24
986 1004
987 1005 set_wfp_delta_f1(); // 0x28
988 1006
989 1007 set_wfp_delta_f2(); // 0x2c
990 1008
991 1009 DEBUG_PRINTF1("delta_snapshot %x\n", waveform_picker_regs->delta_snapshot)
992 1010 DEBUG_PRINTF1("delta_f0 %x\n", waveform_picker_regs->delta_f0)
993 1011 DEBUG_PRINTF1("delta_f0_2 %x\n", waveform_picker_regs->delta_f0_2)
994 1012 DEBUG_PRINTF1("delta_f1 %x\n", waveform_picker_regs->delta_f1)
995 1013 DEBUG_PRINTF1("delta_f2 %x\n", waveform_picker_regs->delta_f2)
996 1014 // 2688 = 8 * 336
997 1015 waveform_picker_regs->nb_data_by_buffer = 0xa7f; // 0x30 *** 2688 - 1 => nb samples -1
998 1016 waveform_picker_regs->snapshot_param = 0xa80; // 0x34 *** 2688 => nb samples
999 1017 waveform_picker_regs->start_date = 0x7fffffff; // 0x38
1000 1018 //
1001 1019 // coarse time and fine time registers are not initialized, they are volatile
1002 1020 //
1003 1021 waveform_picker_regs->buffer_length = 0x1f8;// buffer length in burst = 3 * 2688 / 16 = 504 = 0x1f8
1004 1022 }
1005 1023
1006 1024 void set_wfp_data_shaping( void )
1007 1025 {
1008 1026 /** This function sets the data_shaping register of the waveform picker module.
1009 1027 *
1010 1028 * The value is read from one field of the parameter_dump_packet structure:\n
1011 1029 * bw_sp0_sp1_r0_r1
1012 1030 *
1013 1031 */
1014 1032
1015 1033 unsigned char data_shaping;
1016 1034
1017 1035 // get the parameters for the data shaping [BW SP0 SP1 R0 R1] in sy_lfr_common1 and configure the register
1018 1036 // waveform picker : [R1 R0 SP1 SP0 BW]
1019 1037
1020 1038 data_shaping = parameter_dump_packet.sy_lfr_common_parameters;
1021 1039
1022 1040 waveform_picker_regs->data_shaping =
1023 1041 ( (data_shaping & 0x20) >> 5 ) // BW
1024 1042 + ( (data_shaping & 0x10) >> 3 ) // SP0
1025 1043 + ( (data_shaping & 0x08) >> 1 ) // SP1
1026 1044 + ( (data_shaping & 0x04) << 1 ) // R0
1027 1045 + ( (data_shaping & 0x02) << 3 ) // R1
1028 1046 + ( (data_shaping & 0x01) << 5 ); // R2
1029 1047 }
1030 1048
1031 1049 void set_wfp_burst_enable_register( unsigned char mode )
1032 1050 {
1033 1051 /** This function sets the waveform picker burst_enable register depending on the mode.
1034 1052 *
1035 1053 * @param mode is the LFR mode to launch.
1036 1054 *
1037 1055 * The burst bits shall be before the enable bits.
1038 1056 *
1039 1057 */
1040 1058
1041 1059 // [0000 0000] burst f2, f1, f0 enable f3 f2 f1 f0
1042 1060 // the burst bits shall be set first, before the enable bits
1043 1061 switch(mode) {
1044 1062 case LFR_MODE_NORMAL:
1045 1063 case LFR_MODE_SBM1:
1046 1064 case LFR_MODE_SBM2:
1047 1065 waveform_picker_regs->run_burst_enable = 0x60; // [0110 0000] enable f2 and f1 burst
1048 1066 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0f; // [1111] enable f3 f2 f1 f0
1049 1067 break;
1050 1068 case LFR_MODE_BURST:
1051 1069 waveform_picker_regs->run_burst_enable = 0x40; // [0100 0000] f2 burst enabled
1052 1070 waveform_picker_regs->run_burst_enable = waveform_picker_regs->run_burst_enable | 0x0c; // [1100] enable f3 and f2
1053 1071 break;
1054 1072 default:
1055 1073 waveform_picker_regs->run_burst_enable = 0x00; // [0000 0000] no burst enabled, no waveform enabled
1056 1074 break;
1057 1075 }
1058 1076 }
1059 1077
1060 1078 void set_wfp_delta_snapshot( void )
1061 1079 {
1062 1080 /** This function sets the delta_snapshot register of the waveform picker module.
1063 1081 *
1064 1082 * The value is read from two (unsigned char) of the parameter_dump_packet structure:
1065 1083 * - sy_lfr_n_swf_p[0]
1066 1084 * - sy_lfr_n_swf_p[1]
1067 1085 *
1068 1086 */
1069 1087
1070 1088 unsigned int delta_snapshot;
1071 1089 unsigned int delta_snapshot_in_T2;
1072 1090
1073 1091 delta_snapshot = parameter_dump_packet.sy_lfr_n_swf_p[0]*256
1074 1092 + parameter_dump_packet.sy_lfr_n_swf_p[1];
1075 1093
1076 1094 delta_snapshot_in_T2 = delta_snapshot * 256;
1077 1095 waveform_picker_regs->delta_snapshot = delta_snapshot_in_T2 - 1; // max 4 bytes
1078 1096 }
1079 1097
1080 1098 void set_wfp_delta_f0_f0_2( void )
1081 1099 {
1082 1100 unsigned int delta_snapshot;
1083 1101 unsigned int nb_samples_per_snapshot;
1084 1102 float delta_f0_in_float;
1085 1103
1086 1104 delta_snapshot = waveform_picker_regs->delta_snapshot;
1087 1105 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1088 1106 delta_f0_in_float =nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 24576.) * 256.;
1089 1107
1090 1108 waveform_picker_regs->delta_f0 = delta_snapshot - floor( delta_f0_in_float );
1091 1109 waveform_picker_regs->delta_f0_2 = 0x30; // 48 = 11 0000, max 7 bits
1092 1110 }
1093 1111
1094 1112 void set_wfp_delta_f1( void )
1095 1113 {
1096 1114 unsigned int delta_snapshot;
1097 1115 unsigned int nb_samples_per_snapshot;
1098 1116 float delta_f1_in_float;
1099 1117
1100 1118 delta_snapshot = waveform_picker_regs->delta_snapshot;
1101 1119 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1102 1120 delta_f1_in_float = nb_samples_per_snapshot / 2. * ( 1. / 256. - 1. / 4096.) * 256.;
1103 1121
1104 1122 waveform_picker_regs->delta_f1 = delta_snapshot - floor( delta_f1_in_float );
1105 1123 }
1106 1124
1107 1125 void set_wfp_delta_f2()
1108 1126 {
1109 1127 unsigned int delta_snapshot;
1110 1128 unsigned int nb_samples_per_snapshot;
1111 1129
1112 1130 delta_snapshot = waveform_picker_regs->delta_snapshot;
1113 1131 nb_samples_per_snapshot = parameter_dump_packet.sy_lfr_n_swf_l[0] * 256 + parameter_dump_packet.sy_lfr_n_swf_l[1];
1114 1132
1115 1133 waveform_picker_regs->delta_f2 = delta_snapshot - nb_samples_per_snapshot / 2;
1116 1134 }
1117 1135
1118 1136 //*****************
1119 1137 // local parameters
1120 1138
1121 1139 void increment_seq_counter_source_id( unsigned char *packet_sequence_control, unsigned int sid )
1122 1140 {
1123 1141 /** This function increments the parameter "sequence_cnt" depending on the sid passed in argument.
1124 1142 *
1125 1143 * @param packet_sequence_control is a pointer toward the parameter sequence_cnt to update.
1126 1144 * @param sid is the source identifier of the packet being updated.
1127 1145 *
1128 1146 * REQ-LFR-SRS-5240 / SSS-CP-FS-590
1129 1147 * The sequence counters shall wrap around from 2^14 to zero.
1130 1148 * The sequence counter shall start at zero at startup.
1131 1149 *
1132 1150 * REQ-LFR-SRS-5239 / SSS-CP-FS-580
1133 1151 * All TM_LFR_SCIENCE_ packets are sent to ground, i.e. destination id = 0
1134 1152 *
1135 1153 */
1136 1154
1137 1155 unsigned short *sequence_cnt;
1138 1156 unsigned short segmentation_grouping_flag;
1139 1157 unsigned short new_packet_sequence_control;
1140 1158 rtems_mode initial_mode_set;
1141 1159 rtems_mode current_mode_set;
1142 1160 rtems_status_code status;
1143 1161
1144 1162 //******************************************
1145 1163 // CHANGE THE MODE OF THE CALLING RTEMS TASK
1146 1164 status = rtems_task_mode( RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &initial_mode_set );
1147 1165
1148 1166 if ( (sid == SID_NORM_SWF_F0) || (sid == SID_NORM_SWF_F1) || (sid == SID_NORM_SWF_F2)
1149 1167 || (sid == SID_NORM_CWF_F3) || (sid == SID_NORM_CWF_LONG_F3)
1150 1168 || (sid == SID_BURST_CWF_F2)
1151 1169 || (sid == SID_NORM_ASM_F0) || (sid == SID_NORM_ASM_F1) || (sid == SID_NORM_ASM_F2)
1152 1170 || (sid == SID_NORM_BP1_F0) || (sid == SID_NORM_BP1_F1) || (sid == SID_NORM_BP1_F2)
1153 1171 || (sid == SID_NORM_BP2_F0) || (sid == SID_NORM_BP2_F1) || (sid == SID_NORM_BP2_F2)
1154 1172 || (sid == SID_BURST_BP1_F0) || (sid == SID_BURST_BP2_F0)
1155 1173 || (sid == SID_BURST_BP1_F1) || (sid == SID_BURST_BP2_F1) )
1156 1174 {
1157 1175 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_NORMAL_BURST;
1158 1176 }
1159 1177 else if ( (sid ==SID_SBM1_CWF_F1) || (sid ==SID_SBM2_CWF_F2)
1160 1178 || (sid == SID_SBM1_BP1_F0) || (sid == SID_SBM1_BP2_F0)
1161 1179 || (sid == SID_SBM2_BP1_F0) || (sid == SID_SBM2_BP2_F0)
1162 1180 || (sid == SID_SBM2_BP1_F1) || (sid == SID_SBM2_BP2_F1) )
1163 1181 {
1164 1182 sequence_cnt = (unsigned short *) &sequenceCounters_SCIENCE_SBM1_SBM2;
1165 1183 }
1166 1184 else
1167 1185 {
1168 1186 sequence_cnt = (unsigned short *) NULL;
1169 1187 PRINTF1("in increment_seq_counter_source_id *** ERR apid_destid %d not known\n", sid)
1170 1188 }
1171 1189
1172 1190 if (sequence_cnt != NULL)
1173 1191 {
1174 1192 segmentation_grouping_flag = TM_PACKET_SEQ_CTRL_STANDALONE << 8;
1175 1193 *sequence_cnt = (*sequence_cnt) & 0x3fff;
1176 1194
1177 1195 new_packet_sequence_control = segmentation_grouping_flag | (*sequence_cnt) ;
1178 1196
1179 1197 packet_sequence_control[0] = (unsigned char) (new_packet_sequence_control >> 8);
1180 1198 packet_sequence_control[1] = (unsigned char) (new_packet_sequence_control );
1181 1199
1182 1200 // increment the sequence counter
1183 1201 if ( *sequence_cnt < SEQ_CNT_MAX)
1184 1202 {
1185 1203 *sequence_cnt = *sequence_cnt + 1;
1186 1204 }
1187 1205 else
1188 1206 {
1189 1207 *sequence_cnt = 0;
1190 1208 }
1191 1209 }
1192 1210
1193 1211 //*************************************
1194 1212 // RESTORE THE MODE OF THE CALLING TASK
1195 1213 status = rtems_task_mode( initial_mode_set, RTEMS_PREEMPT_MASK, &current_mode_set );
1196 1214 }
General Comments 0
You need to be logged in to leave comments. Login now