// $RCSfile: hk_ask.c,v $Revision: 1.83 $Date: 2005/03/11 15:08:57 //! Collects HK data from subss and OBS, organises it into TM packets, passes the packets to TMTC_if. #include "hk_ask.dox" #include "allnodes.h" #include "node1.h" #include "configura.h" #include "pubfuncs.h" #include "err_hdl.h" #include "tables.h" #include "conf_tab.h" #include "hs1.h" #include "cmd_seq.h" #include "data_hdl.h" #include "hs_hdl.h" #include "ls.h" #include "res_chk.h" #include "cmd_exec.h" #include "hs_lib.h" #include "ls_hdl.h" #include "data_hdl.h" #include "MM_misc.h" #include "VM_lib.h" #include "hs0.h" #include "init1553.h" #include "hk_ask.h" //---- Global variables -------------------------------------------------------- unsigned int Hk_enable = TRUE; //!< Controls HK enable/disable unsigned int HK_is_asking_spectrometry = 0; //----- Defines ---------------------------------------------------------------- #define HK_FCU_ERRS_LEN 189 /*!< length of FCU errors vector */ #define SPECTR_HK_VALID_IDX 23 // indexes for writing the transfer counters into the hk block #define WBSV_TRANSFER_CNT_HK_IDX 50 #define WBSH_TRANSFER_CNT_HK_IDX 51 #define HRSV_TRANSFER_CNT_HK_IDX 52 #define HRSH_TRANSFER_CNT_HK_IDX 53 #define LC_SS_OFF 0xAA0000AA // Code for SS off to be substituted to actual HK data #define FC_SS_OFF 0xBB0000BB // Code for SS off to be substituted to actual HK data // offset to the buffer of each subsystem (16 bit words) #define HK_FRAME_HRSH_OFFSET HK_TM_HEADER+MAX_ICU_HK*2 #define HK_FRAME_HRSV_OFFSET HK_FRAME_HRSH_OFFSET+HRS_HK_LEN #define HK_FRAME_WBSH_OFFSET HK_FRAME_HRSV_OFFSET+HRS_HK_LEN #define HK_FRAME_WBSV_OFFSET HK_FRAME_WBSH_OFFSET+WBS_HK_LEN // amount of HK words for HRS and WBS #define HS_HK_LEN 2*WBS_HK_LEN+2*HRS_HK_LEN // base offset in the HK buffer that points to the start of HK that come from the Low Serial #define BASE_HK_LS HK_FRAME_WBSV_OFFSET+WBS_HK_LEN //---- Local variables -------------------------------------------------------- static unsigned int word_num; //!< Counters of the number of 16bit words added to HK data vector static unsigned int singlehk_word_num; static K_TIMER * Hk_Timer; //!< HK Timer static unsigned int Hk_wait = 4000; //!< wait interval for HK request timer in milliseconds (default, 5 secs) static K_BLOCK hk_ess_block; //!< Pool block for essential houskeeping static K_BLOCK hk_block; //!< Pool block for houskeeping static K_BLOCK hk_single_block; //!< Pool block for non periodic houskeeping static int * pdata_hs[4]; //!< Pointers to hk data of the hs instruments within the hk_block static int * pdata_obs; // initialized by hk_get_block() to point to the area where icu hk are to be written // Errors static int HK_error_count_FCU_8C_on = 1; //!< FCU error count on (1) or off (0) static int HK_error_count_FCU_8D_on = 1; //!< FCU error count on (1) or off (0) static int HK_error_count_FCU_8F_on = 1; //!< FCU error count on (1) or off (0) static int HK_N_breach_8C = 10; //!< Maximum numbers of breach for 8C commands static int HK_N_breach_8D = 10; //!< Maximum numbers of breach for 8D commands static int HK_N_breach_8F = 10; //!< Maximum numbers of breach for 8F commands static unsigned int HK_FCU_errs[HK_FCU_ERRS_LEN]; //!< Store space for the error codes returned from FCU // Static error counters static int FCU_err8C_counter = 0; //!< error counter for type 8C errors static int FCU_err8D_counter = 0; //!< error counter for type 8D errors static int FCU_err8F_counter = 0; //!< error counter for type 8F errors // Limits static int HK_N_breach_wbsh = 10, HK_limit_wbsh = 1638, HK_check_wbsh = 1; //!< Max number of breach, limit and boolean on/off for wbsh static int HK_N_breach_wbsv = 10, HK_limit_wbsv = 1638, HK_check_wbsv = 1; //!< Max number of breach, limit and boolean on/off for wbsv static int HK_N_breach_htrh = 10, HK_limit_htrh = 63168, HK_check_htrh = 1; //!< Max number of breach, limit and boolean on/off for htrh static int HK_N_breach_htrv = 10, HK_limit_htrv = 63168, HK_check_htrv = 1; //!< Max number of breach, limit and boolean on/off for htrv static int HK_N_breach_lcu = 10, HK_limit_lcu_max = 22028, HK_limit_lcu_min = 20717, HK_check_lcu = 1; //!< Max number of breach, limit and boolean on/off for lcu temperature int HK_LCUnonresp_Nbreach = 700, HK_LCUnonresp_check = 1; //!< Max number of breach and boolean on/off for lcu non response check static int HK_LCUmode_Nbreach = 1, HK_LCUmode_check = 1; //!< Max number of breach and boolean on/off for lcu mode check int HK_LCUcrc_check = 0; //!< boolean on/off for lcu periodic crc check static int HK_breach_wbsh = 0; //!< current number of breach static int HK_breach_wbsv = 0; //!< current number of breach static int HK_breach_htrh = 0; //!< current number of breach static int HK_breach_htrv = 0; //!< current number of breach static int HK_breach_lcu = 0; //!< current number of breach static int HK_breach_lcu_mode = 0; //!< current number of breach int HK_lcu_nonres_breach = 0; // to count the times that the LCU does not respond to a HK request int HK_lcu_nonres_ok = 0; // to count the times that the LCU does respond to a HK request //---- Local functions -------------------------------------------------------- void hk_issue_ls_spectrom( void ); void hk_issue_ls_FCU_LCU( void ); void hk_prepare_data(void); void hk_send_data(void); void hk_ess_prepare_data(void); void hk_ess_send_data(void); int hk_get_block(void); int hk_ess_get_block(void); void hk_error_count(void); void hk_limit_check(void); int hk_this_limit_check(int signed_HK, unsigned int*source, int byte_pos, int limit_val, int* n_breach); int hk_lcu_limit_check(unsigned int*source, int byte_pos, int limit_val_max, int limit_val_min, int* n_breach); void hk_switch_LCU_crc_chk_on (TC_packet * packet); void hk_LCU_crc_chk ( void ); //-------------- hk_ask -------------------------------------------------------- //! Task hk_ask: issues commands to subsyss to produce HK data, collects data, forms a sequence of HK TM packets and sends them to TM void hk_ask (void) { // Start of task: run once section: set the hk period to 3 secs Hk_Timer = KS_LowTimerGet(); // Create a Timer KS_LowTimerStart(Hk_Timer, 5, Hk_wait, HK_REQ_SEMA); // HK_REQ_SEMA semaphore will be signalled every Hk_wait msecs: HK_wait CANNOT be 0!!! // initial delay set to 5 ms in order to allow the lowest priority task (res_chk) to start (this solves spr 356) // Wait loop on HK_REQ_SEMA while(1) { // Test semaphore KS_SemaTestW(HK_REQ_SEMA); // flush the semaphore KS_SemaReset(HK_REQ_SEMA); // restarts the hk ask timer in order to trigger the next hk round KS_LowTimerRestart(Hk_Timer, Hk_wait, Hk_wait); //HK_wait CANNOT be 0!!! But this is guaranteed // check if hk enabled if (Hk_enable == FALSE) continue; // during the execution of an engineering scan or LCU_mem_dump, hk packets production is suspended if (AID_spectroscopy == ENG_SCAN_ID) continue; if (AID_spectroscopy == LCU_MEM_DUMP_ID) continue; // initialise counter of # of Low Speed hk requests word_num = 0; // If no measurement running, issue LS commands to gather Spectrometers HK data hk_issue_ls_spectrom(); // Issue LS commands to gather FCU and LCU HK data hk_issue_ls_FCU_LCU(); // Waits for completion and prepares HK data hk_prepare_data(); // checks and errors hk_error_count(); hk_limit_check(); // Copy subset of HK to essential HK hk_ess_prepare_data(); // Send TM packets to TMTC hk_send_data(); hk_ess_send_data(); // restart the checks on the subframe counters Counter_Flag = 0; } } //------- hk_issue_ls_spectrom ------------------------------------------------- //! Issue LS commands to active susbsystems to gather Spectrometer HK data void hk_issue_ls_spectrom (void) { // check if the HK requestes to the spectrometers are active if ( AID_spectroscopy != REQUIRING_HK ) return; HK_is_asking_spectrometry = 1; // flag to prevent VM start // For wbs we need a real 15 msec long integration: this is done in the following set of instructions if ( ( HK_SubsysStatus & WBS_H_MASK ) || ( HK_SubsysStatus & WBS_V_MASK ) ) { asynchronous_ls_access(&WBS_H_CMD[START_INT_IDX]); KS_TaskSleep(15 - COMMAND_TRANSMIT_TIME - WAIT_LS_END_TIME); // wait integration: the integration duration is 15 msec // time -( COMMAND_TRANSMIT_TIME + WAIT_LS_END_TIME) because the overall time between the two calls // to SendLss (ie between start and stop int) must be equal to 15 msec. asynchronous_ls_access(&WBS_H_CMD[STOP_INT_IDX]); } // wait at least 12 msec between the stop integration and the transfer request KS_TaskSleep(12); // now ask for the data transfer if ( HK_SubsysStatus & WBS_H_MASK ) { asynchronous_ls_access(&WBS_H_CMD[DATA_TRANS_IDX]); // request immediate transfer fifo_0_pending_frames++; // increase pending frame counter } if ( HK_SubsysStatus & WBS_V_MASK ) { asynchronous_ls_access(&WBS_V_CMD[DATA_TRANS_IDX]); // request immediate transfer fifo_1_pending_frames++; // increase pending frame counter } if ( HK_SubsysStatus & HRS_V_MASK ) { asynchronous_ls_access(&HK_req_HRS_V); // request immediate transfer fifo_3_pending_frames++; // increase pending frame counter } if ( HK_SubsysStatus & HRS_H_MASK ) { asynchronous_ls_access(&HK_req_HRS_H); // request immediate transfer fifo_2_pending_frames++; // increase pending frame counter } // require an immediate flush of HK frame if any was requested if ( ( HK_SubsysStatus & WBS_V_MASK ) || ( HK_SubsysStatus & WBS_H_MASK ) || ( HK_SubsysStatus & HRS_H_MASK ) || ( HK_SubsysStatus & HRS_V_MASK ) ) if ( ! hs_flush_is_running ) KS_EventSignal(HS_FLUSH_EVENT); HK_is_asking_spectrometry = 0; // reset flag: now vm can start if pending frames all zero } //---- hk_issue_ls_FCU_LCU ----------------------------------------------------- //! Issue LS commands to gather FCU and LCU HK data void hk_issue_ls_FCU_LCU (void) { int j, * pdata_ls; int i; // prepare pointer to LS data within the HK data block pdata_ls = hk_block.pointer_to_data + BASE_HK_LS; // Poll LCU for (j = 0; j < Size_hk_LCU; j++) { if ((HK_SubsysStatus & LCU_MASK) != 0) // Test if LCU is on ls_put_msg_lp(&HK_LCU_commands[j], (pdata_ls + word_num), 0, NULL); else *(pdata_ls + word_num) = LC_SS_OFF; // Write into the answs table the OFF code if (((HK_LCU_commands[j] & 0x40000000) == 0)) word_num++; } if ( ((HK_SubsysStatus & LCU_MASK) != 0) && (LCU_non_interaction != TRUE ) ) pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= LCU_MASK; // mark lcu data as valid // Poll FCU if (Size_hk_FCU != HK_FCU_ERRS_LEN) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_INTERNAL_ERROR, 1, &Size_hk_FCU); for (j = 0; j < Size_hk_FCU; j++) { if ((HK_SubsysStatus & FCU_MASK) != 0) // Test if FCU is on { HK_FCU_errs[j] = 0; // reset the error ls_put_msg_lp(&HK_FCU_commands[j], (pdata_ls + word_num), 0, &HK_FCU_errs[j]); if ( (HK_FCU_commands[j] & 0xFFFFFF00) == (0xCf050000) ) /* it is a set command. we need to wait before reading */ { // add 4 nops to wait 12 additional msecs for (i=0; i<5; i++) ls_put_msg_lp(NULL, NULL, LS_NOP_REQUEST, NULL); } } else *(pdata_ls + word_num) = FC_SS_OFF; // Write into the answs table the OFF code if (((HK_FCU_commands[j] & 0x40000000) == 0)) word_num++; } if ((HK_SubsysStatus & FCU_MASK) != 0) pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= FCU_MASK; // mark fcu data as valid } //----- hk_prepare_data -------------------------------------------------------- //! Waits for LS commands completion and adds icu hk void hk_prepare_data (void) { // Send a dummy cmd to LS. When this msg is processed all the HK data were collected and LS raises HK_EVENT ls_put_msg_lp(NULL, NULL, HK_EVENT, NULL); // Wait for the last (DUmmy) LS command to be processed by LS. KS_EventTestW(HK_EVENT); // Wait for the event, i.e. transaction completion // Add OBS housekeeping: rc_write_obs_hk(pdata_obs); } //----------- hk_ess_prepare_data ---------------------------------------------- //! Copies selected HK data to essential HK data void hk_ess_prepare_data (void) { int i, pos, disp; unsigned int *source, *dest; // Init position (word) and sequence number of destination and source source = (unsigned int *) hk_block.pointer_to_data; dest = (unsigned int*) hk_ess_block.pointer_to_data + SPH_WLEN + DFH_WLEN + SDH_HK_WLEN; // Copy the essential HK: copy 2 bytes for each entry for (i=0; i> 1; // from bytes to words disp = essential_hk_positions[i]%2; // Add to the ess hk vector switch ( disp ) { case 0: dest[i] = source[pos] & 0x0000FFFF; break; case 1: dest[i] = ((source[pos] & 0x000000FF)<<8 ) + ((source[pos+1] & 0x0000FF00)>>8 ); break; } } } //----------- hk_send_data ----------------------------------------------------- //! Send HK TM packets to TMTC void hk_send_data (void) { HK_TM_MSG hk_msg; // msg to be sent to FIFO HK_QUEUE unsigned int byte_num, ch_per_pack, packt_count; TM_ST3_HEADER *st3_header; // Packetization // word_num now contains the # of 16bits words to send in TM // word_num now contains the # of HK data kept from LS SS word_num = word_num + (MAX_ICU_HK*2) + HS_HK_LEN; // add the size of OBS and HS SS HK data // Now prepare the block for tm_tc: prepare_TM_packet(&hk_block, TM_DFHF_REGULAR, TM_APID_HK, ((word_num+DFH_WLEN+SDH_HK_WLEN+1)<<1)- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) hk_block.pointer_to_data; // write Source Data Header st3_header->structure_ID = PERIODIC_HK_SID; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Cur_BuildingBlock_ID); // max channels per packet byte_num = word_num * 2; // from words to bytes ch_per_pack = HK_TM_MAX_PKT / 2; // from bytes to words packt_count = byte_num / HK_TM_MAX_PKT; // number of packets if (IFSI_MOD(byte_num, HK_TM_MAX_PKT)!=0) packt_count++; // adjust for possible last unfilled packet // passa a reference to the block hk_msg.block = hk_block; // set the length of data header hk_msg.packing = PACKING_16; // 16 bit data, HKP data type hk_msg.packing |= SDH_HK_WLEN << 8; // 12/06/02 hk_msg.packing |= HKP << 16; // the data sholuld always fit into a single packet, but let's double check it if ( packt_count > 1 ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_PKT_NO, 1, &packt_count); // send the packet { // offset of the running packet hk_msg.offset = HK_TM_HEADER ; // no offset // downcount of the packet hk_msg.count = 0; // number of data words to be packetized hk_msg.length = IFSI_MOD(word_num, ch_per_pack); // last packet // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&hk_msg.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_HK_TM_QUEUE, 0, NULL); } } // Block sent to tm_tc. Get a new one for next turn: if (hk_get_block() == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_GET_BLOCK_HKPOOL_FULL, 0, NULL); } //---- hk_ess_send_data -------------------------------------------------------- //! Send essential HK TM packets to TMTC void hk_ess_send_data (void) { HK_TM_MSG hk_msg; // msg to be sent to FIFO HK_QUEUE unsigned int byte_num, ch_per_pack, packt_count; TM_ST3_HEADER *st3_header; // Prepare the block for tm_tc: prepare_TM_packet(&hk_ess_block, TM_DFHF_REGULAR, TM_APID_ESS_HK, ((HK_ESS_PARAMS_NR + DFH_WLEN + SDH_HK_WLEN +1)<<1 )- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) hk_ess_block.pointer_to_data; // write Source Data Header st3_header->structure_ID = ESSENTIAL_HK_SID; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Cur_BuildingBlock_ID); // max channels per packet byte_num = word_num * 2; // from words to bytes ch_per_pack = HK_TM_MAX_PKT / 2; // from bytes to words packt_count = byte_num / HK_TM_MAX_PKT; // number of packets if (IFSI_MOD(byte_num, HK_TM_MAX_PKT)!=0) packt_count++; // adjust for possible last unfilled packet // cycle through packets: prepare the block to be sent in various messages hk_msg.block = hk_ess_block; // set the length of data header hk_msg.packing = PACKING_16; // 16 bit data, HKP data type hk_msg.packing |= SDH_HK_WLEN << 8; // 12/06/02 hk_msg.packing |= HKP << 16; // the data sholuld always fit into a single packet, but let's double check it if ( packt_count > 1 ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_PKT_NO, 1, &packt_count); // send the packets { // offset of the running packet hk_msg.offset = HK_TM_HEADER; // no offset // downcount of the packet hk_msg.count = 0; // number of data words to be packetized hk_msg.length = IFSI_MOD(word_num, ch_per_pack); // last packet // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&hk_msg.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_HK_TM_QUEUE, 0, NULL); } } // Block sent to tm_tc. Get a new one for next turn: if (hk_ess_get_block()== RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_GET_BLOCK_HKPOOL_FULL, 0, NULL); } //------------- hk_init -------------------------------------------------------- //! Inits the HK block. Needs to be called before the task is executed void hk_init( void ) { // request hk block if (hk_get_block() == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_GET_BLOCK_HKPOOL_FULL, 0, NULL); if (hk_ess_get_block() == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_GET_BLOCK_HKPOOL_FULL, 0, NULL); } //------------- hk_process_hrs ------------------------------------------------- //! copies the HK part of the HRS frame into a memory space where the hk packet //! is being built. Exported function to be used by hs1. void hk_process_hrs (int fifo_id, int* pdata) { int * source, * dest, i; // initialization of pointers source = pdata + HRS_FRAME_SD_LEN; // pointer to hk data (placed at the end of the wbs frame) dest = pdata_hs[fifo_id]; // pointer to the memory space where hk data are to be copied // copy hk data into the appriopriate area of the hk packet for (i = 0; i < HRS_FRAME_HK_LEN; i++) { dest[2*i+1] = source[i]; dest[2*i] = dest[2*i+1] >> 16; } // raise the hk validity flag bit and write the transfer counter // corresponding to the hk data just copied switch (fifo_id) { case HRS_H_ID: pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= HRS_H_MASK; pdata_obs[HRSH_TRANSFER_CNT_HK_IDX] = transfer_cnt_value(fifo_id); break; case HRS_V_ID: pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= HRS_V_MASK; pdata_obs[HRSV_TRANSFER_CNT_HK_IDX] = transfer_cnt_value(fifo_id); break; } } //---------- hk_process_wbs ---------------------------------------------------- //! copies the HK part of the WBS frame into a memory space where the hk packet //! is being built. Exported function to be used by hs1. void hk_process_wbs (int fifo_id, int* pdata) { int i, * source, * dest; // Init pointers source = pdata + WBS_FRAME_SD_LEN + 1; // pointer to hk data (placed at the end of the wbs frame) dest = pdata_hs[fifo_id]; // pointer to the memory space where hk data are to be copied // copy data from source to dest for (i = 0; i < (WBS_FRAME_HK_LEN - 1); i++) dest[i] = source[i]; dest[i] = 0; // set to zero the last hk field (scan count) // raise the hk validity flag bit and write the transfer counter // corresponding to the hk data just copied switch (fifo_id) { case WBS_H_ID: pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= WBS_H_MASK; pdata_obs[WBSH_TRANSFER_CNT_HK_IDX] = transfer_cnt_value(fifo_id); break; case WBS_V_ID: pdata_obs[2*SPECTR_HK_VALID_IDX + 1] |= WBS_V_MASK; pdata_obs[WBSV_TRANSFER_CNT_HK_IDX] = transfer_cnt_value(fifo_id); break; } } //-------- hk_get_block -------------------------------------------------------- //! get the blocks from the HK pool and handles the related datas int hk_get_block (void) { // get new block from the hk pool if (get_block(&hk_block, HK_POOL, HK_BLOCK_LEN_BYTES) == RC_FAIL) return RC_FAIL; // init the block init_block(&(hk_block), HK_BLOCK_LEN_WORDS); // lpdeb: I think that this can be removed. // set pointers to hs data pdata_hs[HRS_V_ID] = hk_block.pointer_to_data + HK_FRAME_HRSV_OFFSET; pdata_hs[HRS_H_ID] = hk_block.pointer_to_data + HK_FRAME_HRSH_OFFSET; pdata_hs[WBS_V_ID] = hk_block.pointer_to_data + HK_FRAME_WBSV_OFFSET; pdata_hs[WBS_H_ID] = hk_block.pointer_to_data + HK_FRAME_WBSH_OFFSET; // set pointer to icu data pdata_obs = hk_block.pointer_to_data + SPH_WLEN + DFH_WLEN + SDH_HK_WLEN; return RC_OK; } //---- hk_ess_get_block -------------------------------------------------------- //! get the block for the essential HK from the HK pool and handles the related datas int hk_ess_get_block (void) { // get new block from the hk pool if (get_block(&hk_ess_block, HK_POOL, HK_BLOCK_LEN_BYTES) == RC_FAIL) return RC_FAIL; return RC_OK; } //--------- set_hk_rate -------------------------------------------------------- //! Restart the HK operations. At AVM stage the interval is set to 1 sec. void set_hk_rate (TC_packet * packet) { int index; // the following 4 lines are for interrupting any ongoing activity current_command_number++; // increment the label KS_SemaGroupSignal(Sema_Wait_Group); // signal these semaphores to interrupt any sleep state of tasks hs_hdl and ls_hdl completion_update(packet); // completion management // perform the abortions required for this HK activity LS_activity_preparation(); // extract input data index = packet->data[TC_HKRATE_IDX]; HK_SubsysStatus = (packet->data[TC_HK_SEL_IDX] & SubsysStatus); // check input data if ((index < 0) || (index >= Max_hk_rates)) { enqueue_exec_fail(EXF_HK_ASK_HK_RATE_INDEX_OOL, 1, &index); return; } // switch HK on Hk_enable = TRUE; // This TC field is an entry into the table Hk_wait = HK_rates[index]; if (Hk_wait <= 0 ) Hk_wait = 4000; // restarts the hk ask timer with new virtuoso ticks values KS_LowTimerRestart(Hk_Timer, Hk_wait, Hk_wait); // send completion ack enqueue_exec_compl(); } //****************************************************************************** // SINGLE (NON PERIODIC) HK //****************************************************************************** //----- start_single_hk -------------------------------------------------------- //! Called by TC_acceptance in order to issue a non periodic HK request void start_single_hk(LS_HDL_MSG * msg) { unsigned int j; int * p_aux; // we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // check if FCU is on, otherwise abort if ((SubsysStatus & FCU_MASK) == 0) { enqueue_exec_fail(EXF_HK_ASK_FCU_OFF, 0, NULL); return; } // initialise counter of # of hk commands singlehk_word_num = 0; // get and initialize the block get_block(&hk_single_block, HK_POOL, HK_BLOCK_LEN_BYTES); init_block(&hk_single_block, HK_BLOCK_LEN_WORDS); p_aux = hk_single_block.pointer_to_data + HK_TM_HEADER; // prepare auxiliary pointer for (j = 0; j < Single_HK_len; j++) { // push command in queue towards ls task if (ls_put_msg_hp(&Single_HK_FCU_commands[j], (p_aux + singlehk_word_num), 0, NULL) == RC_FAIL) { release_block(&hk_single_block); enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); singlehk_word_num = 0; return; } singlehk_word_num++; } // Now send a dummy cmd to set the Event # to LS if (ls_put_msg_hp(NULL, (unsigned int*) msg->command_number, NP_HK_COMPLETED, NULL) == RC_FAIL) { release_block(&hk_single_block); enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); return; } } //----------- single_hk -------------------------------------------------------- //! Function that sends the non periodic hk data; executed within ls_hdl. //! Collects data and sends the HK packet to task tmtc_if via the HK_TM_QUEUE fifo. void single_hk (void) { HK_TM_MSG hk_msg; // msg to be sent to FIFO HK_QUEUE TM_ST3_HEADER *st3_header; // Prepare the block for tm_tc: prepare_TM_packet(&hk_single_block, TM_DFHF_REGULAR, TM_APID_HK, ((singlehk_word_num + DFH_WLEN+SDH_HK_WLEN+1)<<1)- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) hk_single_block.pointer_to_data; // write Source Data Header st3_header->structure_ID = NON_PER_FCU_HK_SID; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); // prepare the block to be sent in various messages hk_msg.block = hk_single_block; // set the packetization flag to 16 bit (not necessary) hk_msg.packing = PACKING_16; hk_msg.packing |= SDH_HK_WLEN << 8; // 12/06/02 hk_msg.packing |= HKP << 16; // offset of the running packet hk_msg.offset = HK_TM_HEADER; // no offset // downcount of the packet hk_msg.count = 0; // number of data words to be packetized hk_msg.length = singlehk_word_num; // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&hk_msg.block); enqueue_exec_fail(EXF_HK_ASK_FIFOPUT_HK_TM_QUEUE, 0, NULL); // execution failure } else enqueue_exec_compl(); } //************************************************************************************************ //************************************************************************************************ // ERROR COUNT AND LIMIT check //************************************************************************************************ //************************************************************************************************ //---- hk_switch_FCU_err_count_on -------------------------------------------------------- //! Switch FCU error counting on - to be called by cmd_seq void hk_switch_FCU_err_count_on (TC_packet * packet) { // check consistency of data length; if all right switch error count on if (Size_hk_FCU != HK_FCU_ERRS_LEN) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_SWERR, 1, &Size_hk_FCU); else { HK_error_count_FCU_8C_on = 1; HK_error_count_FCU_8D_on = 1; HK_error_count_FCU_8F_on = 1; } // set the number of breach, extracted from the TC packet HK_N_breach_8C = packet->data[2] & 0x0000FFFF; HK_N_breach_8D = packet->data[3] & 0x0000FFFF; HK_N_breach_8F = packet->data[4] & 0x0000FFFF; FCU_err8C_counter = 0; FCU_err8D_counter = 0; FCU_err8F_counter = 0; } //---- hk_restart_FCU_err_count -------------------------------------------------------- //! Switch FCU error counting on - to be called by cmd_seq void hk_restart_FCU_err_count (int board) { switch( board) { case 0: HK_error_count_FCU_8C_on = 1; FCU_err8C_counter = 0; HK_check_htrh=1; HK_breach_htrh=0; break; case 1: HK_error_count_FCU_8D_on = 1; FCU_err8D_counter = 0; HK_check_htrv=1; HK_breach_htrv=0; break; case 2: HK_error_count_FCU_8F_on = 1; FCU_err8F_counter = 0; break; } } //---- hk_switch_FCU_err_count_off --------------------------------------------- //! Switch FCU error counting off - to be called by cmd_seq void hk_switch_FCU_err_count_off (int action) { switch (action) { case 0 : HK_error_count_FCU_8C_on = 0; HK_error_count_FCU_8D_on = 0; HK_error_count_FCU_8F_on = 0; break; case 1 : HK_error_count_FCU_8C_on = 0; break; case 2 : HK_error_count_FCU_8D_on = 0; break; case 3 : HK_error_count_FCU_8F_on = 0; break; } } //------ hk_error_count -------------------------------------------------------- //! Counts errors returned from LS subsystems. void hk_error_count (void) { // counters for this frame int FCU_err8C, FCU_err8D, FCU_err8F, j, report_param[3]; // Check FCU if ((HK_SubsysStatus & FCU_MASK) != 0) // Test if FCU is on and error count is on { // count errors: reset local counters FCU_err8C = FCU_err8D = FCU_err8F = 0; // cycle for (j = 0; j < Size_hk_FCU; j++) if ( HK_FCU_errs[j] > 0 ) switch ( HK_FCU_commands[j] & 0xFF000000 ) { // count errors of each type case 0x8C000000: if (HK_error_count_FCU_8C_on == 1) FCU_err8C++; break; case 0x8D000000: if (HK_error_count_FCU_8D_on == 1) FCU_err8D++; break; case 0x8F000000: if (HK_error_count_FCU_8F_on == 1) FCU_err8F++; break; default: generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_SWERR, 0, NULL); } // If no errors reset the error counter else add errors if ( FCU_err8C == 0 ) FCU_err8C_counter = 0; else FCU_err8C_counter += FCU_err8C; if ( FCU_err8D == 0 ) FCU_err8D_counter = 0; else FCU_err8D_counter += FCU_err8D; if ( FCU_err8F == 0 ) FCU_err8F_counter = 0; else FCU_err8F_counter += FCU_err8F; // Check N_breach if ((FCU_err8C_counter >= HK_N_breach_8C) && HK_error_count_FCU_8C_on) { if (ls_put_msg_hp(&autonomy_funct_commands[0], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[0] = FCU_err8C_counter; report_param[1] = autonomy_funct_commands[0] >> 16; report_param[2] = autonomy_funct_commands[0] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_ERR_8C, ERR_HK_ASK_ERR_8C, 3, report_param); hk_switch_FCU_err_count_off(1); } if ((FCU_err8D_counter >= HK_N_breach_8D) && HK_error_count_FCU_8D_on) { if (ls_put_msg_hp(&autonomy_funct_commands[1], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[0] = FCU_err8D_counter; report_param[1] = autonomy_funct_commands[1] >> 16; report_param[2] = autonomy_funct_commands[1] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_ERR_8D, ERR_HK_ASK_ERR_8D, 3, report_param); hk_switch_FCU_err_count_off(2); } if ((FCU_err8F_counter >= HK_N_breach_8F) && HK_error_count_FCU_8F_on) { if (ls_put_msg_hp(&autonomy_funct_commands[2], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[0] = FCU_err8F_counter; report_param[1] = autonomy_funct_commands[2] >> 16; report_param[2] = autonomy_funct_commands[2] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_ERR_8F, ERR_HK_ASK_ERR_8F, 3, report_param); hk_switch_FCU_err_count_off(3); } } } //---- hk_switch_limit_check_off -------------------------------------------------------- //! Switch off limit checking for the specified subsystem void hk_switch_limit_check_off (unsigned int subs) { switch(subs) { case TC_FUNMAN_WBSH_LIMCK_AID: HK_check_wbsh = 0; break; case TC_FUNMAN_WBSV_LIMCK_AID: HK_check_wbsv = 0; break; case TC_FUNMAN_HTRH_LIMCK_AID: HK_check_htrh = 0; break; case TC_FUNMAN_HTRV_LIMCK_AID: HK_check_htrv = 0; break; case TC_FUNMAN_LCU_T_LIMCK_AID: HK_check_lcu = 0; break; case TC_FUNMAN_LCU_NONRESP_AID: HK_LCUnonresp_check = 0; break; case TC_FUNMAN_LCU_MODE_AID: HK_LCUmode_check = 0; break; case TC_FUNMAN_LCU_MEMCHK_AID: HK_LCUcrc_check = 0; break; default: break; // lpdeb: to issue an error } } //---- hk_switch_limit_check_on ------------------------------------------------ //! Switch on limit checking for the specified subsystem void hk_switch_limit_check_on (TC_packet * packet) { unsigned int activity_ID; int N_breach, limit, limit_low; // read activity id activity_ID = (packet->data[TC_FUNACT_IDX]) & 0x0FF; // this id handled differently if ( activity_ID == TC_FUNMAN_LCU_MEMCHK_AID) { hk_switch_LCU_crc_chk_on (packet); return; } // read some pars N_breach = packet->data[2] & 0x0FFFF; limit = packet->data[3] & 0x0FFFF; // this does not exist for some packets but it is no problem since it is not used // read the lower LO temperature limit if ( ( activity_ID == TC_FUNMAN_LCU_T_LIMCK_AID )) { // read the lower LO temperature limit limit_low = packet->data[4] & 0x0FFFF; } // Correct the sign if the limit is on the laser if ( ( activity_ID == TC_FUNMAN_WBSH_LIMCK_AID ) || ( activity_ID == TC_FUNMAN_WBSV_LIMCK_AID ) ) { // Correct the sign of the limit: extend with 1 if negative (i.e. if 16th bit is 1 - 2complement representation) if ( limit & 0x8000 ) limit = limit | 0xFFFF0000; } switch (activity_ID) { case TC_FUNMAN_WBSH_LIMCK_AID: HK_check_wbsh=1; HK_N_breach_wbsh=N_breach; HK_limit_wbsh=limit; HK_breach_wbsh=0; break; case TC_FUNMAN_WBSV_LIMCK_AID: HK_check_wbsv=1; HK_N_breach_wbsv=N_breach; HK_limit_wbsv=limit; HK_breach_wbsv=0; break; case TC_FUNMAN_HTRH_LIMCK_AID: HK_check_htrh=1; HK_N_breach_htrh=N_breach; HK_limit_htrh=limit; HK_breach_htrh=0; break; case TC_FUNMAN_HTRV_LIMCK_AID: HK_check_htrv=1; HK_N_breach_htrv=N_breach; HK_limit_htrv=limit; HK_breach_htrv=0; break; case TC_FUNMAN_LCU_T_LIMCK_AID: HK_check_lcu=1; HK_N_breach_lcu=N_breach; HK_limit_lcu_max=limit; HK_limit_lcu_min=limit_low; HK_breach_lcu=0; break; case TC_FUNMAN_LCU_NONRESP_AID: HK_LCUnonresp_check = 1; HK_LCUnonresp_Nbreach = N_breach; HK_lcu_nonres_breach = 0; HK_lcu_nonres_ok = 0; break; case TC_FUNMAN_LCU_MODE_AID: HK_LCUmode_check = 1; HK_LCUmode_Nbreach = N_breach; HK_breach_lcu_mode = 0; break; default: break; // lpdeb: to issue an error } } //---- data for periodic lcu crc check ------------------------------------------------ static unsigned int HK_LCUcrc_check_counter = 0; //!< boolean on/off for lcu periodic crc check static unsigned int HK_LCUcrc_check_counter_max = 0; //!< boolean on/off for lcu periodic crc check static TC_packet start_crc_check_packet; //---- hk_switch_lcu_crc_check_on ------------------------------------------------ //! Switch on limit checking for the LCU crc autonomous funct void hk_switch_LCU_crc_chk_on (TC_packet * packet) { unsigned int *p1, *p2, i; unsigned int hif_step_time; // set vars HK_LCUcrc_check = 1; HK_LCUcrc_check_counter = 0; // copy the TC packet into the buffer p1 = (unsigned int *) &start_crc_check_packet; p2 = (unsigned int *) packet; for (i = 0; i < 14; i++) p1[i] = p2[i]; // read period (second) and convert to msecs hif_step_time = (packet->data[9] & 0x0000FFFF); hif_step_time = hif_step_time * 1000; // impose minimum period of 10 sec if (hif_step_time < 10000) hif_step_time = 10000; // compute max val for counter (Hk_wait is the hk period in msec) HK_LCUcrc_check_counter_max = hif_step_time / Hk_wait; } //---- hk_LCU_crc_chk ------------------------------------------------ //! perform periodic lcu crc check void hk_LCU_crc_chk ( void ) { // increase counter HK_LCUcrc_check_counter++; // check counter if ( HK_LCUcrc_check_counter >= HK_LCUcrc_check_counter_max ) { // reset counter HK_LCUcrc_check_counter = 0; // start check forward_TCpacket_to_ls_hdl (&start_crc_check_packet, START_VERIFY_LCU_MODE1); } } //------ hk_limit_check -------------------------------------------------------- // parameters and (byte) position in the HK packet #define HWH_LASER_T_BYTE_IDX 418 #define HWV_LASER_T_BYTE_IDX 454 #define HF_AH1_DHTR_C_BYTE_IDX 662 #define HF_AV1_DHTR_C_BYTE_IDX 790 #define LCU_T_BYTE_IDX 484 #define WBS_H_LASER_ON_BYTE_IDX 415 #define WBS_V_LASER_ON_BYTE_IDX 451 #define LCU_ON_BYTE_IDX 483 //! Limit checking for the monitored subsystems parameters void hk_limit_check (void) { unsigned int * source; int report_param[5]; source = (unsigned int *) hk_block.pointer_to_data; // point to the HK packet // check LCU crc - only if ss is on + LCU_mode_S != 10 dec + check is on +LCU_non_int is off if (((HK_SubsysStatus & LCU_MASK) != 0) && ((source[LCU_ON_BYTE_IDX>>1] & 0xF0) != (10<<4) ) && HK_LCUcrc_check && (LCU_non_interaction == 0) ) hk_LCU_crc_chk(); // check LCU_mode - only if HK_lcu is ON + lim chk is on + HK is valid if (((HK_SubsysStatus & LCU_MASK) != 0) && HK_LCUmode_check && (pdata_obs[2*SPECTR_HK_VALID_IDX + 1] & LCU_MASK) ) { // check lcu mode if ( ((source[LCU_ON_BYTE_IDX>>1] & 0xF0)>>4) == 0 ) { HK_breach_lcu_mode++; } else { HK_breach_lcu_mode = 0; } // check if max number of breach exceeded if (HK_breach_lcu_mode >= HK_LCUmode_Nbreach) { // set flag and issue warning LCU_safe_and_block (); generate_event(EVENT_ALARM_REPORT, ERR_HK_ASK_LCU_MODE, ERR_HK_ASK_LCU_MODE, 0, NULL); HK_breach_lcu = 0; // reset error counter } } // check LCU_Temperature - only if ss is on + lcu is ON (LCU_mode_S = 10 dec) + lim chk is on + HK is valid + read is valid if (((HK_SubsysStatus & LCU_MASK) != 0) && ((source[LCU_ON_BYTE_IDX>>1] & 0xF0) == (10<<4) ) && HK_check_lcu && (pdata_obs[2*SPECTR_HK_VALID_IDX + 1] & LCU_MASK) && ((source[LCU_T_BYTE_IDX>>1] & 0x8000) == 0 ) ) { // check possible breach report_param[0] = (hk_lcu_limit_check(source, LCU_T_BYTE_IDX, HK_limit_lcu_max, HK_limit_lcu_min, &HK_breach_lcu))& 0x0FFFF; // check if max number of breach exceeded if (HK_breach_lcu > HK_N_breach_lcu) { // issue abort plus goto safe perform_goto_safe_after_abort = 1; abort_measurement(); generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_LOUT_LIMIT, ERR_HK_ASK_LOUT_LIMIT, 1, report_param); HK_breach_lcu = 0; // reset error counter } } // check HWH_LASER_T - only if ss is on and laser is ON and lim chk is on and HK is valid if (((HK_SubsysStatus & WBS_H_MASK) != 0) && ((source[WBS_H_LASER_ON_BYTE_IDX>>1] & 0x30) != 0 ) && HK_check_wbsh && (pdata_obs[2*SPECTR_HK_VALID_IDX + 1] & WBS_H_MASK) ) { // check possible breach report_param[0] = (hk_this_limit_check(1, source, HWH_LASER_T_BYTE_IDX, HK_limit_wbsh, &HK_breach_wbsh))& 0x0FFFF; // check if max number of breach exceeded if (HK_breach_wbsh > HK_N_breach_wbsh) { if (ls_put_msg_hp(&autonomy_funct_commands[3], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&autonomy_funct_commands[4], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[1] = autonomy_funct_commands[3] >> 16; report_param[2] = autonomy_funct_commands[3] & 0x0FFFF; report_param[3] = autonomy_funct_commands[4] >> 16; report_param[4] = autonomy_funct_commands[4] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_WBSH_LIMIT, ERR_HK_ASK_WBSH_LIMIT, 5, report_param); HK_breach_wbsh = 0; // reset error counter } } // check HWV_LASER_T - only if ss is on and lim chk is on and HK is valid if (((HK_SubsysStatus & WBS_V_MASK) != 0) && ((source[WBS_V_LASER_ON_BYTE_IDX>>1] & 0x30) != 0 ) && HK_check_wbsv && (pdata_obs[2*SPECTR_HK_VALID_IDX + 1] & WBS_V_MASK) ) { // check possible breach report_param[0] = (hk_this_limit_check(1, source, HWV_LASER_T_BYTE_IDX, HK_limit_wbsv, &HK_breach_wbsv))& 0x0FFFF; // check if max number of breach exceeded if (HK_breach_wbsv > HK_N_breach_wbsv) { if (ls_put_msg_hp(&autonomy_funct_commands[5], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&autonomy_funct_commands[6], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[1] = autonomy_funct_commands[5] >> 16; report_param[2] = autonomy_funct_commands[5] & 0x0FFFF; report_param[3] = autonomy_funct_commands[6] >> 16; report_param[4] = autonomy_funct_commands[6] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_WBSV_LIMIT, ERR_HK_ASK_WBSV_LIMIT, 5, report_param); HK_breach_wbsv = 0; // reset error counter } } // check HF_AH1 - only if ss is on and lim chk is on if (((HK_SubsysStatus & FCU_MASK) != 0) && HK_check_htrh) { // check possible breach report_param[0] = (hk_this_limit_check(0, source, HF_AH1_DHTR_C_BYTE_IDX, HK_limit_htrh, &HK_breach_htrh))& 0x0FFFF; // check if max number of breach exceeded if (HK_breach_htrh > HK_N_breach_htrh) { if (ls_put_msg_hp(&autonomy_funct_commands[0], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[1] = autonomy_funct_commands[0] >> 16; report_param[2] = autonomy_funct_commands[0] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_HTRH_LIMIT, ERR_HK_ASK_HTRH_LIMIT, 3, report_param); HK_check_htrh = 0; // switch error count off } } // check HF_AV1 - only if ss is on and lim chk is on if (((HK_SubsysStatus & FCU_MASK) != 0) && HK_check_htrv) { // check possible breach report_param[0] = (hk_this_limit_check(0, source, HF_AV1_DHTR_C_BYTE_IDX, HK_limit_htrv, &HK_breach_htrv))& 0x0FFFF; // check if max number of breach exceeded if (HK_breach_htrv > HK_N_breach_htrv) { if (ls_put_msg_hp(&autonomy_funct_commands[1], NULL, 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); report_param[1] = autonomy_funct_commands[1] >> 16; report_param[2] = autonomy_funct_commands[1] & 0x0FFFF; generate_event(EVENT_EVENT_REPORT, ERR_HK_ASK_HTRV_LIMIT, ERR_HK_ASK_HTRV_LIMIT, 3, report_param); HK_check_htrv = 0; // switch error count off } } } //---- hk_this_limit_check ----------------------------------------------------- //! Limit checking and number of breaches update for a single parameter int hk_this_limit_check (int signed_HK, unsigned int*source, int byte_pos, int limit_val, int* n_breach) { int pos; int val; // rad HK pos = byte_pos >> 1; // from byte to word16 val = (source[pos] & 0x0FFFF); // Correct the sign of the limit: extend with 1 if negative (i.e. if 14th bit is 1 - 2complement representation) if (signed_HK) if ( val & 0x2000 ) val = val | 0xFFFFC000; // check against limit if ( val > limit_val ) { (*n_breach)++; return ((int) (source[pos] & 0x0FFFF)); } else { (*n_breach) = 0; return 0; } } //---- hk_lcu_limit_check ----------------------------------------------------- //! Limit checking and number of breaches update for a single parameter int hk_lcu_limit_check (unsigned int*source, int byte_pos, int limit_val_max, int limit_val_min, int* n_breach) { int pos; int val; // rad HK pos = byte_pos >> 1; // from byte to word16 val = (source[pos] & 0x0FFFF); // check against limit if (( val > limit_val_max ) || ( val < limit_val_min )) { (*n_breach)++; return ((int) (source[pos] & 0x0FFFF)); } else { (*n_breach) = 0; return 0; } } //---- hk_limit_check_status ----------------------------------------------------- //! Returns a integer tyhe bits of which report the status (on/off) of the limit checks and error count function //! The word is part of the OBS HK unsigned int hk_limit_check_status(void) { unsigned int status, mask; status = 0; mask = 1; if ( HK_error_count_FCU_8F_on == 1 ) status |= mask; mask = mask << 1; if ( HK_error_count_FCU_8D_on == 1 ) status |= mask; mask = mask << 1; if ( HK_error_count_FCU_8C_on == 1 ) status |= mask; mask = mask << 1; if ( HK_check_htrv == 1 ) status |= mask; mask = mask << 1; if ( HK_check_htrh == 1 ) status |= mask; mask = mask << 1; if ( HK_check_wbsv == 1 ) status |= mask; mask = mask << 1; if ( HK_check_wbsh == 1 ) status |= mask; mask = mask << 1; if ( HK_check_lcu == 1 ) status |= mask; mask = mask << 1; if ( HK_LCUnonresp_check == 1 ) status |= mask; mask = mask << 1; if ( HK_LCUmode_check == 1 ) status |= mask; mask = mask << 1; if ( HK_LCUcrc_check == 1 ) status |= mask; mask = mask << 1; return status; } /******************************************************************************************/ /******************************************************************************************/ // single HK LCU /******************************************************************************************/ /******************************************************************************************/ // The following functions implement the Single_HK_LCU command #define SINGLE_HK_LCU_PARS_LEN 55 /* number of hk to issue */ // TC packet datas static int Freq_nx; static int Band_nx; // TM packet data static unsigned int single_HK_LCU_data[SINGLE_HK_LCU_PARS_LEN]; //------- start_single_HK_LCU ---------------------------------------------------- //! Start step for a single HK LCU request: enqueues the HK requestes towards the LCU by posting the corresponding messages towards ls() int start_single_HK_LCU(LS_HDL_MSG *msg) { int *paux, i; unsigned int freq; static unsigned int LCU_HK_req = 0xB1AAFFFF; static unsigned int single_HK_LCU_current_command[SINGLE_HK_LCU_PARS_LEN]; // prepare an auxiliary pointer paux = (int *) (msg->block).pointer_to_data; // store the data into static top level variables Freq_nx = paux[7]; Band_nx = paux[8]; // we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // some consistency checks if ( single_HK_LCU_cmds_len != 14 * SINGLE_HK_LCU_PARS_LEN) return enqueue_exec_fail(EXF_HK_ASK_SINGLE_HK_LCU_INVALID_DATA, 0, NULL); if ( LCU_frequency_max_len != SINGLE_HK_LCU_PARS_LEN) return enqueue_exec_fail(EXF_HK_ASK_SINGLE_HK_LCU_INVALID_DATA, 0, NULL); if ( Band_nx < 1 || Band_nx > 14 ) return enqueue_exec_fail(EXF_HK_ASK_SINGLE_HK_LCU_INVALID_DATA, 0, NULL); if ( Freq_nx < 0 || Freq_nx > 31 ) return enqueue_exec_fail(EXF_HK_ASK_SINGLE_HK_LCU_INVALID_DATA, 0, NULL); // check if LCU is on, otherwise abort if ((SubsysStatus & LCU_MASK) == 0) return enqueue_exec_fail(EXF_HK_ASK_LCU_OFF, 0, NULL); // Now construct and send the commands to LS for (i = 0; i < SINGLE_HK_LCU_PARS_LEN; i++) { // compute frequency freq = Freq_nx; if ( freq > LCU_frequency_max[i] ) freq = LCU_frequency_max[i]; // construct the command single_HK_LCU_current_command[i] = Single_HK_LCU_commands[(Band_nx-1) * SINGLE_HK_LCU_PARS_LEN + i] | (freq << 8); // push command in queue towards ls task if (ls_put_msg_hp(&single_HK_LCU_current_command[i], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); // issue the HK req if (ls_put_msg_hp(&LCU_HK_req, &single_HK_LCU_data[i], 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); } // push in ls queue the request for signalling upon termination if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, SEND_SINGLE_HK_REPORT, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); // finished return RC_OK; } //---- send_single_HK_LCU_report ------------------------------------------------- //! Second and last step for a single HK LCU request: sends a report containing the data gathered by the first step void send_single_HK_LCU_report(void) { unsigned int i; int *p_aux; K_BLOCK single_lcu_block; HK_TM_MSG hk_msg; // msg to be sent to FIFO HK_QUEUE TM_ST3_HEADER *st3_header; // get and initialize the block get_block(&single_lcu_block, HK_POOL, HK_BLOCK_LEN_BYTES); init_block(&single_lcu_block, HK_BLOCK_LEN_WORDS); p_aux = single_lcu_block.pointer_to_data + HK_TM_HEADER; // prepare auxiliary pointer // copy command parameters (2) *p_aux = Band_nx; p_aux++; *p_aux = Freq_nx; p_aux++; // copy HK results for (i = 0; i < SINGLE_HK_LCU_PARS_LEN; i++) { *p_aux = single_HK_LCU_data[i]; p_aux++; } // Prepare the block for tm_tc: prepare_TM_packet(&single_lcu_block, TM_DFHF_REGULAR, TM_APID_HK, ((2 + SINGLE_HK_LCU_PARS_LEN + DFH_WLEN+SDH_HK_WLEN+1)<<1)- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) single_lcu_block.pointer_to_data; // write Source Data Header st3_header->structure_ID = NON_PER_LCU_HK_SID; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); // prepare the block to be sent hk_msg.block = single_lcu_block; // set the packetization flag to 16 bit (not necessary) hk_msg.packing = PACKING_16; hk_msg.packing |= SDH_HK_WLEN << 8; // 12/06/02 hk_msg.packing |= HKP << 16; // offset of the running packet hk_msg.offset = HK_TM_HEADER; // no offset // downcount of the packet hk_msg.count = 0; // number of data words to be packetized hk_msg.length = 2 + SINGLE_HK_LCU_PARS_LEN; // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&hk_msg.block); enqueue_exec_fail(EXF_HK_ASK_FIFOPUT_HK_TM_QUEUE, 0, NULL); // execution failure } else enqueue_exec_compl(); } /******************************************************************************************/ /******************************************************************************************/ // MEM HK LCU (single HK request for LCU memory dump) /******************************************************************************************/ /******************************************************************************************/ // The following functions implement the Single_HK_LCU command #define MEM_HK_LCU_PARS_LEN 128 /* max number of hk to issue */ // TC packet datas static int start_page; static int start_address; static int words_num; static int report_SID; // TM packet data static unsigned int mem_HK_LCU_data[MEM_HK_LCU_PARS_LEN]; //------- start_mem_HK_LCU ---------------------------------------------------- //! Start step for a single HK LCU request: enqueues the HK requestes towards the LCU by posting the corresponding messages towards ls() int start_mem_HK_LCU(LS_HDL_MSG *msg) { int *paux, i; unsigned int max_num, yy; static unsigned int LCU_mem_HKreq = 0xB300; static unsigned int LCU_mem_LScmd = 0xF30ACC00; static unsigned int mem_HK_LCU_current_request[MEM_HK_LCU_PARS_LEN]; static unsigned int HL_LCU_Status = 0xB200FFFF; static unsigned int HL_error = 0xB201FFFF; // prepare an auxiliary pointer paux = (int *) (msg->block).pointer_to_data; // store the data into static top level variables start_page = paux[7] & 0x00FF; start_address = paux[8]& 0x00FF; words_num = paux[9]; report_SID = paux[10]; // we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // some consistency checks max_num = start_address + 2*words_num; if ( max_num > 0x0100) return enqueue_exec_fail(EXF_HK_ASK_MEM_HK_LCU_INVALID_DATA, 0, NULL); if ( (words_num + 2) > MEM_HK_LCU_PARS_LEN) return enqueue_exec_fail(EXF_HK_ASK_MEM_HK_LCU_INVALID_DATA, 0, NULL); // check if LCU is on, otherwise abort if ((SubsysStatus & LCU_MASK) == 0) return enqueue_exec_fail(EXF_HK_ASK_LCU_OFF, 0, NULL); LCU_mem_LScmd = 0xF30ACC00 | start_page; if (ls_put_msg_hp(&LCU_mem_LScmd, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); // Now construct and send the hk reqs to LS yy = start_address; for (i = 0; i < words_num; yy+=2, i++) { // construct the command mem_HK_LCU_current_request[i] = ((LCU_mem_HKreq | yy) << 16) | 0xffff; // issue the HK req if (ls_put_msg_hp(&mem_HK_LCU_current_request[i], &mem_HK_LCU_data[i], 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); } // read the error status (scr 2063) if (ls_put_msg_hp(&HL_LCU_Status, &mem_HK_LCU_data[words_num], 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&HL_error, &mem_HK_LCU_data[words_num+1], 0, NULL) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); // push in ls queue the request for signalling upon termination if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, SEND_MEM_HK_REPORT, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); // finished return RC_OK; } //---- send_mem_HK_LCU_report ------------------------------------------------- //! Second and last step for a single HK LCU request: sends a report containing the data gathered by the first step void send_mem_HK_LCU_report(void) { unsigned int i; int *p_aux; K_BLOCK single_lcu_block; HK_TM_MSG hk_msg; // msg to be sent to FIFO HK_QUEUE TM_ST3_HEADER *st3_header; static unsigned int LCU_CLR_ERR = 0xF0090909; // send a clear error command (scr 1645) LCU_CLR_ERR = 0xF0090909; if (ls_put_msg_hp(&LCU_CLR_ERR, NULL, 0, NULL) == RC_FAIL) { enqueue_exec_fail(EXF_HK_ASK_ERROR_LS_HP_QUEUE, 0, NULL); return; } // get and initialize the block get_block(&single_lcu_block, HK_POOL, HK_BLOCK_LEN_BYTES); init_block(&single_lcu_block, HK_BLOCK_LEN_WORDS); p_aux = single_lcu_block.pointer_to_data + HK_TM_HEADER; // prepare auxiliary pointer // copy command parameters (3) *p_aux = start_page; p_aux++; *p_aux = start_address; p_aux++; *p_aux = words_num; p_aux++; // copy HK results for (i = 0; i < (words_num+2); i++) { *p_aux = mem_HK_LCU_data[i]; p_aux++; } // Prepare the block for tm_tc: prepare_TM_packet(&single_lcu_block, TM_DFHF_REGULAR, TM_APID_HK, ((3 + words_num + 2 + DFH_WLEN+SDH_HK_WLEN+1)<<1)- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) single_lcu_block.pointer_to_data; // write Source Data Header st3_header->structure_ID = report_SID; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); // prepare the block to be sent hk_msg.block = single_lcu_block; // set the packetization flag to 16 bit (not necessary) hk_msg.packing = PACKING_16; hk_msg.packing |= SDH_HK_WLEN << 8; // 12/06/02 hk_msg.packing |= HKP << 16; // offset of the running packet hk_msg.offset = HK_TM_HEADER; // no offset // downcount of the packet hk_msg.count = 0; // number of data words to be packetized hk_msg.length = 2 + words_num + 2; // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&hk_msg.block); enqueue_exec_fail(EXF_HK_ASK_FIFOPUT_HK_TM_QUEUE, 0, NULL); // execution failure } else enqueue_exec_compl(); }