Table of Contents
Previous Chapter
The purpose of the System Startup and Patch Management units are to initialize and patch the instrument software running on the Back End Processor.
The following lists the use of the System Startup and Patch Management modules and classes:
Figure 47 illustrates the class relationships used by the System Startup routines, and the PatchList class. Although the System Startup routines are implemented in assembler or as stand-alone functions, they are represented as member functions of a class-utility in the figure (as indicated by the shadow on the cloud).
FIGURE 47. System Startup and PatchList relationships
System Startup - This is a collection of assembler and C++ subroutines which load and initialize the instrument software. They provide the ability to load code and initialized data sections from the bulk ROM into the Back End Processor's Instruction and Data cache (asm_loadFromRom), perform low-level processor initialization (asm_startup), perform patch installation, executive initialization and launch the executive (startup), and invoke global constructors once the executive is running and enable execution of the remaining tasks in the system (main). This class uses the BepReg class to determine if the most recent reset was a commanded reset, and if so uses the PatchList class to install the system patches.
PatchList - This class is responsible for maintaining the system patch list, and for installing the patches when invoked by startup. It provides functions which append a patch to the system patch list (addPatch), remove a patch from the list and compact the list (removePatch), determine if the patch list has been corrupted (isValid), and apply the set of patches during startup (applyPatches).
Nucleus RTX - This represents the collection of routines provided by the Nucleus Real-Time Executive. The startup software uses INP_Initialize() to initialize and launch the executive.
The system patch list is maintained in the Instruction Cache RAM (I-cache) on the Back End Processor (BEP). Since writing to I-cache must be accomplished via the Mongoose Command Status Interface, corruption of the list due to stray pointers or crashes is unlikely. However, whenever the BEP receives a power-on reset, or if the BEP is reset while removing a patch from the patchlist, there is the potential for the list to become corrupted. As such, the list maintains a checksum of the contents of the list. If the checksum is invalid, patches will not be applied.
Table 16 illustrates the layout of the system patch list. This list grows backwards, from the end of I-cache toward the start of I-cache.
TABLE 16. I-cache Patch List Layout
--------------------------------------------------------------------------------------------------- Region Address Byte Size Description--------------------------------------------------------------------------------------------------- Patch End of List 0x800ffffc 4 This points to the next location where a Area Pointer patch may be added Checksum 0x800ffff8 4 This is the current 32-bit XOR checksum of the current contents of the patch list. Patch Nodes Variable These are a collection of patch nodes. The format for each node is as follows: Name Offset Bytes Description Patch Id 4*Length 4 Unique code to +8 identify the patch Destination 4*Length 4 Points to where +4 to write patch data Length 4*Length 4 Number of 32-bit words in patch Data 0 4*Length Data to write at startup Current End End of List This is next location after the last patch of Patch List Pointer node in the patch list. This location is pointed to by the End of List Pointer ... Lowest 0x800d7c00 This is the lowest address usable by the Patch patch list. It cannot be moved without a Address patch. Bad Pixel/Column Maps 0x800cac00 53248 Compression Tables 0x800c2c00 32760 Parameter Blocks 0x800c0400 10240 System Configuration 0x800c0000 1024 Code 0x8008000 262144 ---------------------------------------------------------------------------------------------------
The ACIS Bulk Flight ROM consists of a boot section and simple loading routine, which has been linked with the flight code, thus providing it with the locations to install the loadable code and initialized data sections. The code is assumed to precede data in a contiguous area pointed to by the symbol _loadRom (TBD). During system ROM boot, the Back End Processor's Boot Code jumps to the ROM loader. The loader ROM proceeds to copy code and data sections from the ROM into the BEP's I-cache and D-cache. The code is to be copied into I-cache from _ ftext to _etext, while the data is to be located in D-cache from _fdata to _edata. Once the sections have been copied, the loader jumps to the starting execution address of the loaded code designated by _execAddr (TBD).
Nucleus RTX is configured using fixed tables at fixed locations. Table 17 lists the items which must be initialized prior to starting the executive. Refer to the Nucleus RTX include file, in_defs.h, for the definitions of these structures, and the definition of the END_OF_LIST constant.
TABLE 17. Nucleus RTX Configuration Items
----------------------------------------------------------------------------------------------------------------------- Name Type Description----------------------------------------------------------------------------------------------------------------------- SKD_System_Stack_Ptr
unsigned*
This must be initialize to point to the start of the system stack space used by the executive.IN_System_Stack_Size
unsigned
This must be initialize to the total number of 32-bit words to use for the system stack.IN_Last_Memory_Address
unsigned
This variable must be initialized to the last memory location to be used by the executive. The executive uses the area between the address of IN_Last_Address_Used and the location referenced by this variable for stacks, task con trol structures, etc.IN_Last_Address_Used
unsigned
This variable must be initialized to reference the first loca tion used by Nucleus RTX for stacks, task control struc tures, etc.IN_Fixed_Partitions
struct This is an array of partition definition structures. The first IN_FIXED_PARTITION_STRUCT[]
field of entry just after the last used entry must contain the value "END_OF_LIST." This array must contain an initial ized entry for each MemoryPool instance. The index of the entry serves as the RTX identifier for the pool.IN_System_Queues
struct This is an array of queue definition structures. The first field IN_QUEUE_DEFINITION_STRUCT[]
of the entry just after the last defined queue must contain the value "END_OF_LIST." This array must contain an initial ized entry for each Queue instance in the system. The index of the entry serves as the RTX identifier for the queue.IN_System_Event_Groups
unsigned
This is the count of event groups used by the instrument. For ACIS, this must be initialized to the total number of tasks in the system.IN_System_Resources
unsigned
This is the count of semaphores used by the instrument. For ACIS, this must be initialized to the total number of Sema phore instances used by the systemIN_System_Tasks
struct This is an array of task definition structures. The first field IN_TASK_DEFINITION_STRUCT[]
of entry just after the last defined task must contain the value "END_OF_LIST." There must be one entry for each defined Task instance within the instrument. The index of an entry serves as the RTX identifier for the task. -----------------------------------------------------------------------------------------------------------------------
In C++, the constructors for global instances are invoked in the order they appear in an object file. The order in which different object files are processed is undefined by the language. In order to ensure deterministic initialization order, the System Startup uses a single source file for all global objects, globals.C. This file contains the Nucleus RTX initialization structures, and each global declaration, in the order they are to be initialized.
Figure 48 illustrates the sequence of operations which load code and data from the bulk ROM into the Back End Processor RAM. Note: the ROM locations of code and data and the areas in I-cache and in D-cache where they will be located, were compiled into the loader.
FIGURE 48. Loading Code and Data
The code located at the startup execution address is responsible for initializing the some of the Mongoose and R3000's processor registers and setting up a stack for the C++ startup routines. Table 18 lists the register values which must be initialized. The R3000 symbols are defined in mips.h, and the Mongoose register symbols are defined in mongoose.h. (NOTE: By convention, C and C++ assume that uninitialized data section, .bss, be zeroed during startup, ACIS performs this action after the patch list has been applied. Code prior to and during patching shall not rely on uninitialized data having a value of zero).
TABLE 18. Startup Mongoose and R3000 Register Initialization
------------------------------------------------------------------------------------------------- Register Initial Value Description------------------------------------------------------------------------------------------------- C0_SR SR_BEV | SR_CU0 R3000 Co-processor 0 Status Register: This reg (C0:$12) ister must be initialized to use the Boot Excep tion Vector, and to have Co-processor 0 enabled. During startup, all R3000 device interrupts are disabled. C0_CAUSE zero R3000 Co-processor 0 Cause Register: Writing a (C0:$13) zero to the cause register ensures that there are no software interrupts pending. M_CFGREG CR_NODMA | CR_WAITST1 Mongoose Configuration Register: This register (Mongoose) is initialized to ensure that no Mongoose DMA transfers are underway, and that the processor use 1 wait-state for all bulk memory and devices. M_MASK zero Mongoose Interrupt Mask Register: Writing a (Mongoose) zero to the Mongoose interrupt mask disables all Mongoose device interrupts. gp _gp R3000 Global Pointer: This register is initialized (R3000:$28) to the linker defined value for the global pointer. sp startup_stack + stack size - 24 R3000 Stack Pointer: The stack pointer is initial (R3000:$29) ized to point at the end of the stack, minus 24 bytes to support the minimum reserved stack space required by functions which call other functions (i.e. non-leaf functions). -------------------------------------------------------------------------------------------------
Once the registers have been initialized, the startup assembler code jumps to the C++ startup routine, startup().
Prior to enabling interrupts on the R3000, the ACIS software must copy a code-fragment which jumps to the ACIS interrupt handler into the General Exception area of I-cache. On ACIS, this is accomplished by providing the appropriate code section in the bulk ROM (see Section 14.4.2 and Section 14.5.3). This causes the interrupt vector code to be loaded into I-cache when all of the other code and initialized data sections are loaded.
During the development process, however, when code is loaded via the ROM monitor across a serial interface, rather than from the instrument's bulk ROM, the startup code is required to copy the interrupt vector code-fragment into I-cache. This is because the ROM monitor uses non-boot interrupts when loading the images. The installed R3000 interrupt handler must then forward exceptions and UART interrupts to the original monitor's handler.
The first action taken by the C++ startup routine is to determine if the instrument was commanded to reset, and if so, install the patch list. The startup routine uses bepReg.getStatus() to obtain the value of the Back End Processor's status register. If processor was commanded to reset (rather than watchdog reset, or power-on reset), startup calls patchList.applyPatches() to install the contents of the patch list. Figure 49 illustrates the process used to install the patch list.
In order to ensure a deterministic initialization sequence, the System Startup unit declares all global class instances in one file, globals.C. In general, system is initialized from the bottom up. The device classes are declared first, followed by the executive classes, followed by command handlers, and other protocols classes. Finally, the application classes, are declared. The exact order of the global class declarations (and subsequent initialization) is determined by the final implementation, and shall be provided in the AS-BUILT Detailed Design (MIT 36-53200).
The System Startup uses patchable, initialized Nucleus RTX Configuration structures to configure the system's tasks, semaphores, and event groups. Since the memory partitions and queues are coupled to and rely entirely on the allocation of telemetry buffers in the Back End Processor's bulk memory, the System Startup uses a telemetry buffer configuration table to determine which telemetry buffer pools are required, the size of the packets maintained by each pool, and the number of buffers in each pool. The main initialization routine, startup(), calls setupRtx() to initialize the RTX memory partition and queue structures corresponding to each telemetry buffer pool, and establish the total number of telemetry packets in the instrument. This total is then used to initialize the RTX queue used for the telemetry manager's (TlmManager) telemetry packet buffer transmission queue.
Uses:
PatchList
Nucleus RTX
BepReg
TaskManager
Interface:
Operations:
asm_loadFromRom() asm_startup() main() setupRtx() startup()
Hierarchy:
Superclasses:
none
Implementation Uses:
Mongoose
Public Interface:
Operations:
addPatch() applyPatches() isValid() removePatch()
Protected Interface:
Operations:
computeChecksum() findPatch() updateChecksum()
Private Interface:
Has-A Relationships:
Arguments:
unsigned patchId
unsigned* dstAddress
unsigned datalen
const unsigned* patchData
Documentation:
This function adds a patch to the system patch list. patchId is the identifier for the patch to add. dstAddress is the destination address that the patch is written to when applied the next time the instrument receives a commanded reset. datalen is the number of 32-bit data words in the patch, and patchData points to the data belonging to the patch. If a patch already exists with the same patchId, the function returns BoolFalse and the patch is not installed. If no conflicting patch is found, the new patch is appended to the end of the patch list and the function returns BoolTrue.
Arguments:
unsigned patchId
Documentation:
This function searches the patchlist for the patch entry associated with patchId and returns a pointer to the start of the patch. If no such patch is found, the function returns 0. The function uses mongoose.icacheRead() to obtain the end point of the list. It then traverses the list until it reaches the end point, or it finds a patch whose identifier matches patchId. If it finds a match, the function returns the address of the matching patch. If not, it returns 0.
Arguments:
unsigned patchId
Documentation:
This function searches the patch list for a patch containing patchId. If found, the function removes the patch from the list and returns BoolTrue. If the patch is not found, it returns BoolFalse.