[Bootloader]

- use full featured exception handler
- cleaned up Linker script
- added exception and interrupt processing


git-svn-id: http://moon:8086/svn/mips@26 a8ebac50-d88d-4704-bea3-6648445a41b3
This commit is contained in:
2015-05-27 18:56:09 +00:00
parent 9c1ca0aaf3
commit ca387a1ef4
5 changed files with 204 additions and 52 deletions
+10 -7
View File
@@ -31,14 +31,15 @@ ROMGEN=$(MIPS_HOME)/tools/romgen
all: bootloader_flash
libsys: startup_boot.S kernel_boot.S libsys_boot.c
libsys: startup_boot.S kernel_boot.S libsys_boot.c ../libsys/xcpt.c
$(CC) $(CFLAGS) -c startup_boot.S -o startup.o
$(CC) $(CFLAGS) -c kernel_boot.S -o kernel.o
$(CC) $(CFLAGS) -c libsys_boot.c -o libsys.o
$(CC) $(CFLAGS) -c ../libsys/xcpt.c -o xcpt.o
bootloader: libsys bootloader.c
$(CC) $(CFLAGS) -g -c bootloader.c
$(LD) $(LFLAGS) $(LIB_DIRS) startup.o kernel.o libsys.o bootloader.o -o $@.elf $(LIBS) >$@.map
$(LD) $(LFLAGS) $(LIB_DIRS) startup.o kernel.o xcpt.o libsys.o bootloader.o -o $@.elf $(LIBS) >$@.map
$(OBJDUMP) -D $@.elf > $@.dis
$(OBJCOPY) $@.elf -O binary $@.ROM.bin
$(OBJCOPY) -O srec $@.elf $@.srec
@@ -53,13 +54,15 @@ bootloader_flash: libsys bootloader_with_flash.c
$(OBJCOPY) -O srec $@.elf $@.srec
$(ROMGEN) $@.ROM.bin 11 $(ENDIAN_FLAGS)
test: libsys test.c
test: libsys test.c ../libsys/irq.c ../libsys/xcpt.c
$(CC) $(CFLAGS) -g -c test.c
$(LD) $(LFLAGS) $(LIB_DIRS) startup.o kernel.o libsys.o test.o -o $@.elf $(LIBS) >$@.map
$(OBJDUMP) -d $@.elf > $@.dis
$(OBJCOPY) $@.elf -O binary $@.ROM.bin
$(CC) $(CFLAGS) -g -c ../libsys/irq.c
$(CC) $(CFLAGS) -g -c ../libsys/xcpt.c
$(LD) $(LFLAGS) $(LIB_DIRS) startup.o kernel.o libsys.o irq.o xcpt.o test.o -o $@.elf $(LIBS) >$@.map
$(OBJDUMP) -D $@.elf > $@.dis
$(OBJCOPY) $@.elf -j ROM --output-target=binary $@.ROM.bin
$(OBJCOPY) -O srec $@.elf $@.srec
$(ROMGEN) $@.ROM.bin 10 $(ENDIAN_FLAGS)
$(ROMGEN) $@.ROM.bin 11 $(ENDIAN_FLAGS)
clean:
rm -rf *.o *.bin *.map *.dis *.srec *.elf *.vhd* *.tcl bootloader > /dev/null
+3 -14
View File
@@ -18,27 +18,16 @@ sys_timer_sec = 0xA000000C;
SECTIONS
{
.init ORIGIN(rom) :
ROM :
{
start = ALIGN(4);
entry = ALIGN(4);
_entry = ALIGN(4);
__entry = ALIGN(4);
*(.init)
} > rom
.ktext ORIGIN(rom) + 0x180 :
{
. = ORIGIN(rom) + 0x180;
*(.ktext)
} > rom
.text . :
{
*(.text)
} > rom
.rodata . :
{
*(.text*)
*(.rodata*)
} > rom
+173 -26
View File
@@ -1,3 +1,6 @@
#include <regdef.h>
#include <xcpt_asm.h>
.file "kernel.S"
.section .ktext,"ax"
@@ -13,34 +16,178 @@
addiu $sp, -4
.endm
_exc_handler:
.set noreorder
LEAF(_xcpt_handler)
.set noreorder
.set noat
/* Note: exceptions do not save and restore registers k0 and k1.
* on entry, k1 = exception class.
*/
# Set Error LED and ExcCode LEDs
# Get Cause
mfc0 $26, $13
li $27, 0xC0000000
srl $26, 2
andi $26, 0x000F
or $26, $27
la $27, sys_led_port
sw $26, 0($27)
/* allocate exception stack frame (on 8-byte boundary) */
subu k1, sp, XCP_SIZE
srl k1, 3 /* shift right/left -> alligned on boundary */
sll k1, 3
# wait for all interrupts = 0
$w4x: mfc0 $26, $13
nop
srl $26, 8
andi $26, 0xFF
bnez $26, $w4x
nop
/* save enough registers to get by */
sw AT, XCP_AT(k1)
sw v0, XCP_V0(k1)
sw v1, XCP_V1(k1)
sw a0, XCP_A0(k1)
sw a1, XCP_A1(k1)
sw a2, XCP_A2(k1)
sw a3, XCP_A3(k1)
sw sp, XCP_SP(k1)
sw ra, XCP_RA(k1)
# Get return address
mfc0 $26, $14
/* get coprocessor 0 exception state */
mfc0 a0, CP0_CR
mfc0 a1, CP0_SR
mfc0 a2, CP0_BADDR
mfc0 a3, CP0_EPC
# Return
nop
jr $26
/* we can safely use AT now */
.set at
/* switch to using sp to point at exception frame */
move sp, k1
/* nothing sensible to store for k0/k1, store zero */
sw zero, XCP_K0(sp)
sw zero, XCP_K1(sp)
/* we are now interruptible: dump all remaining state
* into the exception stack frame.
*/
/* coprocessor exception state */
sw a0, XCP_CR(sp)
sw a1, XCP_SR(sp)
sw a2, XCP_BADDR(sp)
sw a3, XCP_EPC(sp)
/* mdhi and mdlo */
mfhi v0
mflo v1
sw v0, XCP_MDHI(sp)
sw v1, XCP_MDLO(sp)
/* Save all the other general registers.
* We save zero, s0-s7 and s8 as well, as instruction emulators (e.g. FP
* operations) and debuggers rely on all registers stored together in
* well-defined structure.
*/
sw zero, XCP_ZERO(sp)
sw t0, XCP_T0(sp)
sw t1, XCP_T1(sp)
sw t2, XCP_T2(sp)
sw t3, XCP_T3(sp)
sw t4, XCP_T4(sp)
sw t5, XCP_T5(sp)
sw t6, XCP_T6(sp)
sw t7, XCP_T7(sp)
sw s0, XCP_S0(sp)
sw s1, XCP_S1(sp)
sw s2, XCP_S2(sp)
sw s3, XCP_S3(sp)
sw s4, XCP_S4(sp)
sw s5, XCP_S5(sp)
sw s6, XCP_S6(sp)
sw s7, XCP_S7(sp)
sw t8, XCP_T8(sp)
sw t9, XCP_T9(sp)
sw gp, XCP_GP(sp)
sw s8, XCP_S8(sp)
/* I don't know what the following does. [rb] */
/* load our _gp pointer */
# la gp, _gp
/* and call the C exception handler */
move a0, sp # arg1 = &xcp
subu sp, 16 # (arg save area)
j _xcpt_call
move ra, zero # fake return address
/* This strange call to _xcpt_call with zero return address is to
* help exception-aware debuggers to trace back over the exception event.
* We are basically interposing a bogus stackframe (with a zero return
* address) between the C exception handler and the actual machine
* exception.
*/
$xcptrest:
.set noat
add AT, sp, 16
/* at points to exception frame */
$xcptrestother:
/* restore all state */
/* restore most general registers */
lw t0, XCP_T0(AT)
lw t1, XCP_T1(AT)
lw t2, XCP_T2(AT)
lw t3, XCP_T3(AT)
lw t4, XCP_T4(AT)
lw t5, XCP_T5(AT)
lw t6, XCP_T6(AT)
lw t7, XCP_T7(AT)
lw s0, XCP_S0(AT)
lw s1, XCP_S1(AT)
lw s2, XCP_S2(AT)
lw s3, XCP_S3(AT)
lw s4, XCP_S4(AT)
lw s5, XCP_S5(AT)
lw s6, XCP_S6(AT)
lw s7, XCP_S7(AT)
lw t8, XCP_T8(AT)
lw t9, XCP_T9(AT)
lw gp, XCP_GP(AT)
lw s8, XCP_S8(AT)
/* mdhi and mdlo */
lw v0, XCP_MDHI(AT)
lw v1, XCP_MDLO(AT)
mthi v0
mtlo v1
/* remaining general registers */
lw a0, XCP_A0(AT)
lw a1, XCP_A1(AT)
lw a2, XCP_A2(AT)
lw a3, XCP_A3(AT)
lw ra, XCP_RA(AT)
/* restore the exception-time status register */
.set noreorder
lw v0, XCP_SR(AT)
nop
mtc0 v0, CP0_SR
lw v1, XCP_V1(AT)
lw v0, XCP_V0(AT)
lw sp, XCP_SP(AT)
/* we are not uninterruptible and can use k1 safely */
lw k1, XCP_EPC(AT)
lw AT, XCP_AT(AT)
mtc0 k1, CP0_EPC
j k1
rfe
.set reorder
.set reorder
.set at
END(_xcpt_handler)
LEAF(_xcpt_call)
/* on entry: a0 == &xcp */
subu sp, 24
sw ra, 16(sp)
/* punt out to _xcpt_deliver */
jal _xcpt_deliver
nop
lw ra, 16(sp)
addu sp, 24
beqz ra, $xcptrest
nop
j ra
nop
END(_xcpt_call)
+10
View File
@@ -7,6 +7,16 @@
#include "libsys_boot.h"
// ---------------------------------------------------------------------------------
void _exit(int reason)
{
}
void libsys_init()
{
// Initialzie interrupt support
interrupt_init();
}
// MIPS specific
uint32_t CP0_SR_read(void)
{
+8 -5
View File
@@ -3,6 +3,7 @@ void main()
{
uint32_t i;
volatile uint32_t *pUART0_stat = (uint32_t*)SYS_UART_STAT;
volatile uint32_t *pGPIO = (uint32_t*)SYS_GPIO_0_DATA;
volatile uint32_t *pGPIODIR = (uint32_t*)SYS_GPIO_0_DIR;
volatile uint32_t *pRAM = (uint32_t*)SDRAM_BASE;
@@ -10,21 +11,23 @@ void main()
*pGPIODIR = GPIO_0_DFLT_DIR;
uint8_t led = 0;
// UART: enable RX interrupt
*pUART0_stat |= (1 << 6);
interrupt_enable(3);
sputs("Hello, world!\n");
while(1)
{
sputs("Iteration # ");print_word(led);sputs("\n");
sputs("Uart status : ");print_word(*pUART0_stat);sputs("\n");
sputs("CPU status : ");print_word(CP0_SR_read());sputs("\n");
*pGPIO = led;
if(led == 0)
{
memdump((uint8_t*)pRAM, 0, 16, 256);
}
*pGPIO = led;
for (i=0; i < 1024*1024; i++)
{
pRAM[i] = i;
}
led = (led+1) % 64;
}
*pGPIO = 1;