<< Previous | Index | Next >>

Chapter 6. The Rabbit BIOS

When Dynamic C compiles a user's program to a target board, the BIOS (Basic Input-Output System) is compiled first, as an integral part of the user's program. The BIOS is a separate program file that contains the code needed to interface with Dynamic C. It also normally contains a software interface to the user's particular hardware. Certain drivers in the Dynamic C libraries require BIOS routines to perform tasks that are hardware-dependent.The BIOS also:

A single, general-purpose BIOS is supplied with Dynamic C for the Rabbit. This BIOS will allow you to boot Dynamic C on any Rabbit-based system that follows the basic design rules needed to support Dynamic C. The BIOS requires both a flash memory and a 32K or larger RAM or just a 128K RAM for it to be possible to compile and run Dynamic C programs. If the user uses a flash memory from the list of flash memories that are already supported by the BIOS, the task will be simplified. If the flash memory chip is not already supported, the user will have to write a driver to perform the write operation on the flash memory. This is not difficult provided that a system with 128K of RAM and the flash memory to be used is available for testing.

An existing BIOS can be used as a skeleton BIOS to create a new BIOS. Frequently it will only be necessary to change #define statements at the beginning of the BIOS. In this case it is unnecessary for the user to understand or work out the details of the memory setup and other processor initialization.

6.1 Startup Conditions Set Up By the BIOS

The BIOS sets up initial values for the following registers by means of code and declarations.

All together there are 11 MMU and MIU registers that are set up by the BIOS. These registers determine all aspects of the hardware setup of the memory.

In addition, a number of origin declarations are made in the BIOS to tell the Dynamic C compiler where to place different types of code and data. The compiler maintains a number of assembly counters that it uses to place or allocate root code, extended code, data constants, data variables, and extended data variables. Each of these counters has a starting location and a block size.

6.2 BIOS Flowchart

The following flowchart summarizes the functionality of the BIOS:

Figure 6-1. BIOS Flowchart

6.3 Internally Defined Macros

Some macros used in the BIOS are defined internally by Dynamic C before the BIOS is compiled. They are defined using tests done in the bootstrap loading, or by reading variables set in the GUI. These are:

_FLASH_, _RAM_ - Used for conditional compilation of the BIOS to distinguish between compiling to RAM and compiling to flash. These are set in the Options | Compiler dialog box.

_RAM_SIZE_, _FLASH_SIZE_ - Used to set the MMU registers and code and data sizes available to the compiler. The values given by these macros represent the number of 0x1000 blocks of memory available.

_BOARD_TYPE_ - This is read from the System ID block or defaulted to 0x100 (the BL1810 JackRabbit board) if no System ID block is present. This can be used for conditional compilation based on board type.

6.4 Modifying the BIOS

The BIOS can be modified to be more specific concerning the user's configuration. This can be done one step at a time, making it easy to detect any problems. The source code for the Universal BIOS is in BIOS\RABBITBIOS.C. Dynamic C uses this source code for the BIOS by default, but the user can specify another BIOS for Dynamic C to use in the Options | Compiler dialog box.

There are several macros at the top of RABBITBIOS.C that users may want to modify for boards they design or for special situations involving off-the-shelf Rabbit-based boards. Not all of the macros at the top of the BIOS are described here.

