tc_handler.c
949 lines
| 30.9 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 | |||
|
r75 | unsigned char time[6]; | |
|
r35 | rtems_id queue_rcv_id; | |
rtems_id queue_snd_id; | |||
|
r82 | status = get_message_queue_id_recv( &queue_rcv_id ); | |
|
r35 | if (status != RTEMS_SUCCESSFUL) | |
{ | |||
|
r82 | PRINTF1("in ACTN *** ERR get_message_queue_id_recv %d\n", status) | |
|
r35 | } | |
|
r82 | status = get_message_queue_id_send( &queue_snd_id ); | |
|
r35 | if (status != RTEMS_SUCCESSFUL) | |
{ | |||
|
r82 | PRINTF1("in ACTN *** ERR get_message_queue_id_send %d\n", status) | |
|
r35 | } | |
|
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); | |
|
r75 | getTime( time ); // set time to the current time | |
|
r77 | 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: | |||
|
r75 | result = action_reset( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
case TC_SUBTYPE_LOAD_COMM: | |||
|
r33 | result = action_load_common_par( &TC ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r11 | break; | |
// | |||
|
r9 | case TC_SUBTYPE_LOAD_NORM: | |
|
r75 | result = action_load_normal_par( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_BURST: | |
|
r75 | result = action_load_burst_par( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_SBM1: | |
|
r75 | result = action_load_sbm1_par( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_LOAD_SBM2: | |
|
r75 | result = action_load_sbm2_par( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_DUMP: | |
|
r40 | result = action_dump_par( queue_snd_id ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_ENTER: | |
|
r111 | result = action_enter_mode( &TC, queue_snd_id ); | |
|
r104 | 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 ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_EN_CAL: | |
|
r75 | result = action_enable_calibration( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_DIS_CAL: | |
|
r75 | result = action_disable_calibration( &TC, queue_snd_id, time ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | case TC_SUBTYPE_UPDT_TIME: | |
|
r33 | result = action_update_time( &TC ); | |
|
r104 | close_action( &TC, result, queue_snd_id ); | |
|
r9 | break; | |
|
r11 | // | |
|
r9 | default: | |
break; | |||
} | |||
} | |||
} | |||
} | |||
//*********** | |||
// TC ACTIONS | |||
|
r15 | ||
|
r75 | int action_reset(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time) | |
|
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 | |||
* | |||
*/ | |||
|
r168 | printf("this is the end!!!\n"); | |
exit(0); | |||
|
r75 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time ); | |
|
r21 | return LFR_DEFAULT; | |
|
r9 | } | |
|
r111 | 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; | |||
|
r111 | unsigned int *transitionCoarseTime_ptr; | |
unsigned int transitionCoarseTime; | |||
|
r112 | unsigned char * bytePosPtr; | |
|
r33 | ||
|
r112 | bytePosPtr = (unsigned char *) &TC->packetID; | |
requestedMode = bytePosPtr[ BYTE_POS_CP_MODE_LFR_SET ]; | |||
transitionCoarseTime_ptr = (unsigned int *) ( &bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME ] ); | |||
|
r111 | transitionCoarseTime = (*transitionCoarseTime_ptr) & 0x7fffffff; | |
|
r33 | ||
|
r109 | status = check_mode_value( requestedMode ); | |
|
r110 | ||
|
r112 | if ( status != LFR_SUCCESSFUL ) // the mode value is inconsistent | |
|
r33 | { | |
|
r112 | send_tm_lfr_tc_exe_inconsistent( TC, queue_id, BYTE_POS_CP_MODE_LFR_SET, requestedMode ); | |
|
r33 | } | |
|
r111 | else // the mode value is consistent, check the transition | |
|
r33 | { | |
|
r109 | status = check_mode_transition(requestedMode); | |
|
r111 | if (status != LFR_SUCCESSFUL) | |
|
r109 | { | |
|
r111 | PRINTF("ERR *** in action_enter_mode *** check_mode_transition\n") | |
|
r104 | send_tm_lfr_tc_exe_not_executable( TC, queue_id ); | |
|
r37 | } | |
|
r33 | } | |
|
r111 | if ( status == LFR_SUCCESSFUL ) // the transition is valid, enter the mode | |
{ | |||
status = check_transition_date( transitionCoarseTime ); | |||
if (status != LFR_SUCCESSFUL) | |||
{ | |||
PRINTF("ERR *** in action_enter_mode *** check_transition_date\n") | |||
|
r112 | send_tm_lfr_tc_exe_inconsistent( TC, queue_id, | |
BYTE_POS_CP_LFR_ENTER_MODE_TIME, | |||
bytePosPtr[ BYTE_POS_CP_LFR_ENTER_MODE_TIME + 3 ] ); | |||
|
r111 | } | |
} | |||
if ( status == LFR_SUCCESSFUL ) // the date is valid, enter the mode | |||
{ | |||
PRINTF1("OK *** in action_enter_mode *** enter mode %d\n", requestedMode); | |||
status = enter_mode( requestedMode, transitionCoarseTime ); | |||
} | |||
|
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; | |||
|
r104 | unsigned int status; | |
unsigned char mode; | |||
|
r112 | unsigned char * bytePosPtr; | |
bytePosPtr = (unsigned char *) &TC->packetID; | |||
|
r18 | ||
|
r107 | // check LFR mode | |
|
r112 | mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET5 ] & 0x1e) >> 1; | |
|
r104 | status = check_update_info_hk_lfr_mode( mode ); | |
|
r107 | if (status == LFR_SUCCESSFUL) // check TDS mode | |
|
r104 | { | |
|
r112 | mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0xf0) >> 4; | |
|
r104 | status = check_update_info_hk_tds_mode( mode ); | |
} | |||
|
r107 | if (status == LFR_SUCCESSFUL) // check THR mode | |
|
r104 | { | |
|
r112 | mode = (bytePosPtr[ BYTE_POS_UPDATE_INFO_PARAMETERS_SET6 ] & 0x0f); | |
|
r104 | status = check_update_info_hk_thr_mode( mode ); | |
} | |||
|
r107 | if (status == LFR_SUCCESSFUL) // if the parameter check is successful | |
|
r104 | { | |
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); | |||
} | |||
result = status; | |||
|
r23 | ||
return result; | |||
} | |||
|
r75 | int action_enable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time) | |
|
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; | |||
|
r104 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time ); | |
result = LFR_DEFAULT; | |||
|
r23 | return result; | |
} | |||
|
r75 | int action_disable_calibration(ccsdsTelecommandPacket_t *TC, rtems_id queue_id, unsigned char *time) | |
|
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; | |||
|
r104 | send_tm_lfr_tc_exe_not_implemented( TC, queue_id, time ); | |
result = LFR_DEFAULT; | |||
|
r23 | 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]; | |||
|
r109 | ||
|
r23 | 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); | |||
return LFR_SUCCESSFUL; | |||
} | |||
//******************* | |||
// ENTERING THE MODES | |||
|
r109 | int check_mode_value( unsigned char requestedMode ) | |
{ | |||
int status; | |||
|
r23 | ||
|
r109 | if ( (requestedMode != LFR_MODE_STANDBY) | |
&& (requestedMode != LFR_MODE_NORMAL) && (requestedMode != LFR_MODE_BURST) | |||
&& (requestedMode != LFR_MODE_SBM1) && (requestedMode != LFR_MODE_SBM2) ) | |||
{ | |||
status = LFR_DEFAULT; | |||
} | |||
else | |||
{ | |||
status = LFR_SUCCESSFUL; | |||
} | |||
return status; | |||
} | |||
int check_mode_transition( unsigned char requestedMode ) | |||
|
r23 | { | |
|
r77 | /** This function checks the validity of the transition requested by the TC_LFR_ENTER_MODE. | |
* | |||
* @param requestedMode is the mode requested by the TC_LFR_ENTER_MODE | |||
* | |||
* @return LFR directive status codes: | |||
* - LFR_SUCCESSFUL - the transition is authorized | |||
* - LFR_DEFAULT - the transition is not authorized | |||
* | |||
*/ | |||
|
r23 | 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 | } | |
|
r111 | int check_transition_date( unsigned int transitionCoarseTime ) | |
{ | |||
int status; | |||
unsigned int localCoarseTime; | |||
unsigned int deltaCoarseTime; | |||
status = LFR_SUCCESSFUL; | |||
if (transitionCoarseTime == 0) // transition time = 0 means an instant transition | |||
{ | |||
status = LFR_SUCCESSFUL; | |||
} | |||
else | |||
{ | |||
localCoarseTime = time_management_regs->coarse_time & 0x7fffffff; | |||
|
r112 | if ( transitionCoarseTime <= localCoarseTime ) // SSS-CP-EQS-322 | |
|
r111 | { | |
status = LFR_DEFAULT; | |||
PRINTF2("ERR *** in check_transition_date *** transition = %x, local = %x\n", transitionCoarseTime, localCoarseTime) | |||
} | |||
if (status == LFR_SUCCESSFUL) | |||
{ | |||
deltaCoarseTime = transitionCoarseTime - localCoarseTime; | |||
if ( deltaCoarseTime > 3 ) // SSS-CP-EQS-323 | |||
{ | |||
status = LFR_DEFAULT; | |||
PRINTF1("ERR *** in check_transition_date *** deltaCoarseTime = %x\n", deltaCoarseTime) | |||
} | |||
} | |||
} | |||
return status; | |||
} | |||
|
r109 | int stop_current_mode( void ) | |
|
r20 | { | |
|
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 | ||
|
r99 | // (1) mask interruptions | |
|
r31 | LEON_Mask_interrupt( IRQ_WAVEFORM_PICKER ); // mask waveform picker interrupt | |
|
r103 | LEON_Mask_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt | |
|
r99 | ||
// (2) clear interruptions | |||
LEON_Clear_interrupt( IRQ_WAVEFORM_PICKER ); // clear waveform picker interrupt | |||
|
r103 | LEON_Clear_interrupt( IRQ_SPECTRAL_MATRIX ); // clear spectral matrix interrupt | |
|
r99 | ||
|
r110 | // (3) reset waveform picker registers | |
|
r47 | reset_wfp_burst_enable(); // reset burst and enable bits | |
reset_wfp_status(); // reset all the status bits | |||
|
r110 | ||
// (4) reset spectral matrices registers | |||
|
r106 | set_irq_on_new_ready_matrix( 0 ); // stop the spectral matrices | |
set_run_matrix_spectral( 0 ); // run_matrix_spectral is set to 0 | |||
reset_extractSWF(); // reset the extractSWF flag to false | |||
|
r99 | ||
// <Spectral Matrices simulator> | |||
LEON_Mask_interrupt( IRQ_SM_SIMULATOR ); // mask spectral matrix interrupt simulator | |||
timer_stop( (gptimer_regs_t*) REGS_ADDR_GPTIMER, TIMER_SM_SIMULATOR ); | |||
LEON_Clear_interrupt( IRQ_SM_SIMULATOR ); // clear spectral matrix interrupt simulator | |||
// </Spectral Matrices simulator> | |||
|
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 | } | |
|
r111 | int enter_mode( unsigned char mode, unsigned int transitionCoarseTime ) | |
|