- bootloader_with_flash: fixed apperent bug with GPIO alignmentand masking git-svn-id: http://moon:8086/svn/mips@134 a8ebac50-d88d-4704-bea3-6648445a41b3
181 lines
3.8 KiB
C
181 lines
3.8 KiB
C
#include <board.h>
|
|
#include "libsys.h"
|
|
#include "srec.h"
|
|
|
|
#define MAGIC_EB 0x4A464931 // "JFI1" in big-endian;
|
|
#define MAGIC_EL 0x3149464A // "JFI1" in little-endian;
|
|
|
|
extern uint32_t getBootOffset(uint32_t sel);
|
|
|
|
typedef struct _sflash_img_hdr_t
|
|
{
|
|
uint32_t magic;
|
|
uint32_t target_base;
|
|
uint32_t img_base;
|
|
uint32_t img_size;
|
|
uint32_t hdr_next;
|
|
uint8_t img_name[128];
|
|
uint8_t res[108];
|
|
|
|
} flash_img_hdr_t;
|
|
|
|
void Jump_to(void *pEntry)
|
|
{
|
|
__asm
|
|
(
|
|
".set noreorder\n"
|
|
);
|
|
__asm
|
|
(
|
|
"jr %[pEntry]\n" // jump entry
|
|
"nop\n"
|
|
:
|
|
: [pEntry] "r" (pEntry)
|
|
);
|
|
__asm
|
|
(
|
|
".set reorder\n"
|
|
);
|
|
}
|
|
|
|
void Exec_at(void *pEntry)
|
|
{
|
|
__asm
|
|
(
|
|
".set noreorder\n"
|
|
);
|
|
|
|
__asm
|
|
(
|
|
// Enable User Mode and Interrupts on RFE
|
|
// Exception Vector = 0xBFC00080
|
|
"li $26, 0x10000008\n"
|
|
"mtc0 $26, $12\n"
|
|
);
|
|
|
|
__asm
|
|
(
|
|
"mtc0 %[pEntry], $14\n"
|
|
"nop\n"
|
|
"jr %[pEntry]\n" // jump entry
|
|
"rfe\n"
|
|
:
|
|
: [pEntry] "r" (pEntry)
|
|
);
|
|
|
|
__asm
|
|
(
|
|
".set reorder\n"
|
|
);
|
|
}
|
|
|
|
#define MAX_IMG_SIZE (1024*1024) // bytes
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
uint8_t buf[256];
|
|
srec_t srec;
|
|
int result, srec_state, i;
|
|
uint32_t haddr = 0;
|
|
volatile uint8_t *pMem;
|
|
|
|
flash_img_hdr_t img_hdr;
|
|
|
|
volatile uint32_t *pFlashMem = (uint32_t*)(FLASH_BASE_MEM); // Flash in cached area
|
|
volatile uint32_t *pSdram32 = (uint32_t*)SDRAM_BASE;
|
|
volatile uint32_t *pGPIO_DATA = (uint32_t*)SYS_GPIO_0_DATA;
|
|
volatile uint32_t *pGPIO_DIR = (uint32_t*)SYS_GPIO_0_DIR;
|
|
|
|
*pGPIO_DIR = GPIO_0_DFLT_DIR;
|
|
*pGPIO_DATA = GPIO_0_DFLT_DATA;
|
|
uint32_t block_sel = (uint32_t)((*pGPIO_DATA >> GPIO_0_ALIGN_DIP) & GPIO_0_MASK_DIP);
|
|
uint32_t flash_offset = getBootOffset(block_sel);
|
|
|
|
sputs("\nMIPS bootloader\n");
|
|
pFlashMem += flash_offset >> 2;
|
|
|
|
// ----------------------------------------------------------
|
|
sputs("Loading image from flash at ");print_word((int)pFlashMem);sputs("\n");
|
|
img_hdr = *((flash_img_hdr_t*)pFlashMem);
|
|
if ((img_hdr.magic != MAGIC_EL) && (img_hdr.magic != MAGIC_EB))
|
|
{
|
|
sputs("\n\n");
|
|
sputs("Invalid image found at ");print_word((int)pFlashMem); sputs(". Abort.\n");
|
|
return 1;
|
|
}
|
|
|
|
sputs("target_base = ");print_word(img_hdr.target_base);sputs("\n");
|
|
sputs("img_base = ");print_word(img_hdr.img_base);sputs("\n");
|
|
sputs("img_size = ");print_word(img_hdr.img_size);sputs("\n");
|
|
|
|
pSdram32 = (uint32_t*)img_hdr.target_base;
|
|
|
|
// It's safe to use cached Flash,
|
|
// because D-Cache was invalidated during execution of start code
|
|
pFlashMem += img_hdr.img_base/4;
|
|
|
|
for (i=0; i < img_hdr.img_size/4; i += 8)
|
|
{
|
|
pSdram32[i+0] = pFlashMem[i+0];
|
|
pSdram32[i+1] = pFlashMem[i+1];
|
|
pSdram32[i+2] = pFlashMem[i+2];
|
|
pSdram32[i+3] = pFlashMem[i+3];
|
|
pSdram32[i+4] = pFlashMem[i+4];
|
|
pSdram32[i+5] = pFlashMem[i+5];
|
|
pSdram32[i+6] = pFlashMem[i+6];
|
|
pSdram32[i+7] = pFlashMem[i+7];
|
|
}
|
|
for (i; i < img_hdr.img_size/4; i++)
|
|
{
|
|
pSdram32[i] = pFlashMem[i];
|
|
}
|
|
|
|
sputs("Booting from ");print_word(img_hdr.target_base);sputs("\n\n");
|
|
Exec_at((void*)pSdram32);
|
|
|
|
// ----------------------------------------------------------
|
|
sputs("Booting from UART..");
|
|
|
|
while(1)
|
|
{
|
|
sputs(".");
|
|
while(1)
|
|
{
|
|
result = srec_getline(buf);
|
|
srec_state = srec_decode(&srec, buf, result);
|
|
switch (srec_state)
|
|
{
|
|
case srec_data:
|
|
if ((srec.addr + srec.size) > haddr)
|
|
haddr = srec.addr + srec.size;
|
|
|
|
pMem = (uint8_t*)srec.addr;
|
|
for (i=0; i < srec.size; i++)
|
|
*pMem++ = srec.data[i];
|
|
|
|
break;
|
|
|
|
case srec_eob:
|
|
sputs("done\n\n");
|
|
sputs("Execute program at ");
|
|
print_word(srec.addr);
|
|
sputs("\n\n");
|
|
|
|
Exec_at((void*)srec.addr);
|
|
break;
|
|
|
|
default:
|
|
result = -1;
|
|
break;
|
|
}
|
|
if (result < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
};
|
|
}
|
|
return 0;
|
|
}
|
|
|