<< Previous | Index | Next >>

Chapter 4. How Dynamic C Cold Boots the Target System

Dynamic C assumes that target controller boards using the Rabbit CPU have no pre-installed firmware. Dynamic C takes advantage of the Rabbit's bootstrap (cold boot) mode that allows memory and I/O writes to take place over the programming port.

Figure 4-1. Rabbit Programming Port

The Rabbit programming cable is a smart cable with an active circuit board in its middle. The circuit board converts RS-232 voltage levels used by the PC serial port to CMOS voltage levels used by the Rabbit.

When the programming cable connects a PC serial port to the target controller board, the PC running Dynamic C is connected to the Rabbit as shown in Table 4-1.

PC Serial Port Signal
Rabbit Signal
DTR (output) /RESET (input, reset system)
DSR (input) STATUS (gen purpose output)
TX (serial output) RXA (serial input, chan A)
RX (serial input) TXA (serial output, chan A)
Table 4-1. Programming Port Connections

The programming cable includes an RS-232 to CMOS signal level converter circuit. The level converter is powered from the +5 V or +3.3 V power supply voltage present on the Rabbit programming connector (see Figure 4-1). Plugging the programming cable into the Rabbit programming connector results in pulling the Rabbit SMODE0, SMODE1 (startup mode) lines high. This causes the Rabbit to enter the cold boot mode after reset.

Dynamic C can cold boot the Rabbit-based target system with no pre-existing program installed in the target. The flash memory on the target system can be blank or it may contain any data. The cold boot capability permits the use of soldered-in flash memory on the target. Soldered-in memory eliminates sockets, boot blocks and prom programming devices. However, it is important that the flash memory have its software data protection enabled before it is soldered in.

4.1 How the Cold Boot Mode Works In Detail

The microprocessor starts executing a 12-byte program contained in an internal ROM. The program contains the following code.


; origin zero
00 ld l,n            ; n=0c0h for serial port A
                      ; n=020h for parallel (slave port)
02 ioi ld d,(hl)     ; get address most significant byte
04 ioi ld e,(hl)     ; get least significant byte
06 ioi ld a,(hl)     ; get data (h is ignored)
08 ioi or nop        ; if D(7)==1 ioi, else nop
09 ld (de),A         ; store in memory or I/O
10 jr 0              ; jump back to zero

; note wait states inserted at bytes 3, 5 and 7 waiting
; for serial port or parallel port ready

The contents of the boot ROM vary depending on the settings of the pins SMODE0 and SMODE1 and on the contents of register D bit 7 which determines if the store is to be an I/O store or a data store. If the boot is terminated by storing 0x80 to I/O register 0x24, then when the boot program reaches address zero the boot mode is disabled and instruction fetching resumes at address zero.

Wait states are automatically inserted during the fetching of bytes 3, 5 and 7 in order to wait for the serial or parallel port ready. The wait states continue indefinitely until the serial port is ready. This will cause the processor to be in the middle of an instruction fetch until the next character is ready. While the processor is in this state, the chip select, but not the output enable, will be enabled if the memory mapping registers are such as to normally enable the chip select for the boot ROM address. The chip select will stay low for extended periods while the processor is waiting for the serial or parallel port data to be ready. Additionally, the chip select will go low when a write is performed to an I/O address if the address is such as to enable that chip select if it were a write to a memory address.

4.2 Program Loading Process Overview

The program loading process described here is current through Dynamic C version 7.06.

On start up, Dynamic C first uses the PC's DTR line on the serial port to assert the Rabbit Reset line and put the processor in cold boot mode. Next, Dynamic C uses a four stage process to load a user program:

  1. Load an initial loader (cold loader) via triplets sent at 2400 baud from the PC to a target in cold boot mode.

  2. Run the initial loader and load a secondary loader (pilot BIOS) at 19200 or 57000 baud, depending on the version of Dynamic C.

  3. Run the secondary loader and load the BIOS (as Dynamic C compiles it).

  4. Run the BIOS and load the user program at 115200 baud (after Dynamic C compiles it to a file).

4.2.1 Program Loading Process Details

When Dynamic C starts, the following sequence of events takes place:

  1. The serial port is opened with the DTR line high, closed, then reopened with the DTR line low at 2400 baud. This pulses the reset line on the target low (the programming cable inverts the DTR line) and prepares the PC to send triplets.

  2. A group of triplets defined in the file COLDLOAD.BIN consisting of 2 address bytes and a data byte are sent to the target. The first few bytes sent are sent to I/O addresses to set up the memory mapping unit (MMU) and the memory interface unit (MIU) and do system initialization. The MMU is set up so that RAM is mapped to 0x00000, and flash is mapped to 0x80000.

  3. The remaining triplets place a small initial loader program at memory location 0x00000. The last triplet sent is 0x80, 0x24, 0x80, which tells the CPU to ignore the SMODE pins and start running code at address 0x00000.

  4. The PC now bumps the baud rate on the serial port being used to 19200 or 57000 baud, depending on the version of Dynamic C.

  5. The primary loader measures the crystal speed to determine what divisor is needed to set a baud rate of 19200 (or 57600). The divisor is stored at address 0x4002 for later use by the BIOS, and the programming port is set up to be a 19200 (or 57600) baud serial port.

  6. The program enters a loop where it receives a fixed number of bytes which compose a secondary loader program (pilot.bin sent by the PC) and writes those bytes to memory location 0x4100. After all of the bytes are received, program execution jumps to 0x4100.

  7. The secondary loader does a wrap-around test to determine how much RAM is available, and reads the flash ID. This information is made available for transmittal to Dynamic C when requested.

  8. The secondary loader now enters a finite state machine (FSM) that is used to implement the Dynamic C/Target Communications protocol. Dynamic C compiles the core of the regular BIOS and sends it to the target at address 0x00000 which is still mapped to RAM. Note that this requires that the BIOS core be 0x4000 or less in size.

  9. The FSM checks the memory location 0x4001 (previously set to zero) after receiving each byte. When the compilation and loading to RAM of the BIOS is complete, Dynamic C signals the target that it is time to run the BIOS by sending a one to 0x4001.

  10. The BIOS runs some initialization code including setting up the serial port for 115200 baud, setting up serial interrupts and starting a new FSM.

  11. The BIOS code modifies a jump instruction at the beginning of the program so that the next time it runs, it will skip step 12. It also modifies a byte near the beginning of the program where it stores the baud rate divider to achieve 19200 baud. This constant is used by the serial communications initialization library functions to compute baud rate dividers.

  12. The BIOS copies itself to flash at 0x80000, and switches the mapping of flash and RAM so that RAM is at 0x80000 and flash is at 0x00000. As soon as this remapping is done, the BIOS' execution of instructions begins happening in flash.

  13. Dynamic C is now ready to compile a user program. When the user compiles his program to the target, it is first written to a file, then the file is loaded to the target using the BIOS' FSM. The file is used as an intermediate step because fix-ups are done after the compilation is complete and all unknown addresses are resolved. The fix-ups would cause extra wear on the flash if done straight to the flash.

  14. When the program is fully loaded, Dynamic C sets a breakpoint at the beginning of main and runs the program up to the breakpoint. The board has been programmed, and Dynamic C is now in debug mode.

  15. If the programming cable is removed and the target board is reset, the user's program will start running automatically because the BIOS will check the SMODE pins to determine whether to run the user application or enter the debug kernel.


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