USE115KBAUD
The default value of 1 specifies that Dynamic C will communicate at 115,200 baud with the target. If this macro is set to zero, Dynamic C will communicate at 57,600 baud. The lower baud rate might be needed on some PCs that can not handle 115,200 baud. If USE115KBAUD is changed to zero, the baud rate should be changed to 57,600 in the Dynamic C Options | Communications dialog box. Starting with Dynamic C 7.05, USE115KBAUD is not available to change the baud rate, simply choose the baud rate in Options | Communications.
CLOCK_DOUBLED
The default value of 1 causes the clock speed to be doubled if the crystal speed is less than or equal to 12.9 MHz. Setting this to zero means the clock speed will not be doubled.
ENABLE_CLONING
The default value of 0 disables cloning. Setting this to 1 enables cloning and slightly increases the code size of the BIOS. If cloning is used, PB1 should be pulled up with 50K or so pull up resistor. Various cloning options are available when ENABLE_CLONING is set to one. For more information on cloning, please see Chapter 8, "BIOS Support for Program Cloning," in this manual and/or Technical Note 207, Rabbit 2000 Cloning Board, which is available at rabbitsemiconductor.com.
DATAORG
Beginning logical address for the data segment. The default is 0x6000. This should only be changed to multiples of 0x1000. Increasing it increases the root code space available, and decreases root data space; decreasing it has the opposite effect. It can be changed to as low as 0x3000 or as high as 0xB000.
RAM_SIZE
This macro sets the amount of RAM available. The default value is the internally defined _RAM_SIZE_ The units are the number of 4k pages of RAM. In special situations, such as splitting RAM between two coresident programs, this may be modified to a smaller value than the actual available RAM.
FLASH_SIZE
This macro sets the amount of flash available. The default value is the internally defined _FLASH_SIZE_ The units are the number of 4k pages of flash. In special situations, such as splitting flash between two coresident programs, this may be modified to a smaller value than the actual available flash.
CS1_ALWAYS_ON
Keeping /CS1 active is useful if your system is pushing the limits of RAM access time. It will increase power consumption a little. Set to 0 to disable, 1 to enable
WATCHCODESIZE
These define the number of bytes available to the debugger for compiling watch expression. The default values are 0x200/0x060. Decreasing these increases the amount of RAM available for root data.
NUM_RAM_WAITST, NUM_FLASH_WAITST
These define the number of wait states to be used for RAM and flash. The default value for both is 0. The only valid values are 4, 2, 1 and 0.
MB0CR_INVRT_A18, MB1CR_INVRT_A18, MB2CR_INVRT_A18, MB3CR_INVRT_A18
MB0CR_INVRT_A19, MB1CR_INVRT_A19, MB2CR_INVRT_A19, MB3CR_INVRT_A19
These determine whether the MIU registers for each quadrant are set up to invert address lines A18 and A19 after the logical to physical address conversion. This allows each 256K quadrant of physical memory access up to four 256K pages on the actual memory device. These would be used for special compilations of programs to be coresident on flashes between 512k and 1M in size. See Application Note 202, Rabbit Memory Management In a Nutshell, and Application Note 210, Running Two Application on a TCP/IP Development Board for more details.

See the top of the BIOS source code (\BIOS\RabbitBIOS.c) for more options.

6.5 Origin Statements to the Compiler

The Dynamic C compiler uses the information provided by origin statements to decide where to place code and data in both logical and physical memory. The origin statements are normally defined in the BIOS; however, they may also be useful in an application program for certain tasks such as compiling a pilot BIOS or cold loader, or special situations where a user wants two application coresident within a single 256K quadrant of flash.

6.5.1 Origin Statement Syntax

Prior to Dynamic C 7.05, origin statement syntax is:


#<origin type> <origin name> <segment value> <logical address> <size> apply

All arguments are required.

Starting with Dynamic C 7.05, origin statement syntax (in BNF) is:

origin-directive : #origin-type identifier origin-designator

origin-designator : action-expression | origin-declaration

origin-declaration : physical-address size [follow-expression][action-expression] [debug-expression]

origin-type: rcodorg | xcodorg | wcodorg | rvarorg

follow-expression : follows identifier [splitbin]

action-expression : resume | apply

debug-expression : debug | nodebug | all

size : constant-expression

physical-address : constant-expression constant-expression

The non-terminals, identifier and constant-expressions, are defined in the ANSI C specification.

6.5.2 Origin Statement Semantics

An origin statement associates a code pointer and a memory region with a particular type of code. The type of code is specified by #origin-type.

All code sections (rcodorg, xcodorg code and wcodorg) grow up. All non-constant data sections (rvarorg) grow down. Root constants are generated to the rcodorg region. xdata and xstring are generated to the current xcodorg region.

All origin statements must have a unique ANSI C identifier. The scope of this identifier is only with other origin statements or declarations. In the pre 7.05 syntax this is the <origin name>.

