<< Previous | Index | Next >> | |
|
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:
- Provides a variety of low-level services for the user's program.
- Takes care of microprocessor system initialization.
- Provides the communications services required by Dynamic C for downloading code and performing debugging services such as setting breakpoints or examining data variables.
- Defines the setup of memory.
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.
- The four memory bank control registers --
MB0CR
,MB1CR
,MB2CR
, andMB3CR
--are 8-bit registers, each associated with one quadrant of the 1M memory space. Each register determines which memory chip will be mapped into its quadrant, how many wait states will be used for accessing that memory chip, and whether the memory chip will be write protected.- The
STACKSEG
register is an 8-bit register that determines the location of the stack segment in the 1M memory.- The
DATASEG
register is an 8-bit register that determines the location of the data segment in the 1M memory, normally the location of the data variable space.- The
SEGSIZ
E register is an 8-bit register holding two 4-bit registers. Together the registers determine the relative size of the base segment, data segment and stack segment in the 64K root space.- The
MMIDR
register is an 8-bit register used to force /CS1 to be always enabled or not. Having /CS1 always enabled reduces power consumption.- The
XPC
register is used to address extended memory. Normally the user's code frequently changes this register. The BIOS sets the initial value.- The
SP
register is the system stack pointer. It is frequently changed by the user's code. The BIOS sets up an initial value.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:
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
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
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 andwcodorg
) grow up. All non-constant data sections (rvarorg
) grow down. Root constants are generated to thercodorg
region.xdata
andxstring
are generated to the currentxcodorg
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
andresume
are action-expressions. They tell the compiler to generate code or data in the memory region specified by identifier. Anapply
action resets the code or data pointer for the specified region to the starting physical address of the region and makes the region active. Aresume
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
orresume
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
#rcodorg mycode 0x0 0x5500 0x500 follows yourcode
tells the compiler to activate
mycode
whenyourcode
is full. This action does an implicitresume
on the memory region identified byyourcode
. In this example, the implicitresume
also generates a jump tomycode
whenyourcode
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 causedyourcode
to overflow, the data would be written to the memory region identified bymycode
.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 thesplitbin
option on,hello1.bin
andhello2.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 onlydebug
ornodebug
code in that physical memory region. If debug-expression is not specified, the declaration is treated as anall
region. Anall
region can have bothdebug
andnodebug
code. Activating anall
region (by usingapply
orresume
) will cause bothdebug
andnodebug
regions to become inactive. If anall
region is active, bothdebug
andnodebug
regions must be made active to entirely deactivate theall
region. In other words, if anall
region is active and adebug
region is activated, anynodebug
code will still be generated to theall
region until anodebug
region is made active.With regard to follow-expressions, a
debug
region may not follow anodebug
region or vice versa. Anall
region may follow either adebug
or anodebug
region. Only anall
region may follow anotherall
region. This allowsdebug
andnodebug
regions to spill into a commonall
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.
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 |