1049 lines
42 KiB
C
1049 lines
42 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 : hw_if.c
|
|
|
|
Initialization and test of hardware.
|
|
|
|
Based on the SSF file hw_if.c, rev 1.34, Sun Jul 25 15:47:56 1999.
|
|
|
|
-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "dpu_ctrl.h"
|
|
#include "su_ctrl.h"
|
|
#include "isr_ctrl.h"
|
|
#include "version.h"
|
|
#include "tc_hand.h"
|
|
#include "tm_data.h"
|
|
#include "ttc_ctrl.h"
|
|
|
|
|
|
reset_class_t EXTERNAL s_w_reset;
|
|
/* The type of the last DPU reset, as recorded in Init_DPU. */
|
|
/* Note: this variable must _not_ be initialised here (in */
|
|
/* its declaration), since this would overwrite the value */
|
|
/* set in Init_DPU, which is called from the startup module */
|
|
/* before the variable initialisation code. */
|
|
|
|
|
|
unsigned char EXTERNAL SU_ctrl_register = 0;
|
|
unsigned char EXTERNAL SU_self_test_channel = 0;
|
|
/* These variables store values of these write-only registers. */
|
|
|
|
unsigned char EXTERNAL LOCATION( 0xFF00 ) forbidden_area[ 256 ];
|
|
/* Last 256 bytes of the external data memory are reserved for */
|
|
/* memory mapped registers. No variables are allowed in that area. */
|
|
|
|
|
|
/* Results of the RAM test done at boot time: */
|
|
|
|
code_address_t EXTERNAL failed_code_address;
|
|
data_address_t EXTERNAL failed_data_address;
|
|
#define NO_RAM_FAILURE 0xFFFF
|
|
/* The test records the address of the first failed cell in the */
|
|
/* code (program) RAM and the external data RAM. */
|
|
/* If no problem is found, the address is NO_RAM_FAILURE. */
|
|
/* Note: these variables must _not_ be initialised here (at */
|
|
/* declaration), since this initialisation would be done after */
|
|
/* the RAM test and so would destroy its results. */
|
|
/* These variables are set by Init_DPU, which is called from */
|
|
/* the startup module. */
|
|
|
|
|
|
/* Other memory-control variables: */
|
|
|
|
memory_configuration_t EXTERNAL memory_mode;
|
|
/* The current memory mapping mode. */
|
|
|
|
const unsigned char PROGRAM checksum_nullifier = CODE_CHECKSUM;
|
|
/* Sets the checksum of the unpatched program code to zero. */
|
|
|
|
unsigned char EXTERNAL reference_checksum;
|
|
/* Expected code checksum. Zero for unpatched code. */
|
|
|
|
unsigned char EXTERNAL code_not_patched;
|
|
/* Initial value is 1, set in Init_DPU. Value is 1 when code */
|
|
/* checksum value is valid, cleared to 0 when code memory is */
|
|
/* patched, set to 1 when next checksum calculation */
|
|
/* period is started. */
|
|
|
|
unsigned char EXTERNAL analog_switch_bit[ NUM_SU ] = {0x10, 0x20, 0x40, 0x80};
|
|
/* This array stores the value to be used when analog switch bit */
|
|
/* corresponding to a given SU is set. */
|
|
|
|
/* Function prototypes. */
|
|
void CopyProgramCode( void );
|
|
code_address_t InitCode_RAM ( reset_class_t reset_class );
|
|
void InitData_RAM (
|
|
reset_class_t reset_class,
|
|
code_address_t code_address );
|
|
|
|
/*****************************************************************************/
|
|
/* dpu_ctrl.h */
|
|
/*****************************************************************************/
|
|
|
|
unsigned short int Check_RAM (
|
|
data_address_t start_address,
|
|
data_address_t end_address )
|
|
/* Purpose : Check the working of an area of external RAM. */
|
|
/* Interface : inputs - range of memory addresses. */
|
|
/* outputs - first failed address. */
|
|
/* NO_RAM_FAILURE indicates "no failure". */
|
|
/* subroutines - TestMemBits */
|
|
/* - TestMemSeq */
|
|
/* - TestMemData */
|
|
/* Preconditions : - start_address <= end_address. */
|
|
/* - end_address < 0xFFFF. */
|
|
/* - External Data RAM is not initialised. */
|
|
/* Postconditions : The addresses in the given range are tested up to the */
|
|
/* ending address or the first failing address. */
|
|
/* The original contents of the memory area are lost. */
|
|
/* Algorithm : - The first memory address is tested with TestMemBits. */
|
|
/* - The address range is traversed in pieces acceptable */
|
|
/* to TestMemSeq/Data (max 255 bytes at a time). */
|
|
/* - For each piece, TestMemSeq/Data is called. */
|
|
/* - If an error is found, the failing address */
|
|
/* is returned and the test is interrupted. */
|
|
/* - If no failure is found, 0xFFFF is returned. */
|
|
/* */
|
|
/* This function must not rely on any constants in data RAM, since */
|
|
/* it is called before the C start-up system initialises data. */
|
|
|
|
{
|
|
/* Note that the local variables of this function should all be */
|
|
/* located in the internal data memory. Otherwise they may be */
|
|
/* altered unexpectedly as a side effect of testing memory. */
|
|
|
|
data_address_t INDIRECT_INTERNAL start;
|
|
/* The starting address for TestMemSeq and TestMemData. */
|
|
|
|
uint_least16_t INDIRECT_INTERNAL range;
|
|
/* The remaining range (ending address - starting address). */
|
|
|
|
uint_least8_t INDIRECT_INTERNAL bytes;
|
|
/* The number of bytes to check, for TestMemSeq/Data. */
|
|
|
|
uint_least8_t INDIRECT_INTERNAL bytes_left;
|
|
/* The number of bytes left, returned from TestMemSeq/Data. */
|
|
|
|
start = start_address;
|
|
|
|
if ( TestMemBits( start ) != 0 ) {
|
|
/* Failure in data bus, probably. */
|
|
return start;
|
|
}
|
|
|
|
_Pragma( "loopbound min 0 max 0" )
|
|
while ( start <= end_address ) {
|
|
range = end_address - start;
|
|
/* Number of bytes to check, less one. */
|
|
|
|
if ( range < 255 ) {
|
|
/* One call of TestMemSeq/Data covers the remaining range. */
|
|
bytes = ( uint_least8_t )( range + 1 );
|
|
} else {
|
|
/* One call cannot cover the remaining range. */
|
|
/* Cover as much as possible for one call. */
|
|
bytes = 255;
|
|
}
|
|
|
|
bytes_left = TestMemSeq ( start, bytes );
|
|
|
|
if ( bytes_left == 0 ) {
|
|
/* TestMemSeq succeeded. Try TestMemData. */
|
|
bytes_left = TestMemData ( start, bytes );
|
|
}
|
|
|
|
if ( bytes_left > 0 ) {
|
|
/* Memory error. Return failing address. */
|
|
return ( bytes - bytes_left ) + start;
|
|
}
|
|
|
|
start = start + bytes;
|
|
/* Next address to check, or end_address+1 if all done. */
|
|
/* Wrap-around cannot happen since end_address < 0xFFFF. */
|
|
}
|
|
|
|
/* Memory is OK. */
|
|
return NO_RAM_FAILURE;
|
|
}
|
|
|
|
|
|
void Init_DPU ( reset_class_t reset_class )
|
|
/* Purpose : DEBIE-specific DPU and I/O initialisation at reset. */
|
|
/* Interface : inputs - reset class */
|
|
/* outputs - s_w_reset */
|
|
/* - code_not_patched */
|
|
/* - failed_code_address */
|
|
/* - failed_data_address */
|
|
/* - memory_mode */
|
|
/* subroutines - InitCode_RAM */
|
|
/* - InitData_RAM */
|
|
/* Preconditions : Basic startup initialisation done. */
|
|
/* Code is being executed from PROM. */
|
|
/* Tasks are not yet running. */
|
|
/* External Data RAM is not initialised. */
|
|
/* Postconditions : see algorithm */
|
|
/* Algorithm : see below, self-explanatory. */
|
|
|
|
/* This function is called by the startup assembly code. */
|
|
/* This function must not rely on any constants in data RAM, since */
|
|
/* it is called before the C start-up system initialises data. */
|
|
|
|
{
|
|
/* Note: be careful with use of external Data RAM in this function. */
|
|
/* If InitData_RAM tests the RAM, it will destroy the contents. */
|
|
|
|
volatile reset_class_t INDIRECT_INTERNAL safe_reset_class;
|
|
/* Copy of reset_class in internal RAM, safe from RAM test. */
|
|
|
|
code_address_t INDIRECT_INTERNAL code_address;
|
|
/* Result of InitCode_RAM. */
|
|
|
|
|
|
safe_reset_class = reset_class;
|
|
/* Copy to internal RAM. */
|
|
|
|
SET_WD_RESET_LOW;
|
|
|
|
/* The Watch Dog timer is reset by setting WD_RESET bit low at I/O */
|
|
/* port 1. */
|
|
|
|
SET_INTERRUPT_PRIORITIES;
|
|
/* Define the high/low priority of each interrupt. */
|
|
|
|
SET_INT_TYPE1_EDGE;
|
|
/* The interrupt control type 1 bit is set to 'falling edge' state. */
|
|
|
|
SET_INT_TYPE0_EDGE;
|
|
/* The interrupt control type 1 bit is set to 'falling edge' state. */
|
|
|
|
STOP_TC_TIMER;
|
|
SET_TC_TIMER_MODE;
|
|
DISABLE_TC_TIMER_ISR;
|
|
SET_TC_TIMER_OVERFLOW_FLAG;
|
|
/* Prepare TC timer. */
|
|
|
|
CLEAR_TC_INTERRUPT_FLAG;
|
|
CLEAR_TM_INTERRUPT_FLAG;
|
|
CLEAR_HIT_TRIGGER_ISR_FLAG;
|
|
/* Clear pending interrupts. */
|
|
|
|
/* RAM tests and code copying: */
|
|
|
|
code_address = InitCode_RAM ( safe_reset_class );
|
|
|
|
InitData_RAM ( safe_reset_class, code_address );
|
|
|
|
/* Record RAM test results in external data as follows. */
|
|
/* They will be safe now, since RAM test is over. */
|
|
/* Note, InitData_RAM already set failed_data_address, */
|
|
/* and InitCode_RAM selected the memory mode; here we */
|
|
/* just record the selection in memory_mode. */
|
|
/* The failed_code/data_addresses are not yet set in */
|
|
/* telemetry_data, since the latter will be cleared in */
|
|
/* a later step of the boot sequence. */
|
|
|
|
s_w_reset = safe_reset_class;
|
|
code_not_patched = 1;
|
|
failed_code_address = code_address;
|
|
|
|
if ( code_address == NO_RAM_FAILURE )
|
|
memory_mode = SRAM_e;
|
|
else
|
|
memory_mode = PROM_e;
|
|
|
|
#ifdef USE_ALWAYS_PROM
|
|
memory_mode = PROM_e;
|
|
#endif
|
|
|
|
SET_WD_RESET_HIGH;
|
|
/* The Watch Dog time out signal state is reset HIGH state, as it is*/
|
|
/* falling edge active. */
|
|
}
|
|
|
|
|
|
code_address_t InitCode_RAM ( reset_class_t reset_class )
|
|
/* Purpose : Initialise Program Memory at reset. */
|
|
/* Interface : inputs - reset class */
|
|
/* - failed_code_address (if Warm Reset) */
|
|
/* outputs - returns new value for failed_code_address */
|
|
/* subroutines - Check_RAM */
|
|
/* - CopyProgramCode */
|
|
/* Preconditions : Basic startup initialisation done. */
|
|
/* Code is being executed from PROM. */
|
|
/* Tasks are not yet running. */
|
|
/* External Data RAM is not initialised (except in case */
|
|
/* of a Warm Reset). */
|
|
/* Postconditions : For a reset that is not a Warm Reset: */
|
|
/* - Code SRAM tested, result in return value. */
|
|
/* - Code copied from PROM to SRAM. */
|
|
/* - Running from SRAM if Code RAM is good. */
|
|
/* - Running from PROM if error found in Code RAM. */
|
|
/* For a Warm Reset: */
|
|
/* - Code in SRAM not modified. */
|
|
/* - Running from SRAM or PROM depending on the recorded */
|
|
/* result of an earlier Code RAM test (from the global */
|
|
/* variable failed_code_address). */
|
|
/* - failed_code_address unchanged and returned. */
|
|
/* Algorithm : see below. */
|
|
|
|
/* Note: This initialisation may use external RAM, but any data it */
|
|
/* stores in external RAM will be destroyed by the RAM test, */
|
|
/* which is done after this step in the reset sequence. */
|
|
/* This function must not rely on any constants in data RAM, since */
|
|
/* it is called before the C start-up system initialises data. */
|
|
|
|
{
|
|
code_address_t INDIRECT_INTERNAL code_address;
|
|
/* Value returned by Check_RAM, now or earlier. */
|
|
|
|
if ( reset_class == warm_reset_e ) {
|
|
/* Warm Reset: Do not copy PROM code to RAM. */
|
|
/* Use result of memory test from earlier (non-warm) reset. */
|
|
|
|
code_address = failed_code_address;
|
|
} else {
|
|
/* HW Reset, Soft Reset or Checksum Reset. */
|
|
|
|
code_address = Check_RAM ( BEGIN_SRAM1, END_SRAM1 );
|
|
/* TBC that this does not rely on data RAM constants. */
|
|
|
|
if ( code_address == NO_RAM_FAILURE ) {
|
|
#ifndef USE_ALWAYS_PROM
|
|
CopyProgramCode();
|
|
#endif
|
|
/* Code RAM is good. Copy code to it. */
|
|
/* Later in the boot sequence, the reference checksum */
|
|
/* must be reset to its initial value, to erase its */
|
|
/* memory of any code patches, or to initialise it in */
|
|
/* case of a power-up reset or test of data RAM. */
|
|
}
|
|
}
|
|
|
|
if ( code_address == NO_RAM_FAILURE ) {
|
|
#ifndef USE_ALWAYS_PROM
|
|
SET_MEM_CONF_SRAM;
|
|
#endif
|
|
/* Code RAM is good. Run program from it. */
|
|
/* For a Warm Reset, the Code RAM may contain patches */
|
|
/* relative to the PROM code, and the reference */
|
|
/* checksum should also retain a memory of them. */
|
|
}
|
|
|
|
return code_address;
|
|
}
|
|
|
|
|
|
void InitData_RAM (
|
|
reset_class_t reset_class,
|
|
code_address_t code_address )
|
|
/* Purpose : Initialise Data Memory at reset. */
|
|
/* Interface : inputs - reset class */
|
|
/* - failed code address (in some cases) */
|
|
/* outputs - failed_data_address */
|
|
/* subroutines - Check_RAM */
|
|
/* Preconditions : Basic startup initialisation done. */
|
|
/* Tasks are not yet running. */
|
|
/* External Data RAM is not initialised (except in case */
|
|
/* of a Warm Reset). */
|
|
/* Postconditions : For a Power-Up Reset: */
|
|
/* - Data SRAM tested, result in failed_data_address. */
|
|
/* If the Code RAM test failed (as shown by code_address) */
|
|
/* only the upper half of the Data space is tested here. */
|
|
/* - The data in the tested Data RAM is garbage. */
|
|
/* For other kinds of reset: */
|
|
/* - Data in SRAM not modified. */
|
|
/* Algorithm : see below. */
|
|
|
|
/* This function must not rely on any constants in data RAM, since */
|
|
/* it is called before the C start-up system initialises data. */
|
|
|
|
{
|
|
if ( reset_class == power_up_reset_e ) {
|
|
if ( code_address == NO_RAM_FAILURE ) {
|
|
/* The Code RAM is good, so we have a fresh lower-half */
|
|
/* of the Data RAM to check, as well as the upper-half. */
|
|
|
|
failed_data_address = Check_RAM ( BEGIN_DATA_RAM, END_SRAM3 );
|
|
} else {
|
|
/* The Code RAM is bad, and is still mapped to the */
|
|
/* lower-half of the Data space. Check only the upper */
|
|
/* half of the data space. */
|
|
|
|
failed_data_address = Check_RAM ( BEGIN_SRAM3, END_SRAM3 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CopyProgramCode( void )
|
|
/* Purpose : Copies program code from PROM to SRAM */
|
|
/* Interface : -inputs: PROM */
|
|
/* -outputs: SRAM1 */
|
|
/* Preconditions : Program code is executed from PROM. */
|
|
/* External data RAM not initialised. */
|
|
/* Postconditions : SRAM1 holds same program as PROM. */
|
|
/* Algorithm : Bytes are copied from code memory to same address in */
|
|
/* external data memory in loop that goes through code */
|
|
/* memory */
|
|
/* This function must not rely on any constants in data RAM, since */
|
|
/* it is called before the C start-up system initialises data. */
|
|
|
|
{
|
|
code_address_t i;
|
|
INDIRECT_INTERNAL unsigned char code_byte;
|
|
|
|
_Pragma( "loopbound min 28672 max 28672" )
|
|
for ( i = PROGRAM_COPY_START; i < PROGRAM_COPY_END; i++ ) {
|
|
code_byte = GET_CODE_BYTE( i );
|
|
SET_DATA_BYTE( ( data_address_t )i, code_byte );
|
|
}
|
|
}
|
|
|
|
|
|
reset_class_t GetResetClass( void )
|
|
/* Purpose : Reset class is returned. */
|
|
/* Interface : - inputs: s_w_reset, type of the occurred reset. */
|
|
/* - outputs: s_w_reset */
|
|
/* Preconditions : Valid only when called first time after reset in boot */
|
|
/* sequence. */
|
|
/* Postconditions : s_w_reset is set to error_e value. */
|
|
/* Algorithm : value of s_w_reset is returned and s_w_reset is set to */
|
|
/* error value. */
|
|
{
|
|
register reset_class_t occurred_reset;
|
|
|
|
occurred_reset = s_w_reset;
|
|
s_w_reset = error_e;
|
|
return occurred_reset;
|
|
}
|
|
|
|
|
|
void SignalMemoryErrors ( void )
|
|
/* Purpose : Copy results of RAM test to telemetry_data. */
|
|
/* Interface : - inputs: failed_code_address, failed_data_address */
|
|
/* - outputs: telemetry_data fields: */
|
|
/* failed_code_address */
|
|
/* failed_data_address */
|
|
/* mode_status bits for: */
|
|
/* PROGRAM_MEMORY_ERROR */
|
|
/* DATA_MEMORY_ERROR */
|
|
/* Preconditions : Init_DPU called since reset. */
|
|
/* Postconditions : telemetry_data reflects the results of the memory tests */
|
|
/* done in Init_DPU, as recorded in failed_code_address */
|
|
/* and failed_data_address. */
|
|
/* Note that the TM addresses are zero for "no failure". */
|
|
/* Algorithm : see below. */
|
|
{
|
|
if ( failed_code_address == NO_RAM_FAILURE ) {
|
|
telemetry_data.mode_status &= ~PROGRAM_MEMORY_ERROR;
|
|
telemetry_data.failed_code_address = 0x0000;
|
|
} else {
|
|
telemetry_data.mode_status |= PROGRAM_MEMORY_ERROR;
|
|
telemetry_data.failed_code_address = failed_code_address;
|
|
}
|
|
|
|
if ( failed_data_address == NO_RAM_FAILURE ) {
|
|
telemetry_data.mode_status &= ~DATA_MEMORY_ERROR;
|
|
telemetry_data.failed_data_address = 0x0000;
|
|
} else {
|
|
telemetry_data.mode_status |= DATA_MEMORY_ERROR;
|
|
telemetry_data.failed_data_address = failed_data_address;
|
|
}
|
|
}
|
|
|
|
|
|
void SetMemoryConfiguration ( memory_configuration_t memory )
|
|
/* Purpose : External program memory is selected to be either PROM or */
|
|
/* SRAM1. */
|
|
/* Interface : Port 1 is used. */
|
|
/* output: memory_mode */
|
|
/* Preconditions : After power-up reset PROM is always selected. */
|
|
/* Postconditions : External program memory is set depending on the given */
|
|
/* parameter. */
|
|
/* memory_mode contains the selected mode. */
|
|
/* Algorithm : Memory configuration is selected with the output at the */
|
|
/* I/O port 1. */
|
|
|
|
{
|
|
switch ( memory ) {
|
|
case PROM_e:
|
|
SET_MEM_CONF_PROM;
|
|
break;
|
|
case SRAM_e:
|
|
SET_MEM_CONF_SRAM;
|
|
break;
|
|
}
|
|
memory_mode = memory;
|
|
}
|
|
|
|
|
|
void PatchCode( memory_patch_variables_t EXTERNAL *patch_variables )
|
|
/* Purpose : Code memory patching. */
|
|
/* Interface : Following parameters are given: Address from where to */
|
|
/* copy, address where to copy and the amount of bytes to */
|
|
/* be copied. Execution result is returned. Variables used */
|
|
/* in this function are stored in a struct. Pointer to a */
|
|
/* variable which stores an execution result of the */
|
|
/* function SetMemoryConfiguration is passed on. */
|
|
/* Preconditions : Source and destination addresses should be valid. */
|
|
/* Postconditions : Desired part of the memory is copied. */
|
|
/* Algorithm : Bytes are copied. */
|
|
|
|
{
|
|
|
|
fptr_t patch_function;
|
|
/* Function pointer to the patched memory area. */
|
|
|
|
unsigned char INDIRECT_INTERNAL old_checksum;
|
|
/* Checksum calculated from the old contents of the pachted memory. */
|
|
|
|
unsigned char INDIRECT_INTERNAL new_checksum;
|
|
/* Checksum calculated from the new conrents of the patched memory. */
|
|
|
|
unsigned char INDIRECT_INTERNAL patch_value;
|
|
/* New value of a patched code memory byte. */
|
|
|
|
unsigned char EXTERNAL temp_configuration;
|
|
/* Original memory configuration. */
|
|
|
|
uint_least8_t INDIRECT_INTERNAL i;
|
|
/* Loop variable. */
|
|
|
|
|
|
temp_configuration = GetMemoryConfiguration();
|
|
/* State of the current memory configuration is stored. */
|
|
|
|
DISABLE_INTERRUPT_MASTER;
|
|
/* Disable all interrupts. */
|
|
|
|
SetMemoryConfiguration ( PROM_e );
|
|
/* Enable code patching. */
|
|
|
|
new_checksum = 0;
|
|
old_checksum = 0;
|
|
|
|
/* Memory block is copied from SRAM3 to SRAM1. */
|
|
|
|
_Pragma( "loopbound min 32 max 32" )
|
|
for ( i = 0 ; i < patch_variables -> data_amount ; i++ ) {
|
|
old_checksum ^= GET_DATA_BYTE( patch_variables -> destination + i );
|
|
patch_value = *( patch_variables -> source + i );
|
|
new_checksum ^= patch_value;
|
|
|
|
SET_DATA_BYTE( patch_variables -> destination + i, patch_value );
|
|
}
|
|
|
|
reference_checksum ^= ( old_checksum ^ new_checksum );
|
|
|
|
SetMemoryConfiguration ( temp_configuration );
|
|
/* The initial memory configuration is restored. */
|
|
|
|
switch ( patch_variables -> execution_command ) {
|
|
case 0:
|
|
/* Continue normally. */
|
|
|
|
break;
|
|
|
|
case 0x09:
|
|
/* Execute soft reset. */
|
|
|
|
Reboot ( soft_reset_e );
|
|
/* Function does not return. */
|
|
break;
|
|
|
|
case 0x37:
|
|
/* Execute warm reset. */
|
|
|
|
Reboot ( warm_reset_e );
|
|
/* Function deos not return. */
|
|
break;
|
|
|
|
case 0x5A:
|
|
/* Jump to the patched memory. */
|
|
|
|
patch_function = ( fptr_t )( patch_variables -> destination );
|
|
|
|
CALL_PATCH( patch_function );
|
|
/* Called code may or may not return. */
|
|
|
|
/* TC_state is selected upon return. */
|
|
|
|
break;
|
|
}
|
|
ENABLE_INTERRUPT_MASTER;
|
|
/* Enable all 'enabled' interrupts. */
|
|
|
|
}
|
|
|
|
|
|
memory_configuration_t GetMemoryConfiguration( void ) COMPACT_DATA
|
|
REENTRANT_FUNC
|
|
/* Purpose : Information about selected program memory is acquired */
|
|
/* and returned. */
|
|
/* Interface : input: memory_mode */
|
|
/* Preconditions : none */
|
|
/* Postconditions : none */
|
|
/* Algorithm : Information about current memory configuration is */
|
|
/* stored in a variable. */
|
|
|
|
{
|
|
return memory_mode;
|
|
/*Information about current memory configuration is stored in a global */
|
|
/*variable, which is returned. */
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* su_ctrl.h */
|
|
/*****************************************************************************/
|
|
|
|
/* Sensor Unit power control */
|
|
|
|
void Switch_SU_On (
|
|
sensor_number_t SU_Number,
|
|
unsigned char EXTERNAL *execution_result ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Given Sensor Unit is switched on. */
|
|
/* Interface : Execution result is stored in a variable. */
|
|
/* Preconditions : SU_Number should be 1,2,3 or 4 */
|
|
/* Postconditions : Given Sensor Unit is switced on. */
|
|
/* Algorithm : The respective bit is set high in the SU on/off control */
|
|
/* register with XBYTE. */
|
|
{
|
|
switch ( SU_Number )
|
|
{
|
|
case SU_1:
|
|
|
|
SU_ctrl_register |= 0x10;
|
|
*execution_result = SU_1_ON;
|
|
/* Set high bit 4 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_2:
|
|
|
|
SU_ctrl_register |= 0x20;
|
|
*execution_result = SU_2_ON;
|
|
/* Set high bit 5 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_3:
|
|
|
|
SU_ctrl_register |= 0x40;
|
|
*execution_result = SU_3_ON;
|
|
/* Set high bit 6 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_4:
|
|
|
|
SU_ctrl_register |= 0x80;
|
|
*execution_result = SU_4_ON;
|
|
/* Set high bit 7 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
default:
|
|
*execution_result = SU_NOT_ACTIVATED;
|
|
/*Incorrect SU number has caused an error. */
|
|
break;
|
|
}
|
|
|
|
SET_DATA_BYTE( SU_CONTROL, SU_ctrl_register );
|
|
|
|
telemetry_data.SU_status[ SU_Number - SU_1 ] |= SU_ONOFF_MASK;
|
|
/* SU_status register is updated to indicate that SU is switched on. */
|
|
/* Other bits in this register are preserved. */
|
|
}
|
|
|
|
|
|
void Switch_SU_Off (
|
|
sensor_number_t SU_Number,
|
|
unsigned char EXTERNAL *execution_result ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Given Sensor Unit is switced off. */
|
|
/* Interface : Execution result is stored in a variable. */
|
|
/* Preconditions : SU_Number should be 1,2,3 or 4. */
|
|
/* Postconditions : Given Sensor Unit is switced off. */
|
|
/* Algorithm : The respective bit is set low with XBYTE. */
|
|
{
|
|
switch ( SU_Number )
|
|
{
|
|
case SU_1:
|
|
|
|
SU_ctrl_register &= ~0x10;
|
|
*execution_result = SU_1_OFF;
|
|
/* Set low bit 4 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_2:
|
|
|
|
SU_ctrl_register &= ~0x20;
|
|
*execution_result = SU_2_OFF;
|
|
/* Set low bit 5 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_3:
|
|
|
|
SU_ctrl_register &= ~0x40;
|
|
*execution_result = SU_3_OFF;
|
|
/* Set low bit 6 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
case SU_4:
|
|
|
|
SU_ctrl_register &= ~0x80;
|
|
*execution_result = SU_4_OFF;
|
|
/* Set low bit 7 in the SU on/off control register, */
|
|
/* preserves other bits. */
|
|
break;
|
|
|
|
default:
|
|
*execution_result = SU_NOT_DEACTIVATED;
|
|
/*Incorrect SU number has caused an error. */
|
|
break;
|
|
}
|
|
|
|
SET_DATA_BYTE( SU_CONTROL, SU_ctrl_register );
|
|
|
|
telemetry_data.SU_status[ SU_Number - SU_1 ] &= ( ~SU_ONOFF_MASK );
|
|
/* SU_status register is updated to indicate that SU is switched off. */
|
|
/* Other bits in this register are preserved. */
|
|
}
|
|
|
|
|
|
void EnableAnalogSwitch( sensor_index_t self_test_SU_index )
|
|
/* Purpose : The analog switch output is enabled in the */
|
|
/* self test channel register. */
|
|
/* Interface : inputs - self_test_SU_index */
|
|
/* outputs - SU_self_test_channel, HW register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : The analog switch output is enabled for a given */
|
|
/* self test SU in the SU_self_test_channel register. */
|
|
/* Algorithm : - The respective bit is set in the SU_self_test_channel */
|
|
/* variable and written to HW. */
|
|
{
|
|
SU_self_test_channel |= analog_switch_bit[ self_test_SU_index ];
|
|
/* The respective bit is set in the variable, preserve other bits. */
|
|
|
|
SET_SU_SELF_TEST_CH( SU_self_test_channel );
|
|
}
|
|
|
|
void DisableAnalogSwitch( sensor_index_t self_test_SU_index )
|
|
/* Purpose : The analog switch output is disabled in the */
|
|
/* self test channel register. */
|
|
/* Interface : inputs - self_test_SU_index */
|
|
/* outputs - SU_self_test_channel, HW register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : The analog switch output is disabled for a given */
|
|
/* self test SU in the SU_self_test_channel register. */
|
|
/* Algorithm : - The respective bit is reset in the SU_self_test_channel*/
|
|
/* variable and written to HW. */
|
|
{
|
|
SU_self_test_channel &= ~analog_switch_bit[ self_test_SU_index ];
|
|
/* The respective bit is set in the variable, preserve other bits. */
|
|
|
|
SET_SU_SELF_TEST_CH( SU_self_test_channel );
|
|
}
|
|
|
|
void SelectSelfTestChannel( unsigned char channel )
|
|
/* Purpose : A self test channel is selected in the */
|
|
/* self test channel register. */
|
|
/* Interface : inputs - channel */
|
|
/* outputs - SU_self_test_channel, HW register */
|
|
/* subroutines - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : The given self test channel is selected. */
|
|
/* self test SU in the SU_self_test_channel register. */
|
|
/* Algorithm : - The respective bit is set in the self test channel */
|
|
/* register and written to HW. */
|
|
{
|
|
unsigned char EXTERNAL channel_selector_value[ NUM_CH ];
|
|
/* This array stores the selector bit states related to a given channel. */
|
|
|
|
channel_selector_value[ PLASMA_1_PLUS ] = 0x00;
|
|
channel_selector_value[ PLASMA_1_MINUS ] = 0x01;
|
|
channel_selector_value[ PZT_1 ] = 0x02;
|
|
channel_selector_value[ PZT_2 ] = 0x03;
|
|
channel_selector_value[ PLASMA_2_PLUS ] = 0x04;
|
|
|
|
SU_self_test_channel =
|
|
( SU_self_test_channel & 0xF8 ) | channel_selector_value[ channel ];
|
|
/* Set chosen bits preserve others. */
|
|
|
|
SET_SU_SELF_TEST_CH( SU_self_test_channel );
|
|
}
|
|
|
|
|
|
void ReadDelayCounters ( delays_t EXTERNAL *delay )
|
|
/* Purpose : Read delay counters. */
|
|
/* Interface : Results are stored into a given struct. */
|
|
/* Preconditions : */
|
|
/* Postconditions : Counters are read. */
|
|
/* Algorithm : MSB and LSB are combined to form an 16 bit int. */
|
|
{
|
|
unsigned char msb, lsb;
|
|
|
|
msb = GET_MSB_COUNTER & 0x0F;
|
|
/* Correct set of four bits are selected in the MSB. */
|
|
lsb = GET_LSB1_COUNTER;
|
|
|
|
delay -> FromPlasma1Plus = ( msb << 8 ) | lsb;
|
|
|
|
msb = GET_MSB_COUNTER >> 4;
|
|
/* Correct set of four bits are selected in the MSB. */
|
|
lsb = GET_LSB2_COUNTER;
|
|
|
|
delay -> FromPlasma1Minus = ( msb << 8 ) | lsb;
|
|
}
|
|
|
|
|
|
unsigned char ReadRiseTimeCounter( void ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Plasma1+ rise time counter is read from the specified */
|
|
/* address. */
|
|
/* Interface : Result is returned as an unsigned char. */
|
|
/* Preconditions : */
|
|
/* Postconditions : Data is gained. */
|
|
/* Algorithm : Counter is read with XBYTE. */
|
|
{
|
|
|
|
return GET_DATA_BYTE( RISE_TIME_COUNTER );
|
|
|
|
}
|
|
|
|
void ResetDelayCounters( void ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Delay counters are reset. */
|
|
/* Interface : Port 1 is used. */
|
|
/* Preconditions : Resetting takes place after acquisition. */
|
|
/* Postconditions : Delay counters are reset. */
|
|
/* Algorithm : The counter reset output bit at the I/O port 1 is set */
|
|
/* first and then high. */
|
|
|
|
{
|
|
SET_COUNTER_RESET( LOW );
|
|
/* Counters are reset by setting CNTR_RS bit to low in port 1 */
|
|
|
|
SET_COUNTER_RESET( HIGH );
|
|
/* The bit is set back to high */
|
|
}
|
|
|
|
|
|
void SetTriggerLevel( trigger_set_t EXTERNAL *setting )
|
|
COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Given trigger level is set. */
|
|
/* Interface : Execution result is stored in a variable. */
|
|
/* Preconditions : SU_Number should be 1-4 and channel number 1-5 levels */
|
|
/* Postconditions : Given level is set for specific unit and channel. */
|
|
/* Algorithm : The respective memory address is written into. */
|
|
/* */
|
|
/* This function is used by TelecomandExecutionTask and */
|
|
/* HealthMonitoringTask. despite the fact that it is of type re-enrant */
|
|
/* the two tasks should not use it simultaniously. When */
|
|
/* HealthMonitoringTask is conducting self test and uses */
|
|
/* SetTriggerLevel, TelecomandExecutionTask is able to interrupt and */
|
|
/* possibly set another trigger levels which would foul up the self */
|
|
/* test. On the other hand when TelecomandExecutionTask is setting */
|
|
/* trigger levels HealthMonitoringTask is disabled due to its lower */
|
|
/* priority. */
|
|
|
|
|
|
{
|
|
|
|
setting -> execution_result = TRIGGER_SET_OK;
|
|
|
|
switch ( setting -> sensor_unit )
|
|
/*sensor unit is selected*/
|
|
{
|
|
case SU_1: {
|
|
setting -> base = SU_1_TRIGGER_BASE;
|
|
break;
|
|
}
|
|
case SU_2: {
|
|
setting -> base = SU_2_TRIGGER_BASE;
|
|
break;
|
|
}
|
|
case SU_3: {
|
|
setting -> base = SU_3_TRIGGER_BASE;
|
|
break;
|
|
}
|
|
case SU_4: {
|
|
setting -> base = SU_4_TRIGGER_BASE;
|
|
break;
|
|
}
|
|
default: {
|
|
setting -> execution_result = SU_NOT_SELECTED;
|
|
/*Sensor Unit number is invalid. */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( setting -> execution_result != SU_NOT_SELECTED )
|
|
{
|
|
switch ( setting -> channel )
|
|
/*channel is selected*/
|
|
{
|
|
case PLASMA_1_PLUS: {
|
|
SET_DATA_BYTE( setting -> base + 0, setting -> level );
|
|
break;
|
|
}
|
|
case PLASMA_1_MINUS: {
|
|
SET_DATA_BYTE( setting -> base + 1, setting -> level );
|
|
break;
|
|
}
|
|
case PZT_1_2: {
|
|
SET_DATA_BYTE( setting -> base + 2, setting -> level );
|
|
break;
|
|
}
|
|
default: {
|
|
setting -> execution_result = CHANNEL_NOT_SELECTED;
|
|
/*Given channel parameter is invalid. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void SetTestPulseLevel( unsigned char level ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Testpulse level is set. */
|
|
/* Interface : input: - Desired test pulse level. */
|
|
/* Preconditions : none. */
|
|
/* Postconditions : Level is set. */
|
|
/* Algorithm : Level is written into memory-mapped port address. */
|
|
{
|
|
SET_TEST_PULSE_LEVEL( level );
|
|
}
|
|
|
|
|
|
void GetVoltageStatus( voltage_status_t EXTERNAL *v_status )
|
|
COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Voltage status data is gained. */
|
|
/* Interface : Port 1 is used. */
|
|
/* Preconditions : */
|
|
/* Postconditions : Data is acquired. */
|
|
/* Algorithm : HV status register is read into a struct with XBYTE. */
|
|
/* V_DOWN bit is read from port 1. */
|
|
{
|
|
v_status -> V_down_bit = V_DOWN;
|
|
v_status -> HV_status = GET_DATA_BYTE( HV_STATUS );
|
|
}
|
|
|
|
void ResetPeakDetector( sensor_number_t unit )
|
|
/* Purpose : Peak detector is reset. */
|
|
/* Interface : -'Sensor unit on/off control register' is used */
|
|
/* Preconditions : Resetting takes place after acquisition. */
|
|
/* Postconditions : Peak detector is reset. */
|
|
/* Algorithm : - Interrupts are disabled */
|
|
/* - SignalPeakDetectorReset function is called */
|
|
/* - Interrupts are enabled */
|
|
/* */
|
|
/* This function is used by Acquisition and HealthMonitoringTask. */
|
|
/* However, it does not have to be of re-entrant type because collision */
|
|
/* is avoided through design, as follows. */
|
|
/* HealthMonitoring task uses ResetPeakDetector when Hit Budget has been */
|
|
/* exeeded. This means that Acquisitiontask is disabled. When Acquisition */
|
|
/* task uses ResetPeakDetector HealthMonitoringTask is disabled because */
|
|
/* it is of lower priority . */
|
|
|
|
|
|
{
|
|
DISABLE_INTERRUPT_MASTER;
|
|
/* Disable all interrupts */
|
|
|
|
SignalPeakDetectorReset(
|
|
SU_ctrl_register & ~( 1 << ( unit - SU_1 ) ),
|
|
SU_ctrl_register );
|
|
/* Generate reset pulse. */
|
|
|
|
ENABLE_INTERRUPT_MASTER;
|
|
}
|
|
|
|
void SelectStartSwitchLevel(
|
|
unsigned char test_channel,
|
|
sensor_index_t self_test_SU_index )
|
|
/* Purpose : Select analog switch output level. */
|
|
/* Interface : inputs - self_test_SU_index, test_channel */
|
|
/* outputs - none */
|
|
/* subroutines - EnableAnalogSwitch */
|
|
/* DisableAnalogSwitch */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Analog switch output level is selected depending on the */
|
|
/* given channel. */
|
|
/* Algorithm : - Wanted level is selected. */
|
|
{
|
|
|
|
if ( test_channel == PLASMA_1_PLUS || test_channel == PLASMA_2_PLUS ) {
|
|
/* Channel triggered by falling edge. */
|
|
EnableAnalogSwitch( self_test_SU_index );
|
|
/* Set analog switch output level for the given channel. */
|
|
}
|
|
|
|
else {
|
|
/* Rest of the channels triggered by rising edge. */
|
|
DisableAnalogSwitch( self_test_SU_index );
|
|
/* Set analog switch output level for the given channel. */
|
|
}
|
|
}
|
|
|
|
void SelectTriggerSwitchLevel(
|
|
unsigned char test_channel,
|
|
sensor_index_t self_test_SU_index )
|
|
/* Purpose : Select analog switch output level. */
|
|
/* Interface : inputs - self_test_SU_index, test_channel */
|
|
/* outputs - none */
|
|
/* subroutines - EnableAnalogSwitch */
|
|
/* DisableAnalogSwitch */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Analog switch output level is selected depending on the */
|
|
/* given channel. */
|
|
/* Algorithm : - Wanted level is selected. */
|
|
/* - SW triggering is needed with channel PLASMA_2_PLUS. */
|
|
{
|
|
|
|
if ( test_channel == PLASMA_1_PLUS ) {
|
|
/* Channel triggered by falling edge. */
|
|
|
|
DisableAnalogSwitch( self_test_SU_index );
|
|
/* Set analog switch output level for the given channel. */
|
|
}
|
|
|
|
else
|
|
if ( test_channel == PLASMA_2_PLUS ) {
|
|
/* Channel triggered by falling edge. SW trigger needed. */
|
|
|
|
DisableAnalogSwitch( self_test_SU_index );
|
|
/* Set analog switch output level for the given channel. */
|
|
|
|
SET_SU_SELF_TEST_CH( SU_self_test_channel );
|
|
|
|
SET_HIT_TRIGGER_ISR_FLAG;
|
|
/* SW trigger required. */
|
|
}
|
|
|
|
else {
|
|
/* Rest of the channels triggered by rising edge. */
|
|
|
|
EnableAnalogSwitch( self_test_SU_index );
|
|
/* Set analog switch output level for the given channel. */
|
|
}
|
|
}
|
|
|