GLAST / LAT > DAQ and FSW > FSW > Doxygen Index> PBS / dev > pbs / rad750


Interface   Data Structures   File List   Data Fields   Globals  

TAU.c.vx-ppc750-gcc File Reference

Thermal Assist Unit, implementation. More...

#include <intLib.h>
#include <excLib.h>
#include <semLib.h>
#include <PBS/L.ih>
#include <PBS/MTX.ih>
#include <PBS/TAU.h>
#include <PBS/TAU.ih>
#include <PBI/Alias.h>

Classes

struct  _TAU_tauCtx
 The original interrupt context before the initialization of the TAU facility. This context is restored when TAU_shutdown is called. More...
struct  _TAU_chkCtx
 The context when the TAU facility is running in the check limits mode. More...
struct  _TAU_rdCtx
 The context when the TAU facility is running in the read temperature mode. More...
struct  _TAU_ctx
 The grand context of TAU facility. More...

Defines

#define LOG_MSG(fmt, p0, p1, p2, p3, p4, p5)
#define TAU_A_EXCEPTION_VECTOR   0x1700
#define TAU_K_SITV   (1024)
#define INTERRUPT_IF_GREATER   0
#define INTERRUPT_IF_LESS   1
#define TAU_K_INITIAL_GUESS   63
 The intial guess at the processor temperature.

Typedefs

typedef struct _TAU_tauCtx TAU_tauCtx
 Typedef for struct _TAU_tauCtx.
typedef struct _TAU_chkCtx TAU_chkCtx
 Typedef for struct _TAU_chkCtx.
typedef struct _TAU_rdCtx TAU_rdCtx
 Typedef for struct _TAU_rdCtx.
typedef struct _TAU_ctx TAU_ctx
 Typedef for struct _TAU_ctx.

Functions

static void disable (void)
 Disables the TAU interrupt.
static void enable (int sitv)
 Enables the TAU interrupt with the specified sampling timer interval.
static void save (TAU_tauCtx *tau)
 Saves the current context of the TAU facility.
static int restore (const TAU_tauCtx *tau)
 Restores a previous context of the TAU facility.
static int calcNewLimits (int count)
 Calculates a new set of threshold limits based on the current set and the iteration count.
static int adone (TAU_request *request, int temperature, int count, int sequence)
 Stub routine to act as the completion routine for TAU_aread.
static void limitsSet (int threshold, int direction)
 Sets THRM1 and THRM2 to the specified threshold, but with opposite comparison directions.
static void service (void)
 The interrupt handler for the read temperature facility.
static int acquire (TAU_ctx *ctx)
 Begins an acquisition cycle.
int TAU_initialize (int sitv)
 Initializes the TAU facility.
int TAU_shutdown (void)
 Restores the original VxWorks routine.
TAU_isrTAU_connect (TAU_isr *isr)
 Connects the specified routine as the TAU interrupt handler.
int TAU_restore (TAU_isr *prvIsr)
 Restores the specified interrupt service routine as the current thermal exception handler.
int TAU_qread (TAU_request *request)
 Ques a read of the temperature.
int TAU_aread (TAU_request *request)
 Perform an asynchronous read. This call should be matched with a TAU_await ().
int TAU_await (TAU_request *request)
 Waits for the completion of the read request.
int TAU_read (void)
 Issues a synchronous read request.
int TAU_pread (TAU_request *request)
 Issues a synchronous polled read request.
 ALIAS_FNC (int, TAU_pread, TAU_sread)

Variables

static TAU_ctx TauCtx
 Static variable holding the TAU context.


Detailed Description

Thermal Assist Unit, implementation.

Author:
JJRussell - russell@slac.stanford.edu
    CVS $Id: TAU.c.vx-ppc750-gcc,v 1.4 2011/03/24 23:05:47 apw Exp $

SYNOPSIS
This defines the callable implementation fo the TAU routines. This facility is only available on PPC750 platforms
Thermal Assist Unit Description
The Thermal Assist Unit (TAU) is described in Chapter 10 of the MCP750 RISC Microprocessor Family User's Manual. This unit allows the user to monitor the junction temperature within the MCP750.
The user interface consists of 3 registers, THRM1, THRM2, THRM3. The first two registers, THRM1 and THRM2, are identical in structure. They are used to set thresholds, typically an upper and lower threshold, and record the results of a comparison operation between the thresholds and the the actual junction temperature. The third register, THRM3 acts as a control registering, specifying how long the digitization process takes and when to start it.

