Bootloader
free free ringtones phentermine online soma online real ringtones free jazz ringtones online vicodin zyban online ericsson ringtones sagem ringtones cheap diazepam sharp ringtones cingular ringtones cheap adipex free verizon ringtones qwest ringtones clonazepam online zanaflex online free mtv ringtones free mtv ringtones kyocera ringtones sony ericsson ringtones tenuate online real ringtones cheap valium paxil online cheap didrex order sildenafil free nextel ringtones free midi ringtones cheap ativan xanax online cyclobenzaprine online lorazepam online alltel ringtones didrex online free mp3 ringtones free cingular ringtones tracfone ringtones buy xanax tracfone ringtones order norco cheap fioricet lorazepam online free ringtones viagra online free wwe ringtones buy xanax cheap zoloft free free ringtones sildenafil xenical online samsung ringtones prozac online ultracet online buy norco lipitor motorola ringtones free sagem ringtones meridia online hydrocodone cheap diazepam ativan online cheap norco prozac online sonyericsson ringtones qwest ringtones cheap lisinopril cheap didrex ultram online cialis cheap alprazolam nextel ringtones free cool ringtones lortab online free nextel ringtones order zyban pharmacy online online cheap xanax ativan online sprint ringtones ativan online free sprint ringtones cheap wellbutrin zanaflex online buy carisoprodol cheap propecia buy prozac valium online xanax online free motorola ringtones ortho wellbutrin online cheap levitra fioricet samsung ringtones cheap ortho cool ringtones lorazepam online cheap celexa cheap tramadol free polyphonic ringtones cheap zanaflex free nokia ringtones ortho online samsung ringtones soma online lorazepam online sagem ringtones sprint ringtones buy lipitor mp3 ringtones sprint ringtones buy vigrx polyphonic ringtones cheap lisinopril mp3 ringtones viagra online cingular ringtones cheap tenuate free kyocera ringtones qwest ringtones order norco buy clonazepam cheap sildenafil free nextel ringtones free funny ringtones but cialis cheap ultracet free sprint ringtones diazepam online free ringtones samsung ringtones free ringtones hydrocodone online order tramadol cheap ambien free mtv ringtones free motorola ringtones free funny ringtones free music ringtones cool ringtones cheap fioricet free real ringtones lorazepam cheap soma cheap clomid cheap clonazepam cheap paxil lisinopril online free samsung ringtones sonyericsson ringtones cheap phentermine free alltel ringtones free sprint ringtones clonazepam online buy didrex cheap ultram verizon ringtones cheap celexa but norco buy diethylpropion cheap tenuate free verizon ringtones cheap lipitor buy diazepam free verizon ringtones cheap adipex meridia online samsung ringtones free cingular ringtones clomid lisinopril online carisoprodol online paxil online ericsson ringtones mono ringtones albuterol online free ericsson ringtones cheap ambien levitra online cheap didrex free midi ringtones clomid online cheap lipitor free sagem ringtones cheap meridia free sony ringtones valium online order clomid hoodia free music ringtones hydrocodone but adipex hgh online hgh online cheap levitra tracfone ringtones sony ringtones cheap propecia vicodin online == Overview ==
DSerial bootloader is the program that is the first to run once the C8051F320 microcontroller is powered. It responds to commands from DS on the SPI port and allows to boot DSerial firmware amongst other things.
Contents
Description
The purpose of DSerial bootloader is to:
- Boot DSerial firmware
- Write firmware to internal flash via SPI (other ports may be supported by the bootloader in the future)
- Read internal flash
- Send and receive UART data without booting into firmware (baud rate fixed at 115200 bps)
The following sections will describe how the bootloader functions.
Files
Go to downloads to get the bootloader source code.
Detecting DSerial
Check whether DSerial is inserted using a SPI Flash compatible command:
- DS sends the byte 0x9F (RDID)
- DSerial responds with 0x01 0xAB
This is command is non-destructive to DS game cards. See also DSerial protocol.
Interrupt Vector Table (Currently Used Method)
Interrupt vector table on the C8051F320 is always at offset 0 in FLASH. Unfortunately, we cannot re-target it from bootloader interrupt vector table into the program interrupt vector table with a magic register, since no such register exists in the architecture. Instead, we have to re-target each interrupt separately.
The User Bit in PSW register (also called F1) is used to select bootloader table or firmware table.
<cpp> // Code in bootloader, interrupt.h
/* UART0 interrupt */ void redirS0() __interrupt (4) _naked { _asm push psw jnb psw.1, 00001$ ; if user bit not set, jump to firmware irq
pop psw lcall _uartInterrupt ; otherwise jump to bootloader irq reti
00001$: pop psw ljmp #FIRMWARE_OFFSET IRQ_S0 ; firmware irq _endasm; }
// repeat for the other irqs </cpp>
This code jumps to bootloader interrupt if PSW.1 (also called F1) is set to 1, otherwise it jumps to firmware.
<cpp> // Code in bootloader
void main() { // ... F1 = 1; // relocate interrupts to bootloader EA = 1; // global interrupt enable // ... } </cpp>
<cpp> // Code in firmware
void main() { // ... F1 = 0; // relocate interrupts to FIRMWARE_OFFSET (0x0800) EA = 1; // global interrupt enable // ... } </cpp>
Interrupt Vector Table (Not Used Method)
The following code shows another way that could have been used. It's advantage is that the interrupt vector can be relocated to any address dynamically. The disadvantage is that there's bigger overhead.
<cpp> // Code in bootloader
// Redirects UART IRQ either into our (bootloader's) handler or into firmware handler. void R_uartInterrupt() __interrupt (4) _naked { _asm mov a, _IrqVector ; compare IrqVector to 0 jnz 00001$ mov a, (_IrqVector 1) jz 00002$ 00001$: ; if not 0, then we need to jump to it mov dpl, _IrqVector mov dph, (_IrqVector 1) mov a, #0x23 ; this is the offset for uart irq jmp @a dptr ; call the interrupt handler in firmware 00002$: ; if it's 0, then we'll handle the irq lcall _uartInterrupt ; call our own interrupt handler reti _endasm; }
// repeat for the other irqs </cpp>
IrqVector is a global variable that is set to the location of interrupt vector before enabling interrupts. The bootloader should set IrqVector to 0 while the program should set it to it's location.
<cpp> // Code in firmware
__data __at (0x7e) unsigned int IrqVector;
void main() { // ... IrqVector = 0x0800; // we're relocated to 0x0800 EA = 1; // global interrupt enable // ... } </cpp>