The <flash.h> Header File

Low-level routines for working with the Flash ROM

Functions

BatTooLowFlash
Checks if the battery level is (or ever was) too low to write to the Flash memory.
EM_abandon
Abandon an archive memory block.
EM_blockVerifyErase
Verifies if an archive block is erased.
EM_findEmptySlot
Finds an empty space in the archive memory of the given size.
EM_GC
Performs garbage collection in the archive memory.
EM_getArchiveMemoryBeginning
Returns a pointer to the first byte of the archive memory area.
EM_survey
Collects some useful information about the archive memory.
EM_write
Writes a block into the extended memory.
FL_addCert
Adds a certificate.
FL_download
Installs the product code.
FL_getCert
Gets a certificate.
FL_getHardwareParmBlock
Gets a pointer to the hardware parameter block.
FL_getVerNum
Gets a Flash ROM verification number.
FL_write
Writes a block into the Flash ROM.

Global Variables

CappedHW1ArchiveMemoryBeginning
The address where AMS 2.xx and 3.xx cap the beginning of the archive memory on HW1 calculators.
FlashMemoryEnd
A pointer to the first byte after the end of the archive memory.

Constants

FLASH_SECTOR_SIZE
Size of a Flash sector.
NULL
A null-pointer value.

Predefined Types

Bool
An enumeration to describe true or false values.
HANDLE
Represents a handle associated with an allocated memory block.
HARDWARE_PARM_BLOCK
Structure describing the calculator hardware.
size_t
A type to define sizes of strings and memory blocks.

Note: The functions EM_blockErase, EM_blockVerifyErase, EM_delete, EM_writeToExtMem, EM_open, and EM_put, which were present in the AMS 1.xx TIOS jump table, don't exist in the AMS 2.xx TIOS jump table any more. This is a pity; some of them were useful (especially the last three of them).
In AMS 2.xx: EM_blockErase is replaced by: OSFastArrows.
EM_delete is replaced by: AB_getGateArrayVersion.
EM_open is replaced by: SetAlphaStatus.
EM_put is replaced by: GetAlphaStatus.
It seems that EM_writeToExtMem was simply removed, and there is no function replacing it.

In addition to the functions defined here, three other functions which work with the archive memory are defined in the vat.h header file: EM_moveSymFromExtMem, EM_moveSymToExtMem and EM_twinSymFromExtMem. Maybe these functions are the most useful functions for working with the archive memory. They are defined in vat.h because they are related to other functions and data structures defined in that header file.


BatTooLowFlash

AMS 2.00 or higher

short BatTooLowFlash (unsigned short delay);

Checks if the battery level is (or ever was) too low to write to the Flash memory.

BatTooLowFlash returns TRUE if the battery level is (or ever was) too low to write to the Flash memory, and FALSE otherwise. If delay is non-zero, and USER_TIMER is not already in use, a delay of delay will occur before any checking is done.

For information about USER_TIMER, see OSRegisterTimer.


EM_abandon

void EM_abandon (HANDLE h);

Abandon an archive memory block.

EM_abandon abandons an archive memory block associated with handle h. More precise, it frees the handle by clearing the entry in the heap table, and precedes memory block with flag which indicate that the block is free.

Note: Functions like EM_blockErase are removed in AMS 2.xx to increase the life of the Flash ROM. Really, it is not necessary to erase a block psyhically. It is quite enough to mark it as "deleted", and it will be eventually simply be rewritten later.


EM_blockVerifyErase

short EM_blockVerifyErase (void *src);

Verifies if an archive block is erased.

EM_blockVerifyErase returns TRUE if an archive block of 64KB size is erased (i.e filled with 0xFFFFFFFF), and FALSE otherwise. It is used in the reset routine of AMS 2.xx.

Note: This function behaves differently on AMS 1.xx and AMS 2.xx:


EM_findEmptySlot

void *EM_findEmptySlot (unsigned long Size);

Finds an empty space in the archive memory of the given size.

EM_findEmptySlot returns a pointer to a place in the archive memory which is large enough to store a block which is Size bytes long. It returns NULL if the requirement cannot be satisfied. In such case, a garbage collection (see EM_GC) is recommended, and there is a chance that a next call of EM_findEmptySlot will be successful. If not, there is really not enough space in the archive memory for a block of the given size. Thanks to Johan Eilert for information how this function should be defined to work on both AMS 1.xx and AMS 2.xx.

Note: The pointer returned by EM_findEmptySlot points to the place where the actual block needs to be stored (see EM_write), not to the place where the header of the block should be stored. The header begins 4 bytes before returned value on AMS 1.xx and 22 bytes before returned value on AMS 2.xx. Note that you need to write a header for each stored block if you don't want problems. See EM_write for more info.


EM_GC

short EM_GC (short allowDialog);

Performs garbage collection in the archive memory.