Monitor Mode
The TAU can be used in one of two modes. The more typical mode is to set a temperature window using THRM1 and THRM2. Once THRM3 is set up with a digitization time and enabled, the TAU continuously digitizes the junction temperatures. If the temperature fails outside the allowed window, an interrupt is generated. This allows the user to quietly monitor the junction temperature with only an interrupt service to catch the out-of-bounds condition.
Read Mode - Overview
The second mode is to use the TAU to get the actual temperature. Unfortunately there is no direct read of the digitized temperature. Rather one must restore to a set of comparisons to a variety of thresholds. In the most straightforward implementation, THRM1 is set up with the comparison bit in the less than direction and the THRESHOLD at 0. The digitization process is enabled. The code polls on the valid bit (TIV) until it becomes valid. One notes the result the comparison (TIN bit). If the comparison bit indicates that the threshold is less than the actual temperature, the threshold is raised by 1 and the process is repeated until the comparison bit indicates the threshold is greater than the junction temperaure.
Since the range of the digitization is from 0 to 127 Celsius, this process can take up to approximately 128 * digitization time of 20usecs or about 2.5 millisecs.

Read Mode - Framework
Two factors conspire to make obtaining the junction temperature a more difficult job than it deserves to be. The first is the length of time it takes to obtain the measurement. This is not a call one wishes to drop in the middle of high performance code. The second is the non-reentrant nature of the interface. Once a read sequence is started, the three TAU registers are off-limits.
One could deal with this by creating a server task that one performed the actual reads. The caller would que reads to the service task, then, via some synchronization mechanism, pend for the results.

The tactic taken in this design is a variation of this. Rather than having a service task, one sets up a que that requests can be queued to. A request that causes the que to go from empty to non-empty initialiates the sequence. Instead of polling each digization sequence for completion, the TAU is configured to deliver an interrupt. The interrupt service routine then examines the result of the comparision operation and either declares that the temperature has been found or seeds the TAU with a new threshold, repeating this process until the temperature is found.

Read Mode - Algorithm
The above section addresses the structural issues. One would still like to make the finding of the temperature converge as quickly as possible.
Before describing the final algorithm, some ideas that do not work are presented. The reason for this is two-fold. Some refinements of these ideas do appear in the final algorithm, so this serves as a guide. Second as warning to future developers not to use try what, on the surface seem like good ideas.

Read Mode - Bad Algorithm 1
The first idea was to use the THRM1 and THRM2 to set a window. In this algorithm the window is configured opposition the normal sense. In this configuration, one wishes to always generate an interrupt. Here the thought is that one can divide the range into three segments using the two thresholds. Then, in a obvious variation of a binary search, one continues to narrow the range until the range shrinks to essentially 0.
This idea does not work for two reasons. The first is that TAU does not guarantee that both comparisions will be made. The TAU makes the comparisons to the thresholds in THRM1 and THRM2 in series, not parallel. The documentation states that if THRM1 will generate an interrupt, the interrupt will be generated without first checking the THRM2 threshold. In the ISR, one will note that the THRM2 comparision bit is invalid, but, from a coding viewpoint, this does not help much.

Having lost the ability to do a trinary search, one may be tempted to try a binary search. Here one would set THRM1 and THRM2 with the same values, but opposition comparision directions (this guarantees an interrupt will always be generated) and keeps cutting the range in half. The problem with this approach is that the junction temperature, while very stable, is not completely fixed. If it wanders over a boundary, the binary search can fail. For example, imagine that one starts the search with a threshold of 63 and the temperature is 63.1 at the beginning. The first search tells you to go higher. So now the range is 63-127 and the algorithm selects 85 as its next break point. However in between the two readings the junction temperature moves down to 62.9 and continues to drift down. The result of the search will lead on to believe the answer is in the range 63-85. Eventually the search will settle on 63, even though the temperature may have continued to drift down.

