From d74ba76649ea8e2fe808e2c6ba741a980ec67b3c Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 7 Feb 2009 11:44:03 +0000 Subject: [PATCH] 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@319 cc03376c-175c-47c8-b038-4cd826a8556b --- .../bootloader/bootloader_with_flash.c | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 lib/CPUs/MIPS/bsp/examples/bootloader/bootloader_with_flash.c diff --git a/lib/CPUs/MIPS/bsp/examples/bootloader/bootloader_with_flash.c b/lib/CPUs/MIPS/bsp/examples/bootloader/bootloader_with_flash.c new file mode 100644 index 0000000..07c36ed --- /dev/null +++ b/lib/CPUs/MIPS/bsp/examples/bootloader/bootloader_with_flash.c @@ -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; +} +