3715 lines
93 KiB
C
3715 lines
93 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, test harness for WCET analysis
|
|
Subsystem : DNI (DEBIE Null Interface)
|
|
Module : harness.c
|
|
|
|
Implementations of the DNI operations, suitable for compiling
|
|
and linking the DEBIE I DPU Software as a standard C program,
|
|
on any processor that supports the required data types (eg. 8-bit
|
|
char, 32-bit long) and has enough program and data memory.
|
|
|
|
This implementation is designed to support measurement-based
|
|
timing analysis by feeding the DEBIE SW with selected sets of
|
|
test data.
|
|
|
|
Options: if the preprocessor symbol TRACE_HARNESS is defined,
|
|
the harness operations generate trace message on stdout.
|
|
|
|
Based, with extensive changes, on the SSF file rtx_if.c, rev 1.13,
|
|
Fri May 21 00:14:00 1999.
|
|
|
|
- * --------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* This file contains several sets of operations, as follows:
|
|
|
|
> processor registers as variables: reg52.h
|
|
|
|
> kernel operations: taskctrl.h, isr_ctrl.h, msg_ctrl.h
|
|
|
|
> some DPU operations: dpu_ctrl.h
|
|
|
|
> telecommand and telemetry interface operations: ttc_ctrl.h, isr_ctrl.h
|
|
|
|
> operations for the A/D converted: ad_conv.h
|
|
|
|
> operations on the sensor units: su_ctrl.h, dpu_ctrl.h
|
|
|
|
> accessing the VALUE_OF "unsigned short" telemetry items: keyword.h
|
|
|
|
> "calling" a "patch function": keyword.h
|
|
|
|
> checking the sizes of various types (for analysis only).
|
|
|
|
For testing purposes the main operation is StartSystem(). The DEBIE
|
|
main function calls StartSystem(), which normally activates the
|
|
kernel and the DEBIE application tasks and interrupt handlers. In this
|
|
version, StartSystem() takes over the show and runs the test scenario.
|
|
|
|
Target-specific harness operations are implemented in target.c. There
|
|
is a specific version of target.c for each target processor/compiler.
|
|
|
|
*/
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
#include "keyword.h"
|
|
#include "health.h"
|
|
#include "measure.h"
|
|
#include "tc_hand.h"
|
|
#include "telem.h"
|
|
|
|
|
|
/* Processor registers : reg52.h */
|
|
|
|
|
|
unsigned char EA;
|
|
|
|
|
|
/* Kernel operations : taskctrl.h */
|
|
|
|
#include "taskctrl.h"
|
|
|
|
void CreateTask ( task_info_t EXTERNAL *new_task )
|
|
/* Purpose : Task is created in the RTX. */
|
|
/* Interface : input: - new_task */
|
|
/* output: - telemetry_data.os_create_task_error */
|
|
/* Preconditions : none */
|
|
/* Algorithm : -In case of an error, 'new_task' is stored to telemetry */
|
|
/* as an error indication. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "CreateTask %d\n", new_task->rtx_task_number );
|
|
#endif
|
|
|
|
switch ( new_task->rtx_task_number ) {
|
|
|
|
case TC_TM_INTERFACE_TASK:
|
|
|
|
InitTelecommandTask ();
|
|
|
|
break;
|
|
|
|
case ACQUISITION_TASK:
|
|
|
|
InitAcquisitionTask ();
|
|
|
|
break;
|
|
|
|
case HIT_TRIGGER_ISR_TASK:
|
|
|
|
InitHitTriggerTask ();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "CreateTask: unknown task number\n" );
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void WaitInterval( unsigned char time )
|
|
/* Purpose : Interval is waited with RTX. */
|
|
/* Interface : input: - time */
|
|
/* output: - telemetry_data.os_wait_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Interval for wait is set. */
|
|
/* Algorithm : -In case of an error, 'K_IVL' is stored to telemetry */
|
|
/* as an error indication and error bit is set in */
|
|
/* software_error register. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "WaitInterval %d\n", time );
|
|
#endif
|
|
}
|
|
|
|
|
|
void WaitTimeout( unsigned char time ) COMPACT REENTRANT_FUNC
|
|
/* Purpose : Timeout is waited with RTX. */
|
|
/* Interface : input: - time */
|
|
/* output: - telemetry_data.os_wait_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Specified time has elapsed. */
|
|
/* Algorithm : -In case of an error, 'K_TMO' is stored to telemetry */
|
|
/* as an error indication and error bit is set in */
|
|
/* software_error register. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "WaitTimeout %d\n", time );
|
|
#endif
|
|
}
|
|
|
|
|
|
void SetTimeSlice( unsigned int time_slice )
|
|
/* Purpose : Time slice in the RTX is set. */
|
|
/* Interface : input: - time_slice */
|
|
/* output: - telemetry_data.os_set_slice_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Timeslice which defines the time interval in number of */
|
|
/* processor cycles is set. */
|
|
/* Algorithm : In case of an error, indication bit is set in */
|
|
/* the software_error register. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "SetTimeSlice %d\n", time_slice );
|
|
#endif
|
|
}
|
|
|
|
|
|
static unsigned int ad_converting = 0;
|
|
/* Whether the ADC is now busy with a conversion.
|
|
0 = no, 1 = yes.
|
|
Declared here, because it is cleared by ShortDelay.
|
|
*/
|
|
|
|
|
|
void ShortDelay ( uint_least8_t delay_loops )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "ShortDelay %d\n", delay_loops );
|
|
#endif
|
|
|
|
ad_converting = 0;
|
|
/* Any on-going A/D conversion is assumed to end during the delay.
|
|
ShortDelay is sometimes used, instead of End_Of_ADC, when the
|
|
A/D converter is switched between unipolar and bipolar modes.
|
|
*/
|
|
}
|
|
|
|
|
|
unsigned char isr_send_message (
|
|
unsigned char mailbox,
|
|
uint16_t message )
|
|
/* Purpose : Send mail from ISR to a requested mailbox. */
|
|
/* Interface : input: - mailbox, message */
|
|
/* output: - telemetry_data.os_send_message_error */
|
|
/* Preconditions : Mailbox number should be a value 0 - 7 */
|
|
/* Postconditions : Mail is send to a given mailbox. */
|
|
/* Algorithm : - In case of an error, failed 'mailbox' is stored to */
|
|
/* telemetry. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "isr_send_message to %d, message %d = 0x%x\n",
|
|
mailbox, message, message );
|
|
#endif
|
|
SendTaskMail ( mailbox, message, 0 );
|
|
return OK;
|
|
}
|
|
|
|
|
|
/* Interrupt services : isr_ctrl.h */
|
|
|
|
|
|
#include "isr_ctrl.h"
|
|
|
|
|
|
void AttachInterrupt( unsigned char ISR_VectorNumber )
|
|
/* Purpose : Interrupt with a given number is assigned to a task in */
|
|
/* Interface : input: - ISR_VectorNumber */
|
|
/* output: - telemetry_data.os_attach_interrupt_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Interrupt is attached to a calling task. */
|
|
/* Algorithm : -In case of an error, 'ISR_VectorNumber' is stored to */
|
|
/* telemetry as an error indication. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "AttachInterrupt %d\n", ISR_VectorNumber );
|
|
#endif
|
|
}
|
|
|
|
|
|
void EnableInterrupt( unsigned char ISR_VectorNumber )
|
|
/* Purpose : Interrupt with a given number is enabled in the RTX. */
|
|
/* Interface : input: - ISR_VectorNumber */
|
|
/* output: - telemetry_data.os_enable_isr_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Interrupt is enabled. */
|
|
/* Algorithm : -In case of an error, 'ISR_VectorNumber' is stored to */
|
|
/* telemetry as an error indication. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "EnableInterrupt %d\n", ISR_VectorNumber );
|
|
#endif
|
|
}
|
|
|
|
|
|
void DisableInterrupt( unsigned char ISR_VectorNumber )
|
|
/* Purpose : Interrupt with a given number is disabled in the RTX. */
|
|
/* Interface : input: - ISR_VectorNumber */
|
|
/* output: - telemetry_data.os_disable_isr_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Interrupt is enabled. */
|
|
/* Algorithm : -In case of an error, 'ISR_VectorNumber' is stored to */
|
|
/* telemetry as an error indication. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "DisableInterrupt %d\n", ISR_VectorNumber );
|
|
#endif
|
|
}
|
|
|
|
|
|
signed char SetInterruptMask( unsigned char ISR_MaskNumber )
|
|
/* Purpose : Interrupt mask bit is set is in the RTX. */
|
|
/* Interface : Return value, which describes the execution result, is */
|
|
/* always zero as this function does no parameter checking. */
|
|
/* Used to manipulate special bits, which are part of the */
|
|
/* interrupt enable registers or to modify interrupt enable */
|
|
/* bits from inside a C51 interrupt function. */
|
|
/* Not to be used for interrupt sources attached to RTX51 */
|
|
/* tasks. */
|
|
/* Preconditions : */
|
|
/* Postconditions : Interrupt mask is set. */
|
|
/* Algorithm : RTX syntax is used. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "SetInterruptMask 0x%x\n", ISR_MaskNumber );
|
|
#endif
|
|
return 0; /* Success. */
|
|
}
|
|
|
|
|
|
signed char ResetInterruptMask( unsigned char ISR_MaskNumber )
|
|
/* Purpose : Interrupt mask bit is reset is in the RTX. */
|
|
/* Interface : Return value, which describes the execution result, is */
|
|
/* always zero as this function does no parameter checking. */
|
|
/* Used to manipulate special bits, which are part of the */
|
|
/* interrupt enable registers or to modify interrupt enable */
|
|
/* bits from inside a C51 interrupt function. */
|
|
/* Not to be used for interrupt sources attached to RTX51 */
|
|
/* tasks. */
|
|
/* Preconditions : */
|
|
/* Postconditions : Interrupt mask is reset. */
|
|
/* Algorithm : RTX syntax is used. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "ResetInterruptMask 0x%x\n", ISR_MaskNumber );
|
|
#endif
|
|
return 0; /* Success. */
|
|
}
|
|
|
|
|
|
void WaitInterrupt ( unsigned char ISR_VectorNumber, unsigned char timer )
|
|
/* Purpose : Interrupt is waited in the RTX. */
|
|
/* Interface : input: - ISR_VectorNumber,timer */
|
|
/* output: - telemetry_data.os_wait_error */
|
|
/* Preconditions : none */
|
|
/* Postconditions : Interrupt is waited. */
|
|
/* Postconditions : Interrupt is enabled. */
|
|
/* Algorithm : -In case of an error, 'K_INT' is stored to telemetry */
|
|
/* as an error indication and error bit is set in */
|
|
/* software_error register. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "WaitInterrupt %d, time %d\n", ISR_VectorNumber, timer );
|
|
#endif
|
|
}
|
|
|
|
/* See below, Telecommand and telemetry interface, for the ISR */
|
|
/* operations related to the TC timer. */
|
|
|
|
/* See below for the ISR operations related to the Hit interrupt. */
|
|
|
|
|
|
|
|
/* Message sending : msg_ctrl.h */
|
|
|
|
|
|
#include "msg_ctrl.h"
|
|
|
|
|
|
static uint16_t mail_message[ 8 ];
|
|
/* The last message in the mailbox. */
|
|
|
|
static int mail_count[ 8 ] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
/* The number of messages in the mailbox. */
|
|
/* Should be between 0 and 1. */
|
|
|
|
static int mail_overflows = 0;
|
|
/* The number of times a mailbox has overflowed. */
|
|
|
|
|
|
void SendTaskMail (
|
|
unsigned char mailbox,
|
|
uint16_t message,
|
|
unsigned char timeout )
|
|
/* Purpose : Send mail to a requested mailbox. */
|
|
/* Interface : input: - mailbox, message, timeout */
|
|
/* output: - telemetry_data.os_send_message_error */
|
|
/* Preconditions : Mailbox number should be a value 0 - 7 */
|
|
/* timeout should be a value 0 - 255 */
|
|
/* Postconditions : Mail is send to a given mailbox. */
|
|
/* Algorithm : - In case of an error, failed 'mailbox' is stored to */
|
|
/* telemetry. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "SendTaskMail to %d, message %d, timeout %d\n",
|
|
mailbox, message, timeout );
|
|
#endif
|
|
|
|
if ( mail_count[ mailbox ] == 0 )
|
|
mail_message[ mailbox ] = message;
|
|
else {
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Overflow on mailbox %d, already %d message(s)\n",
|
|
mailbox, mail_count[ mailbox ] );
|
|
#endif
|
|
mail_overflows ++;
|
|
}
|
|
|
|
mail_count[ mailbox ] ++;
|
|
}
|
|
|
|
|
|
void WaitMail ( incoming_mail_t EXTERNAL *message ) COMPACT_DATA REENTRANT_FUNC
|
|
/* Purpose : Mail is waited from the given mailbox. */
|
|
/* Interface : Return value, which describes the execution result, is */
|
|
/* stored in to a struct. */
|
|
/* Preconditions : Mailbox number should be a value 0 - 7 */
|
|
/* Time-out should have a value 0 - 255. */
|
|
/* Postconditions : Message is received or timeout has occurred or error has */
|
|
/* occurred due to unvalid parameter values. */
|
|
/* Algorithm : -In case of an error, 'event_selector' is stored to */
|
|
/* telemetry as an error indication and error bit is set */
|
|
/* in software_error register. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "WaitMail from %d, timeout %d\n",
|
|
message -> mailbox_number, message -> timeout );
|
|
#endif
|
|
|
|
if ( mail_count[ message -> mailbox_number ] > 0 )
|
|
{
|
|
message -> wait_result = MSG_RECEIVED;
|
|
message -> execution_result = MSG_RECEIVED;
|
|
*( message -> message ) = mail_message[ message -> mailbox_number ];
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Message from %d is %d = 0x%x\n",
|
|
message -> mailbox_number,
|
|
*( message -> message ),
|
|
*( message -> message ) );
|
|
#endif
|
|
|
|
mail_count[ message -> mailbox_number ] --;
|
|
} else
|
|
{
|
|
message -> wait_result = TIMEOUT_OCCURRED;
|
|
message -> execution_result = TIMEOUT_OCCURRED;
|
|
*( message -> message ) = 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void FlushMail ( unsigned char mailbox )
|
|
/* Remove all mail from the mailbox. Harness use only. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "FlushMail from box %d, which had %d messages.\n",
|
|
mailbox, mail_count[ mailbox ] );
|
|
#endif
|
|
|
|
mail_count[ mailbox ] = 0;
|
|
}
|
|
|
|
|
|
/* DPU operations : dpu_ctrl.h */
|
|
|
|
|
|
#include "dpu_ctrl.h"
|
|
|
|
|
|
static unsigned int check_current_errors = 0;
|
|
/* The number of consecutive error indications to be returned
|
|
by the next calls of Check_Current.
|
|
*/
|
|
|
|
|
|
unsigned char Check_Current ( unsigned char bits )
|
|
{
|
|
unsigned char val;
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Check_Current 0x%x\n", bits );
|
|
#endif
|
|
switch ( bits ) {
|
|
case 3:
|
|
val = 1;
|
|
break;
|
|
case 12:
|
|
val = 4;
|
|
break;
|
|
case 48:
|
|
val = 16;
|
|
break;
|
|
case 192:
|
|
val = 64;
|
|
break;
|
|
default :
|
|
val = 0;
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Check_Current param error\n" );
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
if ( check_current_errors > 0 ) {
|
|
val = ~val; /* Wrong value => alarm. */
|
|
check_current_errors --;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
/* The memory operations (Get_Data_Byte etc) are implemented in
|
|
target.c for each target processor/compiler.
|
|
*/
|
|
|
|
|
|
/* The following routines are implemented in das/hw_if.c:
|
|
Init_DPU
|
|
GetResetClass
|
|
SignalMemoryErrors
|
|
SetMemoryConfiguration
|
|
GetMemoryConfiguration
|
|
PatchCode
|
|
*/
|
|
|
|
|
|
void Reboot( reset_class_t boot_type )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Reboot %d\n", boot_type );
|
|
#endif
|
|
|
|
if ( boot_type == checksum_reset_e ) {
|
|
/* Make it not happen (at once) again: */
|
|
reference_checksum = code_checksum;
|
|
}
|
|
|
|
TARGET_REBOOT;
|
|
}
|
|
|
|
|
|
/* Functions originally implemented in assembly-language (asmfuncs.a51): */
|
|
|
|
|
|
unsigned char TestMemBits ( data_address_t address )
|
|
/*
|
|
Test each bit of a cell in RAM memory.
|
|
For each of the eight bits, the value with this bit ON and
|
|
all others bits OFF is written to the cell, and the written
|
|
value is read back and verified.
|
|
The original content of the cell is destroyed.
|
|
Parameters:
|
|
address Cell address.
|
|
TestMemBits returns zero for success, and otherwise the
|
|
first bit pattern for which the cell failed.
|
|
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "TestMemBits 0x%x\n", address );
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
unsigned char TestMemData (
|
|
data_address_t start,
|
|
uint_least8_t bytes )
|
|
/*
|
|
Test an area of RAM memory.
|
|
For each RAM cell in the given area, the values AAh
|
|
and 55h are written to the cell, and the written value
|
|
is read back and verified.
|
|
The original content of each cell is destroyed.
|
|
Parameters:
|
|
start Starting address
|
|
bytes Length of area
|
|
1 .. 255. Note, zero is NOT allowed!
|
|
TestMem returns the number of bytes remaining to test
|
|
when the first memory failure occurred.
|
|
If this value is nonzero, the first failing address is
|
|
found by subtracting the return value from 'start+bytes'.
|
|
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "TestMemData start 0x%x, bytes %d\n", start, bytes );
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
unsigned char TestMemSeq (
|
|
data_address_t start,
|
|
uint_least8_t bytes )
|
|
/*
|
|
Test an area of RAM memory.
|
|
For each RAM cell in the given area, the logical complement of
|
|
the low byte of the cell address is written into the cell, in
|
|
one pass from the start to the end. Then, in a second pass,
|
|
each cell is read and the value is is verified.
|
|
The original content of each cell is destroyed.
|
|
Parameters:
|
|
start Starting address
|
|
bytes Length of area
|
|
1 .. 255. Note, zero is NOT allowed!
|
|
TestMemSeq returns the number of bytes remaining to test
|
|
when the first memory failure occurred.
|
|
If this value is nonzero, the first failing address is
|
|
found by subtracting the return value from 'start+bytes'.
|
|
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "TestMemSeq start 0x%x, bytes %d\n", start, bytes );
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Telecommand and telemetry interface : ttc_ctrl.h */
|
|
|
|
|
|
#include "ttc_ctrl.h"
|
|
|
|
|
|
static unsigned char tc_msb, tc_lsb;
|
|
/* Simulated TC interface registers. */
|
|
|
|
static uint16_t tc_word;
|
|
/* The simulated TC word, composed of tc_msb and tc_lsb. */
|
|
|
|
|
|
unsigned char Read_TC_MSB ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Read_TC_MSB\n" );
|
|
#endif
|
|
return tc_msb;
|
|
}
|
|
|
|
|
|
unsigned char Read_TC_LSB ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Read_TC_LSB\n" );
|
|
#endif
|
|
return tc_lsb;
|
|
}
|
|
|
|
|
|
static unsigned char tm_msb, tm_lsb;
|
|
/* Simulated TM interface registers. */
|
|
|
|
|
|
void Write_TM_LSB ( unsigned char value )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Write_TM_LSB %d = 0x%x\n", value, value );
|
|
#endif
|
|
tm_lsb = value;
|
|
}
|
|
|
|
|
|
void Write_TM_MSB ( unsigned char value )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Write_TM_MSB %d = 0x%x\n", value, value );
|
|
#endif
|
|
tm_msb = value;
|
|
}
|
|
|
|
|
|
/* TC timer operations : isr_ctrl.h */
|
|
|
|
|
|
static unsigned char tc_timer_overflow = 1;
|
|
/* Simulated overflow flag on the TC timer. */
|
|
/* 1 = overflow = good, sufficient interval between TCs. */
|
|
/* 0 = no overflow = bad. */
|
|
|
|
|
|
unsigned char TC_Timer_Overflow_Flag ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "TC_Timer_Overflow_Flag\n" );
|
|
#endif
|
|
return tc_timer_overflow;
|
|
}
|
|
|
|
|
|
void Clear_TC_Timer_Overflow_Flag ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Clear_TC_Timer_Overflow_Flag\n" );
|
|
#endif
|
|
tc_timer_overflow = 0;
|
|
}
|
|
|
|
|
|
void Set_TC_Timer_Overflow_Flag ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set_TC_Timer_Overflow_Flag\n" );
|
|
#endif
|
|
tc_timer_overflow = 1;
|
|
}
|
|
|
|
|
|
/* A/D Converter operations : ad_ctrl.h */
|
|
|
|
|
|
#include "ad_conv.h"
|
|
|
|
/* A/D channels
|
|
|
|
Channel Meaning
|
|
------- -------
|
|
dec hex
|
|
0 00 SU 1, plasma 1 +
|
|
1 01 SU 1, plasma 1 -
|
|
2 02 SU 1, piezo 1
|
|
3 03 SU 1, piezo 2
|
|
4 04 SU 1, plasma 2 +
|
|
5 05 SU 1, temperature 0
|
|
6 06 SU 1, temperature 1
|
|
7 07
|
|
8 08 SU 2, plasma 1 +
|
|
9 09 SU 2, plasma 1 -
|
|
10 0A SU 2, piezo 1
|
|
11 0B SU 2, piezo 2
|
|
12 0C SU 2, plasma 2 +
|
|
13 0D SU 2, temperature 0
|
|
14 0E SU 2, temperature 1
|
|
15 0F
|
|
16 10 SU 1 & SU 2, +5V supply
|
|
17 11 SU 3 & SU 4, +5V supply
|
|
18 12 SU 1,2,3,4 , +50V supply
|
|
19 13 DPU +5V supply
|
|
20 14 SU 1 & SU 2, -5V supply
|
|
21 15 SU 3 & SU 4, -5V supply
|
|
22 16 SU 1,2,3,4, -50V supply
|
|
23 17
|
|
24 18 SU 3, plasma 1 +
|
|
25 19 SU 3, plasma 1 -
|
|
26 1A SU 3, piezo 1
|
|
27 1B SU 3, piezo 2
|
|
28 1C SU 3, plasma 2 +
|
|
29 1D SU 3, temperature 0
|
|
30 1E SU 3, temperature 1
|
|
31 1F
|
|
32 20 SU 4, plasma 1 +
|
|
33 21 SU 4, plasma 1 -
|
|
34 22 SU 4, piezo 1
|
|
35 23 SU 4, piezo 2
|
|
36 24 SU 4, plasma 2 +
|
|
37 25 SU 4, temperature 0
|
|
38 26 SU 4, temperature 1
|
|
39 27
|
|
40 28
|
|
|
|
A/D channel-selector register:
|
|
|
|
Bit Meaning
|
|
--- -------
|
|
7 1 = do not use interleave calibration
|
|
6 1 = bipolar, 0 = unipolar
|
|
5 Channel index, 32
|
|
4 Channel index, 16
|
|
3 Channel index, 8
|
|
2 Channel index, 4
|
|
1 Channel index, 2
|
|
0 Channel index, 1
|
|
|
|
*/
|
|
|
|
|
|
typedef struct {
|
|
uint16_t min;
|
|
uint16_t max;
|
|
} ad_limit_t;
|
|
/* Limits on the value of a simulated A/D reading. */
|
|
|
|
static ad_limit_t ad_limit[ AD_CHANNELS ] = {
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff},
|
|
{0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}, {0, 0xffff}
|
|
};
|
|
/* Limits on the simulated A/D readings for all channels. */
|
|
|
|
|
|
void Set_AD_Unlimited ( void )
|
|
/* Sets no A/D limits. */
|
|
{
|
|
uint_least8_t c;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set AD Unlimited\n" );
|
|
#endif
|
|
|
|
_Pragma( "loopbound min 40 max 40" )
|
|
for ( c = 0; c < AD_CHANNELS; c++ ) {
|
|
ad_limit[ c ].min = 0;
|
|
ad_limit[ c ].max = 0xffff;
|
|
}
|
|
}
|
|
|
|
|
|
void Set_AD_Nominal ( void )
|
|
/* Sets A/D limits to ensure nominal (in-range) readings. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set AD Nominal\n" );
|
|
#endif
|
|
|
|
/* SU +5V supply: */
|
|
|
|
ad_limit[ 16 ].min = 0xba00;
|
|
ad_limit[ 16 ].max = 0xe4ff;
|
|
|
|
ad_limit[ 17 ].min = 0xba00;
|
|
ad_limit[ 17 ].max = 0xe4ff;
|
|
|
|
/* SU -5V supply: */
|
|
|
|
ad_limit[ 20 ].min = 0x0d00;
|
|
ad_limit[ 20 ].max = 0x22ff;
|
|
|
|
ad_limit[ 21 ].min = 0x0d00;
|
|
ad_limit[ 21 ].max = 0x22ff;
|
|
|
|
/* SU +50V supply: */
|
|
|
|
ad_limit[ 18 ].min = 0xa800;
|
|
ad_limit[ 18 ].max = 0xe3ff;
|
|
|
|
/* SU -50V supply: */
|
|
|
|
ad_limit[ 22 ].min = 0x0e00;
|
|
ad_limit[ 22 ].max = 0x2cff;
|
|
|
|
/* DPU +5V supply: */
|
|
|
|
ad_limit[ 19 ].min = 0xba00;
|
|
ad_limit[ 19 ].max = 0xe4ff;
|
|
|
|
/* SU 1 temperatures: */
|
|
|
|
ad_limit[ 5 ].min = 0x0000;
|
|
ad_limit[ 5 ].max = 0xfaff;
|
|
ad_limit[ 6 ].min = 0x0000;
|
|
ad_limit[ 6 ].max = 0xf4ff;
|
|
|
|
/* SU 2 temperatures: */
|
|
|
|
ad_limit[ 13 ].min = 0x0000;
|
|
ad_limit[ 13 ].max = 0xfaff;
|
|
ad_limit[ 14 ].min = 0x0000;
|
|
ad_limit[ 14 ].max = 0xf4ff;
|
|
|
|
/* SU 3 temperatures: */
|
|
|
|
ad_limit[ 29 ].min = 0x0000;
|
|
ad_limit[ 29 ].max = 0xfaff;
|
|
ad_limit[ 30 ].min = 0x0000;
|
|
ad_limit[ 30 ].max = 0xf4ff;
|
|
|
|
/* SU 4 temperatures: */
|
|
|
|
ad_limit[ 37 ].min = 0x0000;
|
|
ad_limit[ 37 ].max = 0xfaff;
|
|
ad_limit[ 38 ].min = 0x0000;
|
|
ad_limit[ 38 ].max = 0xf4ff;
|
|
}
|
|
|
|
|
|
static int ad_conv_timer;
|
|
/* Simulate some delay in the conversion. This is a signed
|
|
number so that the delay can be made large by initializing
|
|
the timer to a large negative value.
|
|
*/
|
|
|
|
#define AD_NUM_CONV 6
|
|
/* The number of consecutive A/D conversions separately simulated. */
|
|
|
|
static int ad_conv_delay[ AD_NUM_CONV ];
|
|
/* The conversion finishes when ad_conv_timer >= ad_conv_delay,
|
|
with provision for up to AD_NUM_CONV different delays for
|
|
many consecutive conversions. A value of 0 or 1 means that
|
|
the conversion is immediately ready, assuming that ad_conv_time
|
|
starts counting from zero (and not from a negative value).
|
|
*/
|
|
|
|
static unsigned int ad_conv_num = 0;
|
|
/* Counts the consecutive conversions for ad_conv_delay[ ]. */
|
|
|
|
|
|
#define AD_NUM_RAND 319
|
|
/* The amount of random A/D data defined below. */
|
|
|
|
static unsigned char ad_random[ AD_NUM_RAND ] = {
|
|
0x6a, 0xde, 0xba, 0x90, 0xf2, 0x18, 0x48, 0xf3,
|
|
0x9e, 0x2b, 0x31, 0xdb, 0xe0, 0x7e, 0xc6, 0x18,
|
|
0x43, 0xd0, 0xd7, 0x6e, 0xbc, 0xee, 0x93, 0x9a,
|
|
0x06, 0xb2, 0x3d, 0x1f, 0xc1, 0x51, 0x66, 0x69,
|
|
0xbf, 0x1c, 0x9c, 0xfc, 0x9b, 0xf7, 0xf2, 0xd0,
|
|
0xf4, 0x26, 0x60, 0x69, 0xc4, 0xd9, 0xdb, 0xd4,
|
|
0xe7, 0x2b, 0x8a, 0xea, 0x9f, 0xab, 0x40, 0x3e,
|
|
0xc3, 0xd8, 0x21, 0x61, 0x3b, 0x0f, 0xc1, 0x49,
|
|
0xd3, 0x09, 0x9a, 0x4d, 0x33, 0x52, 0x7b, 0x8e,
|
|
0x7e, 0x7b, 0x6a, 0x88, 0x4f, 0x84, 0xa2, 0xb4,
|
|
0x83, 0xd9, 0xba, 0x79, 0x7d, 0x8f, 0xdf, 0xb2,
|
|
0x8c, 0x86, 0x77, 0x4f, 0x29, 0x86, 0xd4, 0x8b,
|
|
0x11, 0x65, 0x55, 0x74, 0xf4, 0x76, 0x83, 0x88,
|
|
0xd6, 0xa6, 0xa7, 0x33, 0x22, 0xa3, 0x2e, 0x88,
|
|
0x06, 0x54, 0x90, 0x37, 0xd5, 0xdb, 0xce, 0x7c,
|
|
0x0b, 0xd1, 0xe1, 0xc0, 0x7d, 0xa5, 0x0b, 0xc9,
|
|
0xaf, 0xe3, 0x75, 0xc5, 0xf5, 0xaf, 0xaa, 0xe2,
|
|
0x2a, 0xff, 0x6e, 0x84, 0x0e, 0x04, 0x10, 0xf0,
|
|
0x78, 0xdc, 0x96, 0x3d, 0x22, 0x96, 0x64, 0x5b,
|
|
0x7b, 0x9e, 0x83, 0x45, 0xba, 0xb8, 0xe1, 0x31,
|
|
0xc7, 0x0a, 0xe0, 0x31, 0xce, 0x29, 0x3d, 0x01,
|
|
0xb8, 0xfc, 0x79, 0x83, 0x3d, 0xd1, 0x40, 0xe1,
|
|
0x46, 0xfa, 0xe7, 0xc5, 0xdc, 0xc4, 0x1c, 0x24,
|
|
0x29, 0x5a, 0xef, 0xeb, 0x92, 0x57, 0xba, 0x06,
|
|
0x13, 0x1d, 0x35, 0xef, 0xb0, 0x2d, 0x69, 0x20,
|
|
0x92, 0xb1, 0x82, 0x00, 0x8e, 0x3b, 0x12, 0xb3,
|
|
0x78, 0xd7, 0x18, 0xb3, 0x54, 0x0f, 0xd1, 0x8e,
|
|
0x88, 0x5d, 0x4e, 0x2b, 0x30, 0x30, 0x2d, 0x85,
|
|
0xaa, 0x21, 0x01, 0xe1, 0x2c, 0x35, 0xa1, 0xee,
|
|
0xa2, 0x17, 0xed, 0x60, 0x1b, 0x98, 0xea, 0x12,
|
|
0x85, 0x21, 0xde, 0x45, 0x26, 0xef, 0x12, 0x3c,
|
|
0x02, 0x8c, 0xd7, 0x49, 0xbd, 0x02, 0xa7, 0x7d,
|
|
0xe7, 0x1c, 0x15, 0xf9, 0xaa, 0x44, 0x15, 0xb1,
|
|
0xaa, 0x76, 0x5e, 0xf2, 0xb4, 0xfb, 0x85, 0x77,
|
|
0xb9, 0x32, 0xb4, 0xc9, 0x70, 0xe1, 0xdb, 0x44,
|
|
0x9f, 0x5b, 0x87, 0xca, 0xaa, 0xcb, 0x43, 0x53,
|
|
0x7e, 0x49, 0xec, 0x1a, 0x13, 0x1d, 0xe1, 0x1b,
|
|
0x13, 0xc3, 0x34, 0x95, 0x5d, 0x5a, 0xc3, 0xd0,
|
|
0x33, 0x05, 0x82, 0x4a, 0x2e, 0x6d, 0x39, 0xeb,
|
|
0x9c, 0x65, 0x81, 0x7f, 0xa1, 0x62, 0x11
|
|
};
|
|
/* Random A/D data. */
|
|
|
|
|
|
void Next ( unsigned int *index )
|
|
/* Go on to the next random value. */
|
|
{
|
|
( *index ) ++;
|
|
if ( ( *index ) >= AD_NUM_RAND ) *index = 0;
|
|
}
|
|
|
|
|
|
unsigned char Next_Rand ( unsigned int *index )
|
|
/* Go on to the next random value and return it. */
|
|
{
|
|
Next ( index );
|
|
return ad_random[ *index ];
|
|
}
|
|
|
|
|
|
void Set_AD_Delay ( int delay )
|
|
/* Sets ad_conv_delay[ all ] = delay. */
|
|
{
|
|
int i;
|
|
_Pragma( "loopbound min 6 max 6" )
|
|
for ( i = 0; i < AD_NUM_CONV; i++ )
|
|
ad_conv_delay[ i ] = delay;
|
|
}
|
|
|
|
|
|
static unsigned int ad_delay_rand = 0;
|
|
/* A roving index to randomize the A/D delays. */
|
|
|
|
|
|
void Random_AD_Delay ( void )
|
|
/* Sets random ad_conv_delay[ ]. */
|
|
{
|
|
int i;
|
|
_Pragma( "loopbound min 6 max 6" )
|
|
for ( i = 0; i < AD_NUM_CONV; i++ )
|
|
ad_conv_delay[ i ] = ( Next_Rand ( &ad_delay_rand ) % ( ADC_MAX_TRIES + 10 ) );
|
|
}
|
|
|
|
|
|
static unsigned int ad_rand_index = 0;
|
|
/* A roving index to the random A/D data. */
|
|
|
|
static unsigned int max_adc_hits = 0;
|
|
/* Maximum number of particle "hits" that may occur during
|
|
A/D conversions (in the Monitoring task, we assume).
|
|
*/
|
|
|
|
static unsigned int ad_hit_rand_index = 0;
|
|
/* A roving index to the random A/D data, for randomizing
|
|
the occurrence of "hits" during A/D conversions.
|
|
*/
|
|
|
|
static unsigned int total_adc_hits = 0;
|
|
/* The number of simulated particle "hits" during A/D conversion. */
|
|
|
|
static unsigned int ad_random_failures = 0;
|
|
/* The number of A/D conversion failures (conversion never done)
|
|
to be simulated, at random times, in the next conversions
|
|
(calls of Start_Conversion).
|
|
*/
|
|
|
|
static unsigned int ad_fail_index = 0;
|
|
/* A roving index to the random A/D data, for randomizing
|
|
the occurrence of A/D failures (conversion never done).
|
|
*/
|
|
|
|
/* See also ad_converting, declarer earlier. */
|
|
|
|
|
|
void Update_ADC_Channel_Reg ( unsigned char channel )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Update_ADC_Channel_Reg %x\n", channel );
|
|
#endif
|
|
}
|
|
|
|
|
|
static unsigned int start_conversion_count = 0;
|
|
/* Counts the number of calls of Start_Conversion. */
|
|
|
|
static uint16_t ad_value = 0;
|
|
/* Simulated ADC value, set at Start_Conversion and reported
|
|
byte by byte.
|
|
*/
|
|
|
|
|
|
void Start_Conversion ( void )
|
|
{
|
|
uint_least8_t channel;
|
|
|
|
channel = ADC_channel_register & 0x3f;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Start_Conversion on channel %d\n", channel );
|
|
#endif
|
|
|
|
if ( ad_converting != 0 ) {
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "- previous conversion did not end.\n" );
|
|
#endif
|
|
}
|
|
|
|
/* Pick an A/D reading for this channel: */
|
|
|
|
ad_value = ( ( uint16_t )Next_Rand ( &ad_rand_index ) ) << 8;
|
|
ad_value |= ( uint16_t )Next_Rand ( &ad_rand_index );
|
|
|
|
if ( ad_value < ad_limit[ channel ].min )
|
|
ad_value = ad_limit[ channel ].min;
|
|
else
|
|
if ( ad_value > ad_limit[ channel ].max )
|
|
ad_value = ad_limit[ channel ].max;
|
|
|
|
start_conversion_count ++;
|
|
|
|
ad_conv_timer = 0;
|
|
/* Normal case, may be changed below. */
|
|
|
|
ad_conv_num ++;
|
|
if ( ad_conv_num >= AD_NUM_CONV ) ad_conv_num = 0;
|
|
|
|
if ( ad_random_failures > 0 ) {
|
|
if ( Next_Rand ( &ad_fail_index ) > 0x3f ) {
|
|
/* Pretend that this conversion will fail (not end). */
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Start_Conversion starts a failing A/D conversion.\n" );
|
|
#endif
|
|
ad_conv_timer = -5000;
|
|
|
|
ad_random_failures --;
|
|
}
|
|
}
|
|
|
|
ad_converting = 1;
|
|
}
|
|
|
|
|
|
void Report_Start_Conversion_Count ( int problem )
|
|
/* Reports and then clears the count of Start_Conversion calls.
|
|
The problem parameter associates this count with a given
|
|
analysis problem for this benchmark.
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Called Start_Conversion %d times in problem %d.\n",
|
|
start_conversion_count, problem );
|
|
#endif
|
|
|
|
start_conversion_count = 0;
|
|
}
|
|
|
|
|
|
static unsigned int end_of_adc_count = 0;
|
|
/* Counts the number of calls of End_Of_ADC. */
|
|
|
|
|
|
unsigned char End_Of_ADC ( void )
|
|
/* Is the A/D conversion done, that is, ready for readout?
|
|
0 (CONVERSION_ACTIVE) means yes, any other value means no.
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "End_Of_ADC\n" );
|
|
#endif
|
|
|
|
if ( ad_converting == 0 ) {
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "- conversion not going on.\n" );
|
|
#endif
|
|
}
|
|
|
|
end_of_adc_count ++;
|
|
|
|
ad_conv_timer ++;
|
|
|
|
if ( ad_conv_timer >= ad_conv_delay[ ad_conv_num ] ) {
|
|
/* Conversion done. */
|
|
|
|
ad_converting = 0;
|
|
|
|
return 0;
|
|
} else {
|
|
/* Conversion still going on. */
|
|
|
|
/* Perhaps get a preemptive "hit": */
|
|
|
|
if ( max_adc_hits > 0 ) {
|
|
/* We have some hits in reserve. */
|
|
|
|
if ( Next_Rand ( &ad_hit_rand_index ) > 0x7f ) {
|
|
/* Hit me again, Sam. */
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Hit during A/D\n" );
|
|
#endif
|
|
confirm_hit_result = 1;
|
|
|
|
total_adc_hits ++;
|
|
max_adc_hits --;
|
|
|
|
ad_converting = 0;
|
|
|
|
return 0;
|
|
/* No point in going on. */
|
|
}
|
|
}
|
|
|
|
/* Conversion not yet finished and no hit. */
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
void Report_End_Of_ADC_Count ( int problem )
|
|
/* Reports and then clears the count of End_Of_ADC calls.
|
|
The problem parameter associates this count with a given
|
|
analysis problem for this benchmark.
|
|
*/
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Called End_Of_ADC %d times in problem %d.\n",
|
|
end_of_adc_count, problem );
|
|
#endif
|
|
|
|
end_of_adc_count = 0;
|
|
}
|
|
|
|
|
|
unsigned char Get_Result ( void )
|
|
{
|
|
unsigned char value;
|
|
|
|
/* Return the current MSB of ad_value: */
|
|
|
|
value = ( ad_value >> 8 ) & 0xff;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Get_Result %d = 0x%x\n", value, value );
|
|
#endif
|
|
|
|
/* Shift the LSB to the MSB, for next Get_Result: */
|
|
|
|
ad_value <<= 8;
|
|
|
|
return value;
|
|
}
|
|
|
|
void Set_DAC_Output ( unsigned char level )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set_DAC_Output %d\n", level );
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/* The variable ADC_channel_register is defined in health.c. */
|
|
|
|
|
|
/* Sensor Unit operations : su_ctrl.h, dpu_ctrl.h, isr_ctrl.h */
|
|
|
|
|
|
#include "su_ctrl.h"
|
|
|
|
|
|
/* Variables simulating the event sensors: */
|
|
|
|
static unsigned char hit_enabled = 0;
|
|
static unsigned char trigger_flag = 1;
|
|
static unsigned char event_flag = ACCEPT_EVENT;
|
|
static unsigned char trigger_source_0 = 0;
|
|
static unsigned char trigger_source_1 = 0;
|
|
|
|
static unsigned char msb_counter = 134;
|
|
static unsigned char lsb1_counter = 77;
|
|
static unsigned char lsb2_counter = 88;
|
|
static unsigned char rise_time_counter = 102;
|
|
|
|
static unsigned char sim_self_test = 0;
|
|
/* Whether to simulate (successful) SU Self Test. */
|
|
|
|
static unsigned char self_test_pulse = 0;
|
|
/* The level of the SU Self Test pulse. */
|
|
|
|
|
|
void Sim_Self_Test_Trigger ( void )
|
|
/* If conditions are such that a Self Test Hit Trigger should
|
|
be generated, simulate this occurrence by modifying the
|
|
SU_state for the SU being tested as the Hit Trigger ISR would do.
|
|
This supports the testing of the SU Self Test sequences in the
|
|
Monitoring task.
|
|
|
|
The simulation does not actually invoke the Hit Trigger ISR
|
|
nor does it process the Self Test event. These DEBIE functions
|
|
are tested by calling Hit Trigger ISR directly, not from the
|
|
SU Self Test sequences.
|
|
*/
|
|
{
|
|
if ( ( sim_self_test == 1 )
|
|
&& ( hit_enabled == 1 )
|
|
&& ( self_test_pulse > 0 )
|
|
&& ( self_test_SU_number != NO_SU )
|
|
&& ( SU_state[ self_test_SU_number - SU1 ] == self_test_trigger_e ) ) {
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "SU Self Test trigger!\n" );
|
|
#endif
|
|
SU_state[ self_test_SU_number - SU1 ] = self_test_e;
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned int event_rand_index = 0;
|
|
/* Roving index for ad_random, for randomizing the event data. */
|
|
|
|
|
|
void Random_Event ( void )
|
|
/* Sets random data in the event sensors. */
|
|
{
|
|
unsigned char val;
|
|
|
|
val = Next_Rand ( &event_rand_index );
|
|
|
|
trigger_flag = ( val >> 7 ) & 1;
|
|
event_flag = ( val >> 6 ) & 1;
|
|
trigger_source_0 = ( val >> 5 ) & 1;
|
|
trigger_source_1 = ( val >> 4 ) & 1;
|
|
|
|
msb_counter = Next_Rand ( &event_rand_index );
|
|
lsb1_counter = Next_Rand ( &event_rand_index );
|
|
lsb2_counter = Next_Rand ( &event_rand_index );
|
|
rise_time_counter = Next_Rand ( &event_rand_index );
|
|
}
|
|
|
|
|
|
static void Set_Trigger_SU ( sensor_index_t SU )
|
|
/* Sets the given SU in trigger_source_0/1. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set Trigger SU index %d\n", SU );
|
|
#endif
|
|
|
|
trigger_source_0 = SU & 1;
|
|
trigger_source_1 = ( SU >> 1 ) & 1;
|
|
}
|
|
|
|
|
|
void Enable_Hit_Trigger ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Enable_Hit_Trigger\n" );
|
|
#endif
|
|
hit_enabled = 1;
|
|
Sim_Self_Test_Trigger ();
|
|
}
|
|
|
|
void Disable_Hit_Trigger ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Disable_Hit_Trigger\n" );
|
|
#endif
|
|
hit_enabled = 0;
|
|
Sim_Self_Test_Trigger ();
|
|
}
|
|
|
|
|
|
unsigned char Hit_Trigger_Flag ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Hit_Trigger_Flag\n" );
|
|
#endif
|
|
return trigger_flag;
|
|
/* 1 means hit trigger ITs are enabled
|
|
0 means they are disabled.
|
|
*/
|
|
}
|
|
|
|
|
|
unsigned char Event_Flag ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Event_Flag \n" );
|
|
#endif
|
|
return event_flag;
|
|
}
|
|
|
|
|
|
unsigned char Get_MSB_Counter ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Get_MSB_Counter\n" );
|
|
#endif
|
|
return msb_counter;
|
|
}
|
|
|
|
|
|
unsigned char Get_LSB1_Counter ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Get_LSB1_Counter\n" );
|
|
#endif
|
|
return lsb1_counter;
|
|
}
|
|
|
|
|
|
unsigned char Get_LSB2_Counter ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Get_LSB2_Counter\n" );
|
|
#endif
|
|
return lsb2_counter;
|
|
}
|
|
|
|
|
|
unsigned char Rise_Time_Counter ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Rise_Time_Counter\n" );
|
|
#endif
|
|
return rise_time_counter;
|
|
}
|
|
|
|
|
|
unsigned char Trigger_Source_0 ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Trigger_Source_0\n" );
|
|
#endif
|
|
return trigger_source_0;
|
|
}
|
|
|
|
|
|
unsigned char Trigger_Source_1 ( void )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Trigger_Source_1\n" );
|
|
#endif
|
|
return trigger_source_1;
|
|
}
|
|
|
|
|
|
void Set_SU_Self_Test_Ch ( unsigned char value )
|
|
/* Set the SU Self Test Channel selectors. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set SU Self-Test Channel %x\n", value );
|
|
#endif
|
|
}
|
|
|
|
|
|
void Set_Test_Pulse_Level ( unsigned char level )
|
|
/* Set the SU Self Test pulse level. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Set SU Self-Test Pulse Level %d\n", level );
|
|
#endif
|
|
self_test_pulse = level;
|
|
Sim_Self_Test_Trigger ();
|
|
}
|
|
|
|
|
|
static unsigned int v_down_errors = 0;
|
|
/* The number of consecutive error results to
|
|
be returned from the next calls of V_Down.
|
|
*/
|
|
|
|
|
|
unsigned char V_Down ( void )
|
|
{
|
|
unsigned char result;
|
|
|
|
if ( v_down_errors > 0 ) {
|
|
result = 0; /* Bad. */
|
|
v_down_errors --;
|
|
} else
|
|
result = 1; /* Good. */
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "V_Down %d\n", result );
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void SignalPeakDetectorReset(
|
|
unsigned char low_reset_value,
|
|
unsigned char high_reset_value )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "SignalPeakDetectorReset low %d, high %d\n",
|
|
low_reset_value, high_reset_value );
|
|
#endif
|
|
}
|
|
|
|
|
|
/* The following operations are implemented in hw_if.c:
|
|
ReadDelayCounters
|
|
ReadRiseTimeCounter
|
|
ResetDelayCounters
|
|
ResetPeakDetector
|
|
SetTriggerLevel
|
|
SetTestPulseLevel
|
|
GetVoltageStatus
|
|
Switch_SU_On
|
|
Switch_SU_Off
|
|
EnableAnalogSwitch
|
|
DisableAnalogSwitch
|
|
SelectSelfTestChannel
|
|
SelectTriggerSwitchLevel
|
|
SelectStartSwitchLevel
|
|
*/
|
|
|
|
|
|
/* Accessing unaligned tm_ushort_t data */
|
|
|
|
|
|
unsigned short int Short_Value ( tm_ushort_t *x )
|
|
{
|
|
unsigned short val;
|
|
wcc_memcpy ( &val, x, sizeof ( val ) );
|
|
return val;
|
|
}
|
|
|
|
|
|
/* "Calling" a "patch function" */
|
|
|
|
|
|
void Call_Patch ( fptr_t func )
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Call_Patch 0x%x\n", ( code_address_t )func );
|
|
#endif
|
|
}
|
|
|
|
|
|
/* Checking the sizes of some types */
|
|
|
|
#include "tm_data.h"
|
|
|
|
static volatile uint_least8_t tsize_s;
|
|
static volatile uint_least16_t tsize_l;
|
|
|
|
void Check_Type_Size ( void )
|
|
/*
|
|
Disassemble the code of this function to see the sizes of
|
|
the types char, short, ..., science_data_file_t.
|
|
This function is never called.
|
|
|
|
*/
|
|
{
|
|
tsize_s = sizeof ( char );
|
|
tsize_s = sizeof ( short );
|
|
tsize_s = sizeof ( int );
|
|
tsize_s = sizeof ( long );
|
|
|
|
tsize_s = sizeof ( tm_ushort_t );
|
|
tsize_s = sizeof ( dpu_time_t );
|
|
tsize_s = sizeof ( tm_dpu_time_t );
|
|
tsize_s = sizeof ( SU_settings_t );
|
|
tsize_s = sizeof ( telemetry_data_t );
|
|
|
|
tsize_s = sizeof ( event_record_t );
|
|
tsize_l = sizeof ( science_data_file_t );
|
|
}
|
|
|
|
|
|
/* Test scenarios */
|
|
|
|
/*
|
|
These test cases are not intended as a full functional test.
|
|
They are intended to provide sufficient coverage for measurement-
|
|
based WCET analysis of the tested code. Built-in checks of test
|
|
execution (program state) are used only to check that the DEBIE
|
|
software has done the expected thing in each test case, but the
|
|
checks are definitely not exhaustive.
|
|
|
|
Each test cases contributes measurements towards one of the
|
|
"analysis problems" defined for this benchmark. The macro
|
|
FOR_PROBLEM(P) is defined in problems.h and marks the start of
|
|
a test case to be included in problem P. Here P is an integer
|
|
number that identifies the analysis problem as follows:
|
|
|
|
P Problem
|
|
-- -------
|
|
10 1 : TC interrupt handler
|
|
21 2a: TM interrupt handler, most common case
|
|
22 2b: TM interrupt handler, send internal time register
|
|
23 2c: TM interrupt handler, end of TM
|
|
31 3a: Hit Trigger interrupt handler, no ADC errors
|
|
32 3b: Hit Trigger interrupt handler, at most one ADC error
|
|
33 3c: Hit Trigger interrupt handler, any number of ADC errors
|
|
41 4a: TC Execution task, general case
|
|
42 4b: TC Execution task, start TC buffering, MSB
|
|
43 4c: TC Execution task, start TC buffering, LSB
|
|
44 4d: TC Execution task, buffer TC word
|
|
51 5a: Acquisition task, science data not full
|
|
52 5b: Acquisition task, science data full
|
|
61 6a: Monitoring task, no hits or errors
|
|
62 6b: Monitoring task, one hit during A/D conversion
|
|
63 6c: Monitoring task, many hits during A/D conversion
|
|
64 6d: Monitoring task, some SU error detected
|
|
65 6e: Monitoring task, any number of hits and errors
|
|
|
|
The macro END_PROBLEM is also defined in problems.h and marks
|
|
the end of execution of a case belonging to the problem named
|
|
by the most recently executed FOR_PROBLEM. Note that more cases
|
|
for the same problem can be added later with another FOR_PROBLEM.
|
|
*/
|
|
|
|
#define Prob1 10
|
|
|
|
#define Prob2a 21
|
|
#define Prob2b 22
|
|
#define Prob2c 23
|
|
|
|
#define Prob3a 31
|
|
#define Prob3b 32
|
|
#define Prob3c 33
|
|
|
|
#define Prob4a 41
|
|
#define Prob4b 42
|
|
#define Prob4c 43
|
|
#define Prob4d 44
|
|
|
|
#define Prob5a 51
|
|
#define Prob5b 52
|
|
|
|
#define Prob6a 61
|
|
#define Prob6b 62
|
|
#define Prob6c 63
|
|
#define Prob6d 64
|
|
#define Prob6e 65
|
|
|
|
#include "problems.h"
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
#define CASE(TXT) printf ("\nCASE: %s:\n\n", TXT)
|
|
#else
|
|
#define CASE(TXT)
|
|
#endif
|
|
|
|
|
|
static int checks = 0;
|
|
/* Counts the number of checks done in Check/Zero/Nonzero. */
|
|
|
|
static int check_errors = 0;
|
|
/* Counts the number of errors found in Check/Zero/Nonzero. */
|
|
|
|
|
|
static void Report_Checks ( void )
|
|
/* Print number of checks and check-errors. */
|
|
{
|
|
TARGET_MARK;
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Total checks done %d, failed %d\n", checks, check_errors );
|
|
#endif
|
|
}
|
|
|
|
|
|
static void Fail_Check ( char *message )
|
|
/* Reports a failed check. */
|
|
{
|
|
check_errors ++;
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "%s: FAILED (#%d)\n", message, check_errors );
|
|
#endif
|
|
}
|
|
|
|
|
|
static void Check_Zero ( int cond )
|
|
/* Checks that cond == 0. */
|
|
{
|
|
checks ++;
|
|
if ( cond )
|
|
Fail_Check( "Check_Zero" );
|
|
}
|
|
|
|
|
|
static void Check_Nonzero ( int cond )
|
|
/* Checks that cond != 0. */
|
|
{
|
|
checks ++;
|
|
if ( cond == 0 )
|
|
Fail_Check ( "Check_Nonzero" );
|
|
}
|
|
|
|
|
|
#define Check Check_Nonzero
|
|
/* Check that the (boolean) parameter is true (not zero). */
|
|
|
|
|
|
static void Check_No_Errors ( void )
|
|
/* Checks that no errors are flagged in telemetry_data.error_status. */
|
|
{
|
|
Check_Zero ( telemetry_data.error_status );
|
|
}
|
|
|
|
|
|
static void TC_Interrupt ( void )
|
|
/* Runs the TC Interrupt Service. */
|
|
{
|
|
FOR_PROBLEM( Prob1 );
|
|
TC_InterruptService();
|
|
END_PROBLEM;
|
|
}
|
|
|
|
|
|
static void Send_TC ( unsigned char address, unsigned char code )
|
|
/* Invokes TC_InterruptService with a TC composed of the
|
|
given address and code, provided with valid (even) parity.
|
|
*/
|
|
{
|
|
unsigned char par;
|
|
/* The parity. */
|
|
|
|
/* Encode the address and code in the TC interface registers: */
|
|
|
|
tc_msb = address << 1;
|
|
tc_lsb = code;
|
|
|
|
/* Generate the even parity bit: */
|
|
|
|
par = tc_msb ^ tc_lsb;
|
|
par = ( par & 0x0F ) ^ ( par >> 4 );
|
|
par = ( par & 0x03 ) ^ ( par >> 2 );
|
|
par = ( par & 0x01 ) ^ ( par >> 1 );
|
|
|
|
tc_msb |= par;
|
|
|
|
tc_word = ( tc_msb << 8 ) | tc_lsb;
|
|
|
|
/* Invoke the TC ISR: */
|
|
|
|
tc_timer_overflow = 1;
|
|
|
|
TC_Interrupt ();
|
|
}
|
|
|
|
|
|
static void Send_TC_Word ( uint_least16_t word )
|
|
/* Invokes TC_InterruptService with the given TC word,
|
|
exactly as given.
|
|
*/
|
|
{
|
|
/* Set the high and low TC bytes: */
|
|
|
|
tc_msb = ( word >> 8 ) & 0xff;
|
|
tc_lsb = word & 0xff;
|
|
|
|
tc_word = ( tc_msb << 8 ) | tc_lsb;
|
|
|
|
/* Invoke the TC ISR: */
|
|
|
|
tc_timer_overflow = 1;
|
|
|
|
TC_Interrupt ();
|
|
}
|
|
|
|
static void TC_ISR_Tests ( void )
|
|
/* Test of TC_InterruptService. */
|
|
{
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "\nTC_ISR_Tests\n" );
|
|
#endif
|
|
|
|
CASE( "TC rejected because timer overflow is not set" );
|
|
|
|
tc_timer_overflow = 0;
|
|
TC_Interrupt ();
|
|
|
|
CASE( "TC rejected because TC_state is SC_TM_e" );
|
|
|
|
TC_state = SC_TM_e;
|
|
Send_TC ( 0, 0 );
|
|
|
|
CASE( "TC rejected because TC_state is memory_dump_e" );
|
|
|
|
TC_state = memory_dump_e;
|
|
Send_TC ( 0, 0 );
|
|
|
|
CASE( "TC in TC_state = memory_patch_e" );
|
|
|
|
TC_state = memory_patch_e;
|
|
Send_TC ( 0, 0 );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 1 );
|
|
FlushMail ( TCTM_MAILBOX );
|
|
|
|
CASE( "TC with parity error" );
|
|
|
|
TC_state = TC_handling_e;
|
|
tc_timer_overflow = 1;
|
|
tc_msb = 0;
|
|
tc_lsb = 1;
|
|
tc_word = 1;
|
|
TC_Interrupt ();
|
|
|
|
Check_Nonzero ( telemetry_data.error_status & PARITY_ERROR );
|
|
|
|
CASE( "TC = ERROR_STATUS_CLEAR, ok" );
|
|
|
|
Send_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR );
|
|
|
|
/* The parity-error flag is not yet reset, because */
|
|
/* the TC was not yet executed: */
|
|
|
|
Check_Nonzero ( telemetry_data.error_status & PARITY_ERROR );
|
|
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 1 );
|
|
FlushMail ( TCTM_MAILBOX );
|
|
|
|
/* Clear the error manually: */
|
|
|
|
telemetry_data.error_status = 0;
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC = SEND_STATUS_REGISTER, ok" );
|
|
|
|
Send_TC ( SEND_STATUS_REGISTER, 8 );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == register_TM_e );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 1 );
|
|
FlushMail ( TCTM_MAILBOX );
|
|
|
|
|
|
CASE( "TC type ALL_INVALID" );
|
|
|
|
/* An invalid TC code: */
|
|
|
|
Send_TC ( 4, 4 );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
telemetry_data.error_status = 0;
|
|
|
|
CASE( "TC type ONLY_EQUAL, fail" );
|
|
|
|
Send_TC ( ERROR_STATUS_CLEAR, ~ERROR_STATUS_CLEAR );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
telemetry_data.error_status = 0;
|
|
|
|
CASE ( "TC type ON_OFF_TC, fail" );
|
|
|
|
/* Neither ON_VALUE nor OFF_VALUE nor SELF_TEST. */
|
|
|
|
Send_TC ( SWITCH_SU_3, 0x3F );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
telemetry_data.error_status = 0;
|
|
|
|
CASE ( "TC type ONLY_EVEN, fail (odd)" );
|
|
|
|
Send_TC ( SEND_STATUS_REGISTER, 5 );
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
telemetry_data.error_status = 0;
|
|
|
|
CASE ( "TC type ONLY_EVEN, fail (too large)" );
|
|
|
|
Send_TC ( SEND_STATUS_REGISTER, LAST_EVEN + 2 );
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
telemetry_data.error_status = 0;
|
|
|
|
|
|
/* Other tests of TC ISR:
|
|
TC in TC_state = register_TM_e: See TM_Tests.
|
|
*/
|
|
}
|
|
|
|
|
|
static void Handle_TC ( int problem )
|
|
/* Checks that the TC mailbox has a message, then invokes
|
|
HandleTelecommand to handle (usually, execute) the message.
|
|
The problem parameter shows in which analysis problem the
|
|
HandleTelecommand should be included.
|
|
*/
|
|
{
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 1 );
|
|
|
|
FOR_PROBLEM( problem );
|
|
HandleTelecommand ();
|
|
END_PROBLEM;
|
|
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
}
|
|
|
|
|
|
static void Exec_TC (
|
|
unsigned char address, unsigned char code,
|
|
int problem )
|
|
/* Invokes TC_InterruptService with a TC composed of the
|
|
given address and code, provided with valid (even) parity,
|
|
then invokes HandleTelecommand to execute the TC.
|
|
The problem parameter shows in which analysis problem the
|
|
HandleTelecommand should be included.
|
|
*/
|
|
{
|
|
Send_TC ( address, code );
|
|
Handle_TC ( problem );
|
|
}
|
|
|
|
|
|
static void Send_Patch_Code (
|
|
uint16_t address,
|
|
unsigned char *checksum )
|
|
/* Sends the multi-word TC to patch code memory at the given address,
|
|
with some arbitary contents. Returns the checksum of the patch,
|
|
for use in the final word of the TC, which is not sent here.
|
|
*/
|
|
{
|
|
uint_least8_t i;
|
|
unsigned char sum;
|
|
|
|
/* Send the patch address: */
|
|
|
|
Exec_TC ( WRITE_CODE_MEMORY_MSB, ( address >> 8 ) & 0xff, Prob4b );
|
|
|
|
sum = ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == write_memory_e );
|
|
|
|
Exec_TC ( WRITE_CODE_MEMORY_LSB, address & 0xff, Prob4c );
|
|
|
|
sum ^= ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == memory_patch_e );
|
|
|
|
/* Send the patch contents, 16 words = 32 octets: */
|
|
|
|
_Pragma( "loopbound min 16 max 16" )
|
|
for ( i = 0; i < 16; i++ ) {
|
|
Send_TC_Word ( ( ( uint_least16_t ) i ) << 6 );
|
|
sum ^= ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
Handle_TC ( Prob4d );
|
|
}
|
|
|
|
/* The last word remains to be sent. */
|
|
|
|
*checksum = sum;
|
|
}
|
|
|
|
|
|
static void Send_Patch_Data (
|
|
uint16_t address,
|
|
unsigned char *checksum )
|
|
/* Sends the multi-word TC to patch data memory at the given address,
|
|
with some arbitary contents. Returns the checksum of the patch,
|
|
for use in the final word of the TC, which is not sent here.
|
|
*/
|
|
{
|
|
uint_least8_t i;
|
|
unsigned char sum;
|
|
|
|
/* Send the patch address: */
|
|
|
|
Exec_TC ( WRITE_DATA_MEMORY_MSB, ( address >> 8 ) & 0xff, Prob4b );
|
|
|
|
sum = ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == write_memory_e );
|
|
|
|
Exec_TC ( WRITE_DATA_MEMORY_LSB, address & 0xff, Prob4c );
|
|
|
|
sum ^= ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == memory_patch_e );
|
|
|
|
/* Send the patch contents, 16 words = 32 octets: */
|
|
|
|
_Pragma( "loopbound min 16 max 16" )
|
|
for ( i = 0; i < 16; i++ ) {
|
|
Send_TC_Word ( ( ( uint_least16_t ) i ) << 6 );
|
|
sum ^= ( tc_word >> 8 ) ^ ( tc_word & 0xff );
|
|
Handle_TC ( Prob4d );
|
|
}
|
|
|
|
/* The last word remains to be sent. */
|
|
|
|
*checksum = sum;
|
|
}
|
|
|
|
|
|
static void Read_Data_Memory ( uint16_t address )
|
|
/* Sends the TC to read 32 octets of data memory, starting at
|
|
the given address, receives the corresponding TM block, and
|
|
handles the TM_READY message to the TC Execution task.
|
|
*/
|
|
{
|
|
uint_least8_t i;
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_MSB, ( address >> 8 ) & 0xff, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == read_memory_e );
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_LSB, address & 0xff, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == memory_dump_e );
|
|
|
|
/* The 16 first words of data: */
|
|
|
|
_Pragma( "loopbound min 16 max 16" )
|
|
for ( i = 0; i < 16; i++ ) {
|
|
Check ( telemetry_pointer < telemetry_end_pointer );
|
|
|
|
/* The first TM IT, below, acknowledges the immediate TC
|
|
response and transmits the first data word.
|
|
*/
|
|
|
|
FOR_PROBLEM( Prob2a );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
|
|
Check ( TC_state == memory_dump_e );
|
|
}
|
|
|
|
/* The last word, with the checksum: */
|
|
|
|
Check ( telemetry_pointer == telemetry_end_pointer );
|
|
|
|
/* The TM IT below acknowledges the last data word and
|
|
transmits the very last word of the Read Data Memory
|
|
sequence, containing the data checksum.
|
|
*/
|
|
|
|
FOR_PROBLEM( Prob2c );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
|
|
/* The TM_READY message: */
|
|
|
|
Handle_TC ( Prob1 );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
/* There is a design error in TM_InterruptService:
|
|
when the Read Data Memory sequence ends, with the
|
|
transmission of the checksum word, the TM IT is
|
|
left enabled. If the TC Execution task does not
|
|
react quickly to the TM_READY message, and disable
|
|
the TM IT before the transmission of the checksum
|
|
word is completed, a new TM IT can invoke
|
|
TM_InterruptService once again, sending the checksum
|
|
word a second time, and perhaps a third time etc.
|
|
*/
|
|
}
|
|
|
|
|
|
void Clear_Errors ( void )
|
|
/* Executes the ERROR_STATUS_CLEAR TC. */
|
|
{
|
|
Exec_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
}
|
|
|
|
|
|
static void TC_Task_Tests ( void )
|
|
/* Test of TelecommandExecutionTask. */
|
|
{
|
|
unsigned char chsum;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "\nTC_Task_Tests\n" );
|
|
#endif
|
|
|
|
CASE( "TC = ERROR_STATUS_CLEAR, ok" );
|
|
|
|
/* Flag an error manually: */
|
|
telemetry_data.error_status = PARITY_ERROR;
|
|
|
|
Send_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR );
|
|
|
|
/* The parity-error flag is not yet reset, because */
|
|
/* the TC was not yet executed: */
|
|
|
|
Check_Nonzero ( telemetry_data.error_status & PARITY_ERROR );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
/* Now the parity-error flag is reset: */
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC to set SU parameters" );
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1P_THRESHOLD, 23, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1P_THRESHOLD, 26, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1P_THRESHOLD, 32, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1P_THRESHOLD, 102, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1M_THRESHOLD, 205, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1M_THRESHOLD, 123, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1M_THRESHOLD, 99, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1M_THRESHOLD, 1, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PIEZO_THRESHOLD, 14, Prob4a );
|
|
Exec_TC ( SET_SU_2_PIEZO_THRESHOLD, 54, Prob4a );
|
|
Exec_TC ( SET_SU_3_PIEZO_THRESHOLD, 74, Prob4a );
|
|
Exec_TC ( SET_SU_4_PIEZO_THRESHOLD, 104, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1P_CLASS_LEVEL, 104, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1P_CLASS_LEVEL, 204, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1P_CLASS_LEVEL, 214, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1P_CLASS_LEVEL, 234, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1M_CLASS_LEVEL, 104, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1M_CLASS_LEVEL, 88, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1M_CLASS_LEVEL, 66, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1M_CLASS_LEVEL, 33, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_2P_CLASS_LEVEL, 61, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_2P_CLASS_LEVEL, 21, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_2P_CLASS_LEVEL, 81, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_2P_CLASS_LEVEL, 11, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PIEZO_1_CLASS_LEVEL, 14, Prob4a );
|
|
Exec_TC ( SET_SU_2_PIEZO_1_CLASS_LEVEL, 24, Prob4a );
|
|
Exec_TC ( SET_SU_3_PIEZO_1_CLASS_LEVEL, 33, Prob4a );
|
|
Exec_TC ( SET_SU_4_PIEZO_1_CLASS_LEVEL, 77, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PIEZO_2_CLASS_LEVEL, 14, Prob4a );
|
|
Exec_TC ( SET_SU_2_PIEZO_2_CLASS_LEVEL, 14, Prob4a );
|
|
Exec_TC ( SET_SU_3_PIEZO_2_CLASS_LEVEL, 14, Prob4a );
|
|
Exec_TC ( SET_SU_4_PIEZO_2_CLASS_LEVEL, 14, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1E_1I_MAX_TIME, 191, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1E_1I_MAX_TIME, 171, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1E_1I_MAX_TIME, 161, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1E_1I_MAX_TIME, 151, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1E_PZT_MIN_TIME, 11, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1E_PZT_MIN_TIME, 22, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1E_PZT_MIN_TIME, 33, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1E_PZT_MIN_TIME, 44, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1E_PZT_MAX_TIME, 111, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1E_PZT_MAX_TIME, 122, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1E_PZT_MAX_TIME, 133, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1E_PZT_MAX_TIME, 144, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1I_PZT_MIN_TIME, 11, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1I_PZT_MIN_TIME, 10, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1I_PZT_MIN_TIME, 9, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1I_PZT_MIN_TIME, 8, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_SU_1_PLASMA_1I_PZT_MAX_TIME, 211, Prob4a );
|
|
Exec_TC ( SET_SU_2_PLASMA_1I_PZT_MAX_TIME, 210, Prob4a );
|
|
Exec_TC ( SET_SU_3_PLASMA_1I_PZT_MAX_TIME, 209, Prob4a );
|
|
Exec_TC ( SET_SU_4_PLASMA_1I_PZT_MAX_TIME, 208, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC to set classification coefficients" );
|
|
|
|
Exec_TC ( SET_COEFFICIENT_1, 1, Prob4a );
|
|
Exec_TC ( SET_COEFFICIENT_2, 2, Prob4a );
|
|
Exec_TC ( SET_COEFFICIENT_3, 3, Prob4a );
|
|
Exec_TC ( SET_COEFFICIENT_4, 4, Prob4a );
|
|
Exec_TC ( SET_COEFFICIENT_5, 5, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC to patch code memory, call patch" );
|
|
|
|
Send_Patch_Code ( 0x1100, &chsum );
|
|
|
|
chsum ^= 0x5A; /* Call patch function. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x5A00 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
CASE( "TC to patch code memory, no action" );
|
|
|
|
Send_Patch_Code ( 0x1300, &chsum );
|
|
|
|
chsum ^= 0x00; /* No action. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x0000 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
CASE( "TC to patch code memory, soft reset" );
|
|
|
|
Send_Patch_Code ( 0x1400, &chsum );
|
|
|
|
chsum ^= 0x09; /* Sof Reset. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x0900 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
CASE( "TC to patch code memory, warm reset" );
|
|
|
|
Send_Patch_Code ( 0x2100, &chsum );
|
|
|
|
chsum ^= 0x37; /* Soft Reset. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x3700 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
CASE( "TC to patch code memory, invalid action" );
|
|
|
|
Send_Patch_Code ( 0x2400, &chsum );
|
|
|
|
chsum ^= 0x62; /* Invalid. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x6200 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch code memory, invalid address" );
|
|
|
|
Send_Patch_Code ( 0x0fff, &chsum );
|
|
|
|
chsum ^= 0x00; /* No action. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x0000 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch code memory, checksum error" );
|
|
|
|
Send_Patch_Code ( 0x1200, &chsum );
|
|
|
|
chsum ^= 0x5A; /* Correct checksum. */
|
|
chsum ^= 0xff; /* Wrong checksum. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x5A00 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Nonzero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch code, TC sequence error at first word" );
|
|
|
|
Exec_TC ( WRITE_CODE_MEMORY_LSB, 0x32, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch code, TC sequence error at second word" );
|
|
|
|
Exec_TC ( WRITE_CODE_MEMORY_MSB, 0x32, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == write_memory_e );
|
|
|
|
Exec_TC ( CLEAR_WATCHDOG_FAILURES, CLEAR_WATCHDOG_FAILURES, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch data memory" );
|
|
|
|
Send_Patch_Data ( 0x2200, &chsum );
|
|
|
|
chsum ^= 0x11; /* Irrelevant for data patch. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x1100 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
CASE( "TC to patch data memory, address error" );
|
|
|
|
Send_Patch_Data ( 0xfef0, &chsum );
|
|
|
|
chsum ^= 0x11; /* Irrelevant for data patch. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x1100 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch data memory, TC sequence error at first word" );
|
|
|
|
Exec_TC ( WRITE_DATA_MEMORY_LSB, 0x32, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch data memory, TC sequence error at second word" );
|
|
|
|
Exec_TC ( WRITE_DATA_MEMORY_MSB, 0x32, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == write_memory_e );
|
|
|
|
Exec_TC ( CLEAR_WATCHDOG_FAILURES, CLEAR_WATCHDOG_FAILURES, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch data memory, checksum error" );
|
|
|
|
Send_Patch_Data ( 0x2300, &chsum );
|
|
|
|
chsum ^= 0x11; /* Correct checksum. */
|
|
chsum ^= 0xff; /* Wrong checksum. */
|
|
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Send_TC_Word ( 0x1100 | chsum );
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_Nonzero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to patch data memory, time-out on TC word reception" );
|
|
|
|
Send_Patch_Data ( 0x2200, &chsum );
|
|
|
|
chsum ^= 0x11; /* Irrelevant for data patch. */
|
|
|
|
Check ( TC_state == memory_patch_e );
|
|
Check_Zero ( telemetry_data.mode_status & MEMORY_WRITE_ERROR );
|
|
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
|
|
/* Empty mailbox => WaitMail signals "time-out". */
|
|
|
|
FOR_PROBLEM( Prob4a );
|
|
HandleTelecommand ();
|
|
END_PROBLEM;
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC timeout during TC handling, normal" );
|
|
|
|
Check ( mail_count[ TCTM_MAILBOX ] == 0 );
|
|
|
|
/* Empty mailbox => WaitMail signals "time-out". */
|
|
|
|
FOR_PROBLEM( Prob4a );
|
|
HandleTelecommand ();
|
|
END_PROBLEM;
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC to read data memory" );
|
|
|
|
Read_Data_Memory ( 0x2041 );
|
|
|
|
CASE( "TC to read data memory, address error" );
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_MSB, 0xfe, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == read_memory_e );
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_LSB, 0xf0, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to read data memory, TC sequence error at first word" );
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_LSB, 0xfe, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to read data memory, TC sequence error at second word" );
|
|
|
|
Exec_TC ( READ_DATA_MEMORY_MSB, 0xab, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == read_memory_e );
|
|
|
|
Exec_TC ( CLEAR_WATCHDOG_FAILURES, CLEAR_WATCHDOG_FAILURES, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC = CLEAR_WATCHDOG_FAILURES" );
|
|
|
|
telemetry_data.watchdog_failures = 3;
|
|
|
|
Exec_TC ( CLEAR_WATCHDOG_FAILURES, CLEAR_WATCHDOG_FAILURES, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check_Zero ( telemetry_data.watchdog_failures );
|
|
|
|
CASE( "TC = CLEAR_CHECKSUM_FAILURES" );
|
|
|
|
telemetry_data.checksum_failures = 9;
|
|
|
|
Exec_TC ( CLEAR_CHECKSUM_FAILURES, CLEAR_CHECKSUM_FAILURES, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check_Zero ( telemetry_data.checksum_failures );
|
|
|
|
CASE( "TC to set DEBIE time" );
|
|
|
|
Exec_TC ( SET_TIME_BYTE_3, 0x44, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_2, 0x33, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_1, 0x22, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_0, 0x11, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Check ( internal_time == 0x44332211 );
|
|
|
|
CASE( "TC to set DEBIE time, sequence error at byte 2" );
|
|
|
|
internal_time = 0x01122334;
|
|
|
|
Exec_TC ( SET_TIME_BYTE_3, 0x44, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_1, 0x33, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check ( internal_time == 0x44000000 );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to set DEBIE time, sequence error at byte 1" );
|
|
|
|
internal_time = 0x01122334;
|
|
|
|
Exec_TC ( SET_TIME_BYTE_3, 0x44, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_2, 0x33, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_0, 0x22, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check ( internal_time == 0x44330000 );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC to set DEBIE time, sequence error at byte 0" );
|
|
|
|
internal_time = 0x01122334;
|
|
|
|
Exec_TC ( SET_TIME_BYTE_3, 0x44, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_2, 0x33, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_1, 0x22, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SET_TIME_BYTE_2, 0x11, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check ( internal_time == 0x44332200 );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC = SOFT_RESET" );
|
|
|
|
Exec_TC ( SOFT_RESET, SOFT_RESET, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "TC = STOP_ACQUISITION in STAND_BY, fail" );
|
|
|
|
Check ( GetMode() == STAND_BY );
|
|
|
|
Exec_TC ( STOP_ACQUISITION, STOP_ACQUISITION, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
Check ( GetMode() == STAND_BY );
|
|
|
|
Clear_Errors ();
|
|
|
|
/* Telecommands tested elsewhere:
|
|
|
|
ERROR_STATUS_CLEAR See TC_ISR_Tests, TM_Tests, others.
|
|
SEND_STATUS_REGISTER See TM_Tests.
|
|
SEND_SCIENCE_DATA_FILE See TM_Tests, Acquisition_Tests.
|
|
START_ACQUISITION See Acquisition_Tests.
|
|
STOP_ACQUISITION See Acquisition_Tests.
|
|
SWITCH_SU_1/2/3/4 See Acquisition_Tests, SU_Self_Test_Tests.
|
|
TM_READY message See TM_Tests.
|
|
*/
|
|
}
|
|
|
|
|
|
void Monitor_Health ( int problem )
|
|
/* Executes HandleHealthMonitoring for a particular analysis problem. */
|
|
{
|
|
start_conversion_count = 0;
|
|
end_of_adc_count = 0;
|
|
|
|
FOR_PROBLEM( problem );
|
|
HandleHealthMonitoring();
|
|
END_PROBLEM;
|
|
|
|
Report_Start_Conversion_Count ( problem );
|
|
Report_End_Of_ADC_Count ( problem );
|
|
}
|
|
|
|
|
|
void Monitoring_Task_Tests ( void )
|
|
/* Tests of the Health Monitoring task. */
|
|
{
|
|
int sec;
|
|
int tot_errors, max_errors = 20;
|
|
|
|
/* Reset all cycles: */
|
|
|
|
health_mon_round = HEALTH_COUNT ;
|
|
temp_meas_count = TEMP_COUNT ;
|
|
voltage_meas_count = VOLTAGE_COUNT;
|
|
checksum_count = CHECK_COUNT ;
|
|
|
|
Set_AD_Nominal ();
|
|
/* To avoid monitoring alarms. */
|
|
|
|
CASE( "Monitoring without errors or interrupting hits" );
|
|
|
|
/* A/D conversions ready on second poll: */
|
|
Set_AD_Delay ( 2 );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT );
|
|
Check ( temp_meas_count == TEMP_COUNT );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT );
|
|
Check ( checksum_count == CHECK_COUNT );
|
|
|
|
/* The first 9 seconds: */
|
|
|
|
_Pragma( "loopbound min 9 max 9" )
|
|
for ( sec = 1; sec <= 9; sec ++ ) {
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT - sec );
|
|
Check ( temp_meas_count == TEMP_COUNT );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT );
|
|
Check ( checksum_count == CHECK_COUNT - sec );
|
|
}
|
|
|
|
/* The 10th second: */
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT );
|
|
Check ( temp_meas_count == TEMP_COUNT - 1 );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT - 1 );
|
|
Check ( checksum_count == CHECK_COUNT - 10 );
|
|
|
|
/* The remaining 170 seconds of the full period: */
|
|
|
|
_Pragma( "loopbound min 170 max 170" )
|
|
for ( sec = 11; sec <= 180; sec ++ )
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT );
|
|
Check ( temp_meas_count == TEMP_COUNT );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT );
|
|
Check ( checksum_count == CHECK_COUNT );
|
|
|
|
Check_No_Errors ();
|
|
|
|
|
|
CASE( "Monitoring without errors, at most one interrupting hit" );
|
|
|
|
total_adc_hits = 0;
|
|
|
|
_Pragma( "loopbound min 180 max 180" )
|
|
for ( sec = 1; sec <= 180; sec ++ ) {
|
|
max_adc_hits = 1;
|
|
Monitor_Health ( Prob6b );
|
|
}
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Total hits %d\n", total_adc_hits );
|
|
#endif
|
|
|
|
Check_Nonzero ( total_adc_hits );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT );
|
|
Check ( temp_meas_count == TEMP_COUNT );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT );
|
|
Check ( checksum_count == CHECK_COUNT );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Monitoring without errors, many interrupting hits" );
|
|
|
|
total_adc_hits = 0;
|
|
|
|
_Pragma( "loopbound min 180 max 180" )
|
|
for ( sec = 1; sec <= 180; sec ++ ) {
|
|
max_adc_hits = HIT_BUDGET_DEFAULT;
|
|
Monitor_Health ( Prob6c );
|
|
}
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Total hits %d\n", total_adc_hits );
|
|
#endif
|
|
|
|
Check_Nonzero ( total_adc_hits );
|
|
|
|
Check ( health_mon_round == HEALTH_COUNT );
|
|
Check ( temp_meas_count == TEMP_COUNT );
|
|
Check ( voltage_meas_count == VOLTAGE_COUNT );
|
|
Check ( checksum_count == CHECK_COUNT );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Monitoring with SU errors, no interrupting hits" );
|
|
|
|
Set_AD_Unlimited ();
|
|
max_adc_hits = 0;
|
|
|
|
tot_errors = 0;
|
|
|
|
_Pragma( "loopbound min 106 max 106" )
|
|
do {
|
|
if ( tot_errors == 4 ) check_current_errors = 5;
|
|
|
|
if ( tot_errors == max_errors - 1 ) v_down_errors = 1;
|
|
/* The V_DOWN error has a dramatic effect, so
|
|
we save it for last.
|
|
*/
|
|
|
|
_Pragma( "loopbound min 180 max 180" )
|
|
for ( sec = 1; sec <= 180; sec ++ )
|
|
Monitor_Health ( Prob6d );
|
|
|
|
if ( telemetry_data.error_status != 0 ) {
|
|
tot_errors ++;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Monitoring (6d) error %d, error status %x\n",
|
|
tot_errors, telemetry_data.error_status );
|
|
#endif
|
|
Clear_Errors ();
|
|
}
|
|
} while ( tot_errors < max_errors );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Monitoring with any kind of error and interrupting hit" );
|
|
|
|
Set_AD_Unlimited ();
|
|
|
|
tot_errors = 0;
|
|
|
|
_Pragma( "loopbound min 64 max 64" )
|
|
do {
|
|
if ( tot_errors == 4 ) check_current_errors = 5;
|
|
|
|
if ( tot_errors == max_errors - 1 ) v_down_errors = 1;
|
|
/* The V_DOWN error has a dramatic effect, so
|
|
we save it for last.
|
|
*/
|
|
|
|
_Pragma( "loopbound min 180 max 180" )
|
|
for ( sec = 1; sec <= 180; sec ++ ) {
|
|
max_adc_hits = HIT_BUDGET_DEFAULT;
|
|
if ( sec > 2 * tot_errors ) ad_random_failures = 2;
|
|
Monitor_Health ( Prob6e );
|
|
}
|
|
|
|
if ( telemetry_data.error_status != 0 ) {
|
|
tot_errors ++;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Monitoring (6e) error %d, error status %x\n",
|
|
tot_errors, telemetry_data.error_status );
|
|
#endif
|
|
Clear_Errors ();
|
|
}
|
|
} while ( tot_errors < max_errors );
|
|
|
|
Check_No_Errors ();
|
|
}
|
|
|
|
|
|
void TM_Tests ( void )
|
|
/* Test of TM_InterruptService and telemetry functionality. */
|
|
{
|
|
int octets;
|
|
/* Number of octets sent and acknowledge by TM interrupt. */
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "\nTM_ISR_Tests\n" );
|
|
#endif
|
|
|
|
CASE( "One whole round of register TM" );
|
|
|
|
Send_TC ( SEND_STATUS_REGISTER, 0 );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == register_TM_e );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == register_TM_e );
|
|
|
|
_Pragma( "loopbound min 62 max 62" )
|
|
for ( octets = 0; octets < sizeof ( telemetry_data_t ); octets += 2 ) {
|
|
|
|
if ( telemetry_pointer != ( unsigned char * ) &telemetry_data.time ) {
|
|
FOR_PROBLEM( Prob2a );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
} else {
|
|
FOR_PROBLEM( Prob2b );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
}
|
|
|
|
Check ( TC_state == register_TM_e );
|
|
}
|
|
|
|
CASE( "Partial register TM, stop by TC" );
|
|
|
|
Send_TC ( SEND_STATUS_REGISTER, 22 );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == register_TM_e );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == register_TM_e );
|
|
|
|
_Pragma( "loopbound min 20 max 20" )
|
|
for ( octets = 0; octets < 40; octets += 2 ) {
|
|
|
|
if ( telemetry_pointer != ( unsigned char * ) &telemetry_data.time ) {
|
|
FOR_PROBLEM( Prob2a );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
} else {
|
|
FOR_PROBLEM( Prob2b );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
}
|
|
|
|
Check ( TC_state == register_TM_e );
|
|
}
|
|
|
|
Send_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR );
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Science Data TM" );
|
|
|
|
Send_TC ( SEND_SCIENCE_DATA_FILE, SEND_SCIENCE_DATA_FILE );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == SC_TM_e );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == SC_TM_e );
|
|
|
|
/* Absorb TM until a TM_READY message is sent to the TC task: */
|
|
|
|
octets = 0;
|
|
|
|
_Pragma( "loopbound min 22 max 22" )
|
|
while ( mail_count[ TCTM_MAILBOX ] == 0 ) {
|
|
if ( telemetry_pointer < telemetry_end_pointer ) {
|
|
FOR_PROBLEM( Prob2a );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
} else {
|
|
FOR_PROBLEM( Prob2c );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
}
|
|
|
|
octets += 2;
|
|
Check ( TC_state == SC_TM_e );
|
|
}
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Science TM octets sent %d\n", octets );
|
|
#endif
|
|
|
|
/* Handle the TM_READY message: */
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
/* TM tests elsewhere:
|
|
End of memory-dump TM : See Read_Data_Memory and TC_Task_Tests.
|
|
Science Data TM (also): See Acquisition_Tests.
|
|
*/
|
|
}
|
|
|
|
|
|
static void Trigger_Hit ( int problem )
|
|
/* Invoke HandleHitTrigger.
|
|
The problem parameter defines the analysis problem for this test.
|
|
*/
|
|
{
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 0 );
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Hit!\n" );
|
|
#endif
|
|
|
|
FOR_PROBLEM( problem );
|
|
|
|
HandleHitTrigger ();
|
|
|
|
END_PROBLEM;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
if ( mail_count[ ACQUISITION_MAILBOX ] == 0 )
|
|
printf ( "- hit rejected\n" );
|
|
else
|
|
printf ( "- hit accepted\n" );
|
|
#endif
|
|
}
|
|
|
|
|
|
static void Trigger_SU_Hit (
|
|
sensor_index_t SU,
|
|
int problem )
|
|
/* Invoke HandleHitTrigger with the given SU in trigger_source_0/1.
|
|
The problem parameter defines the analysis problem for this test.
|
|
*/
|
|
{
|
|
Set_Trigger_SU ( SU );
|
|
Trigger_Hit ( problem );
|
|
}
|
|
|
|
|
|
static void Acquire_Hit (
|
|
int hit_problem,
|
|
int acq_problem )
|
|
/* Invoke HandleHitTrigger followed by HandleAcquisition if the hit
|
|
was accepted in the ISR. The problem parameters define the analysis
|
|
problems for this test, separately for the Hit Trigger ISR and
|
|
for the Acquisition task.
|
|
*/
|
|
{
|
|
Trigger_Hit ( hit_problem );
|
|
|
|
if ( mail_count[ ACQUISITION_MAILBOX ] > 0 ) {
|
|
FOR_PROBLEM( acq_problem );
|
|
HandleAcquisition ();
|
|
END_PROBLEM;
|
|
}
|
|
}
|
|
|
|
|
|
static void Hit_ISR_Tests ( void )
|
|
/* Test of HandleHitTrigger. */
|
|
{
|
|
sensor_index_t su;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "\nHit_ISR_Tests\n" );
|
|
#endif
|
|
|
|
/* Reset the historical record: */
|
|
|
|
telemetry_data.hit_budget_exceedings = 0;
|
|
|
|
/* Test: */
|
|
|
|
CASE( "Hit Trigger, budget exhausted" );
|
|
|
|
Check ( telemetry_data.hit_budget_exceedings == 0 );
|
|
|
|
hit_budget_left = 0;
|
|
|
|
/* Once: */
|
|
|
|
Trigger_SU_Hit ( 0, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 0 );
|
|
|
|
Check ( telemetry_data.hit_budget_exceedings == 1 );
|
|
|
|
/* Once more: */
|
|
|
|
Trigger_SU_Hit ( 1, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 0 );
|
|
|
|
Check ( telemetry_data.hit_budget_exceedings == 2 );
|
|
|
|
CASE( "Hit Trigger, budget exhausted for the 255th and 256th time" );
|
|
|
|
telemetry_data.hit_budget_exceedings = 254;
|
|
|
|
hit_budget_left = 0;
|
|
|
|
/* 255th time: */
|
|
|
|
Trigger_SU_Hit ( 3, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 0 );
|
|
|
|
Check ( telemetry_data.hit_budget_exceedings == 255 );
|
|
|
|
/* 256th time: */
|
|
|
|
Trigger_SU_Hit ( 1, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 0 );
|
|
|
|
Check ( telemetry_data.hit_budget_exceedings == 255 );
|
|
|
|
CASE( "Hit Trigger, budget left, no A/D errors" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
Set_AD_Delay ( 2 );
|
|
ad_conv_num = 0;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su ++ ) {
|
|
Trigger_SU_Hit ( su, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check ( mail_message[ ACQUISITION_MAILBOX ] == su + 1 );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
CASE( "Hit Trigger, budget left, no A/D errors, SU self test ok" );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su++ ) {
|
|
/* Right self test pulse: */
|
|
|
|
self_test_SU_number = su + 1;
|
|
|
|
SU_state[ su ] = self_test_trigger_e;
|
|
|
|
Trigger_SU_Hit ( su, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check ( mail_message[ ACQUISITION_MAILBOX ] == self_test_SU_number );
|
|
|
|
Check ( SU_state[ su ] == self_test_e );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
CASE( "Hit Trigger, budget left, no A/D errors, SU self test wrong" );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su++ ) {
|
|
/* Wrong self test pulse: */
|
|
|
|
self_test_SU_number = su + 1;
|
|
|
|
SU_state[ su ] = self_test_e;
|
|
|
|
Trigger_SU_Hit ( su, Prob3a );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check (
|
|
mail_message[ ACQUISITION_MAILBOX ]
|
|
== ( self_test_SU_number | HIT_SELF_TEST_RESET ) );
|
|
|
|
Check ( SU_state[ su ] == self_test_e );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
/* Reset the SU states: */
|
|
|
|
self_test_SU_number = NO_SU;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su++ ) SU_state[ su ] = off_e;
|
|
|
|
CASE( "Hit Trigger, budget left, all A/D delays at limit but ok" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
Set_AD_Delay ( ADC_MAX_TRIES );
|
|
|
|
ad_conv_num = 0;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su ++ ) {
|
|
Trigger_SU_Hit ( su, Prob3b );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check (
|
|
mail_message[ ACQUISITION_MAILBOX ]
|
|
== ( ( su + 1 ) ) ); // | HIT_ADC_ERROR));
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
CASE( "Hit Trigger, budget left, one A/D failure, others at limit" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
ad_conv_delay[ 0 ] = ADC_MAX_TRIES + 1;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( su = 0; su < NUM_SU; su ++ ) {
|
|
ad_conv_num = su;
|
|
/* Offset starting index to make a different channel fail. */
|
|
|
|
Trigger_SU_Hit ( su, Prob3b );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check (
|
|
mail_message[ ACQUISITION_MAILBOX ]
|
|
== ( ( su + 1 ) | HIT_ADC_ERROR ) );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
CASE( "Hit Trigger, budget left, any number of A/D failures" );
|
|
|
|
hit_budget_left = 80;
|
|
|
|
su = NUM_SU - 1;
|
|
|
|
_Pragma( "loopbound min 80 max 80" )
|
|
while ( hit_budget_left > 0 ) {
|
|
Random_AD_Delay ();
|
|
|
|
Trigger_SU_Hit ( su, Prob3c );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check (
|
|
( mail_message[ ACQUISITION_MAILBOX ] & SU_NUMBER_MASK )
|
|
== su + 1 );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
|
|
if ( su > 0 ) su --;
|
|
else su = NUM_SU - 1;
|
|
}
|
|
|
|
/* More tests in SU_Self_Test_Tests. */
|
|
}
|
|
|
|
|
|
unsigned char switch_su_cmd[ NUM_SU ] = {
|
|
SWITCH_SU_1,
|
|
SWITCH_SU_2,
|
|
SWITCH_SU_3,
|
|
SWITCH_SU_4
|
|
};
|
|
/* The commands to switch Sensor Units ON or OFF. */
|
|
|
|
|
|
void Report_Event_Histo ( void )
|
|
/* Report the collected event counts per SU and class. */
|
|
{
|
|
sensor_index_t sen;
|
|
int class;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
_Pragma( "loopbound min 10 max 10" )
|
|
for ( class = 0; class < NUM_CLASSES; class ++ ) {
|
|
printf ( "Events from SU %d, class %d: %d\n",
|
|
sen, class, science_data.event_counter[ sen ][ class ] );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
static void Acquisition_Tests ( void )
|
|
/* Tests of AcquisitionTask. */
|
|
{
|
|
sensor_index_t sen;
|
|
unsigned int hits;
|
|
int octets;
|
|
|
|
/* These tests are constructed as a "nominal operation"
|
|
scenario, which incidentally tests the AcquisitionTask
|
|
and the Hit Trigger ISR, as well as other functions.
|
|
The scenario is:
|
|
|
|
- TC to switch sensors ON
|
|
- Run Monitoring task to drive the SU state transition.
|
|
- TC to START ACQUISITION
|
|
- Particle hits until the Science Data is full
|
|
- The same number of particle hits with the Science Data full
|
|
- Science Data TM
|
|
- some particle hits during science TM
|
|
- TC to enter STANDBY mode
|
|
- TC to switch sensors OFF.
|
|
|
|
*/
|
|
|
|
CASE( "Turn Sensor Units ON" );
|
|
|
|
/* Send the SWITCH ON commands: */
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
Check ( SU_state[ sen ] == off_e );
|
|
|
|
Exec_TC ( switch_su_cmd[ sen ], ON_VALUE, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( SU_state[ sen ] == start_switching_e );
|
|
}
|
|
|
|
/* Prevent all errors in Monitoring: */
|
|
|
|
Set_AD_Nominal ();
|
|
max_adc_hits = 0;
|
|
ad_random_failures = 0;
|
|
check_current_errors = 0;
|
|
v_down_errors = 0;
|
|
|
|
/* Run Health Monitoring to drive the SUs ON: */
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == switching_e );
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == on_e );
|
|
|
|
CASE( "SWITCH_SU_ON when already ON, fail" );
|
|
|
|
Exec_TC ( SWITCH_SU_2, ON_VALUE, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check ( SU_state[ 1 ] == on_e );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "Start Acquisition" );
|
|
|
|
Check ( ( telemetry_data.mode_status & MODE_BITS_MASK ) == STAND_BY );
|
|
|
|
Exec_TC ( START_ACQUISITION, START_ACQUISITION, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Check ( ( telemetry_data.mode_status & MODE_BITS_MASK ) == ACQUISITION );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == acquisition_e );
|
|
|
|
CASE( "TC = SWITCH_SU in ACQUISITION, fail" );
|
|
|
|
Exec_TC ( SWITCH_SU_1, ON_VALUE, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "TC = START_ACQUISITION in ACQUISITION, fail" );
|
|
|
|
Exec_TC ( START_ACQUISITION, START_ACQUISITION, Prob4a );
|
|
|
|
Check ( telemetry_data.error_status == TC_ERROR );
|
|
|
|
Check ( GetMode() == ACQUISITION );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "Hits with Science Data not full" );
|
|
|
|
Set_AD_Delay ( 2 );
|
|
|
|
hits = 0;
|
|
|
|
_Pragma( "loopbound min 2625 max 2625" )
|
|
while ( free_slot_index < max_events ) {
|
|
hits ++;
|
|
internal_time ++;
|
|
hit_budget_left = 10;
|
|
|
|
Random_Event ();
|
|
|
|
Acquire_Hit ( Prob3a, Prob5a );
|
|
}
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Science Data filled with %d events after %d hits.\n",
|
|
max_events, hits );
|
|
#endif
|
|
Report_Event_Histo ();
|
|
|
|
CASE( "Hits with Science Data full" );
|
|
|
|
_Pragma( "loopbound min 2625 max 2625" )
|
|
while ( hits > 0 ) {
|
|
hits --;
|
|
internal_time ++;
|
|
hit_budget_left = 10;
|
|
|
|
Random_Event ();
|
|
|
|
Acquire_Hit ( Prob3a, Prob5b );
|
|
}
|
|
|
|
Report_Event_Histo ();
|
|
|
|
CASE( "Science Data TM, full Science Data, some hits during TM" );
|
|
|
|
Send_TC ( SEND_SCIENCE_DATA_FILE, SEND_SCIENCE_DATA_FILE );
|
|
|
|
Check_No_Errors ();
|
|
Check ( TC_state == SC_TM_e );
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == SC_TM_e );
|
|
|
|
/* Absorb TM until a TM_READY message is sent to the TC task,
|
|
and simulate some particle hits at the same time:
|
|
*/
|
|
|
|
hits = 0;
|
|
/* We will make MAX_QUEUE_LENGTH + 4 hits. */
|
|
|
|
hit_budget_left = MAX_QUEUE_LENGTH + 2;
|
|
/* Ensure that some hits are rejected for budget exhaustion. */
|
|
|
|
Check_Zero ( event_queue_length );
|
|
|
|
octets = 0;
|
|
|
|
_Pragma( "loopbound min 17676 max 17676" )
|
|
while ( mail_count[ TCTM_MAILBOX ] == 0 ) {
|
|
if ( telemetry_pointer < telemetry_end_pointer ) {
|
|
FOR_PROBLEM( Prob2a );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
} else {
|
|
FOR_PROBLEM( Prob2c );
|
|
TM_InterruptService ();
|
|
END_PROBLEM;
|
|
}
|
|
|
|
octets += 2;
|
|
Check ( TC_state == SC_TM_e );
|
|
|
|
if ( hits < MAX_QUEUE_LENGTH + 4 ) {
|
|
/* Hit during Science Data TM: */
|
|
|
|
internal_time ++;
|
|
Random_Event ();
|
|
event_flag = ACCEPT_EVENT;
|
|
|
|
Acquire_Hit ( Prob3a, Prob5b );
|
|
|
|
hits ++;
|
|
|
|
if ( hits <= MAX_QUEUE_LENGTH )
|
|
Check ( event_queue_length == hits );
|
|
else
|
|
Check ( event_queue_length == MAX_QUEUE_LENGTH );
|
|
}
|
|
}
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Science TM octets sent %d\n", octets );
|
|
#endif
|
|
|
|
Check_Zero ( hit_budget_left );
|
|
|
|
Check ( hits == MAX_QUEUE_LENGTH + 4 );
|
|
|
|
/* Handle the TM_READY message: */
|
|
|
|
Handle_TC ( Prob4a );
|
|
|
|
Check ( TC_state == TC_handling_e );
|
|
|
|
/* Check that the queued events have been recorded: */
|
|
|
|
Check_Zero ( event_queue_length );
|
|
|
|
Check ( free_slot_index == MAX_QUEUE_LENGTH );
|
|
|
|
CASE( "Switch to Self Test in Acquisition mode, fail" );
|
|
|
|
Check ( GetMode() == ACQUISITION );
|
|
|
|
Check_Zero ( telemetry_data.error_status & TC_ERROR );
|
|
|
|
Exec_TC ( SWITCH_SU_2, SELF_TEST, Prob4a );
|
|
|
|
Check_Nonzero ( telemetry_data.error_status & TC_ERROR );
|
|
|
|
Exec_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR, Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.error_status & TC_ERROR );
|
|
|
|
CASE( "Stop acquisition" );
|
|
|
|
Exec_TC ( STOP_ACQUISITION, STOP_ACQUISITION, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Check ( ( telemetry_data.mode_status & MODE_BITS_MASK ) == STAND_BY );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == on_e );
|
|
|
|
CASE( "Turn Sensor Units OFF" );
|
|
|
|
/* Send the SWITCH OFF commands: */
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
Exec_TC ( switch_su_cmd[ sen ], OFF_VALUE, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( SU_state[ sen ] == off_e );
|
|
}
|
|
}
|
|
|
|
void SU_Self_Test_Tests ( void )
|
|
/* Tests of the "SU Self Test" function. */
|
|
{
|
|
sensor_index_t sen;
|
|
|
|
sim_self_test = 1;
|
|
|
|
CASE( "Turn Sensor Units ON for Self Test" );
|
|
|
|
/* Send the SWITCH ON commands: */
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
Check ( SU_state[ sen ] == off_e );
|
|
|
|
Exec_TC ( switch_su_cmd[ sen ], ON_VALUE, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( SU_state[ sen ] == start_switching_e );
|
|
}
|
|
|
|
/* Prevent all errors in Monitoring: */
|
|
|
|
Set_AD_Nominal ();
|
|
max_adc_hits = 0;
|
|
ad_random_failures = 0;
|
|
check_current_errors = 0;
|
|
v_down_errors = 0;
|
|
|
|
/* Run Health Monitoring to drive the SUs ON: */
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == switching_e );
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ )
|
|
Check ( SU_state[ sen ] == on_e );
|
|
|
|
CASE( "Switch SU2 to Self Test in Standby mode" );
|
|
|
|
Check ( GetMode() == STAND_BY );
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SWITCH_SU_2, SELF_TEST, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_mon_e );
|
|
|
|
CASE ( "Switch SU3 (also) to Self Test, fail" );
|
|
|
|
Exec_TC ( SWITCH_SU_3, SELF_TEST, Prob4a );
|
|
|
|
Check_Nonzero ( telemetry_data.error_status & TC_ERROR );
|
|
|
|
Exec_TC ( ERROR_STATUS_CLEAR, ERROR_STATUS_CLEAR, Prob4a );
|
|
|
|
Check_Zero ( telemetry_data.error_status & TC_ERROR );
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Run Self Test for SU2" );
|
|
|
|
/* Run Monitoring up to but not including round_7_e: */
|
|
|
|
_Pragma( "loopbound min 8 max 8" )
|
|
while ( health_mon_round != round_7_e )
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_mon_e );
|
|
|
|
/* Run round_7_e of Monitoring to start Self Test: */
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_e );
|
|
|
|
/* Run round_6_e of Monitoring to execute Self Test: */
|
|
|
|
Check ( health_mon_round == round_6_e );
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == NO_SU );
|
|
Check ( SU_state[ 1 ] == on_e );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Run Self Test for SU2, fail" );
|
|
|
|
Check ( GetMode() == STAND_BY );
|
|
Check_No_Errors ();
|
|
|
|
Exec_TC ( SWITCH_SU_2, SELF_TEST, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_mon_e );
|
|
|
|
sim_self_test = 0;
|
|
/* Force self-test to fail. */
|
|
|
|
/* Run Monitoring up to but not including round_7_e: */
|
|
|
|
_Pragma( "loopbound min 8 max 8" )
|
|
while ( health_mon_round != round_7_e )
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_mon_e );
|
|
|
|
/* Run round_7_e of Monitoring to start Self Test: */
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == 2 );
|
|
Check ( SU_state[ 1 ] == self_test_e );
|
|
|
|
/* Run round_6_e of Monitoring to execute Self Test: */
|
|
|
|
Check ( health_mon_round == round_6_e );
|
|
|
|
Monitor_Health ( Prob6a );
|
|
|
|
Check ( self_test_SU_number == NO_SU );
|
|
Check ( SU_state[ 1 ] == on_e );
|
|
|
|
Check_Nonzero ( telemetry_data.SU_status[ 1 ] & SELF_TEST_ERROR );
|
|
Check ( telemetry_data.error_status == 0x20 );
|
|
|
|
Clear_Errors ();
|
|
|
|
CASE( "Hit Trigger, SU Self Test, correct pulse" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
Set_AD_Delay ( 2 );
|
|
ad_conv_num = 0;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
self_test_SU_number = sen + SU1;
|
|
|
|
SU_state[ sen ] = self_test_trigger_e;
|
|
|
|
Trigger_SU_Hit ( sen, Prob3a );
|
|
|
|
Check ( SU_state[ sen ] == self_test_e );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check ( mail_message[ ACQUISITION_MAILBOX ] == sen + SU1 );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
CASE( "Hit Trigger, SU Self Test, incorrect pulse" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
Set_AD_Delay ( 2 );
|
|
ad_conv_num = 0;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
self_test_SU_number = sen + SU1;
|
|
|
|
SU_state[ sen ] = self_test_e;
|
|
|
|
Trigger_SU_Hit ( sen, Prob3a );
|
|
|
|
Check ( SU_state[ sen ] == self_test_e );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check ( mail_message[ ACQUISITION_MAILBOX ] ==
|
|
( ( sen + SU1 ) | HIT_SELF_TEST_RESET ) );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
CASE( "Hit Trigger, SU Self Test, other pulse" );
|
|
|
|
hit_budget_left = 15;
|
|
|
|
Set_AD_Delay ( 2 );
|
|
ad_conv_num = 0;
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
self_test_SU_number = sen + SU1;
|
|
|
|
SU_state[ sen ] = on_e;
|
|
|
|
Trigger_SU_Hit ( sen, Prob3a );
|
|
|
|
Check ( SU_state[ sen ] == on_e );
|
|
|
|
Check ( mail_count[ ACQUISITION_MAILBOX ] == 1 );
|
|
|
|
Check ( mail_message[ ACQUISITION_MAILBOX ] == sen + SU1 );
|
|
|
|
FlushMail ( ACQUISITION_MAILBOX );
|
|
}
|
|
|
|
Check ( hit_budget_left == 15 - NUM_SU );
|
|
|
|
Check_No_Errors ();
|
|
|
|
CASE( "Turn Sensor Units OFF after Self Tests" );
|
|
|
|
/* Send the SWITCH OFF commands: */
|
|
|
|
_Pragma( "loopbound min 4 max 4" )
|
|
for ( sen = 0; sen < NUM_SU; sen ++ ) {
|
|
Exec_TC ( switch_su_cmd[ sen ], OFF_VALUE, Prob4a );
|
|
|
|
Check_No_Errors ();
|
|
Check ( SU_state[ sen] == off_e );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* StartSystem () : test scenario */
|
|
|
|
|
|
static unsigned int test_round = 0;
|
|
/* Counts test repetitions. */
|
|
|
|
|
|
void StartSystem( unsigned char task_number )
|
|
/* ORIGINALLY: */
|
|
/* Purpose : Starts the system. */
|
|
/* Interface : input - none */
|
|
/* output - none */
|
|
/* Preconditions : none */
|
|
/* Postconditions : First task is called and system started. */
|
|
/* Algorithm : See below, self explanatory. */
|
|
/* IN HARNESS: */
|
|
/* Executes the test scenario. */
|
|
{
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "StartSystem %d\n", task_number );
|
|
#endif
|
|
|
|
/* Initialize the global data of the tasks: */
|
|
|
|
InitHealthMonitoring ();
|
|
|
|
/* Testing the ISRs and tasks: */
|
|
|
|
_Pragma( "loopbound min 1 max 1" )
|
|
do {
|
|
test_round ++;
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Test round %d\n", test_round );
|
|
#endif
|
|
|
|
TARGET_START_TEST;
|
|
|
|
TC_ISR_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
TC_Task_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
Monitoring_Task_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
TM_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
Hit_ISR_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
Acquisition_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
SU_Self_Test_Tests ();
|
|
|
|
Report_Checks ();
|
|
|
|
/* Clear for next round: */
|
|
|
|
checks = 0;
|
|
} while ( TARGET_REPEAT_TEST );
|
|
|
|
#if defined(TRACE_HARNESS)
|
|
printf ( "Total mailbox overflows %d\n", mail_overflows );
|
|
exit ( 0 );
|
|
#endif
|
|
|
|
}
|