Read Algorithm
Give the fact that the temperature can move as the measurement is being made, one must always see the transition from greater than to less than. In the binary search, once one hit 63, one must then test 62 to see if the comparison results change.
Even a modified binary search will take at least 8 comparisons to converge on a 7 bit number. Can one do better. The answer is yes. Given that the temperature moves very slowly a reasonable algorithm is to remember the last reading and first test the boundary at that reading. The odds are that this is still the right answer, so one will find the answer in two iterations.

The astute reader will notice that since the comparison to THRM1 occurs first, if possible, one should bias the algorithm such that THRM1 will generate the interrupt.

Example
Suppose the last reading was 55.5 Celsius and the current reading is the same. If THRM1 is set to 56 and the direction of comparison is less than and THRM2 is set to 55 and the direction of comparison is 55 and the direction of comparison is greater than. The result of the comparison is:
         T2   T1        T2      T1  Iter     Time  Lo  Hi   Lo  Hi 
        <55  >55   invalid    TRUE     1  20usecs   0 127   55 127
        <56  >56      TRUE invalid     2  40usecs  55 127   55  56

Now suppose the temperature has changed to 54.5 The sequence should be

         T2   T1        T2      T1  Iter     Time  Lo  Hi   Lo  Hi 
        <55  >55      TRUE invalid     1  40usecs   0 127    0  55
        >54  <54      TRUE invalid     2  40usecs   0  55   54  55

    T = 53.5   
    --------
         T2   T1        T2      T1  Iter     Time  Lo  Hi   Lo  Hi 
        <55  >55      TRUE invalid     1  40usecs   0 127    0  55
        >54  <54   invalid    TRUE     2  20usecs   0  55    0  54
        >53  <53      TRUE invalid     3  40usecs   0  54   53  54

    T = 56.5
    --------
         T2   T1        T2      T1  Iter     Time  Lo  Hi   Lo  Hi 
        <55  >55   invalid    TRUE     1  20usecs   0 127   55 127
        <56  >56   invalid    TRUE     1  20usecs  55 127   56 127
        <57  >57      TRUE invalid     1  40usecs  56 127   56  57

Define Documentation

#define TAU_K_INITIAL_GUESS   63

The intial guess at the processor temperature.

This is used to seed the first search. Subsequent searches are seeded with the last temperature reading

Referenced by TAU_initialize().


Function Documentation

int acquire ( TAU_ctx ctx  )  [inline, static]

Begins an acquisition cycle.

Returns:
Status
The thermal interrupt is disable, then new limits for THRM1 and THRM2 are established. The acquisition interrupt service routine is connected and then the thermal interrupt is reenabled.

References _TAU_rdCtx::count, disable(), enable(), _TAU_rdCtx::last, limitsSet(), _TAU_ctx::rd, _TAU_rdCtx::save, save(), _TAU_rdCtx::sequence, service(), _TAU_rdCtx::sitv, and TAU_connect().

Referenced by TAU_qread().

void adone ( TAU_request request,
int  temperature,
int  count,
int  sequence 
) [static]

Stub routine to act as the completion routine for TAU_aread.

Returns:
Status
Parameters:
request The request descriptor
temperature The temperature
count The number of iterations to converge
sequence The sequence number of this reading

References _TAU_request::count, _TAU_request::prm, _TAU_request::sequence, and _TAU_request::temperature.

Referenced by TAU_aread().

int calcNewLimits ( int  count  )  [static]

Calculates a new set of threshold limits based on the current set and the iteration count.

Returns:
>=0, the temperature, i.e. the process has converged, else < 0
Parameters:
count The iteration count

References _TAU_reg::bf, TAU__get1(), TAU__get2(), TAU__set1(), TAU__set2(), _TAU_reg_bf::threshold, _TAU_reg_bf::tid, _TAU_reg_bf::tin, and _TAU_reg::val.

Referenced by service(), and TAU_pread().

void enable ( int  sitv  )  [inline, static]

Enables the TAU interrupt with the specified sampling timer interval.

Parameters:
sitv The sampling timer interval

References _TAU_ctl::bf, _TAU_ctl_bf::e, _TAU_ctl_bf::rsvd, _TAU_ctl_bf::sitv, TAU__set3(), and _TAU_ctl::val.

Referenced by acquire(), service(), and TAU_pread().

void limitsSet ( int  threshold,
int  direction 
) [inline, static]

