Difference between revisions of "Bootloader"
(→Interrupt Vector) |
(→Interrupt Vector) |
||
Line 13: | Line 13: | ||
jnz 00001$ | jnz 00001$ | ||
mov a, (_IrqVector+1) | mov a, (_IrqVector+1) | ||
− | jz 00002$ | + | jz 00002$ |
00001$: ; if not 0, then we need to jump to it | 00001$: ; if not 0, then we need to jump to it | ||
mov dpl, _IrqVector | mov dpl, _IrqVector | ||
mov dph, (_IrqVector+1) | mov dph, (_IrqVector+1) | ||
mov a, #0x23 ; this is the offset for uart irq | mov a, #0x23 ; this is the offset for uart irq | ||
− | jmp @a+dptr | + | jmp @a+dptr |
00002$: ; if it's 0, then we'll handle the irq | 00002$: ; if it's 0, then we'll handle the irq | ||
lcall _uartInterrupt ; call our own interrupt handler | lcall _uartInterrupt ; call our own interrupt handler |
Revision as of 02:35, 13 December 2006
Overview
Interrupt Vector
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. Instead, we have to re-target each interrupt separately.
The following code shows how it's done in DSerial bootloader.
<cpp> 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 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> __data __at (0x7e) unsigned int IrqVector;
void main() { // ... IrqVector = 0x0800; EA = 1; // Global interrupt enable // ... } </cpp>