Initial version

Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@272 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2009-01-21 08:52:05 +00:00
parent 25e3d4f36f
commit 8867efa451
50 changed files with 11439 additions and 0 deletions
@@ -0,0 +1,30 @@
ROM_WORDADDR_WIDTH=11
TOOLS_DIR=../../../tools
CFLAGS=-G 0 -O2 -I. -I../ -msoft-float -march=r3000
LFLAGS=-G0 -M -T bootloader.ld
LIB_DIRS=-L /usr/local/mipsel-elf/lib -L /usr/local/lib/gcc/mipsel-elf/4.3.0
LIBS=-lc -lm -lgcc
CC=mipsel-elf-gcc
LD=mipsel-elf-ld
all: bootloader
libsys: startup_boot.S init_boot.S kernel_boot.S libsys_boot.c
$(CC) $(CFLAGS) -c startup_boot.S -o startup.o
$(CC) $(CFLAGS) -c init_boot.S -o init.o
$(CC) $(CFLAGS) -c kernel_boot.S -o kernel.o
$(CC) $(CFLAGS) -c libsys_boot.c -o libsys.o
bootloader: libsys bootloader.c
$(CC) $(CFLAGS) -g -c bootloader.c
$(CC) $(CFLAGS) -g -c ../cfiflash.c
$(LD) $(LFLAGS) $(LIB_DIRS) startup.o init.o kernel.o libsys.o cfiflash.o bootloader.o -o bootloader.elf $(LIBS) >bootloader.map
mipsel-elf-objdump -d bootloader.elf > bootloader.dis
mipsel-elf-objcopy bootloader.elf -O binary bootloader.ROM.bin
mipsel-elf-objcopy -O srec bootloader.elf bootloader.srec
$(TOOLS_DIR)/romgen bootloader.ROM.bin $(ROM_WORDADDR_WIDTH)
clean:
rm -rf *.o *.bin *.map *.dis *.srec *.elf *.vhd* *.tcl bootloader > /dev/null
@@ -0,0 +1,360 @@
#include "libsys_boot.h"
#include "cfiflash.h"
typedef struct _ssrec_t
{
UINT32 addr;
UINT32 size;
UINT32 type;
UINT8 *data;
} srec_t;
typedef struct _sflash_img_hdr_t
{
UINT8 magic[4];
UINT32 target_addr;
UINT32 img_offset;
UINT32 img_size;
UINT32 hdr_next;
UINT8 img_name[128];
UINT8 res[108];
} flash_img_hdr_t;
enum srec_type
{
srec_err, srec_sob, srec_data, srec_rec, srec_eob
};
UINT8 h2i(UINT8 *c)
{
int i;
UINT8 t, b = 0;
for (i=0; i < 2; i++)
{
t = c[i];
if (t >= 'A')
t = t - 'A' + 10;
else
t -= '0';
b = (b << 4) | t;
}
return b;
}
int decode_srec(srec_t *pRec, UINT8 *pBuf, int buflen)
{
UINT8 chksum, byte;
int alen, i;
if (!buflen)
return srec_err;
pRec->type = srec_rec;
alen = 0;
if ((pBuf[1] > '0') && (pBuf[1] < '4'))
{
alen = pBuf[1] - '0' + 1;
pRec->type = srec_data;
}
else if ((pBuf[1] >= '7') && (pBuf[1] <= '9'))
{
alen = 11 - (pBuf[1] - '0');
pRec->type = srec_eob;
}
else if (pBuf[1] == '0')
{
alen = 2;
pRec->type = srec_sob;
}
byte = h2i(&pBuf[2]);
pRec->size = byte;
chksum = byte;
pRec->addr = 0;
for (i=0; i < alen; i++)
{
byte = h2i(&pBuf[4+2*i]);
pRec->addr = pRec->addr << 8 | byte;
chksum += byte;
}
pRec->size -= (alen+1);
pRec->data = (UINT8*) &pBuf[4 + 2*alen];
for (i=0; i < (int)pRec->size; i++)
{
byte = h2i(&pRec->data[2*i]);
pRec->data[i] = byte;
chksum += byte;
}
chksum = ~chksum;
byte = h2i(&pRec->data[2*i]);
if (chksum != byte)
return 0;
return pRec->type;
}
int srec_getline(UINT8 *pLine)
{
char c;
int i = 0;
do
{
c = readchar();
} while ((c != 's') && (c != 'S'));
while(((c != 0x0D) && (c != 0x0A)))
{
pLine[i++] = c;
c = readchar();
};
return i;
}
void Jump_to(void *pEntry)
{
__asm
(
".set noreorder\n"
);
__asm
(
"jr %[pEntry]\n" // jump entry
:
: [pEntry] "r" (pEntry)
);
__asm
(
"nop\n"
);
__asm
(
".set reorder\n"
);
}
void Exec_at(void *pEntry)
{
__asm
(
".set noreorder\n"
);
__asm
(
"mfc0 $26, $12\n" // change exception vector
"li $27, 0xFFBFFFFF\n"
"and $26, $27\n"
"mtc0 $26, $12\n"
);
__asm
(
"jr %[pEntry]\n" // jump entry
:
: [pEntry] "r" (pEntry)
);
__asm
(
"rfe\n"
);
__asm
(
".set reorder\n"
);
}
void PrintCPUinfo(void)
{
int result, rev_id;
char *cpu_type_str[7] = {"invalid", "R2000", "R3000", "R6000", "R4000", "reserved", "R6000A"};
// Print Status register
result = CP0_SR_read();
sputs("Status : ");
print_word(result);
sputs("\n");
// Print Revision
result = CP0_PRID_read();
rev_id = (result >> 8) & 0xFF;
sputs("CPU type: ");
if ((rev_id > 0) && (rev_id < 0x07))
{
sputs(cpu_type_str[rev_id]);
sputs(" Rev.");
rev_id = result & 0xFF;
print_byte((char)rev_id);
}
else
sputs("Unknown");
sputs("\n");
}
#define MAX_IMG_SIZE (1024*1024) // bytes
#define SDRAM_BASE 0x40000000
#define FLASH_OFFSET 0x00000000
int main(int argc, char *argv[])
{
UINT8 buf[256];
srec_t srec;
int result, srec_state, i;
UINT32 haddr;
flash_t flash;
flash_img_hdr_t img_hdr = {0};
flash_img_hdr_t *pImg_hdr;
UINT32 img_size;
volatile UINT32 *pReg = (UINT32*)sys_led_port;
volatile UINT32 *pBtn = (UINT32*)sys_gpio0;
volatile UINT8 *pMem;
volatile UINT32 *pROM32;
volatile UINT32 *pMem32;
volatile UINT32 *pFlash = (UINT32*)sys_flash_io;
volatile UINT32 *pUSB = (UINT32*)sys_usb_data;
volatile UINT8 *ram8 = (UINT8*)SDRAM_BASE;
volatile UINT16 *ram16 = (UINT16*)SDRAM_BASE;
volatile UINT32 *ram32 = (UINT32*)SDRAM_BASE;
*pReg = 0;
haddr = 0;
// ----------------------------------------------------------
ram32 = (UINT32*)(SDRAM_BASE);
pFlash = (UINT32*)(sys_flash_io + FLASH_OFFSET);
if (!*pBtn)
{
sputs("\n\n");
sputs("Booting from flash...");
pImg_hdr = (flash_img_hdr_t*)pFlash;
ram32 = (UINT32*)pImg_hdr->target_addr;
pFlash = (UINT32*)(sys_flash_io + pImg_hdr->img_offset);
img_size = pImg_hdr->img_size;
for (i=0; i < img_size/4; i++)
ram32[i] = pFlash[i];
sputs("done\n\n");
Exec_at((void*)ram32);
}
else
{
if (flash_find(&flash, sys_flash_io) < 0)
{
sputs("Cannot find flash device. Exit now!\n\n");
return 1;
}
// Erase SDRAM
for (i=0; i < MAX_IMG_SIZE/4; i++)
ram32[i] = 0;
sputs("\n\n");
sputs("Booting from UART..");
while(1)
{
sputs(".");
while(1)
{
result = srec_getline(buf);
srec_state = decode_srec(&srec, buf, result);
*pReg = 0;
switch (srec_state)
{
case srec_data:
if ((srec.addr + srec.size) > haddr)
haddr = srec.addr + srec.size;
pMem = (UINT8*)srec.addr;
for (i=0; i < srec.size; i++)
*pMem++ = srec.data[i];
break;
case srec_eob:
sputs("done\n\n");
img_hdr.magic[0] = 'J';
img_hdr.magic[1] = 'F';
img_hdr.magic[2] = 'I';
img_hdr.magic[3] = '1';
img_hdr.target_addr = srec.addr;
img_hdr.img_size = haddr - srec.addr;
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
img_hdr.hdr_next = FLASH_OFFSET;
sputs("Flash erase...");
result = flash_erase(&flash, FLASH_OFFSET, img_hdr.img_size + sizeof(flash_img_hdr_t));
if (result < 0)
{
sputs("failed!\n");
break;
}
sputs("done\n");
sputs("Flash write...");
result = flash_program(&flash, FLASH_OFFSET, (UINT8*)&img_hdr, sizeof(flash_img_hdr_t));
if (result < 0)
{
sputs("failed!\n");
break;
}
result = flash_program(&flash, img_hdr.img_offset, (UINT8*)ram32, img_hdr.img_size);
if (result < 0)
{
sputs("failed!\n");
break;
}
sputs("done\n");
sputs("Flash verify...");
result = flash_verify(&flash, img_hdr.img_offset, (UINT8*)ram32, img_hdr.img_size);
if (result < 0)
{
sputs("failed!\n");
break;
}
sputs("passed\n");
Jump_to((void*)0xBFC00000);
// sputs("\nPush reset button to boot!\n");
// *pReg = 1;
break;
default:
result = -1;
break;
}
if (result < 0)
{
*pReg = 0x40000000;
break;
}
};
}
}
return 0;
}
@@ -0,0 +1,47 @@
MEMORY
{
rom : ORIGIN = 0xBFC00000, LENGTH = 0x00002000 /* 8K */
sram : ORIGIN = 0x40000000, LENGTH = 0x02000000 /* 32M */
}
stack_ptr = 0x7FFFFFF0;
baudrate = 0x0D;
sys_led_port = 0xA0000000;
sys_uart_data = 0xA0010000;
sys_uart_stat = 0xA0010004;
sys_uart_baud = 0xA0010008;
sys_timer_usec = 0xA000008;
sys_timer_sec = 0xA000000C;
SECTIONS
{
.stext ORIGIN(rom) :
{
start = ALIGN(4);
entry = ALIGN(4);
_entry = ALIGN(4);
__entry = ALIGN(4);
*(.stext)
} > rom
.ktext ORIGIN(rom) + 0x180 :
{
*(.ktext)
} > rom
.text . :
{
*(.text)
} > rom
.rodata . :
{
*(.rodata*)
} > rom
.data ORIGIN(rom) :
{
*(.data)
} > rom
}
@@ -0,0 +1,208 @@
.file "init.S"
.text
.align 2
.globl _init
.extern end
_init:
.set noreorder
# set uart
la $26, sys_uart_baud
addiu $27, $0, baudrate
sb $27, 0($26)
# set stack pointer
la $sp, stack_ptr
# j $jmain
# TEST
li $26, +5
beqz $26, _terminate
li $26, -5
beqz $26, _terminate
li $26, 0
beqz $26, $_L11
nop
j _terminate
nop
$_L11:
li $26, +5
li $27, +6
beq $26, $27, _terminate
li $26, -5
beq $26, $27, _terminate
li $26, 0
beq $26, $27, _terminate
li $26, +6
beq $26, $27, $_L12
nop
j _terminate
nop
$_L12:
li $26, -5
bgez $26, _terminate
li $26, +5
bgez $26, $_L13
nop
j _terminate
$_L13: li $26, 0
bgez $26, $_L14
nop
j _terminate
$_L14:
li $26, -5
bgtz $26, _terminate
li $26, 0
bgtz $26, _terminate
li $26, +5
bgtz $26, $_L15
nop
j _terminate
$_L15:
li $26, +5
blez $26, _terminate
li $26, 0
blez $26, $_L16
nop
j _terminate
$_L16: li $26, -5
blez $26, $_L17
nop
j _terminate
$_L17:
li $26, +5
bltz $26, _terminate
li $26, 0
bltz $26, _terminate
li $26, -5
bltz $26, $_L18
nop
j _terminate
$_L18:
li $26, +5
li $27, +6
bne $26, $27, $_L19
nop
j _terminate
$_L19: li $26, -5
bne $26, $27, $_L20
nop
j _terminate
$_L20: li $26, -6
bne $26, $27, $_L21
nop
j _terminate
$_L21: li $26, 0
bne $26, $27, $_L22
nop
j _terminate
$_L22: li $26, +6
bne $26, $27, _terminate
li $26, +5
bnez $26, $_L23
nop
j _terminate
$_L23: li $26, -5
bnez $26, $_L24
nop
j _terminate
$_L24: li $26, 0
bnez $26, _terminate
$_L25:
li $27, +5
sltiu $26,$27,+6
sltiu $26,$27,-6
li $27, -5
sltiu $26,$27,+6
sltiu $26,$27,-6
li $27, +6
sltiu $26,$27,+5
sltiu $26,$27,-5
li $27, -6
sltiu $26,$27,+5
sltiu $26,$27,-5
li $27, +5
slti $26,$27,+6
slti $26,$27,-6
li $27, -5
slti $26,$27,+6
slti $26,$27,-6
li $27, +6
slti $26,$27,+5
slti $26,$27,-5
li $27, -6
slti $26,$27,+5
slti $26,$27,-5
li $26, +5
li $27, +6
sltu $26,$26,$27
li $26, +5
li $27, -6
sltu $26,$26,$27
li $26, -5
li $27, +6
sltu $26,$26,$27
li $26, -5
li $27, -6
sltu $26,$26,$27
li $26, +6
li $27, +5
sltu $26,$26,$27
li $26, +6
li $27, -5
sltu $26,$26,$27
li $26, -6
li $27, +5
sltu $26,$26,$27
li $26, -6
li $27, -5
sltu $26,$26,$27
li $26, +5
li $27, +6
slt $26,$26,$27
li $26, +5
li $27, -6
slt $26,$26,$27
li $26, -5
li $27, +6
slt $26,$26,$27
li $26, -5
li $27, -6
slt $26,$26,$27
li $26, +6
li $27, +5
slt $26,$26,$27
li $26, +6
li $27, -5
slt $26,$26,$27
li $26, -6
li $27, +5
slt $26,$26,$27
li $26, -6
li $27, -5
slt $26,$26,$27
# TEST
# jump main
$jmain: la $26, main
jalr $26
_terminate:
nop
j _terminate
nop
.set reorder
@@ -0,0 +1,45 @@
.file "kernel.S"
.section .ktext,"ax"
.align 2
.macro kpush reg
addiu $sp, 4
sw \reg, 0($sp)
.endm
.macro kpop reg
lw \reg, 0($sp)
addiu $sp, -4
.endm
_exc_handler:
.set noreorder
# Set Error LED and ExcCode LEDs
# Get Cause
mfc0 $26, $13
la $27, sys_led_port
srl $26, 2
andi $26, 0x000F
or $26, $27
sw $26, 0($27)
# wait for all interrupts = 0
$w4x: mfc0 $26, $13
nop
srl $26, 8
andi $26, 0xFF
bnez $26, $w4x
nop
# Get return address
mfc0 $26, $14
# Return
nop
jr $26
rfe
.set reorder
@@ -0,0 +1,142 @@
#include <sys/times.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include "libsys_boot.h"
// ---------------------------------------------------------------------------------
// MIPS specific
UINT32 CP0_SR_read(void)
{
UINT32 result;
__asm
(
"mfc0 %[val], $12\n"
: [val] "=r" (result)
);
return result;
}
void CP0_SR_write(UINT32 val)
{
__asm
(
"mtc0 %[val], $12\n"
: /* no output */
: [val] "r" (val)
);
}
UINT32 CP0_CR_read(void)
{
UINT32 result;
__asm
(
"mfc0 %[val], $13\n"
: [val] "=r" (result)
);
return result;
}
void CP0_CR_write(UINT32 val)
{
__asm
(
"mtc0 %[val], $13\n"
:
: [val] "r" (val)
);
}
UINT32 CP0_PRID_read(void)
{
UINT32 result;
__asm
(
"mfc0 %[val], $15\n"
: [val] "=r" (result)
);
return result;
}
// ---------------------------------------------------------------------------------
char readchar(void)
{
volatile UINT32 *pUART_stat = (UINT32*)sys_uart_stat;
volatile UINT32 *pUART_data = (UINT32*)sys_uart_data;
while(!(0x10 & *pUART_stat));
return (char)*pUART_data;
}
void writechar(char c)
{
volatile UINT32 *pUART_stat = (UINT32*)sys_uart_stat;
volatile UINT32 *pUART_data = (UINT32*)sys_uart_data;
while((0x02 & *pUART_stat) != 0);
*pUART_data = (UINT32)c;
}
void _putchar(char c)
{
if (c == 0x0A)
{
writechar(0x0D);
}
writechar(c);
}
int sputs(char *pStr)
{
char *start;
start = pStr;
while(*pStr)
_putchar(*(pStr++));
return pStr - start;
}
void print_byte(char byte)
{
int i;
unsigned char c, nibble;
for (i=0; i < 2; i++)
{
nibble = (char)((byte >> 4) & 0xF);
byte <<= 4;
if (nibble < 10)
c = nibble + '0';
else
c = nibble + 'A' - 10;
_putchar(c);
}
}
void print_word(int word)
{
int i;
unsigned char c, nibble;
for (i=0; i < 4; i++)
{
c = (char) (word >> 24);
print_byte(c);
word <<= 8;
}
}
@@ -0,0 +1,50 @@
#ifndef LIBSYS_H
#define LIBSYS_H
// ---------------------------------------------------------
// Types
// ---------------------------------------------------------
#define INT8 char
#define INT16 short
#define INT32 long
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
#define INT int
#define UINT unsigned int
#define FLOAT32 float
#define FLOAT64 double
#define sys_gpio0 0xA0000000
#define sys_gpio1 0xA0000004
#define sys_led_port sys_gpio0
#define sys_usb_ctrl sys_gpio1
#define sys_timer_usec 0xA0000008
#define sys_timer_sec 0xA000000C
#define sys_uart_data 0xA0010000
#define sys_uart_stat 0xA0010004
#define sys_uart_baud 0xA0010008
#define sys_usb_data 0xA0020000
#define sys_usb_mbx 0xA0020004
#define sys_usb_addr 0xA0020008
#define sys_usb_status 0xA002000C
#define sys_flash_io 0xA4000000
// MIPS specific
UINT32 CP0_SR_read(void);
void CP0_SR_write(UINT32 val);
UINT32 CP0_CR_read(void);
void CP0_CR_write(UINT32 val);
UINT32 CP0_PRID_read(void);
// General
char readchar(void);
void writechar(char c);
int write(int file, char *ptr, int len);
int sputs(char *pStr);
void print_byte(char byte);
void print_word(int word);
#endif // LIBSYS_H
@@ -0,0 +1,25 @@
.file "startup.S"
.section .stext,"ax"
.extern _init
.align 2
_start:
.set noreorder
# Set Kernel mode
li $26, 0x1040000C
mtc0 $26, $12
li $26, 0x00000000
mtc0 $26, $13
mfc0 $26, $15
nop
mtc0 $26, $31
# jump init
la $26, _init
jr $26
nop
.set reorder