EM_GC performs garbage collection, i.e. rearranges blocks in the archive memory on such way that all used blocks become contiguous, without free blocks between them. If allowDialog is TRUE, a confirmation dialog will be displayed, and if it is FALSE, the garbage collection will be performed without asking user for the confirmation. EM_GC returns TRUE if garbage collection occured, otherwise it returns FALSE.


EM_getArchiveMemoryBeginning

AMS 2.00 or higher

unsigned char * EM_getArchiveMemoryBeginning(void);

Returns a pointer to the first byte of the archive memory area.

This ROM_CALL first calls OO_GetEndOfAllFlashApps and rounds the result up to the next Flash sector boundary (multiple of 64 KB). Then, it calls a subroutine which, on two hardware models, increases the address to artificially reduce the amount of usable archive memory (MaxMem, XPand and tiosmod+amspatch nullify this code):

Finally, it returns the result to the user.

The capping described above can be defeated on both hardware models. This ROM_CALL and OO_GetEndOfAllFlashApps can be used to detect whether the capping was defeated.

See also: OO_GetFirstFlashAppSectorAddress, CappedHW1ArchiveMemoryBeginning


EM_survey

void EM_survey (unsigned long *inUse, unsigned long *freedByGC, unsigned long *free, unsigned long *unusedSectors, unsigned long *badSectors, unsigned long *allExceptBaseCode);

Collects some useful information about the archive memory.

EM_survey collects some useful information about the archive memory and stores them in six variables pointed to by arguments. *inUse is the number of used bytes. *freedByGC is the number of bytes which will be freed by performing garbage collection (see EM_GC). free is the number of free bytes (not counting bytes occupied by "deleted" blocks, which will become "free" only after the garbage collection). *unusedSectors is the number of bytes in "unused" sectors. I don't know why the archive memory contains usually one unused sector (i.e. sector which is never used for archiving purposes). The program called "MoreMem" just marks such unused sectors as "sectors in use" to get more archive memory (?). *badSectors is the number of bytes in bad sectors, but I am not so sure what "bad sectors" really means. *allExceptBaseCode is the number of all bytes in the Flash ROM which are not occupied by TIOS. This argument is new in AMS 2.xx, but you must use six arguments even on AMS 1.xx. If you don't need a particular information, you may pass NULL as the argument. TIOS will see it's a null pointer and will not save anything in it.

TIOS uses only freedByGC and free and always passes NULL to everything else. *freedByGC + *free is used to tell the user how much archive memory is available. Thanks to Johan Eilert for information how EM_survey should be used correctly on both AMS 1.xx and AMS 2.xx.


EM_write

void EM_write (const void *src, void *dest, unsigned long size);

Writes a block into the extended memory.

EM_write is mostly identical as FL_write, except an error will be thrown if dest points out of the archive memory (i.e. user portion of the Flash ROM).

Note: For anybody who wants to write something into the archive memory, the following information may be useful:

Function EM_findEmptySlot may be used for finding an empty space in the archive memory of a given size. Of course, if you are not an experienced programmer, avoid direct writing in the archive memory. Use safe high-level functions like EM_moveSymToExtMem instead.


FL_addCert

unsigned short FL_addCert (void *src, unsigned long size);

Adds a certificate.