Each memory region is defined by calculating a physical address from an 8-bit base address (first constant-expression of physical-address) and a 16-bit logical address (second constant-expression of physical-address). The size of the memory region is determined by 20-bit size. Overflow of these three values is truncated. In the pre 7.05 syntax these three values are <segment value>, <logical address> and <size>.

The keywords apply and resume are action-expressions. They tell the compiler to generate code or data in the memory region specified by identifier. An apply action resets the code or data pointer for the specified region to the starting physical address of the region and makes the region active. A resume action does not reset the code or data pointer, but does make the memory region active.

A region remains active (i.e., the compiler will continue to generate code or data to it) until another region of the same origin-type is activated with an apply or resume action or until the memory region is full.

The option follow-expression is best described with an example. First, let us declare yourcode in an origin statement containing an origin-declaration. A follow-expression can only name a region that has already been declared in an origin-declaration.


#rcodorg yourcode 0x0 0x5000 0x500

then the origin statement:


#rcodorg mycode 0x0 0x5500 0x500 follows yourcode

tells the compiler to activate mycode when yourcode is full. This action does an implicit resume on the memory region identified by yourcode. In this example, the implicit resume also generates a jump to mycode when yourcode is full. For data regions, the data that would overflow the region is moved to the region that follows. Combined data and code regions (like #rcodorg) use both methods, which one is used depends on whether code or data caused the region to overflow. In our example, if data caused yourcode to overflow, the data would be written to the memory region identified by mycode.

Furthermore, a follow-expression may specify that when the code or data resumes at the next region it should generate a separate bin file. This option is designed to support burning multiple flash or EPROM devices. The binary files generated share the same base name as the original file, but appended with a number which is followed by the .bin extension. For example, if hello.c, a large program that spans both flash chips, is compiled to file with the splitbin option on, hello1.bin and hello2.bin will be generated. Obviously, this option is only meaningful when compiling to a file.

The optional debug-expression is only valid with the xcodorg origin-type. It tells the compiler to generate only debug or nodebug code in that physical memory region. If debug-expression is not specified, the declaration is treated as an all region. An all region can have both debug and nodebug code. Activating an all region (by using apply or resume) will cause both debug and nodebug regions to become inactive. If an all region is active, both debug and nodebug regions must be made active to entirely deactivate the all region. In other words, if an all region is active and a debug region is activated, any nodebug code will still be generated to the all region until a nodebug region is made active.

With regard to follow-expressions, a debug region may not follow a nodebug region or vice versa. An all region may follow either a debug or a nodebug region. Only an all region may follow another all region. This allows debug and nodebug regions to spill into a common all region.

6.5.3 Origin Statement Examples

Figure 6-2 shows how the origin statements define the mapping between the logical and physical address spaces.


#define DATASEGVAL  0x91
#rvarorg rootdata   (DATASEGVAL) 0xc5ff 0x6600  apply      // grows down
#rcodorg rootcode   0x00         0x0000 0x6000  apply
#wcodorg watcode    (DATASEGVAL) 0xc600 0x0400  apply
#xcodorg xmemcode   0xf8         0xe000 0x1a000 apply
// data declarations start here

Dynamic C defines macros that include information about compiling to RAM or flash and identifying memory device types, memory sizes, and board type. The origin setup shown above differs from that included in the standard BIOS included with Dynamic C as the standard BIOS uses additional macros values for dealing with a wider range of boards and memory device types.

Figure 6-2. Logical to physical mapping

6.5.4 Origin Directives in Program Code

To place programs in different places in root memory or to compile a boot strapping program, such as a pilot BIOS or cold loader, origin statements may be used in the user's program code.

For example, the first line of a pilot BIOS program, pilot.c, would be


#rcodorg rootcode 0x0 0x0 0x6000 apply

A program with such an origin directive could only be compiled to a .bin file, because compiling it to the target would overwrite the running BIOS.


Rabbit 2000
Designer's Handbook
<< Previous | Index | Next>> rabbit.com