tc_handler.c
768 lines
| 24.0 KiB
| text/x-c
|
CLexer
/ src / tc_handler.c
|
r40 | /** Functions and tasks related to TeleCommand handling. | |
* | |||
* @file | |||
* @author P. LEROY | |||
* | |||
* A group of functions to handle TeleCommands:\n | |||
* action launching\n | |||
* TC parsing\n | |||
* ... | |||
* | |||
*/ | |||
#include "tc_handler.h" | |||
|
r5 | ||
|
r7 | //*********** | |
// RTEMS TASK | |||
|
r5 | ||
|
r9 | rtems_task actn_task( rtems_task_argument unused ) | |
{ | |||
|
r40 | /** This RTEMS task is responsible for launching actions upton the reception of valid TeleCommands. | |
* | |||
* @param unused is the starting argument of the RTEMS task | |||
* | |||
* The ACTN task waits for data coming from an RTEMS msesage queue. When data arrives, it launches specific actions depending | |||
* on the incoming TeleCommand. | |||
* | |||
*/ | |||
|
r23 | int result; | |
rtems_status_code status; // RTEMS status code | |||
ccsdsTelecommandPacket_t TC; // TC sent to the ACTN task | |||
size_t size; // size of the incoming TC packet | |||
unsigned char subtype; // subtype of the current TC packet | |||
|
r35 | rtems_id queue_rcv_id; | |
rtems_id queue_snd_id; | |||
|
r42 | status = rtems_message_queue_ident( misc_name[QUEUE_RECV], 0, &queue_rcv_id ); | |
|
r35 | if (status != RTEMS_SUCCESSFUL) | |
{ | |||
PRINTF1("in ACTN *** ERR getting queue_rcv_id %d\n", status) | |||
} | |||
|
r42 | status = rtems_message_queue_ident( misc_name[QUEUE_SEND], 0, &queue_snd_id ); | |
|
r35 | if (status != RTEMS_SUCCESSFUL) | |
{ | |||
PRINTF1("in ACTN *** ERR getting queue_snd_id %d\n", status) | |||
} | |||
|
r23 | ||
result = LFR_SUCCESSFUL; | |||
subtype = 0; // subtype of the current TC packet | |||
|
r5 | ||
|
r35 | BOOT_PRINTF("in ACTN *** \n") | |
|
r11 | ||
|
r9 | while(1) | |
{ | |||
|
r35 | status = rtems_message_queue_receive( queue_rcv_id, (char*) &TC, &size, | |
|
r9 | RTEMS_WAIT, RTEMS_NO_TIMEOUT); | |
|
r22 | if (status!=RTEMS_SUCCESSFUL) PRINTF1("ERR *** in task ACTN *** error receiving a message, code %d \n", status) | |
|
r9 | else | |
{ | |||
|
r23 | subtype = TC.serviceSubType; | |
|
r9 | switch(subtype) | |
{ | |||
case TC_SUBTYPE_RESET: | |||
|
r35 | result = action_reset( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
case TC_SUBTYPE_LOAD_COMM: | |||
|
r33 | result = action_load_common_par( &TC ); | |
|
r35 | close_action( &TC, result, queue_snd_id ); | |
|
r11 | break; | |
// | |||
|
r9 | case TC_SUBTYPE_LOAD_NORM: | |
|
r35 | result = action_load_normal_par( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_BURST: | |
|
r35 | result = action_load_burst_par( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_SBM1: | |
|
r35 | result = action_load_sbm1_par( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_SBM2: | |
|
r35 | result = action_load_sbm2_par( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_DUMP: | |
|
r40 | result = action_dump_par( queue_snd_id ); | |
|
r35 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_ENTER: | |
|
r35 | result = action_enter_mode( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_UPDT_INFO: | |
|
r35 | result = action_update_info( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_EN_CAL: | |
|
r35 | result = action_enable_calibration( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_DIS_CAL: | |
|
r35 | result = action_disable_calibration( &TC, queue_snd_id ); | |
close_action( &TC, result, queue_snd_id ); | |||
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_UPDT_TIME: | |
|
r33 | result = action_update_time( &TC ); | |
|
r35 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | default: | |
break; | |||
} | |||
} | |||
} | |||
} | |||
//*********** | |||
// TC ACTIONS | |||
|
r15 | ||
|
r35 | int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id) | |
|
r9 | { | |
|
r40 | /** This function executes specific actions when a TC_LFR_RESET TeleCommand has been received. | |
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
*/ | |||
|
r35 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id ); | |
|
r21 | return LFR_DEFAULT; | |
|
r9 | } | |
|
r35 | int action_enter_mode(ccsdsTelecommandPacket_t *TC, rtems_id queue_id) | |
|
r33 | { | |
|
r40 | /** This function executes specific actions when a TC_LFR_ENTER_MODE TeleCommand has been received. | |
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
*/ | |||
|
r33 | rtems_status_code status; | |
unsigned char requestedMode; | |||
requestedMode = TC->dataAndCRC[1]; | |||
|
r37 | if ( (requestedMode != LFR_MODE_STANDBY) | |
&& (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST) | |||
&& (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) ) | |||
|
r33 | { | |
|
r37 | status = RTEMS_UNSATISFIED; | |
send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_LFR_MODE, requestedMode ); | |||
|
r33 | } | |
else | |||
{ | |||
|
r37 | printf("try to enter mode %d\n", requestedMode); | |
#ifdef PRINT_TASK_STATISTICS | |||
if (requestedMode != LFR_MODE_STANDBY) | |||
{ | |||
rtems_cpu_usage_reset(); | |||
maxCount = 0; | |||
} | |||
#endif | |||
status = transition_validation(requestedMode); | |||
if ( status == LFR_SUCCESSFUL ) { | |||
if ( lfrCurrentMode != LFR_MODE_STANDBY) | |||
{ | |||
status = stop_current_mode(); | |||
} | |||
if (status != RTEMS_SUCCESSFUL) | |||
{ | |||
PRINTF("ERR *** in action_enter *** stop_current_mode\n") | |||
} | |||
status = enter_mode(requestedMode, TC); | |||
} | |||
else | |||
{ | |||
PRINTF("ERR *** in action_enter *** transition rejected\n") | |||
send_tm_lfr_tc_exe_not_executable( TC, queue_id ); | |||
} | |||
|
r33 | } | |
return status; | |||
} | |||
|
r40 | int action_update_info(ccsdsTelecommandPacket_t *TC, rtems_id queue_id) | |
{ | |||
/** This function executes specific actions when a TC_LFR_UPDATE_INFO TeleCommand has been received. | |||
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
|
r46 | * @return LFR directive status code: | |
* - LFR_DEFAULT | |||
* - LFR_SUCCESSFUL | |||
* | |||
|
r40 | */ | |
|
r23 | unsigned int val; | |
int result; | |||
result = LFR_DEFAULT; | |||
|
r18 | ||
|
r46 | val = housekeeping_packet.hk_lfr_update_info_tc_cnt[0] * 256 | |
+ housekeeping_packet.hk_lfr_update_info_tc_cnt[1]; | |||
val++; | |||
housekeeping_packet.hk_lfr_update_info_tc_cnt[0] = (unsigned char) (val >> 8); | |||
housekeeping_packet.hk_lfr_update_info_tc_cnt[1] = (unsigned char) (val); | |||
|
r23 | ||
return result; | |||
} | |||
|
r35 | int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id) | |
|
r23 | { | |
|
r40 | /** This function executes specific actions when a TC_LFR_ENABLE_CALIBRATION TeleCommand has been received. | |
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
*/ | |||
|
r23 | int result; | |
unsigned char lfrMode; | |||
result = LFR_DEFAULT; | |||
lfrMode = (housekeeping_packet.lfr_status_word[0] & 0xf0) >> 4; | |||
|
r51 | if ( (lfrMode == LFR_MODE_STANDBY) || (lfrMode == LFR_MODE_BURST) || (lfrMode == LFR_MODE_SBM2) ) { | |
|
r35 | send_tm_lfr_tc_exe_not_executable( TC, queue_id ); | |
|
r23 | result = LFR_DEFAULT; | |
} | |||
else { | |||
|
r35 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id ); | |
|
r23 | result = LFR_DEFAULT; | |
} | |||
return result; | |||
} | |||
|
r35 | int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id) | |
|
r23 | { | |
|
r40 | /** This function executes specific actions when a TC_LFR_DISABLE_CALIBRATION TeleCommand has been received. | |
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
*/ | |||
|
r23 | int result; | |
unsigned char lfrMode; | |||
result = LFR_DEFAULT; | |||
lfrMode = (housekeeping_packet.lfr_status_word[0] & 0xf0) >> 4; | |||
|
r51 | if ( (lfrMode == LFR_MODE_STANDBY) || (lfrMode == LFR_MODE_BURST) || (lfrMode == LFR_MODE_SBM2) ) { | |
|
r35 | send_tm_lfr_tc_exe_not_executable( TC, queue_id ); | |
|
r23 | result = LFR_DEFAULT; | |
} | |||
else { | |||
|
r35 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id ); | |
|
r23 | result = LFR_DEFAULT; | |
} | |||
return result; | |||
} | |||
|
r33 | int action_update_time(ccsdsTelecommandPacket_t *TC) | |
|
r23 | { | |
|
r40 | /** This function executes specific actions when a TC_LFR_UPDATE_TIME TeleCommand has been received. | |
* | |||
* @param TC points to the TeleCommand packet that is being processed | |||
* @param queue_id is the id of the queue which handles TM transmission by the SpaceWire driver | |||
* | |||
|
r46 | * @return LFR_SUCCESSFUL | |
* | |||
|
r40 | */ | |
|
r23 | unsigned int val; | |
|
r19 | ||
|
r23 | time_management_regs->coarse_time_load = (TC->dataAndCRC[0] << 24) | |
+ (TC->dataAndCRC[1] << 16) | |||
+ (TC->dataAndCRC[2] << 8) | |||
+ TC->dataAndCRC[3]; | |||
val = housekeeping_packet.hk_lfr_update_time_tc_cnt[0] * 256 | |||
+ housekeeping_packet.hk_lfr_update_time_tc_cnt[1]; | |||
val++; | |||
housekeeping_packet.hk_lfr_update_time_tc_cnt[0] = (unsigned char) (val >> 8); | |||
housekeeping_packet.hk_lfr_update_time_tc_cnt[1] = (unsigned char) (val); | |||
|
r33 | time_management_regs->ctrl = time_management_regs->ctrl | 1; | |
|
r23 | ||
return LFR_SUCCESSFUL; | |||
} | |||
//******************* | |||
// ENTERING THE MODES | |||
int transition_validation(unsigned char requestedMode) | |||
{ | |||
int status; | |||
|
r19 | ||
|
r23 | switch (requestedMode) | |
{ | |||
case LFR_MODE_STANDBY: | |||
|
r33 | if ( lfrCurrentMode == LFR_MODE_STANDBY ) { | |
|
r23 | status = LFR_DEFAULT; | |
} | |||
else | |||
{ | |||
status = LFR_SUCCESSFUL; | |||
} | |||
break; | |||
case LFR_MODE_NORMAL: | |||
|
r33 | if ( lfrCurrentMode == LFR_MODE_NORMAL ) { | |
|
r23 | status = LFR_DEFAULT; | |
} | |||
else { | |||
status = LFR_SUCCESSFUL; | |||
} | |||
break; | |||
case LFR_MODE_BURST: | |||
|
r33 | if ( lfrCurrentMode == LFR_MODE_BURST ) { | |
|
r23 | status = LFR_DEFAULT; | |
} | |||
else { | |||
status = LFR_SUCCESSFUL; | |||
} | |||
break; | |||
case LFR_MODE_SBM1: | |||
|
r33 | if ( lfrCurrentMode == LFR_MODE_SBM1 ) { | |
|
r23 | status = LFR_DEFAULT; | |
} | |||
else { | |||
status = LFR_SUCCESSFUL; | |||
} | |||
break; | |||
case LFR_MODE_SBM2: | |||
|
r33 | if ( lfrCurrentMode == LFR_MODE_SBM2 ) { | |
|
r23 | status = LFR_DEFAULT; | |
} | |||
else { | |||
status = LFR_SUCCESSFUL; | |||
} | |||
break; | |||
default: | |||
status = LFR_DEFAULT; | |||
break; | |||
} | |||
|
r19 | ||
|
r21 | return status; | |
|
r10 | } | |
|
r20 | int stop_current_mode() | |
{ | |||
|
r40 | /** This function stops the current mode by masking interrupt lines and suspending science tasks. | |
* | |||
* @return RTEMS directive status codes: | |||
* - RTEMS_SUCCESSFUL - task restarted successfully | |||
* - RTEMS_INVALID_ID - task id invalid | |||
* - RTEMS_ALREADY_SUSPENDED - task already suspended | |||
* | |||
*/ | |||
|
r21 | rtems_status_code status; | |
|
r23 | ||
status = RTEMS_SUCCESSFUL; | |||
|
r22 | ||
|
r31 | #ifdef GSA | |
LEON_Mask_interrupt( IRQ_WF ); // mask waveform interrupt (coming from the timer VHDL IP) | |||
|
r20 | LEON_Clear_interrupt( IRQ_WF ); // clear waveform interrupt (coming from the timer VHDL IP) | |
|
r31 | timer_stop( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_WF_SIMULATOR ); | |
#else | |||
|
r47 | // mask interruptions | |
|
r31 | LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt | |
|
r33 | LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // mask spectral matrix interrupt | |
|
r47 | // reset registers | |
reset_wfp_burst_enable(); // reset burst and enable bits | |||
reset_wfp_status(); // reset all the status bits | |||
// creal interruptions | |||
LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt | |||
LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectarl matrix interrupt | |||
|
r31 | #endif | |
|
r33 | //********************** | |
|
r20 | // suspend several tasks | |
|
r35 | if (lfrCurrentMode != LFR_MODE_STANDBY) { | |
|
r40 | status = suspend_science_tasks(); | |
|
r21 | } | |
|
r20 | ||
|
r22 | if (status != RTEMS_SUCCESSFUL) | |
{ | |||
|
r40 | PRINTF1("in stop_current_mode *** in suspend_science_tasks *** ERR code: %d\n", status) | |
|
r22 | } | |
|
r21 | return status; | |
|
r20 | } | |
|
r23 | int enter_mode(unsigned char mode, ccsdsTelecommandPacket_t *TC ) | |
|
r20 | { | |
|
r21 | rtems_status_code status; | |
|
r20 | ||
|
r33 | status = RTEMS_UNSATISFIED; | |
housekeeping_packet.lfr_status_word[0] = (unsigned char) ((mode << 4) + 0x0d); | |||
|
r51 | updateLFRCurrentMode(); | |
|
r33 | ||
|
r23 | switch(mode){ | |
case LFR_MODE_STANDBY: | |||
|
r51 | status = enter_standby_mode( ); | |
|
r23 | break; | |
case LFR_MODE_NORMAL: | |||
|
r51 | status = enter_normal_mode( ); | |
|
r23 | break; | |
case LFR_MODE_BURST: | |||
|
r51 | status = enter_burst_mode( ); | |
|
r23 | break; | |
case LFR_MODE_SBM1: | |||
|
r51 | status = enter_sbm1_mode( ); | |
|
r23 | break; | |
case LFR_MODE_SBM2: | |||
|
r51 | status = enter_sbm2_mode( ); | |
|
r23 | break; | |
default: | |||
status = RTEMS_UNSATISFIED; | |||
|
r21 | } | |
|
r20 | ||
|
r33 | if (status != RTEMS_SUCCESSFUL) | |
|
r23 | { | |
|
r33 | PRINTF("in enter_mode *** ERR\n") | |
status = RTEMS_UNSATISFIED; | |||
|
r23 | } | |
|
r21 | ||
return status; | |||
|
r20 | } | |
|
r33 | int enter_standby_mode() | |
|
r20 | { | |
|
r34 | PRINTF1("maxCount = %d\n", maxCount) | |
|
r33 | #ifdef PRINT_TASK_STATISTICS | |
rtems_cpu_usage_report(); | |||
#endif | |||
|
r34 | ||
#ifdef PRINT_STACK_REPORT | |||
rtems_stack_checker_report_usage(); | |||
#endif | |||
|
r23 | return LFR_SUCCESSFUL; | |
|
r22 | } | |
|
r33 | int enter_normal_mode() | |
|
r22 | { | |
rtems_status_code status; | |||
|
r32 | status = restart_science_tasks(); | |
|
r22 | ||
#ifdef GSA | |||
|
r31 | timer_start( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_WF_SIMULATOR ); | |
timer_start( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_SM_SIMULATOR ); | |||
|
r30 | LEON_Clear_interrupt( IRQ_WF ); | |
LEON_Unmask_interrupt( IRQ_WF ); | |||
|
r32 | // | |
set_local_nb_interrupt_f0_MAX(); | |||
|
r31 | LEON_Clear_interrupt( IRQ_SM ); // the IRQ_SM seems to be incompatible with the IRQ_WF on the xilinx board | |
LEON_Unmask_interrupt( IRQ_SM ); | |||
|
r22 | #else | |
|
r33 | //**************** | |
|
r32 | // waveform picker | |
|
r47 | reset_waveform_picker_regs(); | |
set_wfp_burst_enable_register(LFR_MODE_NORMAL); | |||
|
r30 | LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); | |
LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER ); | |||
|
r33 | //**************** | |
|
r32 | // spectral matrix | |
|
r23 | #endif | |
return status; | |||
} | |||
|
r33 | int enter_burst_mode() | |
|
r23 | { | |
rtems_status_code status; | |||
|
r32 | status = restart_science_tasks(); | |
|
r23 | ||
#ifdef GSA | |||
|
r33 | LEON_Unmask_interrupt( IRQ_SM ); | |
|
r23 | #else | |
|
r47 | reset_waveform_picker_regs(); | |
set_wfp_burst_enable_register(LFR_MODE_BURST); | |||
|
r33 | LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); | |
LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER ); | |||
|
r20 | #endif | |
|
r22 | ||
return status; | |||
} | |||
|
r33 | int enter_sbm1_mode() | |
|
r22 | { | |
rtems_status_code status; | |||
|
r32 | status = restart_science_tasks(); | |
|
r22 | ||
|
r32 | set_local_sbm1_nb_cwf_max(); | |
reset_local_sbm1_nb_cwf_sent(); | |||
|
r23 | ||
#ifdef GSA | |||
|
r33 | LEON_Unmask_interrupt( IRQ_SM ); | |
|
r23 | #else | |
|
r47 | reset_waveform_picker_regs(); | |
set_wfp_burst_enable_register(LFR_MODE_SBM1); | |||
|
r23 | LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); | |
LEON_Unmask_interrupt( IRQ_WAVEFORM_PICKER ); | |||
|
r34 | // SM simulation |