FL_addCert adds size bytes long certificate pointed to by src to the Flash ROM (see cert.h for more info). Returns certificate error code (I don't know too much about its meaning). It is unlikely that this routine may be efficiently used without cooperation with TI.


FL_download

void FL_download (unsigned long dummy);

Installs the product code.

FL_download installs the product code (there is no exit from this routine). It calls startup boot code, reinstates vector table, then enters a receiving loop. It seems that parameter dummy is ignored.


FL_getCert

void FL_getCert (HANDLE *hDest, unsigned long *len, short decrypt);

Gets a certificate.

FL_getCert allocates a space in the RAM and stores in it all relevant information which can be collected from the certificate area of Flash ROM (which is read-protected). It stores a handle of allocated space to a variable pointed to by hDest, and stores the length of it in the variable pointed to by len. decrypt is a Boolean parameter, which determines whether the crypted part of the certificate will be stored or not (it will be decrypted before storing, so crypted parts of the certificate are always invisible). See cert.h header file for more info.


FL_getHardwareParmBlock

const void *FL_getHardwareParmBlock (void);

Gets a pointer to the hardware parameter block.

FL_getHardwareParmBlock returns a pointer to a HARDWARE_PARM_BLOCK structure describing the hardware. If the parameter block of the boot code is not found, it returns the address of the default parameter block.


FL_getVerNum

unsigned short FL_getVerNum (void);

Gets a Flash ROM verification number.

FL_getVerNum returns the encrypted Flash ROM verification number from the Flash ROM certificate.


FL_write

void FL_write (const void *src, void *dest, unsigned long size);

Writes a block into the Flash ROM.

FL_write writes a size bytes long block which begins at address pointed to by src (RAM or Flash memory) into the Flash ROM at the address dest. Writing is allowed only to the user portion of the Flash ROM (also known as "archive memory"), which starts at an address depending on the hardware model and OS version.
The general rule on AMS 2.xx and 3.xx is that storage for FlashApps starts at the first sector boundary after the end of the OS, and that the archive memory starts at the first sector boundary after the end of the FlashApps. There is always at least one sector for FlashApps, even if it's empty. See EM_getArchiveMemoryBeginning for the exceptions to this general rule.
User portion of the Flash ROM ends at 0x400000 (TI-89), 0x600000 (TI-92 Plus, V200) or 0x800000 (TI-89T). Any attempt to write something out of this region will be ignored. Attempts to read the Flash memory (in Protection disabled mode) are, however, not filtered.


CappedHW1ArchiveMemoryBeginning

AMS 2.00 or higher

unsigned char *const CappedHW1ArchiveMemoryBeginning;

The address where AMS 2.xx and 3.xx cap the beginning of the archive memory on HW1 calculators.

This ROM call points to ROM_base+0x190000, i.e. the address where the archive memory starts on HW1 calculators running AMS 2.00+.
This is because AMS 2.00+ versions cap the beginning the archive memory, effectively decreasing the amount of archive memory available to users by 192 or 256 KB (depending on the AMS version).

There's a way around this limitation, see EM_getArchiveMemoryBeginning.

See also: EM_getArchiveMemoryBeginning


FlashMemoryEnd

AMS 2.00 or higher

unsigned char *const FlashMemoryEnd;

A pointer to the first byte after the end of the archive memory.

FlashMemoryEnd can be used in a function reading the archive memory like this:

void ReadSomethingInArchive(unsigned char *start)
{
  unsigned char *end = FlashMemoryEnd;
  for (; start < end; start++)
    {
      // Read something here...
    }
}

See also: ROM_base


FLASH_SECTOR_SIZE

#define FLASH_SECTOR_SIZE (0x10000)

Size of a Flash sector.

On TI-68k calculators, a flash sector is 64 KB (65536 bytes).


HARDWARE_PARM_BLOCK

typedef struct {
unsigned short len; /* length of parameter block */
unsigned long hardwareID; /* 1 = TI-92 Plus, 3 = TI-89, 8 = V200, 9 = TI-89T */
unsigned long hardwareRevision; /* hardware revision number */
unsigned long bootMajor; /* boot code version number */
unsigned long bootRevision; /* boot code revision number */
unsigned long bootBuild; /* boot code build number */
unsigned long gateArray; /* gate array version number */
unsigned long physDisplayBitsWide; /* display width */
unsigned long physDisplayBitsTall; /* display height */
unsigned long LCDBitsWide; /* visible display width */
unsigned long LCDBitsTall; /* visible display height */
} HARDWARE_PARM_BLOCK;

Structure describing the calculator hardware.

The hardware parameter block contains a description of the calculator hardware. This structure is mainly used with the FL_getHardwareParmBlock function.

Some fields of the HARDWARE_PARM_BLOCK structure are not available in earlier versions of the calculator. Only the len and hardwareID fields are available in all boot code versions. It is important to check the value of len before accessing any values after hardwareID. You can use offsetof to determine if a particular field is present.

The TI-89 / 89T and TI-92 Plus / V200 allocate the same amount of memory for the LCD. However, the TI-89 / 89T cannot display as much as the TI-92 Plus / V200. LCDBitsWide and LCDBitsTall reflect how much of the calculator's LCD memory the user can see.

If len is 24 or more, gateArray contains a hardware version number (currently 1 (HW1) or 2 (HW2) for 89, 92+ and V200; 3 (HW3) or 4 (HW4) for 89T). Otherwise, the calculator is certainly a HW1 calculator.

Here is an example (called "Hardware Parameters") which returns the complete hardware parameter block as a list:

// Return the hardware parameter block as a list

#define USE_TI89              // Compile for TI-89
#define USE_TI92PLUS          // Compile for TI-92 Plus
#define USE_V200              // Compile for V200

#define RETURN_VALUE          // Return Pushed Expression
#define MIN_AMS 100           // Compile for AMS 1.00 or higher

#include <tigcclib.h>         // Include All Header Files

// Main Function
void _main(void)
{
  const HARDWARE_PARM_BLOCK *hpb = FL_getHardwareParmBlock ();
  const unsigned long *curptr;
  push_END_TAG ();
  for (curptr = (const unsigned long *) &(hpb->hardwareID) + hpb->len / 4 - 1; (unsigned long) curptr > (unsigned long) hpb; curptr--)
    {
      push_quantum (*curptr);
      push_quantum (1);
      push_quantum (POSINT_TAG);
    }
  push_quantum (hpb->len);
  push_quantum (1);
  push_quantum (POSINT_TAG);
  push_LIST_TAG ();
}

See also: FL_getHardwareParmBlock


Return to the main index