2638 lines
116 KiB
C
2638 lines
116 KiB
C
/*------------------------------------------------------------------------------
|
|
|
|
Copyright (C) 1998 : Space Systems Finland Ltd.
|
|
|
|
Space Systems Finland Ltd (SSF) allows you to use this version of
|
|
the DEBIE-I DPU software for the specific purpose and under the
|
|
specific conditions set forth in the Terms Of Use document enclosed
|
|
with or attached to this software. In particular, the software
|
|
remains the property of SSF and you must not distribute the software
|
|
to third parties without written and signed authorization from SSF.
|
|
|
|
System Name: DEBIE DPU SW
|
|
Subsystem : DAS
|
|
Module : health.c
|
|
|
|
Monitoring DEBIE DPU and system health.
|
|
|
|
Based on the SSF file health.c, rev 1.74, Fri Oct 15 20:18:02 1999.
|
|
|
|
- * -----------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "ad_conv.h"
|
|
#include "dpu_ctrl.h"
|
|
#include "taskctrl.h"
|
|
#include "health.h"
|
|
#include "ttc_ctrl.h"
|
|
#include "measure.h"
|
|
#include "tc_hand.h"
|
|
#include "keyword.h"
|
|
#include "kernobj.h"
|
|
#include "tm_data.h"
|
|
#include "telem.h"
|
|
#include "isr_ctrl.h"
|
|
#include "version.h"
|
|
#include "class.h"
|
|
|
|
|
|
#define BOOT_WAIT_INTERVAL 55
|
|
/* Boot wait interval: 55 x 10 ms = 550 ms */
|
|
|
|
#define SYSTEM_INTERVAL 9198
|
|
/* Sets system time interval to 10 ms, assuming a clock */
|
|
/* frequency of exactly 11.0592 MHz. */
|
|
/* SYSTEM_INTERVAL is in units of the processor cycle, */
|
|
/* and is computed as follows, in principle: */
|
|
/* 10 ms * 11.0592 MHz / 12 */
|
|
/* where 12 is the number of clock cycles per processor */
|
|
/* cycle. */
|
|
/* The above calculation gives the value 9216 precisely. */
|
|
/* In practice this value makes the DPU time (updated by */
|
|
/* the Health Monitoring Task) retard by about 0.2%. */
|
|
/* This is probably due to imprecise handling of timer */
|
|
/* ticks by RTX-51. As a primitive correction, we reduce */
|
|
/* the value by 0.2% to 9198. This correction will not */
|
|
/* be exact, especially under heavy interrupt load. */
|
|
|
|
#define HM_INTERVAL 100
|
|
/* Health Monitoring interval wait: 100 x 10 ms = 1s */
|
|
/* This wait time should be waited 10 times to get */
|
|
/* period of 10s. */
|
|
/* Alternatively the execution of the Health Monitoring */
|
|
/* Task can be divided to ten steps which are executed */
|
|
/* 1 second apart from each other and then all actions */
|
|
/* of the task would be executed once in 10 seconds */
|
|
|
|
#define ADC_TEMPERATURE_MAX_TRIES 255
|
|
/* When temperatures are measured this macro defines the maximum */
|
|
/* amount of tries to be used in reading and handling an AD channel in */
|
|
/* 'Read_AD_Channel()'. */
|
|
|
|
#define CONVERSION_TEMPERATURE_MAX_TRIES 255
|
|
/* When temperatures are measured this macro defines the maximum */
|
|
/* amount of tries to be used when End Of Conversion indication is */
|
|
/* waited in function 'Convert_AD()'. */
|
|
|
|
#define ADC_VOLTAGE_MAX_TRIES 255
|
|
/* When voltages are measured this macro defines the maximum */
|
|
/* amount of tries to be used in reading and handling an AD channel in */
|
|
/* 'Read_AD_Channel()'. */
|
|
|
|
#define CONVERSION_VOLTAGE_MAX_TRIES 255
|
|
/* When voltages are measured this macro defines the maximum */
|
|
/* amount of tries to be used when End Of Conversion indication is */
|
|
/* waited in function 'Convert_AD()'. */
|
|
|
|
#define DPU_5V_SELECTOR 3
|
|
#define SU_1_2_P5V_SELECTOR 0
|
|
#define SU_1_2_M5V_SELECTOR 4
|
|
/* DPU Self Test voltage measurement channel selectors. */
|
|
/* See MeasureVoltage function. */
|
|
|
|
#define SU_P5V_ANA_LOWER_LIMIT 0xBA
|
|
#define SU_P5V_ANA_UPPER_LIMIT 0xE4
|
|
#define SU_M5V_ANA_LOWER_LIMIT 0x0D
|
|
#define SU_M5V_ANA_UPPER_LIMIT 0x22
|
|
#define SU_P50V_LOWER_LIMIT 0xA8
|
|
#define SU_P50V_UPPER_LIMIT 0xE3
|
|
#define SU_M50V_LOWER_LIMIT 0x0E
|
|
#define SU_M50V_UPPER_LIMIT 0x2C
|
|
#define DPU_P5V_DIG_LOWER_LIMIT 0xBA
|
|
#define DPU_P5V_DIG_UPPER_LIMIT 0xE4
|
|
/* Upper and lower limits for monitoring */
|
|
/* SU and DPU supply voltages. */
|
|
|
|
#define SELF_TEST_DONE 0
|
|
#define SELF_TEST_RUNNING 1
|
|
/* Used in SU self test. */
|
|
|
|
typedef struct {
|
|
channel_t ADC_channel;
|
|
uint_least8_t ADC_max_tries;
|
|
uint_least8_t conversion_max_tries;
|
|
unsigned int unsigned_ADC;
|
|
signed int signed_ADC;
|
|
unsigned char AD_execution_result;
|
|
sensor_number_t sensor_unit;
|
|
} ADC_parameters_t;
|
|
/* This struct is used to hold parameters for Reading AD channels. */
|
|
/* */
|
|
/* 'ADC_channel' Stores the number the AD channel to be measured. */
|
|
/* Includes BP_UP bit to select unipolar/bipolar mode.*/
|
|
/* 'ADC_max_tries' Gives the function the maximum amount of tries */
|
|
/* used in reading and handling an AD channel. */
|
|
/* 'conversion_max_tries' Gives the function the maximum amount of tries */
|
|
/* used in reading and handling a single AD */
|
|
/* conversion. */
|
|
/* 'unsigned_ADC' These variables are used for storing an ADC */
|
|
/* 'signed_ADC' result. */
|
|
/* 'AD_execution_result' Indicates whether the AD measurent is a success or */
|
|
/* indicates what has gone wrong with following */
|
|
/* values. */
|
|
/* sensor_unit See the function DAC_SelfTest. */
|
|
/* CONVERSION_ACTIVE 0 */
|
|
/* RESULT_OK 1 */
|
|
/* HIT_OCCURRED 2 */
|
|
|
|
|
|
typedef enum {
|
|
su1_e, su2_e, su3_e, su4_e
|
|
} SU_index_t;
|
|
|
|
|
|
|
|
uint_least8_t EXTERNAL temp_meas_count = TEMP_COUNT;
|
|
/* This variable is used for counting temperature measurement interval */
|
|
/* 1/60 secs. */
|
|
|
|
uint_least8_t EXTERNAL voltage_meas_count = VOLTAGE_COUNT;
|
|
/* This variable is used for counting voltage measurement interval 1/180 */
|
|
/* secs. */
|
|
|
|
uint_least8_t EXTERNAL checksum_count = CHECK_COUNT;
|
|
/* This variable is used for counting checksum counter, interval 1/60 */
|
|
/* secs. */
|
|
|
|
unsigned char EXTERNAL code_checksum;
|
|
/* This variable is used for calculating checksum from the memory. */
|
|
|
|
unsigned char EXTERNAL self_test_flag = SELF_TEST_DONE;
|
|
/* Used with SU self test initiation. */
|
|
|
|
/* enumerations */
|
|
|
|
typedef enum {
|
|
channel_0_e, channel_1_e, channel_2_e, channel_3_e, channel_4_e,
|
|
channel_5_e, channel_6_e
|
|
|
|
} AD_channel_t;
|
|
|
|
unsigned char EXTERNAL ADC_channel_register = 0x80;
|
|
/* Holds value of the ADC Channel HW register */
|
|
/* Is used by Hit Trigger ISR task and Health */
|
|
/* Monitoring task. */
|
|
/* Updating must be atomic in the Health Monitoring */
|
|
/* task, because Hit Trigger can preempt it. */
|
|
|
|
|
|
dpu_time_t EXTERNAL internal_time;
|
|
/* DEBIE internal time counter. */
|
|
|
|
|
|
/* Function prototypes. */
|
|
|
|
void DelayAwhile ( unsigned short duration );
|
|
void Read_AD_Channel ( ADC_parameters_t EXTERNAL *ADC_results );
|
|
void DAC_SelfTest( unsigned char DAC_output,
|
|
ADC_parameters_t EXTERNAL *ADC_test_parameters ) ;
|
|
void Monitor( uint_least8_t health_mon_round );
|
|
void UpdateTime( void );
|
|
void MeasureTemperature( sensor_index_t SU_index );
|
|
void HighVoltageCurrent( sensor_index_t SU_index );
|
|
void LowVoltageCurrent( void );
|
|
void MeasureVoltage( uint_least8_t channel_selector );
|
|
void InitSystem( void );
|
|
void CalculateChecksum( uint_least8_t checksum_count );
|
|
void UpdatePeriodCounter( uint_least8_t EXTERNAL *counter,
|
|
uint_least8_t full_counter_value );
|
|
void Convert_AD ( ADC_parameters_t EXTERNAL *ADC_parameters );
|
|
void TemperatureFailure( sensor_index_t SU_index );
|
|
void VoltageFailure( channel_t ADC_channel );
|
|
|
|
void SelfTest_SU( sensor_index_t self_test_SU_index );
|
|
void Monitor_DPU_Voltage( void );
|
|
void Monitor_SU_Voltage( sensor_index_t self_test_SU_index );
|
|
unsigned char ExceedsLimit(
|
|
unsigned char value,
|
|
unsigned char lower_limit,
|
|
unsigned char upper_limit );
|
|
void RestoreSettings( sensor_index_t self_test_SU_index );
|
|
void SelfTestChannel( sensor_index_t self_test_SU_index );
|
|
void ExecuteChannelTest(
|
|
sensor_index_t self_test_SU_index,
|
|
unsigned char test_channel,
|
|
unsigned char test_pulse_start_level );
|
|
|
|
|
|
/* Other function prototypes. */
|
|
|
|
void Set_SU_TriggerLevels (
|
|
sensor_number_t sensor_unit,
|
|
SU_settings_t EXTERNAL *settings );
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Boot and DPU self test */
|
|
/*****************************************************************************/
|
|
|
|
void Clear_RTX_Errors( void )
|
|
/* Purpose : Clears RTX error registers in telemetry */
|
|
/* Interface : input - */
|
|
/* output - telemetry_data, rtx error registers */
|
|
/* Preconditions : none */
|
|
/* Postconditions : RTX error registers are cleared. */
|
|
/* Algorithm : See below, self explanatory. */
|
|
{
|
|
telemetry_data.isr_send_message_error = 0xFF;
|
|
telemetry_data.os_send_message_error = 0xFF;
|
|
telemetry_data.os_create_task_error = 0xFF;
|
|
telemetry_data.os_wait_error = 0xFF;
|
|
telemetry_data.os_attach_interrupt_error = 0xFF;
|
|
telemetry_data.os_enable_isr_error = 0xFF;
|
|
telemetry_data.os_disable_isr_error = 0xFF;
|
|
}
|
|
|
|
|
|
void SetSoftwareError( unsigned char error ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : This function will be called always when */
|
|
/* bit(s) in the software error status */
|
|
/* register are set. */
|
|
/* Interface : inputs - software error status register */
|
|
/* - measurement_error, which specifies what */
|
|
/* bits are set in software error status. */
|
|
/* Value is as follows, */
|
|
/* */
|
|
/* MEASUREMENT_ERROR */
|
|
/* */
|
|
/* outputs - software error status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to software error status register */
|
|
/* - Enable interrupts */
|
|
{
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.software_error |= error;
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
void ClearSoftwareError()
|
|
/* Purpose : This function will be called always when all */
|
|
/* bits in the software error status */
|
|
/* register are cleared. */
|
|
/* Interface : inputs - software error status register */
|
|
/* outputs - software error status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : */
|
|
/* - Write to SoftwareErrorStatuRegister */
|
|
|
|
{
|
|
telemetry_data.software_error = 0;
|
|
}
|
|
|
|
void SetModeStatusError( unsigned char mode_status_error )
|
|
COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : This function will be called always when */
|
|
/* error bit(s) in the mode status register are set. */
|
|
/* Interface : inputs - mode status register */
|
|
/* - mode_status_error, which specifies what */
|
|
/* bit(s) are to be set in */
|
|
/* mode status register. Value is one of */
|
|
/* the following, */
|
|
/* */
|
|
/* SUPPLY_ERROR */
|
|
/* DATA_MEMORY_ERROR */
|
|
/* PROGRAM_MEMORY_ERROR */
|
|
/* MEMORY_WRITE_ERROR */
|
|
/* ADC_ERROR */
|
|
/* */
|
|
/* outputs - mode status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to Mode Status register */
|
|
/* - Enable interrupts */
|
|
{
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.mode_status |= ( mode_status_error & ( ~MODE_BITS_MASK ) );
|
|
/* The mode bits are secured against unintended modification by */
|
|
/* clearing those bits in 'mode_status_error' before "or":ing */
|
|
/* its value to 'telemetry_data.mode_status'. */
|
|
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
void ClearModeStatusError( void )
|
|
/* Purpose : This function will be called always when all */
|
|
/* error bits in the mode status register are cleared. */
|
|
/* Interface : inputs - mode status register */
|
|
/* */
|
|
/* outputs - mode status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to Mode Status register */
|
|
/* - Enable interrupts */
|
|
{
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.mode_status &= MODE_BITS_MASK;
|
|
/* Error bits in the mode status register are cleared. */
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
void SetMode( DEBIE_mode_t mode ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : This function will be called always when */
|
|
/* mode in the mode status register is set. */
|
|
/* Interface : inputs - mode status register */
|
|
/* mode_bits, which specify the mode to be */
|
|
/* stored in the mode status register. */
|
|
/* Value is on one of the following: */
|
|
/* DPU self test */
|
|
/* stand by */
|
|
/* acquisition */
|
|
/* */
|
|
/* outputs - mode status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to Mode Status register */
|
|
/* - Enable interrupts */
|
|
|
|
{
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.mode_status = ( telemetry_data.mode_status & ~MODE_BITS_MASK )
|
|
| ( mode & MODE_BITS_MASK );
|
|
/* First mode status bits are cleared, and then the given mode is set. */
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
DEBIE_mode_t GetMode()
|
|
/* Purpose : This function will be called always when */
|
|
/* mode in the mode status register is checked. */
|
|
/* Interface : */
|
|
/* inputs - mode status register */
|
|
/* */
|
|
/* outputs - mode status register */
|
|
/* - Mode bits, which specify the mode */
|
|
/* stored in the ModeStatus register. */
|
|
/* Value is on one of the following: */
|
|
/* DPU self test */
|
|
/* stand by */
|
|
/* acquisition */
|
|
/* */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : */
|
|
/* - Read Mode Status register */
|
|
|
|
|
|
{
|
|
return ( telemetry_data.mode_status & MODE_BITS_MASK );
|
|
/* Return the value of the two least significant bits in */
|
|
/* mode status register and return this value. */
|
|
}
|
|
|
|
|
|
void Clear_SU_Error( void )
|
|
/* Purpose : This function will be called always when all */
|
|
/* error bits in the SU# status register are cleared. */
|
|
/* Interface : inputs - SU# status register */
|
|
/* */
|
|
/* outputs - SU# status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to Mode Status register */
|
|
/* - Enable interrupts */
|
|
{
|
|
sensor_index_t EXTERNAL i;
|
|
|
|
DISABLE_INTERRUPT_MASTER;
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( i = 0; i < NUM_SU; i++ ) {
|
|
telemetry_data.SU_status[ i ] &= SUPPLY_VOLTAGE_MASK;
|
|
/* Error bits in the SU# status register are cleared. */
|
|
}
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
|
|
void Set_SU_Error( sensor_index_t SU_index, unsigned char SU_error )
|
|
/* Purpose : This function will be called always when */
|
|
/* error bit(s) in the SU# status register are set. */
|
|
/* Interface : inputs - SU# status register */
|
|
/* - 'SU_index' (0-3) */
|
|
/* - 'SU_error' is one of the following: */
|
|
/* */
|
|
/* LV_SUPPLY_ERROR */
|
|
/* HV_SUPPLY_ERROR */
|
|
/* TEMPERATURE_ERROR */
|
|
/* SELF_TEST_ERROR */
|
|
/* */
|
|
/* outputs - SU# status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to SU# status register */
|
|
/* - Set corresponding SU# error bit in the */
|
|
/* error status register. */
|
|
/* - Enable interrupts */
|
|
{
|
|
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.SU_status[ SU_index ] |=
|
|
( SU_error & ( ~SUPPLY_VOLTAGE_MASK ) );
|
|
/* Error bits in the SU# status register are cleared. */
|
|
/* The voltage status bits in the SU# status register */
|
|
/* are secured against unintended modification by */
|
|
/* clearing those bits in 'SU_error' before */
|
|
/* "or":ing its value to */
|
|
/* 'telemetry_data.SU_status'. */
|
|
|
|
SetErrorStatus( ERROR_STATUS_OFFSET << SU_index );
|
|
/* SU# error is set in the error status register, if */
|
|
/* anyone of the error bits in the SU# status register */
|
|
/* is set. */
|
|
/* Because this subroutine enables itself the interrupts, */
|
|
/* the call of it must be the last operation in the */
|
|
/* interrupt blocked area ! */
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
|
|
void Set_SU_TriggerLevels (
|
|
sensor_number_t sensor_unit,
|
|
SU_settings_t EXTERNAL *settings )
|
|
/* Purpose : Set all trigger-levels of one SU. */
|
|
/* Interface : inputs - SU number in 'sensor_unit'. */
|
|
/* - Triggering levels in 'settings'. */
|
|
/* outputs - Hardware trigger levels. */
|
|
/* subroutines - SetTriggerLevel */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - set trigger level for Plasma 1+ */
|
|
/* - set trigger level for Plasma 1- */
|
|
/* - set trigger level for Piezos. */
|
|
{
|
|
trigger_set_t EXTERNAL trigger;
|
|
/* Holds parameters for SetTriggerLevel. */
|
|
|
|
trigger.sensor_unit = sensor_unit;
|
|
|
|
trigger.level = settings -> plasma_1_plus_threshold;
|
|
trigger.channel = PLASMA_1_PLUS;
|
|
SetTriggerLevel ( &trigger );
|
|
|
|
trigger.level = settings -> plasma_1_minus_threshold;
|
|
trigger.channel = PLASMA_1_MINUS;
|
|
SetTriggerLevel ( &trigger );
|
|
|
|
trigger.level = settings -> piezo_threshold;
|
|
trigger.channel = PZT_1_2;
|
|
SetTriggerLevel ( &trigger );
|
|
}
|
|
|
|
|
|
void SetErrorStatus( unsigned char error_source )
|
|
/* Purpose : This function will be called always when */
|
|
/* error bit(s) in the error status register are set. */
|
|
/* Exceptionally TC_ERROR will be set with a separate */
|
|
/* function as it is used so often. */
|
|
/* Interface : inputs - error status register */
|
|
/* - 'error_source' specifies the error bit */
|
|
/* to be set. Its value is one of the */
|
|
/* following, */
|
|
/* */
|
|
/* SU4_ERROR */
|
|
/* SU3_ERROR */
|
|
/* SU2_ERROR */
|
|
/* SU1_ERROR */
|
|
/* CHECKSUM_ERROR */
|
|
/* WATCHDOG_ERROR */
|
|
/* PARITY_ERROR */
|
|
/* */
|
|
/* outputs - error status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : - Disable interrupts */
|
|
/* - Write to error status register */
|
|
/* - Enable interrupts */
|
|
{
|
|
|
|
DISABLE_INTERRUPT_MASTER;
|
|
|
|
telemetry_data.error_status |= ( error_source & ( ~TC_ERROR ) );
|
|
/* Error bits in the error status register are set. */
|
|
/* The TC_ERROR bit in the error status register */
|
|
/* is secured against unintended modification by */
|
|
/* clearing that bit in 'error_source' before */
|
|
/* "or":ing its value to */
|
|
/* 'telemetry_data.error_status'. */
|
|
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
|
|
void ClearErrorStatus()
|
|
/* Purpose : This function will be called always when */
|
|
/* error bits in the error status register are cleared. */
|
|
/* Interface : inputs - error status register */
|
|
/* */
|
|
/* outputs - error status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : */
|
|
/* - Write to error status register */
|
|
|
|
{
|
|
telemetry_data.error_status = 0;
|
|
/* Error bits in the error status register are */
|
|
/* cleared. */
|
|
}
|
|
|
|
|
|
void DPU_SelfTest ( void )
|
|
/* Purpose : Executes the DPU voltage self test. */
|
|
/* Interface : inputs - none */
|
|
/* */
|
|
/* outputs - none */
|
|
/* subroutines - Monitor_DPU_Voltage */
|
|
/* Preconditions : none */
|
|
/* Postconditions : - Chosen supply voltages are measured. */
|
|
/* Algorithm : - Chosen supply voltages are measured and monitored with */
|
|
/* Monitor_DPU_Voltage */
|
|
{
|
|
Monitor_DPU_Voltage();
|
|
}
|
|
|
|
void Boot( void )
|
|
/* Purpose : Executes Boot sequence */
|
|
/* Interface : inputs - failed_code_address */
|
|
/* - failed_data_address */
|
|
/* outputs - intialized state of all variables */
|
|
/* subroutines - SetSensorUnitOff */
|
|
/* GetResetClass */
|
|
/* SignalMemoryErros */
|
|
/* ResetDelayCounters */
|
|
/* InitClassification */
|
|
/* ClearErrorStatus */
|
|
/* ClearSoftwareError */
|
|
/* Set_SU_TriggerLevels */
|
|
/* Preconditions : Init_DPU called earlier, after reset. */
|
|
/* Keil C startup code executed; xdata RAM initialised. */
|
|
/* Tasks are not yet running. */
|
|
/* Postconditions : DAS variables initialised. */
|
|
/* All Sensor Units are in off state */
|
|
/* If boot was caused by power-up reset, TM data registers */
|
|
/* and Science Data File are initialized */
|
|
/* If boot was not caused by watchdog-reset, error counters */
|
|
/* are cleared */
|
|
/* DEBIE mode is DPU_SELF_TEST */
|
|
/* Algorithm : see below. */
|
|
|
|
{
|
|
EXTERNAL unsigned char execution_result;
|
|
/* Execution result for SetSensorUnitOff function. */
|
|
|
|
EXTERNAL unsigned char *DIRECT_INTERNAL fill_pointer;
|
|
/* Used for data structure initialization */
|
|
|
|
DIRECT_INTERNAL reset_class_t reset_class;
|
|
/* What kind of reset caused this boot ? */
|
|
|
|
DIRECT_INTERNAL unsigned int i;
|
|
/* Loop variable */
|
|
|
|
|
|
SU_ctrl_register |= 0x0F;
|
|
SET_DATA_BYTE( SU_CONTROL, SU_ctrl_register );
|
|
/* Set all Peak detector reset signals to high */
|
|
|
|
max_events = MAX_EVENTS;
|
|
|
|
ResetDelayCounters();
|
|
|
|
SetSensorUnitOff( su1_e, &execution_result );
|
|
/* Set Sensor Unit 1 to Off state */
|
|
|
|
SetSensorUnitOff( su2_e, &execution_result );
|
|
/* Set Sensor Unit 2 to Off state */
|
|
|
|
SetSensorUnitOff( su3_e, &execution_result );
|
|
/* Set Sensor Unit 3 to Off state */
|
|
|
|
SetSensorUnitOff( su4_e, &execution_result );
|
|
/* Set Sensor Unit 4 to Off state */
|
|
|
|
ADC_channel_register |= 0x80;
|
|
UPDATE_ADC_CHANNEL_REG;
|
|
/* ADC interleave calibration is not used. */
|
|
|
|
reset_class = GetResetClass();
|
|
/* Find out what caused the reset. */
|
|
|
|
|
|
if ( reset_class != warm_reset_e ) {
|
|
/* We are running the PROM code unpatched, either */
|
|
/* from PROM or from SRAM. */
|
|
|
|
reference_checksum = INITIAL_CHECKSUM_VALUE;
|
|
/* 'reference_checksum' is used as a reference when */
|
|
/* the integrity of the code is checked by */
|
|
/* HealthMonitoringTask. It is set to its initial */
|
|
/* value here, after program code is copied from */
|
|
/* PROM to RAM. */
|
|
}
|
|
|
|
if ( reset_class == power_up_reset_e ) {
|
|
/* Data RAM was tested and is therefore garbage. */
|
|
/* Init TM data registers and Science Data File. */
|
|
|
|
internal_time = 0;
|
|
|
|
fill_pointer = ( EXTERNAL unsigned char *DIRECT_INTERNAL )&telemetry_data;
|
|
|
|
_Pragma( "loopbound min 124 max 124" )
|
|
for ( i = 0; i < sizeof( telemetry_data ); i++ ) {
|
|
*fill_pointer = 0;
|
|
fill_pointer++;
|
|
}
|
|
|
|
ResetEventQueueLength();
|
|
/* Empty event queue. */
|
|
|
|
ClearEvents();
|
|
/* Clears the event counters, quality numbers */
|
|
/* and free_slot_index of the event records in */
|
|
/* the science data memory. */
|
|
|
|
InitClassification();
|
|
/* Initializes thresholds, classification levels and */
|
|
/* min/max times related to classification. */
|
|
|
|
Clear_RTX_Errors();
|
|
/* RTX error indicating registers are initialized. */
|
|
|
|
}
|
|
|
|
else
|
|
if ( reset_class == watchdog_reset_e ) {
|
|
/* Record watchdog failure in telemetry. */
|
|
|
|
telemetry_data.error_status |= WATCHDOG_ERROR;
|
|
|
|
if ( telemetry_data.watchdog_failures < 255 )
|
|
telemetry_data.watchdog_failures++;
|
|
}
|
|
|
|
else
|
|
if ( reset_class == checksum_reset_e ) {
|
|
/* Record checksum failure in telemetry. */
|
|
|
|
telemetry_data.error_status |= CHECKSUM_ERROR;
|
|
|
|
if ( telemetry_data.checksum_failures < 255 )
|
|
telemetry_data.checksum_failures++;
|
|
}
|
|
|
|
else {
|
|
/* Soft or Warm reset. */
|
|
/* Preserve most of telemetry_data; clear some parts. */
|
|
|
|
ClearErrorStatus();
|
|
Clear_SU_Error();
|
|
Clear_RTX_Errors();
|
|
ClearSoftwareError();
|
|
telemetry_data.mode_status &= MODE_BITS_MASK;
|
|
telemetry_data.watchdog_failures = 0;
|
|
telemetry_data.checksum_failures = 0;
|
|
telemetry_data.TC_word = 0;
|
|
/* Clear error status bits, error status counters */
|
|
/* and Command Status register. */
|
|
|
|
ResetEventQueueLength();
|
|
/* Empty event queue. */
|
|
|
|
ClearEvents();
|
|
/* Clears the event counters, quality numbers */
|
|
/* and free_slot_index of the event records in */
|
|
/* the science data memory. */
|
|
|
|
InitClassification();
|
|
/* Initializes thresholds, classification levels and */
|
|
/* min/max times related to classification. */
|
|
|
|
self_test_SU_number = NO_SU;
|
|
/* Self test SU number indicating parameter */
|
|
/* is set to its default value. */
|
|
}
|
|
|
|
|
|
telemetry_data.mode_status =
|
|
( telemetry_data.mode_status & ~MODE_BITS_MASK ) | DPU_SELF_TEST;
|
|
/* Enter DPU self test mode. */
|
|
|
|
/* Software version information is stored in the telemetry data. */
|
|
telemetry_data.SW_version = SW_VERSION;
|
|
|
|
SignalMemoryErrors();
|
|
/* Copy results of RAM tests to telemetry_data. */
|
|
|
|
SetTestPulseLevel( DEFAULT_TEST_PULSE_LEVEL );
|
|
/* Initializes test pulse level. */
|
|
|
|
Set_SU_TriggerLevels ( SU_1, &telemetry_data.sensor_unit_1 );
|
|
Set_SU_TriggerLevels ( SU_2, &telemetry_data.sensor_unit_2 );
|
|
Set_SU_TriggerLevels ( SU_3, &telemetry_data.sensor_unit_3 );
|
|
Set_SU_TriggerLevels ( SU_4, &telemetry_data.sensor_unit_4 );
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Health Monitoring Task */
|
|
/*****************************************************************************/
|
|
|
|
|
|
uint_least8_t EXTERNAL health_mon_round = HEALTH_COUNT;
|
|
/* This variable is used for counting the ten health monitoring rounds */
|
|
/* which altogether equal 10 secs. */
|
|
|
|
|
|
void _Pragma( "entrypoint" ) InitHealthMonitoring ( void )
|
|
/* Purpose : Initialize the health monitoring for DEBIE. */
|
|
/* Interface : inputs - none */
|
|
/* */
|
|
/* outputs - telemetry_data */
|
|
/* */
|
|
/* subroutines - InitSystem() */
|
|
/* DPU_SelfTest() */
|
|
/* SetMode() */
|
|
/* */
|
|
/* Preconditions : Debie is on */
|
|
/* Postconditions : See subroutines */
|
|
/* Algorithm : */
|
|
/* - Executes InitSystem() */
|
|
/* - Executes DPU_SelfTest() */
|
|
/* - Enter stand_by mode */
|
|
{
|
|
InitSystem();
|
|
/* Initializes the system. */
|
|
|
|
DPU_SelfTest();
|
|
/* Execute the DPU self test. */
|
|
|
|
SetMode( STAND_BY );
|
|
/* Switch to Standby mode */
|
|
}
|
|
|
|
|
|
void _Pragma( "entrypoint" ) HandleHealthMonitoring ( void )
|
|
/* Purpose : One round of health monitoring for DEBIE. */
|
|
/* Interface : inputs - telemetry_data */
|
|
/* */
|
|
/* outputs - telemetry_data */
|
|
/* */
|
|
/* subroutines - UpdateTime() */
|
|
/* Monitor() */
|
|
/* UpdatePeriodCounter() */
|
|
/* WaitInterval() */
|
|
/* */
|
|
/* Preconditions : Debie is on */
|
|
/* Postconditions : See subroutines */
|
|
/* Algorithm : */
|
|
/* - Updates sensor unit states */
|
|
/* - Executes UpdateTime() */
|
|
/* - Calls Monitor() function */
|
|
/* - UpdatePeriodCounter() function advances the */
|
|
/* health monitoring counter */
|
|
/* - Executes WaitInterval() */
|
|
{
|
|
Update_SU_State ( 0 );
|
|
Update_SU_State ( 1 );
|
|
Update_SU_State ( 2 );
|
|
Update_SU_State ( 3 );
|
|
|
|
UpdateTime();
|
|
/* Update telemetry registers. */
|
|
|
|
Monitor( health_mon_round );
|
|
/* Execute current Health Monitoring Round. */
|
|
|
|
UpdatePeriodCounter( &health_mon_round, HEALTH_COUNT );
|
|
/* Decrease or reset health monitor loop counter depending on its */
|
|
/* current and limiting values. */
|
|
|
|
WaitInterval( HM_INTERVAL );
|
|
/* Wait for next activation */
|
|
}
|
|
|
|
|
|
void HealthMonitoringTask( void ) TASK( HEALTH_MONITORING_TASK )
|
|
PRIORITY( HEALTH_MONITORING_PR )
|
|
/* Purpose : Takes care of health monitoring for DEBIE. */
|
|
/* Interface : inputs - telemetry_data */
|
|
/* */
|
|
/* outputs - telemetry_data */
|
|
/* */
|
|
/* subroutines - UpdateTime() */
|
|
/* Monitor() */
|
|
/* UpdatePeriodCounter() */
|
|
/* WaitInterval() */
|
|
/* */
|
|
/* Preconditions : Debie is on */
|
|
/* Postconditions : See subroutines */
|
|
/* Algorithm : */
|
|
/* - InitHealthMonitoring */
|
|
/* - loop forever: */
|
|
/* - HandleHealthMonitoring */
|
|
{
|
|
InitHealthMonitoring ();
|
|
|
|
_Pragma( "loopbound min 0 max 0" )
|
|
while ( 1 )
|
|
HandleHealthMonitoring ();
|
|
}
|
|
|
|
|
|
void Monitor( uint_least8_t health_mon_round )
|
|
/* Purpose : Monitors DEBIE's vital signs */
|
|
/* Interface : inputs - Health Monitoring Round count */
|
|
/* outputs - none */
|
|
/* subroutines - MeasureTemperature() */
|
|
/* CheckCurrent() */
|
|
/* MeasureVoltage() */
|
|
/* CalculateChecksum() */
|
|
/* Preconditions : Health monitoring is on. */
|
|
/* Postconditions : Health monitoring duties are carried out. */
|
|
/* Algorithm : */
|
|
/* - Executes the given health monitor loop round. */
|
|
/* - Starts three loops: */
|
|
/* - voltage measurement loop 180 secs */
|
|
/* - temperature measurement loop 60 secs */
|
|
/* - checksum count loop 60 secs */
|
|
/* The values of these counters are decreased after each */
|
|
/* loop cycle. */
|
|
/* */
|
|
/* Health monitoring loop which lasts 10 secs and is */
|
|
/* divided into 10 individual rounds. On each round */
|
|
/* some specific Health Monitoring duties are carried */
|
|
/* out. For example the Watchdog counter is resetted. */
|
|
/* */
|
|
/* Temperature measurement loop lasts 60 secs and */
|
|
/* consists of 6 Health Monitoring loop cycles each */
|
|
/* lasting 10 secs. It is executed partly on each 10 sec */
|
|
/* Health Monitoring cycle by measuring temperatures of */
|
|
/* one SU on each cycle. Measurement starts on the second*/
|
|
/* Health Monitoring cycle and is completed after six */
|
|
/* cycles. */
|
|
/* */
|
|
/* Voltage measurement loop lasts 180 secs and consists */
|
|
/* of 18 Health Monitoring loop cycles each lasting 10 */
|
|
/* secs. On each cycle some of its duties are carried */
|
|
/* out. */
|
|
/* */
|
|
/* Checksum calculation loop lasts 60 secs and consists */
|
|
/* of 6 Health Monitoring loop cycles each lasting 10 */
|
|
/* secs. It is executed partly on each Health Monitoring*/
|
|
/* round. */
|
|
/* */
|
|
/* Illustration of the process: */
|
|
/* */
|
|
/* M */
|
|
/* _________|_________ */
|
|
/* | | */
|
|
/* |R-R-R-R-R-R-R-R-R-R> : Health Monitoring loop: M */
|
|
/* <---------------------< Round: R = 1 sec */
|
|
/* M = 10*R = 10 secs */
|
|
/* */
|
|
/* T */
|
|
/* _____|_____ */
|
|
/* | | */
|
|
/* |M-M-M-M-M-M> Temperature Measurement loop: T */
|
|
/* <-----------< Health Monitoring loop: M = 10 sec */
|
|
/* T = 6*M = 60 secs */
|
|
/* */
|
|
/* C */
|
|
/* _____________|____________ Checksum count loop: C */
|
|
/* | | */
|
|
/* |R-R-R-R-R-R-R-R-R-R> */
|
|
/* >R-R-R-R-R-R-R-R-R-R> */
|
|
/* >R-R-R-R-R-R-R-R-R-R> */
|
|
/* >R-R-R-R-R-R-R-R-R-R> */
|
|
/* >R-R-R-R-R-R-R-R-R-R> */
|
|
/* >R-R-R-R-R-R-R-R-R-R> */
|
|
/* Health Monitoring loop cycle: R = 1 sec */
|
|
/* C = 60*R = 60 secs */
|
|
/* */
|
|
/* V */
|
|
/* _________________|__________________ */
|
|
/* | | */
|
|
/* |M-M-M-M-M-M-M-M-M-M-M-M-M-M-M-M-M-M> Voltage Measurement loop: V */
|
|
/* <-----------------------------------< Health Monitoring loop: M */
|
|
/* V = 18*M = 180 secs */
|
|
{
|
|
CalculateChecksum( checksum_count );
|
|
/* A 1/60th part of the memory checksum is calculated. */
|
|
|
|
UpdatePeriodCounter( &checksum_count, CHECK_COUNT );
|
|
/* Decrease or reset checksum counter */
|
|
/* depending on its current and limiting values. */
|
|
|
|
|
|
switch ( health_mon_round ) {
|
|
case round_0_e:
|
|
|
|
HighVoltageCurrent( ( sensor_index_t )health_mon_round );
|
|
/* Overcurrent indicating bits related to sensor unit 1 in HV */
|
|
/* status register are checked. */
|
|
|
|
UpdatePeriodCounter( &temp_meas_count, TEMP_COUNT );
|
|
UpdatePeriodCounter( &voltage_meas_count, VOLTAGE_COUNT );
|
|
/* Decrease or reset temperature, checksum and voltage counters */
|
|
/* depending on their current and limiting values. */
|
|
|
|
|
|
hit_budget_left = hit_budget;
|
|
/* Health Monitoring period ends and new hit budget can be started. */
|
|
|
|
if ( HIT_TRIGGER_FLAG == 0 ) {
|
|
/* Hit budget was exceeded during this ending Health Monitoring */
|
|
/* period. */
|
|
|
|
ResetPeakDetector( SU_1 );
|
|
ResetPeakDetector( SU_2 );
|
|
ResetPeakDetector( SU_3 );
|
|
ResetPeakDetector( SU_4 );
|
|
/* Reset all Peak detectors */
|
|
|
|
WaitTimeout( COUNTER_RESET_MIN_DELAY );
|
|
|
|
ENABLE_HIT_TRIGGER;
|
|
/* Allows a later falling edge on T2EX to cause */
|
|
/* a Hit Trigger interrupt (i.e. to set EXF2). */
|
|
|
|
ResetDelayCounters();
|
|
/* Resets the SU logic that generates Hit Triggers. */
|
|
/* Brings T2EX to a high level, making a new falling */
|
|
/* edge possible. */
|
|
/* This statement must come after the above "enable", */
|
|
/* since T2EX edges are not remembered by the HW from */
|
|
/* before the "enable", unlike normal interrupt enable */
|
|
/* and disable masking. */
|
|
}
|
|
|
|
break;
|
|
|
|
case round_1_e:
|
|
|
|
HighVoltageCurrent( ( sensor_index_t )health_mon_round );
|
|
/* Overcurrent indicating bits related to sensor unit 2 in HV */
|
|
/* status register are checked. */
|
|
|
|
break;
|
|
|
|
case round_2_e:
|
|
|
|
HighVoltageCurrent( ( sensor_index_t )health_mon_round );
|
|
/* Overcurrent indicating bits related to sensor unit 3 in HV */
|
|
/* status register are checked. */
|
|
|
|
break;
|
|
|
|
case round_3_e:
|
|
|
|
HighVoltageCurrent( ( sensor_index_t )health_mon_round );
|
|
/* Overcurrent indicating bits related to sensor unit 4 in HV */
|
|
/* status register are checked. */
|
|
|
|
break;
|
|
|
|
case round_4_e:
|
|
|
|
LowVoltageCurrent();
|
|
/* 'V_DOWN' indicator bit is checked. */
|
|
|
|
|
|
break;
|
|
|
|
case round_5_e:
|
|
|
|
if ( voltage_meas_count < 7 )
|
|
|
|
{
|
|
/* Seven Secondary voltage channels are measured starting when */
|
|
/* 'voltage_meas_count' reaches a value of 6. Last measurement is*/
|
|
/* executed on voltage_meas_count value 0. */
|
|
|
|
MeasureVoltage( voltage_meas_count );
|
|
}
|
|
|
|
break;
|
|
|
|
case round_6_e:
|
|
|
|
if ( ( self_test_SU_number != NO_SU ) &&
|
|
( SU_state[ self_test_SU_number - SU1 ] == self_test_e ) ) {
|
|
/* SU self test sequence continues */
|
|
|
|
SelfTestChannel( self_test_SU_number - SU1 );
|
|
/* SU channels are monitored in this round. */
|
|
|
|
self_test_SU_number = NO_SU;
|
|
/* SU self test sequence ends here */
|
|
}
|
|
|
|
break;
|
|
|
|
case round_7_e:
|
|
|
|
if ( self_test_SU_number != NO_SU ) {
|
|
/* SU self test sequence has started */
|
|
|
|
self_test_flag = SELF_TEST_RUNNING;
|
|
/* Indication of a started test. */
|
|
|
|
SelfTest_SU( self_test_SU_number - SU1 );
|
|
/* Supply voltages and SU temperatures are monitored in this round. */
|
|
|
|
if ( self_test_SU_number != NO_SU )
|
|
SU_state[ self_test_SU_number - SU1 ] = self_test_e;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case round_8_e:
|
|
|
|
SET_WD_RESET_HIGH;
|
|
|
|
/* The Watch Dog time out signal state is reset HIGH state, as it is*/
|
|
/* falling edge active. */
|
|
|
|
break;
|
|
|
|
case round_9_e:
|
|
|
|
if ( temp_meas_count < NUM_SU )
|
|
|
|
{
|
|
/* Two channels of one sensor unit are measured when */
|
|
/* 'temp_meas_count' reaches 3 -> 2 -> 1 -> 0. I.e. measuring */
|
|
/* begins after 10 secs and is finished after 50 secs. */
|
|
|
|
MeasureTemperature( ( sensor_index_t )temp_meas_count );
|
|
}
|
|
|
|
SET_WD_RESET_LOW;
|
|
|
|
/* The Watch Dog timer is reset by setting WD_RESET bit low at I/O */
|
|
/* port 1. This is done here with 10 sec interval. The watch dog */
|
|
/* time-out is 12.1 secs. */
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void UpdateTime( void )
|
|
/* Purpose : advances time in the telemetry */
|
|
/* Interface : inputs - telemetry_data.time */
|
|
/* outputs - telemetry_data.time */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Time updated in telemetry_data. */
|
|
/* Algorithm : */
|
|
/* Time in the telemetry_data.time is advanced until */
|
|
/* maximum value for the variable is reached, after that it */
|
|
/* is implicitely wrapped-around on overflow. */
|
|
{
|
|
|
|
DISABLE_INTERRUPT_MASTER;
|
|
/* Disable all interrupts. */
|
|
|
|
internal_time ++;
|
|
/* Increment internal time. */
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
/* Enable all interrupts. */
|
|
|
|
}
|
|
|
|
|
|
void MeasureTemperature( sensor_index_t SU_index )
|
|
/* Purpose : Measures and monitors SU temperatures */
|
|
/* Interface : inputs - SU_index, sensor unit index (0 - 3) */
|
|
/* telemetry_data */
|
|
/* outputs - telemetry_data */
|
|
/* subroutines - Read_AD_Channel() */
|
|
/* TemperatureFailure() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : - ADC temperature channels are measured. */
|
|
/* - In case of an overheated SU, */
|
|
/* 'TemperatureFailure()' function is called.i.e. */
|
|
/* all secondary supply voltages to that SU are switched */
|
|
/* off, SU related Bit in the Error Status Register is set*/
|
|
/* and temperature error indicating bit in the SU_Status */
|
|
/* register is set. */
|
|
/* - If a measurement has failed, in addition to overheating*/
|
|
/* response also measurement error indication bit in mode */
|
|
/* status register is set */
|
|
/* Algorithm : - Temperatures of a given sensor unit are measured. */
|
|
/* - If measured temperature is large enough, it is stored */
|
|
/* into telemetry. */
|
|
/* */
|
|
/* - Else measured temperature value is too small to be */
|
|
/* stored. Zero value is stored into telemetry. */
|
|
/* */
|
|
/* - If temperature of any of the Sensor Units is over */
|
|
/* MAX_TEMP, 'TemperatureFailure()' function is */
|
|
/* called. */
|
|
/* */
|
|
/* - If temperature measurement of a Sensor Unit has failed,*/
|
|
/* temperature error indicating bit in the SU_Status */
|
|
/* register is set and TemperatureFailure()' */
|
|
/* function is called. */
|
|
{
|
|
|
|
ADC_parameters_t EXTERNAL AD_temperature_parameters;
|
|
/* This struct is used to hold parameters for Reading AD channels. */
|
|
|
|
unsigned char temp_limit_value;
|
|
|
|
uint_least8_t EXTERNAL j;
|
|
/* This variable is used in for-loop. */
|
|
|
|
|
|
|
|
_Pragma( "loopbound min 2 max 2" )
|
|
for ( j = 0; j < NUM_TEMP; j++ )
|
|
|
|
{
|
|
AD_temperature_parameters.ADC_channel =
|
|
5 + ( SU_index & 1 ) * 8 + ( SU_index & 2 ) * 12 + j;
|
|
/* Select the channel to be measured. */
|
|
|
|
AD_temperature_parameters.ADC_max_tries = ADC_TEMPERATURE_MAX_TRIES;
|
|
/* When temperatures are measured this variable defines the maximum */
|
|
/* amount of tries to be used in reading and handling an AD channel in */
|
|
/* 'Read_AD_Channel()'. */
|
|
|
|
AD_temperature_parameters.conversion_max_tries =
|
|
CONVERSION_TEMPERATURE_MAX_TRIES;
|
|
/* When temperatures are measured this variable defines the maximum */
|
|
/* amount of tries to be used when End Of Conversion indication is */
|
|
/* waited in function 'Convert_AD()'. */
|
|
|
|
Read_AD_Channel( &AD_temperature_parameters );
|
|
/* Get ADC temperature measurement result. */
|
|
|
|
|
|
|
|
if ( AD_temperature_parameters.unsigned_ADC & 0x8000 )
|
|
|
|
{
|
|
/* Temperature is stored in the telemetry. */
|
|
|
|
telemetry_data.SU_temperature[ SU_index ][ j ] =
|
|
( unsigned char )( ( AD_temperature_parameters.unsigned_ADC
|
|
& 0x7FFF ) >> 7 );
|
|
/* Store bits 7 .. 14 */
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
telemetry_data.SU_temperature[ SU_index ][ j ] = 0;
|
|
/* Temperature too small -> store zero */
|
|
|
|
}
|
|
|
|
temp_limit_value = ( j == 0 ? MAX_TEMP_1 : MAX_TEMP_2 );
|
|
|
|
if ( telemetry_data.SU_temperature[ SU_index ][ j ] > temp_limit_value )
|
|
|
|
{
|
|
/* Temperature has exeeded a predefined limit */
|
|
|
|
TemperatureFailure( SU_index );
|
|
/* Given SU is switched off, error and SU status registers are */
|
|
/* updated in telemetry. */
|
|
|
|
}
|
|
|
|
if ( AD_temperature_parameters.AD_execution_result != RESULT_OK )
|
|
|
|
{
|
|
/* An anomaly has occurred during the measurement. */
|
|
|
|
SetSoftwareError( MEASUREMENT_ERROR );
|
|
/* Set measurement error indication bit in */
|
|
/* software error status register. */
|
|
|
|
|
|
|
|
|
|
|
|
TemperatureFailure( SU_index );
|
|
/* Given SU is switched off and error and SU status registers are */
|
|
/* updated in telemetry. */
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void HighVoltageCurrent( sensor_index_t SU_index )
|
|
/* Purpose : Monitors overcurrent indicating bits in the HV Status */
|
|
/* register for a given sensor unit. */
|
|
/* Interface : inputs - SU_index, sensor unit index (0 - 3) */
|
|
/* telemetry_data */
|
|
/* HV_status register */
|
|
/* outputs - telemetry_data */
|
|
/* subroutines - SetErrorStatus() */
|
|
/* Set_SU_Error() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : following registers are updated in case of an error, */
|
|
/* - Sensor Unit or units are switched off */
|
|
/* - Error Status register updated */
|
|
/* - SU Status register updated */
|
|
/* Algorithm : */
|
|
/* - if any of the HV_Status bits indicate a short */
|
|
/* circuit or overload, the corresponding Error Status */
|
|
/* Bits in the Error Status and SU_Status Registers are */
|
|
/* set. */
|
|
{
|
|
unsigned char EXTERNAL SU_current_mask[ ] = {3, 12, 48, 192};
|
|
/* This array holds parameters for checking the HV status register. */
|
|
|
|
unsigned char EXTERNAL valid_value[ ] = {1, 4, 16, 64};
|
|
/* This array holds comparison parameters for checking the HV status */
|
|
/* register. */
|
|
|
|
if ( CHECK_CURRENT( SU_current_mask[ SU_index ] ) !=
|
|
valid_value[ SU_index ] )
|
|
|
|
{
|
|
/* Overcurrent is detected. */
|
|
|
|
SetErrorStatus( ERROR_STATUS_OFFSET << SU_index );
|
|
/* Set high corresponding bit for the SU in Error Status Register. */
|
|
|
|
Set_SU_Error( SU_index, HV_SUPPLY_ERROR );
|
|
/* Set high HV supply error indicating bit in the SU_Status register*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void LowVoltageCurrent( void )
|
|
/* Purpose : Monitors low voltage currents in Sensor Units. */
|
|
/* Interface : inputs - telemetry_data */
|
|
/* V_DOWN bit */
|
|
/* outputs - telemetry_data */
|
|
/* subroutines - SetSensorUnitOff() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Following actions are taken in case of an error, */
|
|
/* - Sensor Unit or units are switched off */
|
|
/* - SU Status register updated */
|
|
/* - Error Status register updated */
|
|
/* Algorithm : */
|
|
/* - If V_DOWN bit in I/O port 1 is LOW indicating that */
|
|
/* +-5 V DC/DC converter(s) is(are) limiting the output */
|
|
/* current, all SU supply voltages are */
|
|
/* switched off and corresponding bits in the Error and */
|
|
/* mode Status Register are set. */
|
|
{
|
|
|
|
sensor_index_t EXTERNAL i;
|
|
/* This variable is used in a for-loop. */
|
|
|
|
unsigned char EXTERNAL exec_result;
|
|
/* This variable is used by SetSensorUnitOff() function. */
|
|
|
|
if ( V_DOWN == LOW )
|
|
|
|
{
|
|
/* An error is detected, output current is limited. */
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( i = 0; i < NUM_SU; i++ )
|
|
|
|
{
|
|
/* Switch off all Sensor Units. */
|
|
|
|
SetSensorUnitOff( i, &exec_result );
|
|
/* Switch off given sensor unit. */
|
|
|
|
Set_SU_Error( i, LV_SUPPLY_ERROR );
|
|
/* Set high LV supply error indicating bit in the SU_Status */
|
|
/* register. */
|
|
}
|
|
|
|
SetErrorStatus( OVERALL_SU_ERROR );
|
|
/* Set all SU error status bits in 'error status register' at telemetry.*/
|
|
|
|
}
|
|
}
|
|
|
|
void MeasureVoltage( uint_least8_t channel_selector )
|
|
/* Purpose : Measure secondary Sensor Unit voltages. */
|
|
/* Interface : inputs - Channel selector, values 0 - 6 */
|
|
/* outputs - telemetry_data.mode_status */
|
|
/* subroutines - Read_AD_Channel() */
|
|
/* VoltageFailure() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : - Measurement results are written to telemetry. */
|
|
/* - If a measurement has failed, measurement error */
|
|
/* indication bit in mode status register is set and */
|
|
/* 'VoltageFailure()' function is called.i.e. */
|
|
/* SUs related to failed ADC channel are switched */
|
|
/* off, SU related Bit in the Error Status Register is set*/
|
|
/* and LV error indicating bit in the SU_Status */
|
|
/* register is set. */
|
|
/* Algorithm : - Secondary SU supply voltages are measured from */
|
|
/* a given channel. */
|
|
/* - If measurement has failed, */
|
|
/* measurement error indication bit in mode status */
|
|
/* register is set and 'VoltageFailure()' */
|
|
/* function is called. */
|
|
/* - If no errors have occurred, results are stored */
|
|
/* in telemetry_data. */
|
|
{
|
|
|
|
ADC_parameters_t EXTERNAL AD_voltage_parameters;
|
|
/* This struct is used to hold parameters for Reading AD channels. */
|
|
|
|
unsigned char EXTERNAL voltage_channel[ ] = {
|
|
0x10, 0x11, 0x12, 0x13, 0x54, 0x55, 0x56
|
|
};
|
|
/* This array holds parameters for setting the ADC channel for the */
|
|
/* measurement. */
|
|
|
|
AD_voltage_parameters.ADC_channel = voltage_channel[ channel_selector ];
|
|
/* Select the channel to be measured: */
|
|
/* channel_selector -> ADC channel */
|
|
/* 0 -> 0x10 */
|
|
/* 1 -> 0x11 */
|
|
/* 2 -> 0x12 */
|
|
/* 3 -> 0x13 */
|
|
/* 4 -> 0x54 */
|
|
/* 5 -> 0x55 */
|
|
/* 6 -> 0x56 */
|
|
|
|
AD_voltage_parameters.ADC_max_tries = ADC_VOLTAGE_MAX_TRIES;
|
|
/* When voltages are measured this variable defines the maximum */
|
|
/* amount of tries to be used in reading and handling an AD channel in */
|
|
/* 'Read_AD_Channel()'. */
|
|
|
|
AD_voltage_parameters.conversion_max_tries =
|
|
CONVERSION_VOLTAGE_MAX_TRIES;
|
|
/* When voltages are measured this variable defines the maximum */
|
|
/* amount of tries to be used when End Of Conversion indication is */
|
|
/* waited in function 'Convert_AD()'. */
|
|
|
|
Read_AD_Channel( &AD_voltage_parameters );
|
|
/* Voltage channel is read. */
|
|
|
|
if ( AD_voltage_parameters.AD_execution_result != RESULT_OK ) {
|
|
/* An anomaly has occurred during the measurement. */
|
|
|
|
SetSoftwareError( MEASUREMENT_ERROR );
|
|
/* Set measurement error indication bit in */
|
|
/* software error status register. */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch ( channel_selector ) {
|
|
/* Measurement result bits 8..15 from channels involving positive */
|
|
/* voltages are written to telemetry. */
|
|
|
|
case channel_0_e:
|
|
|
|
telemetry_data.sensor_unit_1.plus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
telemetry_data.sensor_unit_2.plus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
case channel_1_e:
|
|
|
|
telemetry_data.sensor_unit_3.plus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
telemetry_data.sensor_unit_4.plus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
case channel_2_e:
|
|
|
|
telemetry_data.SU_plus_50 = AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
case channel_3_e:
|
|
|
|
telemetry_data.DPU_plus_5_digital =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
|
|
/* Measurement result bits 8..15 from channels involving negative */
|
|
/* voltages are written to telemetry. */
|
|
/* Note that even here, the "unsigned" or "raw" conversion result is */
|
|
/* used; this is a requirement. */
|
|
|
|
case channel_4_e:
|
|
|
|
telemetry_data.sensor_unit_1.minus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
telemetry_data.sensor_unit_2.minus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
case channel_5_e:
|
|
|
|
telemetry_data.sensor_unit_3.minus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
telemetry_data.sensor_unit_4.minus_5_voltage =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
|
|
case channel_6_e:
|
|
|
|
telemetry_data.SU_minus_50 =
|
|
AD_voltage_parameters.unsigned_ADC >> 8;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void InitSystem( void )
|
|
/* Purpose : Initialize system after RTX system is started. */
|
|
/* Interface : inputs - none */
|
|
/* outputs - none */
|
|
/* subroutines - SetTimeSlice() */
|
|
/* WaitInterval() */
|
|
/* CreateTask() */
|
|
/* Preconditions : RTX is on. */
|
|
/* Postconditions : System initialization duties are carried out i.e. rtx */
|
|
/* tasks are activated, system clock interval is set. */
|
|
/* Algorithm : - Set system clock interval */
|
|
/* - Wait for automatic A/D converter calibration. */
|
|
/* - Activate the Telecommand Execution task. */
|
|
/* - Activate the Acquisition task. */
|
|
/* - Activate Hit Trigger Interrupt Service task. */
|
|
{
|
|
task_info_t EXTERNAL new_task;
|
|
/* Parameters for creating new task */
|
|
|
|
SetTimeSlice( SYSTEM_INTERVAL );
|
|
/* Set system clock interval */
|
|
|
|
WaitInterval( BOOT_WAIT_INTERVAL );
|
|
/* Wait for automatic A/D converter calibration */
|
|
|
|
new_task.rtx_task_number = TC_TM_INTERFACE_TASK;
|
|
new_task.task_main_function = TC_task;
|
|
CreateTask( &new_task );
|
|
/* Activate the Telecommand Execution task */
|
|
|
|
new_task.rtx_task_number = ACQUISITION_TASK;
|
|
new_task.task_main_function = acq_task;
|
|
CreateTask( &new_task );
|
|
/* Activate the Acquisition task */
|
|
|
|
new_task.rtx_task_number = HIT_TRIGGER_ISR_TASK;
|
|
new_task.task_main_function = hit_task;
|
|
CreateTask( &new_task );
|
|
/* Activate Hit Trigger Interrupt Service task */
|
|
|
|
}
|
|
|
|
void CalculateChecksum( uint_least8_t checksum_count )
|
|
/* Purpose : Calculates memory checksum. */
|
|
/* Interface : inputs - 'checksum_count' gives the current */
|
|
/* checksum loop cycle value, */
|
|
/* MIN_CHECKSUM_COUNT <= 'checksum_count' */
|
|
/* <= MAX_CHECKSUM_COUNT */
|
|
/* */
|
|
/* - 'reference_checksum' variable to verify */
|
|
/* correct codememory. */
|
|
/* - global variable 'code_not_patched' */
|
|
/* outputs - 'code_checksum' is modified. */
|
|
/* - value of global variable */
|
|
/* 'code_not_patched' is conditionally set. */
|
|
/* subroutines - Reboot() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Changes values of variable 'code_checksum' and */
|
|
/* on first round variable 'code_not_patched'. */
|
|
/* */
|
|
/* - In case of a checksum error, */
|
|
/* Soft reset is executed, if 'code_not_patched' */
|
|
/* indication enables this. */
|
|
/* */
|
|
/* Algorithm : - Health monitoring calculates checksum with XOR for */
|
|
/* CHECK_SIZE amount of codememory bytes at a time. At */
|
|
/* the end of the check cycle, i.e. 'checksum_count' = 0, */
|
|
/* the variable 'code_checksum' */
|
|
/* should be equal with 'reference_checksum', if no */
|
|
/* errors have occurred and code has not been patched */
|
|
/* during the checksum cycle. */
|
|
/* */
|
|
/* - If an error is detected in the code memory, Reboot() */
|
|
/* function is called. */
|
|
/* */
|
|
/* - if no anomalies have been encountered there will be no */
|
|
/* changes and checksum loop starts from the beginning */
|
|
/* i.e. on 'checksum_count' = 59, 'code_not_patched' */
|
|
/* is set and 'code_checksum' is initialised. */
|
|
{
|
|
code_address_t EXTERNAL i;
|
|
/* This variable is used in a for-loop. */
|
|
|
|
code_address_t EXTERNAL check_start;
|
|
/* This variable is used for determining the start address of a given */
|
|
/* check. */
|
|
|
|
code_address_t EXTERNAL check_end;
|
|
/* This variable is used for determining the end address of a given check.*/
|
|
|
|
check_start = checksum_count * CHECK_SIZE;
|
|
|
|
if ( checksum_count == MAX_CHECKSUM_COUNT )
|
|
|
|
{
|
|
/* This piece ends at the top memory address. */
|
|
check_end = CODE_MEMORY_END;
|
|
}
|
|
|
|
else
|
|
|
|
check_end = check_start + ( CHECK_SIZE - 1 );
|
|
|
|
if ( checksum_count == MAX_CHECKSUM_COUNT ) {
|
|
|
|
code_checksum = 0;
|
|
/* This global variable is used to store the result from each XOR */
|
|
/* calculation during a code memory checksum round. It is cleared */
|
|
/* here at the beginning of a new cycle and checked at the end of */
|
|
/* each cycle against 'reference_checksum'. */
|
|
|
|
code_not_patched = 1;
|
|
/* This global variable shows whether code is patched during a code */
|
|
/* memory checksum cycle. It is set here at the beginning of a new */
|
|
/* cycle and checked at the end of each cycle whether it has been */
|
|
/* cleared as an indication of an executed code patching. */
|
|
}
|
|
|
|
|
|
_Pragma( "loopbound min 547 max 547" )
|
|
for ( i = check_start; i <= check_end; i++ )
|
|
|
|
{
|
|
/* It is assumed that 'CODE_MEMORY_END' < 2^16 - 1 */
|
|
/* Otherwise variable 'i' can never have a value */
|
|
/* larger than 'check_end' and this loop will never */
|
|
/* stop. */
|
|
|
|
code_checksum ^= GET_CODE_BYTE( i );
|
|
/* XOR is counted for code memory byte under check. */
|
|
}
|
|
|
|
if ( ( checksum_count == MIN_CHECKSUM_COUNT )
|
|
&& ( code_checksum != reference_checksum ) ) {
|
|
/* Checksum mismatch due to a memory error or */
|
|
/* code memory patch. */
|
|
|
|
if ( code_not_patched ) {
|
|
/* An anomaly has been detected in the code memory */
|
|
/* area. Code has not been patched during this code */
|
|
/* memory checksum cycle. */
|
|
|
|
Reboot ( checksum_reset_e );
|
|
/* Soft reset is executed, as global variable */
|
|
/* 'code_not_patched' enables it. Note that */
|
|
/* Reboot() does not return here. */
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void UpdatePeriodCounter(
|
|
uint_least8_t EXTERNAL *counter,
|
|
uint_least8_t full_counter_value )
|
|
/* Purpose : Advances counters */
|
|
/* Interface : inputs - address to counter variable */
|
|
/* outputs - none */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : counter value is adjusted */
|
|
/* Algorithm : - If a given counter is not already zero, its value is */
|
|
/* decreased. */
|
|
/* - Else it set to its initialization value. */
|
|
{
|
|
if ( *counter )
|
|
|
|
{
|
|
( *counter )--;
|
|
/* Decrease temperature measurement counter. */
|
|
}
|
|
|
|
else {
|
|
*counter = full_counter_value;
|
|
/* Reset temperature measurement counter. */
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Convert_AD ( ADC_parameters_t EXTERNAL *ADC_parameters )
|
|
/* Purpose : Conversion is executed on a selected AD channel */
|
|
/* Interface : inputs - Address of a struct for storing the ADC */
|
|
/* results. */
|
|
/* outputs - ADC results are stored to the given struct */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : ADC results are written to a struct */
|
|
/* Algorithm : - AD Conversion is started on the selected channel. */
|
|
/* - End of conversion is polled, EOC bit at I/O port 1, */
|
|
/* as long as the preset limit is not exceeded. */
|
|
/* - If limit has not been exeeded, resulting MSB and LSB of*/
|
|
/* the conversion are read from the HW registers and */
|
|
/* combined into one word. */
|
|
/* Else end of conversion can no longer be waited. No */
|
|
/* results are gained, instead a zero is stored with an */
|
|
/* indication of this occurred anomaly. */
|
|
{
|
|
unsigned char DIRECT_INTERNAL conversion_count;
|
|
|
|
/* Counts the amount of end of conversion polls. */
|
|
|
|
unsigned char DIRECT_INTERNAL msb, lsb;
|
|
/* MSB and LSB of the conversion result */
|
|
|
|
unsigned int DIRECT_INTERNAL word;
|
|
/*This variable is used to combine MSB and LSB bytes into one word. */
|
|
|
|
START_CONVERSION;
|
|
|
|
conversion_count = 0;
|
|
|
|
_Pragma( "loopbound min 0 max 5" )
|
|
while ( conversion_count < ADC_parameters -> conversion_max_tries
|
|
&& ( END_OF_ADC != CONVERSION_ACTIVE ) ) {
|
|
/* Previous conversion is still active. */
|
|
conversion_count++;
|
|
}
|
|
|
|
/* There is a slight chance for the following occurrence: */
|
|
/* Conversion has ended after max_tries has been reached but before the */
|
|
/* following condition loop is entered. As a result measurement is failed */
|
|
/* even if conversion has ended in time. The effect is dimished if the */
|
|
/* max_tries is a large value i.e. end of conversion has been waited long */
|
|
/* enough. */
|
|
|
|
if ( conversion_count < ADC_parameters -> conversion_max_tries )
|
|
|
|
{
|
|
/* Conversion has ended. Read AD result. */
|
|
|
|
msb = GET_RESULT;
|
|
lsb = GET_RESULT;
|
|
|
|
word = ( unsigned int )msb * 256 + lsb;
|
|
/* Combine MSB and LSB as type 'unsigned int' in the given struct. */
|
|
|
|
ADC_parameters -> signed_ADC = ( signed short int )( word ^ 0x8000 );
|
|
/* Store result as of type 'signed int'. */
|
|
|
|
ADC_parameters -> unsigned_ADC = word;
|
|
/* Store result as of type 'unsigned int'. */
|
|
|
|
ADC_parameters -> AD_execution_result = RESULT_OK;
|
|
/* Store indication of an succesful measurement. */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Conversion has not ended in time. No results gained, store zero. */
|
|
ADC_parameters -> unsigned_ADC = 0;
|
|
ADC_parameters -> signed_ADC = 0;
|
|
|
|
/* Store indication of an unsuccesful measurement. */
|
|
ADC_parameters -> AD_execution_result = CONVERSION_ACTIVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void VoltageFailure( channel_t ADC_channel )
|
|
/* Purpose : Takes care of resulting actions in case of a failed */
|
|
/* measurement. */
|
|
/* Interface : inputs - 'ADC_channel' related to the failed */
|
|
/* measurement. */
|
|
/* */
|
|
/* outputs - telemetry_data.error_status register */
|
|
/* telemetry_data.SU_status register */
|
|
/* telemetry_data.mode_status register */
|
|
/* subroutines - none */
|
|
/* Preconditions : There has been an anomaly */
|
|
/* during an ADC channel measurement. */
|
|
/* Postconditions : Sensor unit(s) related error indication bit(s) are set */
|
|
/* in error_status, SU_status and mode_status registers. */
|
|
/* Algorithm : */
|
|
/* 'ADC_channel' is the number of the channel which failed */
|
|
/* measurement. The following actions are taken. */
|
|
/* - Find out which sensor units are related to failed */
|
|
/* measurement and store indications of these target */
|
|
/* SUs in the 'SU_action[ ]' array. */
|
|
/* - If channel number indicates that the DPU voltage */
|
|
/* measurement has failed, set high DPU +5V measurement*/
|
|
/* error indicating bit in the mode_status register. */
|
|
/* - Set Error status bit of the related SU(s) in error */
|
|
/* status register. */
|
|
/* - If the channel number is for +- 50V, set high the */
|
|
/* HV supply error indicating bit in the SU_Status */
|
|
/* register for the related SU(s). */
|
|
/* - If the channel number if low voltage, set high the */
|
|
/* LV supply error indicating bit in the SU_Status */
|
|
/* register for the related SU(s). */
|
|
{
|
|
unsigned char EXTERNAL i;
|
|
/* This variable is used in a for-loop. */
|
|
|
|
unsigned char EXTERNAL SU_action[ NUM_SU ] = {LOW, LOW, LOW, LOW};
|
|
/* This array stores actions targeted at a SU judging by the given */
|
|
/* ADC information. */
|
|
|
|
|
|
/* Voltage measurement has failed, actions are taken accordingly. */
|
|
|
|
|
|
if ( ADC_channel == 0x10 || ADC_channel == 0x54 )
|
|
|
|
{
|
|
/* Measurement of channels related to sensor units 1 and 2 have */
|
|
/* failed. */
|
|
|
|
SU_action[ su1_e ] = HIGH;
|
|
SU_action[ su2_e ] = HIGH;
|
|
|
|
/* Select sensor units 1 and 2 as targets in the 'SU_action' array. */
|
|
|
|
SetModeStatusError( SUPPLY_ERROR );
|
|
/* Set Supply Error. */
|
|
|
|
|
|
}
|
|
|
|
else
|
|
if ( ADC_channel == 0x11 || ADC_channel == 0x55 )
|
|
|
|
{
|
|
/* Measurement of channels related to sensor units 3 and 4 have */
|
|
/* failed. */
|
|
|
|
SU_action[ su3_e ] = HIGH;
|
|
SU_action[ su4_e ] = HIGH;
|
|
|
|
/* Select sensor units 3 and 4 as targets in the 'SU_action' array. */
|
|
}
|
|
|
|
else
|
|
if ( ADC_channel == 0x12 || ADC_channel == 0x56 )
|
|
|
|
{
|
|
/* Measurement of channels related to all sensor units have */
|
|
/* failed. */
|
|
|
|
SU_action[ su1_e ] = HIGH;
|
|
SU_action[ su2_e ] = HIGH;
|
|
SU_action[ su3_e ] = HIGH;
|
|
SU_action[ su4_e ] = HIGH;
|
|
|
|
/* Select all sensor units as targets in the 'SU_action' array. */
|
|
}
|
|
|
|
else
|
|
if ( ADC_channel == 0x13 )
|
|
|
|
{
|
|
/* Measurement of a channel related to DPU voltage has failed. */
|
|
|
|
SetModeStatusError( SUPPLY_ERROR );
|
|
/* Set high DPU +5V supply error indicating bit in the */
|
|
/* mode status register. */
|
|
|
|
}
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( i = 0; i < NUM_SU; i++ )
|
|
|
|
{
|
|
/* Set error indications related to selected Sensor Units. */
|
|
|
|
if ( SU_action[ i ] )
|
|
|
|
{
|
|
SetErrorStatus ( ERROR_STATUS_OFFSET << i );
|
|
/* Set Error status bit of the related SU in error status */
|
|
/* register. */
|
|
|
|
if ( ADC_channel == 0x12
|
|
|| ADC_channel == 0x56 ) {
|
|
Set_SU_Error ( i, HV_SUPPLY_ERROR );
|
|
/* Set high HV supply error indicating bit in the */
|
|
/* SU_Status register. */
|
|
}
|
|
|
|
if ( ADC_channel == 0x10
|
|
|| ADC_channel == 0x11
|
|
|| ADC_channel == 0x54
|
|
|| ADC_channel == 0x55 ) {
|
|
Set_SU_Error ( i, LV_SUPPLY_ERROR );
|
|
/* Set high LV supply error indicating bit in the */
|
|
/* SU_Status register. */
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void TemperatureFailure( sensor_index_t SU_index )
|
|
/* Purpose : Takes care of resulting actions in case of a failed */
|
|
/* measurement. */
|
|
/* Interface : inputs - 'SU_index' which contains sensor unit */
|
|
/* index number related to failed measurement */
|
|
/* or overheated SU. */
|
|
/* outputs - telemetry_data.error_status register */
|
|
/* telemetry_data.SU_status register */
|
|
/* subroutines - SetSensorUnitOff() */
|
|
/* Preconditions : There has been an anomaly */
|
|
/* during an ADC temperature channel measurement or */
|
|
/* measurement has revealed that the given SU is */
|
|
/* overheated. */
|
|
/* Postconditions : Selected Sensor unit is switched off and error indication*/
|
|
/* bit is set in error_status register and SU_status */
|
|
/* register. */
|
|
/* Algorithm : Following actions are taken, */
|
|
/* - switch off given sensor unit */
|
|
/* - Set Error status bit of the related SU in error */
|
|
/* status register. */
|
|
/* - Set high temperature error indicating bit in the */
|
|
/* SU_Status register. */
|
|
{
|
|
|
|
unsigned char EXTERNAL exec_result;
|
|
/* This variable is used by SetSensorUnitOff() function. */
|
|
|
|
/* Temperature measurement has failed, actions are taken accordingly. */
|
|
|
|
SetSensorUnitOff( SU_index, &exec_result );
|
|
/* Switch off given sensor unit. */
|
|
|
|
SetErrorStatus( ERROR_STATUS_OFFSET << SU_index );
|
|
/* Set Error status bit of the related SU in error status register. */
|
|
|
|
Set_SU_Error( SU_index, TEMPERATURE_ERROR );
|
|
/* Set high temperature error indicating bit in the SU_Status */
|
|
/* register. */
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* AD conversion routines */
|
|
/*****************************************************************************/
|
|
|
|
|
|
void DelayAwhile ( unsigned short duration )
|
|
/* Purpose : Delay for a (brief) duration. */
|
|
/* Interface : inputs - delay duration, in ShortDelay() units. */
|
|
/* outputs - none. */
|
|
/* subroutines - ShortDelay() */
|
|
/* Preconditions : none. */
|
|
/* Postconditions : at least "duration" time units have passed. */
|
|
/* Algorithm : Call ShortDelay() as many times as necessary to delay */
|
|
/* for at least the desired duration. */
|
|
{
|
|
_Pragma( "loopbound min 1 max 1" )
|
|
while ( duration > MAX_SHORT_DELAY ) {
|
|
ShortDelay ( MAX_SHORT_DELAY );
|
|
duration = duration - MAX_SHORT_DELAY;
|
|
/* Since ShortDelay() has a positive constant delay term, the */
|
|
/* actual total delay will be a little larger than 'duration'. */
|
|
}
|
|
|
|
if ( duration > 0 ) {
|
|
/* Some delay left after the loop above. */
|
|
ShortDelay ( ( unsigned char ) duration );
|
|
}
|
|
}
|
|
|
|
|
|
void Read_AD_Channel ( ADC_parameters_t EXTERNAL *ADC_parameters )
|
|
/* Purpose : Reading an ADC channel */
|
|
/* Interface : inputs - Address of a struct which contains */
|
|
/* parameters for this function. */
|
|
/* outputs - Results are stored to the previously */
|
|
/* mentioned structure. */
|
|
/* subroutines - Convert() */
|
|
/* Preconditions : Health monitoring is on. */
|
|
/* ADC_parameters.ADC_max_tries > 0. */
|
|
/* Postconditions : AD channels are measured and results written to a given */
|
|
/* structure. */
|
|
/* Algorithm : */
|
|
/* while */
|
|
/* - Hit trigger interrupt indicating flag is resetted. */
|
|
/* - Handling of the given channel is started in a while */
|
|
/* loop. */
|
|
/* - Channel to be converted is selected by setting bits */
|
|
/* 0 - 6 from ADC Channel register to value of channel.*/
|
|
/* Channel value includes BP_UP bit to select */
|
|
/* unipolar/bipolar mode. */
|
|
/* - Convert_AD() function executes the conversion and */
|
|
/* stores the results in the given struct mentioned */
|
|
/* earlier. */
|
|
/* - If Hit trigger interrupt flag indicates that no */
|
|
/* hit trigger interrupts have occurred during the */
|
|
/* channel reading, exit the while loop. */
|
|
/* Else continue loop from beginning, if */
|
|
/* predefined limit for executing the loop has not been*/
|
|
/* reached. */
|
|
/* - If all the conversion tries have been used up and */
|
|
/* Hit trigger interrupt has corrupted the results, */
|
|
/* only a zero is stored with an indication of this */
|
|
/* occurred anomaly. */
|
|
/* End of loop */
|
|
{
|
|
unsigned char EXTERNAL tries_left;
|
|
/* Number of attempts remaining to try conversion without */
|
|
/* interference from a particle hit. */
|
|
|
|
unsigned short EXTERNAL delay_limit;
|
|
/* Delay between channel selection and start of conversion in */
|
|
/* ShortDelay() units. */
|
|
|
|
delay_limit = DELAY_LIMIT( 2000 );
|
|
/* Set delay limit to 2ms. */
|
|
|
|
tries_left = ADC_parameters -> ADC_max_tries;
|
|
/* Limits the number of conversion attempts repeated because */
|
|
/* of particle hit interrupts. Assumed to be at least 1. */
|
|
|
|
_Pragma( "loopbound min 1 max 8" )
|
|
while ( tries_left > 0 ) {
|
|
confirm_hit_result = 0;
|
|
/* Clear interrupt indicating flag. */
|
|
|
|
ADC_channel_register = ( ADC_channel_register & 0x80 ) |
|
|
ADC_parameters -> ADC_channel;
|
|
UPDATE_ADC_CHANNEL_REG;
|
|
/* AD Channel register is set. */
|
|
|
|
START_CONVERSION;
|
|
/* Initiate dummy cycle to set AD mode to unipolar or bipolar. */
|
|
|
|
DelayAwhile ( delay_limit );
|
|
/* Wait for analog signal and MUX to settle. */
|
|
|
|
Convert_AD( ADC_parameters );
|
|
/* Start conversion and measurement. */
|
|
|
|
tries_left--;
|
|
/* Repeat while-loop until the max number of tries. */
|
|
|
|
if ( confirm_hit_result == 0 ) {
|
|
/* Conversion has NOT been interrupted by a hit trigger interrupt. */
|
|
/* Exit from the while-loop. */
|
|
|
|
tries_left = 0;
|
|
}
|
|
}
|
|
|
|
if ( confirm_hit_result != 0 )
|
|
|
|
{
|
|
/* Conversion has been interrupted by a hit trigger interrupt. Discard */
|
|
/* corrupted results. */
|
|
|
|
ADC_parameters -> unsigned_ADC = 0;
|
|
ADC_parameters -> signed_ADC = 0;
|
|
|
|
ADC_parameters -> AD_execution_result = HIT_OCCURRED;
|
|
/* Store indication of an unsuccessful measurement. */
|
|
|
|
}
|
|
|
|
else
|
|
if ( ADC_parameters -> AD_execution_result == CONVERSION_ACTIVE
|
|
&& confirm_hit_result == 0 ) {
|
|
SetModeStatusError( ADC_ERROR );
|
|
/* ADC error indication is set because a time-out has */
|
|
/* occurred during AD conversion and no hit trigger interrupt */
|
|
/* has occurred. */
|
|
}
|
|
|
|
|
|
/* Either RESULT_OK or CONVERSION_ACTIVE indications are already */
|
|
/* stored in the 'ADC_parameters -> AD_execution_result' field */
|
|
/* as a result from conversion in the Convert() function. */
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DAC_SelfTest( unsigned char DAC_output,
|
|
ADC_parameters_t EXTERNAL *ADC_test_parameters )
|
|
/* Purpose : To test the analog signal chain in the circuitry. */
|
|
/* Interface : inputs - Test data 'DAC_Output */
|
|
/* - struct 'ADC_test_parameters' */
|
|
/* outputs - none */
|
|
/* subroutines - Read_AD_Channel() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : DAC selftest is carried out and results written to a */
|
|
/* given struct. */
|
|
/* Algorithm : */
|
|
/* - Test data is written to HW registers. */
|
|
/* - Test channel is AD converted. */
|
|
/* - Results are stored in a given structure. */
|
|
/* - If the measurement has failed, */
|
|
/* */
|
|
/* - Set self test error indication bit in mode status */
|
|
/* register */
|
|
/* - Set measurement error indication bit in mode status */
|
|
/* register. */
|
|
{
|
|
|
|
SET_DAC_OUTPUT( DAC_output );
|
|
/*test data is written to DAC output */
|
|
|
|
Read_AD_Channel( ADC_test_parameters );
|
|
/* Start reading the channel. */
|
|
|
|
if ( ADC_test_parameters -> AD_execution_result != RESULT_OK )
|
|
|
|
{
|
|
/* An anomaly has occurred during the measurement. */
|
|
|
|
Set_SU_Error( ADC_test_parameters -> sensor_unit - SU1,
|
|
SELF_TEST_ERROR );
|
|
/* Self self test error indication bit in mode status register. */
|
|
/* Offset in numbering is taken into account by transforming */
|
|
/* 'sensor_unit' (value 1-4) to a sensor unit index (value 0-3) */
|
|
|
|
SetSoftwareError( MEASUREMENT_ERROR );
|
|
/* Set measurement error indication bit in */
|
|
/* software error status register. */
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void Monitor_DPU_Voltage( void )
|
|
/* Purpose : Monitors DPU voltages */
|
|
/* Interface : inputs - telemetry_data, DPU voltages */
|
|
/* outputs - telemetry_data.mode_status */
|
|
/* telemetry_data, supply voltages */
|
|
/* subroutines - SetModeStatusError */
|
|
/* ExceedsLimit */
|
|
/* MeasureVoltage */
|
|
/* Preconditions : none */
|
|
/* Postconditions : DPU voltages are measured and monitored. */
|
|
/* Algorithm : */
|
|
/* - Channels are checked one by one and in case of an error*/
|
|
/* corresponding error bit is set. */
|
|
{
|
|
MeasureVoltage( DPU_5V_SELECTOR );
|
|
MeasureVoltage( SU_1_2_P5V_SELECTOR );
|
|
MeasureVoltage( SU_1_2_M5V_SELECTOR );
|
|
|
|
/* Result of voltage measurement from SU_1/2 +5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_1.plus_5_voltage,
|
|
SU_P5V_ANA_LOWER_LIMIT,
|
|
SU_P5V_ANA_UPPER_LIMIT ) )
|
|
SetModeStatusError( SUPPLY_ERROR );
|
|
|
|
/* Result of voltage measurement from SU_1/2 -5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_1.minus_5_voltage,
|
|
SU_M5V_ANA_LOWER_LIMIT,
|
|
SU_M5V_ANA_UPPER_LIMIT ) )
|
|
SetModeStatusError( SUPPLY_ERROR );
|
|
|
|
/* Result of voltage measurement from DIG +5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.DPU_plus_5_digital,
|
|
DPU_P5V_DIG_LOWER_LIMIT,
|
|
DPU_P5V_DIG_UPPER_LIMIT ) )
|
|
SetModeStatusError( SUPPLY_ERROR );
|
|
|
|
}
|
|
|
|
|
|
void Monitor_SU_Voltage( sensor_index_t self_test_SU_index )
|
|
/* Purpose : Monitors SU voltages */
|
|
/* Interface : inputs - self_test_SU_index */
|
|
/* telemetry_data, sensor voltages */
|
|
/* outputs - telemetry_data.SU_error */
|
|
/* subroutines - ExceedsLimit */
|
|
/* Set_SU_Error */
|
|
/* Preconditions : SU voltages are measured */
|
|
/* Postconditions : SU voltages are monitored. */
|
|
/* Algorithm : */
|
|
/* - Channels are checked one by one and in case of an error*/
|
|
/* corresponding error bit is set. */
|
|
{
|
|
switch ( self_test_SU_index ) {
|
|
case su1_e:
|
|
case su2_e:
|
|
|
|
/* Result of voltage measurement from SU_1/2 +5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_1.plus_5_voltage,
|
|
SU_P5V_ANA_LOWER_LIMIT,
|
|
SU_P5V_ANA_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, LV_LIMIT_ERROR );
|
|
|
|
/* Result of voltage measurement from SU_1/2 -5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_1.minus_5_voltage,
|
|
SU_M5V_ANA_LOWER_LIMIT,
|
|
SU_M5V_ANA_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, LV_LIMIT_ERROR );
|
|
|
|
break;
|
|
|
|
|
|
case su3_e:
|
|
case su4_e:
|
|
|
|
/* Result of voltage measurement from SU_3/4 +5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_3.plus_5_voltage,
|
|
SU_P5V_ANA_LOWER_LIMIT,
|
|
SU_P5V_ANA_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, LV_LIMIT_ERROR );
|
|
|
|
/* Result of voltage measurement from SU_3/4 -5V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.sensor_unit_3.minus_5_voltage,
|
|
SU_M5V_ANA_LOWER_LIMIT,
|
|
SU_M5V_ANA_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, LV_LIMIT_ERROR );
|
|
|
|
break;
|
|
}
|
|
|
|
/* Result of voltage measurement from SU +50V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.SU_plus_50,
|
|
SU_P50V_LOWER_LIMIT,
|
|
SU_P50V_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, HV_LIMIT_ERROR );
|
|
|
|
/* Result of voltage measurement from SU -50V is compared against */
|
|
/* limits. */
|
|
|
|
if ( ExceedsLimit( telemetry_data.SU_minus_50,
|
|
SU_M50V_LOWER_LIMIT,
|
|
SU_M50V_UPPER_LIMIT ) )
|
|
Set_SU_Error( self_test_SU_index, HV_LIMIT_ERROR );
|
|
}
|
|
|
|
void SelfTest_SU( sensor_index_t self_test_SU_index )
|
|
/* Purpose : Execute SU self tests */
|
|
/* Interface : inputs - self_test_SU_index */
|
|
/* outputs - none */
|
|
/* subroutines - LowVoltageCurrent() */
|
|
/* MeasureVoltage() */
|
|
/* MeasureTemperature() */
|
|
/* HighVoltageCurrent() */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Part of the Self Test sequence regarding temperatures, */
|
|
/* voltages and overcurrents is completed. */
|
|
/* Algorithm : - V_DOWN is checked */
|
|
/* - Voltage channels are checked one by one and in case of */
|
|
/* an error corresponding error bit is set. */
|
|
/* - SU Temperatures and HV Status Register is checked. */
|
|
{
|
|
uint_least8_t EXTERNAL i;
|
|
/* Used in a for loop */
|
|
|
|
LowVoltageCurrent();
|
|
/* V_DOWN is checked. */
|
|
|
|
HighVoltageCurrent( self_test_SU_index );
|
|
/* HV Status register is checked. */
|
|
|
|
/* SU voltages are measured */
|
|
_Pragma( "loopbound min 7 max 7" )
|
|
for ( i = channel_0_e; i <= channel_6_e; i++ ) {
|
|
MeasureVoltage( i );
|
|
/* All voltage channels are measured. */
|
|
}
|
|
|
|
Monitor_SU_Voltage( self_test_SU_index );
|
|
/* Voltage measurement results are monitored against limits. */
|
|
|
|
MeasureTemperature( self_test_SU_index );
|
|
/* SU temperatures are measured and monitored. */
|
|
}
|
|
|
|
unsigned char ExceedsLimit(
|
|
unsigned char value,
|
|
unsigned char lower_limit,
|
|
unsigned char upper_limit )
|
|
/* Purpose : Tests given value against given limits. */
|
|
/* Interface : inputs - value */
|
|
/* lower_limit */
|
|
/* upper_limit */
|
|
/* outputs - boolean value */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Given value is tested. */
|
|
/* Algorithm : See below, self explanatory. */
|
|
{
|
|
return ( value < lower_limit || value > upper_limit );
|
|
}
|
|
|
|
|
|
void SelfTestChannel( sensor_index_t self_test_SU_index )
|
|
/* Purpose : Starts channel tests */
|
|
/* Interface : inputs - self_test_SU_index */
|
|
/* outputs - none */
|
|
/* subroutines - SetTestPulseLevel */
|
|
/* SetTriggerLevel */
|
|
/* RestoreSettings */
|
|
/* ExecuteChannelTest */
|
|
/* DisableAnalogSwitch */
|
|
/* Preconditions : none */
|
|
/* Postconditions : SU channels are self tested. */
|
|
/* voltages and overcurrents is completed. */
|
|
/* Algorithm : - Threshold level is set high. */
|
|
/* - Test pulse level for a given channel is set high. */
|
|
/* - Channels are tested. */
|
|
/* - Threshold level is set low. */
|
|
/* - Test pulse level for a given channel is set low . */
|
|
/* - Channels are tested. */
|
|
/* - A pseudo trigger is generated in order to reset peak */
|
|
/* detector and delay counter in AcquisitionTask. */
|
|
/* - Threshold levels are restored to the level prior to */
|
|
/* the test. SU state for the SU under test is restored */
|
|
/* to ON. */
|
|
{
|
|
trigger_set_t EXTERNAL test_threshold;
|
|
|
|
DISABLE_HIT_TRIGGER;
|
|
|
|
/* Initial parameters for SetTriggerLevel function. */
|
|
test_threshold.sensor_unit = self_test_SU_number;
|
|
test_threshold.level = MAX_PLASMA_SELF_TEST_THRESHOLD;
|
|
test_threshold.channel = PLASMA_1_PLUS;
|
|
SetTriggerLevel( &test_threshold );
|
|
test_threshold.channel = PLASMA_1_MINUS;
|
|
SetTriggerLevel( &test_threshold );
|
|
test_threshold.channel = PLASMA_2_PLUS;
|
|
SetTriggerLevel( &test_threshold );
|
|
|
|
test_threshold.level = MAX_PIEZO_SELF_TEST_THRESHOLD;
|
|
test_threshold.channel = PZT_1_2;
|
|
SetTriggerLevel( &test_threshold );
|
|
|
|
|
|
/* Set initial test pulse value to 0. Test pulse value is also zeroed */
|
|
/* before returning from ExecuteChannelTest procedure also. */
|
|
SetTestPulseLevel( 0 );
|
|
|
|
/* Test threshold level is set before each channel test for every channel*/
|
|
/* and value is set back to the maximum threshold level before returning */
|
|
/* from the following ExecuteChannelTest procedure calls. */
|
|
|
|
test_threshold.channel = PLASMA_1_PLUS;
|
|
test_threshold.level = HIGH_PLASMA_1_PLUS_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_1_PLUS, PLASMA_1_PLUS_HIGH );
|
|
|
|
test_threshold.channel = PLASMA_1_MINUS;
|
|
test_threshold.level = HIGH_PLASMA_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_1_MINUS, PLASMA_1_MINUS_HIGH );
|
|
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_2_PLUS, PLASMA_2_PLUS_HIGH );
|
|
|
|
test_threshold.channel = PZT_1_2;
|
|
test_threshold.level = HIGH_PIEZO_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PZT_1, PZT_1_HIGH );
|
|
|
|
test_threshold.channel = PZT_1_2;
|
|
test_threshold.level = HIGH_PIEZO_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PZT_2, PZT_2_HIGH );
|
|
|
|
test_threshold.channel = PLASMA_1_PLUS;
|
|
test_threshold.level = LOW_PLASMA_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_1_PLUS, PLASMA_1_PLUS_LOW );
|
|
|
|
test_threshold.channel = PLASMA_1_MINUS;
|
|
test_threshold.level = LOW_PLASMA_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_1_MINUS, PLASMA_1_MINUS_LOW );
|
|
|
|
ExecuteChannelTest( self_test_SU_index, PLASMA_2_PLUS, PLASMA_2_PLUS_LOW );
|
|
|
|
test_threshold.channel = PZT_1_2;
|
|
test_threshold.level = LOW_PIEZO_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PZT_1, PZT_1_LOW );
|
|
|
|
test_threshold.channel = PZT_1_2;
|
|
test_threshold.level = LOW_PIEZO_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
ExecuteChannelTest( self_test_SU_index, PZT_2, PZT_2_LOW );
|
|
|
|
ENABLE_HIT_TRIGGER;
|
|
|
|
SET_HIT_TRIGGER_ISR_FLAG;
|
|
/* A pseudo trigger is generated in order to reset peak */
|
|
/* detector and delay counter in AcquisitionTask. */
|
|
/* No event is recorded i.e. event processing is disabled */
|
|
/* because SU state is 'self_test_e'. */
|
|
|
|
RestoreSettings( self_test_SU_index );
|
|
}
|
|
|
|
|
|
void ExecuteChannelTest(
|
|
sensor_index_t self_test_SU_index,
|
|
unsigned char test_channel,
|
|
unsigned char test_pulse_level )
|
|
/* Purpose : Execute SU self tests */
|
|
/* Interface : inputs - self_test_SU_index, test_channel */
|
|
/* outputs - telemetry_data.SU# Status */
|
|
/* subroutines - SelectSelfTestChannel */
|
|
/* SelectStartSwitchLevel */
|
|
/* WaitTimeout */
|
|
/* DelayAwhile */
|
|
/* SelectTriggerSwitchLevel */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Self test trigger siggnal is generated. */
|
|
/* voltages and overcurrents is completed. */
|
|
/* Algorithm : - Self test channel is selected. */
|
|
/* - Analog switch starting level is selected depending on */
|
|
/* the channel. */
|
|
/* - A pseudo trigger is generated in order to reset peak */
|
|
/* detector and delay counter in AcquisitionTask. */
|
|
/* - Hit trigger processing is waited for 40 ms. */
|
|
/* - Hit trigger processing for this self test pulse is */
|
|
/* enabled by setting SU state to 'self_test_trigger_e' */
|
|
/* - Analog switch triggering level is selected depending */
|
|
/* on the channel (rising or falliing edge). */
|
|
/* - If self test trigger pulse did not cause an interrupt, */
|
|
/* set SELF_TEST_ERROR indication in SU status register */
|
|
/* and restore SU state to 'self_test_e'. */
|
|
{
|
|
unsigned short EXTERNAL delay_limit;
|
|
trigger_set_t EXTERNAL test_threshold;
|
|
|
|
if ( test_channel == PLASMA_1_PLUS ||
|
|
test_channel == PLASMA_1_MINUS ||
|
|
test_channel == PLASMA_2_PLUS ) {
|
|
SelectSelfTestChannel( test_channel );
|
|
|
|
EnableAnalogSwitch( self_test_SU_index );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
ResetPeakDetector( self_test_SU_index + SU1 );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
ResetPeakDetector( self_test_SU_index + SU1 );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
CLEAR_HIT_TRIGGER_ISR_FLAG;
|
|
|
|
ResetDelayCounters();
|
|
|
|
SU_state[ self_test_SU_index ] = self_test_trigger_e;
|
|
/* Enable hit trigger processing for this self test pulse. */
|
|
|
|
ENABLE_HIT_TRIGGER;
|
|
|
|
SetTestPulseLevel( test_pulse_level );
|
|
|
|
/* Set at least 1ms test pulse */
|
|
delay_limit = DELAY_LIMIT( 1000 );
|
|
DelayAwhile( delay_limit );
|
|
|
|
/* For plasma 1i channel triggering must take place in 1ms after */
|
|
/* rising edge. */
|
|
if ( test_channel == PLASMA_1_MINUS &&
|
|
SU_state[ self_test_SU_index ] == self_test_trigger_e ) {
|
|
/* Self test trigger pulse did not cause an interrupt. */
|
|
Set_SU_Error( self_test_SU_index, SELF_TEST_ERROR );
|
|
|
|
SU_state[ self_test_SU_index ] = self_test_e;
|
|
/* Triggering of a self test pulse is disabled by restoring */
|
|
/* the self_test_e state. */
|
|
}
|
|
|
|
/* Test pulse is always at least 3ms (=1ms+2ms) */
|
|
delay_limit = DELAY_LIMIT( 2000 );
|
|
DelayAwhile( delay_limit );
|
|
|
|
SetTestPulseLevel( 0 );
|
|
|
|
if ( test_channel == PLASMA_2_PLUS )
|
|
SET_HIT_TRIGGER_ISR_FLAG;
|
|
|
|
/* If channel is plasma 1e or 2e then wait at least 1ms after */
|
|
/* falling edge. */
|
|
if ( test_channel != PLASMA_1_MINUS ) {
|
|
delay_limit = DELAY_LIMIT( 1000 );
|
|
/* Set at least 1ms test pulse */
|
|
DelayAwhile( delay_limit );
|
|
}
|
|
|
|
DISABLE_HIT_TRIGGER;
|
|
|
|
if ( test_channel != PLASMA_2_PLUS ) {
|
|
test_threshold.sensor_unit = self_test_SU_index + SU1;
|
|
test_threshold.channel = test_channel;
|
|
test_threshold.level = MAX_PLASMA_SELF_TEST_THRESHOLD;
|
|
SetTriggerLevel( &test_threshold );
|
|
}
|
|
|
|
DisableAnalogSwitch( self_test_SU_index );
|
|
} else {
|
|
SelectSelfTestChannel( test_channel );
|
|
|
|
SetTestPulseLevel( test_pulse_level );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
ResetPeakDetector( self_test_SU_index + SU1 );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
ResetPeakDetector( self_test_SU_index + SU1 );
|
|
|
|
WaitTimeout( 1 );
|
|
|
|
CLEAR_HIT_TRIGGER_ISR_FLAG;
|
|
|
|
ResetDelayCounters();
|
|
|
|
SU_state[ self_test_SU_index ] = self_test_trigger_e;
|
|
/* Enable hit trigger processing for this self test pulse. */
|
|
|
|
ENABLE_HIT_TRIGGER;
|
|
|
|
EnableAnalogSwitch( self_test_SU_index );
|
|
|
|
/* Set at least 1ms test pulse */
|
|
delay_limit = DELAY_LIMIT( 1000 );
|
|
DelayAwhile( delay_limit );
|
|
|
|
DISABLE_HIT_TRIGGER;
|
|
|
|
SetTestPulseLevel( 0 );
|
|
|
|
DisableAnalogSwitch( self_test_SU_index );
|
|
|
|
test_threshold.sensor_unit = self_test_SU_index + SU1;
|
|
test_threshold.level = MAX_PIEZO_SELF_TEST_THRESHOLD;
|
|
test_threshold.channel = PZT_1_2;
|
|
SetTriggerLevel( &test_threshold );
|
|
}
|
|
|
|
if ( SU_state[ self_test_SU_index ] == self_test_trigger_e ) {
|
|
/* Self test trigger pulse did not cause an interrupt. */
|
|
Set_SU_Error( self_test_SU_index, SELF_TEST_ERROR );
|
|
|
|
SU_state[ self_test_SU_index ] = self_test_e;
|
|
/* Triggering of a self test pulse is disabled by restoring */
|
|
/* the self_test_e state. */
|
|
}
|
|
}
|
|
|
|
void RestoreSettings( sensor_index_t self_test_SU_index )
|
|
/* Purpose : Restores settings after SU self tests. */
|
|
/* Interface : inputs - self_test_SU_index, */
|
|
/* telemetry_data, SU threshold levels */
|
|
/* outputs - HW registers, thresholds */
|
|
/* SU state */
|
|
/* subroutines - SetTriggerLevel */
|
|
/* Switch_SU_State */
|
|
/* Preconditions : none */
|
|
/* Postconditions : - Threshold levels are restored to the level prior to */
|
|
/* the test. SU state for the SU under test is restored */
|
|
/* to ON. */
|
|
/* Algorithm : - Original threshold levels are copied from */
|
|
/* telemetry_data and written in to HW registers with */
|
|
/* SetTriggerLevel. */
|
|
/* - SU state is restored to ON with Switch_SU_State. */
|
|
{
|
|
SU_settings_t EXTERNAL *const PROGRAM setting_map_c[ ] = {
|
|
&telemetry_data.sensor_unit_1,
|
|
&telemetry_data.sensor_unit_2,
|
|
&telemetry_data.sensor_unit_3,
|
|
&telemetry_data.sensor_unit_4
|
|
};
|
|
/* Pointers to Sensor Unit configuration data in telemetry */
|
|
/* data area. */
|
|
|
|
SU_settings_t EXTERNAL *INDIRECT_INTERNAL SU_setting;
|
|
/* Pointer to configuration data of the Sensor Unit being */
|
|
/* Self Tested. */
|
|
|
|
sensor_unit_t EXTERNAL SU_switch;
|
|
trigger_set_t EXTERNAL threshold;
|
|
/* Parameters for subroutines. */
|
|
|
|
SU_setting = setting_map_c[ self_test_SU_index ];
|
|
|
|
threshold.sensor_unit = self_test_SU_number;
|
|
|
|
threshold.level =
|
|
SU_setting -> plasma_1_plus_threshold;
|
|
threshold.channel = PLASMA_1_PLUS;
|
|
SetTriggerLevel( &threshold );
|
|
/* Restore Plasma 1 Plus trigger threshold. */
|
|
|
|
threshold.level =
|
|
SU_setting -> plasma_1_minus_threshold;
|
|
threshold.channel = PLASMA_1_MINUS;
|
|
SetTriggerLevel( &threshold );
|
|
/* Restore Plasma 1 Minus trigger threshold. */
|
|
|
|
threshold.level =
|
|
SU_setting -> piezo_threshold;
|
|
threshold.channel = PZT_1_2;
|
|
SetTriggerLevel( &threshold );
|
|
/* Restore Piezo trigger threshold. */
|
|
|
|
SU_switch.SU_number = self_test_SU_number;
|
|
SU_switch.SU_state = on_e;
|
|
SU_switch.expected_source_state = self_test_e;
|
|
Switch_SU_State( &SU_switch );
|
|
/* Switch SU State back to On. */
|
|
|
|
}
|
|
|
|
|