Sets THRM1 and THRM2 to the specified threshold, but with opposite comparison directions.

Parameters:
threshold The threshold value
direction The comparison direction for THRM1. THRM2 will be set in the opposite direction. This ensures that any temperature will generate and interrupt.

References _TAU_reg::bf, TAU__set1(), TAU__set2(), _TAU_reg_bf::threshold, _TAU_reg_bf::tid, _TAU_reg_bf::tie, _TAU_reg_bf::v, and _TAU_reg::val.

Referenced by acquire().

restore ( const TAU_tauCtx tau  )  [static]

Restores a previous context of the TAU facility.

Parameters:
tau The TAU context to restore

References disable(), _TAU_tauCtx::handler, TAU__set1(), TAU__set2(), TAU__set3(), TAU_restore(), _TAU_tauCtx::thrm1, _TAU_tauCtx::thrm2, and _TAU_tauCtx::thrm3.

Referenced by service(), TAU_pread(), and TAU_shutdown().

save ( TAU_tauCtx tau  )  [static]

Saves the current context of the TAU facility.

Parameters:
tau Structure to receive the saved context

References _TAU_tauCtx::handler, TAU__get1(), TAU__get2(), TAU__get3(), _TAU_tauCtx::thrm1, _TAU_tauCtx::thrm2, and _TAU_tauCtx::thrm3.

Referenced by acquire(), TAU_initialize(), and TAU_pread().

int TAU_aread ( TAU_request request  ) 

Perform an asynchronous read. This call should be matched with a TAU_await ().

Returns:
Status of the que operation, if 0, successfully queued
Parameters:
request An un-initialized request structure

References adone(), _TAU_request::completion, _TAU_request::prm, _TAU_ctx::rd, _TAU_rdCtx::synch, and TAU_qread().

int TAU_await ( TAU_request request  ) 

Waits for the completion of the read request.

Returns:
Status
Parameters:
request The request being waited on

References _TAU_request::prm.

TAU_isr* TAU_connect ( TAU_isr isr  ) 

Connects the specified routine as the TAU interrupt handler.

Returns:
The current interrupt service routine. The user should restore this routine when finished. NULL is returned on failure.
Parameters:
isr The interrupt service routine to connect

Referenced by acquire().

int TAU_initialize ( int  sitv  ) 

Initializes the TAU facility.

This is a one-time only initialization call. When finished with the facility, call TAU_shutdown ().

References _TAU_rdCtx::count, L__init(), _TAU_rdCtx::last, _TAU_rdCtx::mtx, MTX__create(), _TAU_ctx::org, _TAU_ctx::rd, _TAU_rdCtx::requests, save(), _TAU_rdCtx::sequence, _TAU_rdCtx::sitv, _TAU_rdCtx::synch, and TAU_K_INITIAL_GUESS.

Referenced by PBS_initialize2().

status TAU_pread ( TAU_request request  ) 

int TAU_qread ( TAU_request request  ) 

Ques a read of the temperature.

Returns:
Status, indicating the success or failure of queing the read
Parameters:
request A previously initialized read request. One should use the macro TAU_REQUEST_INIT to initialize this structure.
This routine calls back the completion routine buried in the request structure when the read is complete.

References acquire(), L__insert(), _TAU_request::node, _TAU_ctx::rd, and _TAU_rdCtx::requests.

Referenced by TAU_aread().

int TAU_read ( void   ) 

Issues a synchronous read request.

Returns:
If > 0, the temperature, else, error

References TAU_sread(), and _TAU_request::temperature.

int TAU_restore ( TAU_isr prvIsr  ) 

Restores the specified interrupt service routine as the current thermal exception handler.

Returns:
Status
prvIsr The interrupt service routine to restore

Referenced by restore().

int TAU_shutdown ( void   ) 

Restores the original VxWorks routine.

This routine restores the original interrupt service handler

References L__destroy(), _TAU_rdCtx::mtx, MTX__destroy(), _TAU_ctx::org, _TAU_ctx::rd, _TAU_rdCtx::requests, restore(), and _TAU_rdCtx::synch.

Referenced by PBS_shutdown().


Generated on Fri Aug 5 18:41:09 2011 by  doxygen 1.5.8