// This is the flash programming utility. Use this program to download // code into the Flash memory block. This is very simple at this point, // I'm counting on software developers to enhance this substantially! // It assumes that the remap has been executed and the Flash and external // SRAM are accessible. It works by downloading code into the external // SRAM, up to 2Mbytes. If this downloads correctly, then the data is // copied into the Flash Eprom. The FPGA boot ROM is mapped to 0x810000, // this program calls some of those utilites. // // WARNING: THERE IS A BUG THAT STOPS PROGRAMMING BEFORE THE END OF THE // DOWNLOADED FILE. ADD A LAST LINE TO THE HCS_XPRESS.TXT FILE // THAT IS256 bytes AFTER THE FINISH TO ENSURE IT ALL GETS PROGRAMMED #include "hcs_constants.h" // NOTE: FLASH LOADER MAXIMUM SIZE FILE is currently set to 65Kbytes! // This prevents totally spurious file writes--HCS_C is too new and // needs a little idiot protection.. #define MAX_FILE_SIZE 0x03ffff // set this to your largest conceivable file size #define RET_CHAR 0xd // ctl-M carriage return #define FLASH_WE_ADDR1 0x50e00c // For top side EPROMS, bottom is difft #define FLASH_WE_ADDR2 0x4105c0 // For top side EPROMS, bottom is difft #define FLASH_WE_DATA1 0xaa #define FLASH_WE_DATA2 0x55 #define FLASH_PROGRAM_DATA 0xa0 #define FLASH_ERASE_DATA 0x80 #define FLASH_CONFIRM_ERASE_DATA 0x10 #define EXT_SRAM_ADDR 0x600000 // Old run-from-ROM, linked to 400000 // #define SRAM_TO_FLASH_OFFSET 0x200000 // file 400000 sram 600000 // New run-from-RAM, linked to 000000 #define SRAM_TO_FLASH_OFFSET 0x600000 // file 000000 sram 600000 #define FLASH_SEL 0x140 // use 0: 0x140 1: 0x281 2: 0x182 3: 0x243 //#define FLASH_ADDR 0x700000 #define FLASH_ADDR 0x400000 // Function prototypes void sram_to_flash(int); void enable_programming(); void disable_programming(); char program_byte(int offset); char check_before_program(int); void init_sram(); // External declarations #include "hcs_utils.p" main() { int last_addr; short *rptr; char flash_busy; short *flash_addr; char checkval; init_console(); char_to_console('O'); char_to_console('K'); send_string("Flash loader version 1.05. Starting..."); init_sram(); // Load up external SRAM send_string("\nNOTE: File size maximum is currently set to 256Kbytes"); send_string("\nWhile downloading, you will see dots appear. When that"); send_string("\nstops, hit any key to continue."); send_string("\n\n Normally the linking"); send_string("\nloader does NOT require you to erase before loading an"); send_string("\nupdate. If you want to erase, you must download something"); send_string("\nanyway, then type n (NO) when it asks you if you want to"); send_string("\nprogram. At that point, it will ask if you want to erase."); send_string("\n\nAt any point (except while erasing) you can hit the reset"); send_string("\nbutton to abort."); send_string("\n\nNow download your program..."); last_addr = console_to_memory(SRAM_TO_FLASH_OFFSET); if (last_addr == 0) { while (TRUE) {} } send_string("\nYour program downloaded with byte count = "); word_to_console(last_addr >> 16); word_to_console(last_addr); send_string(".\nNow say yes to program, or n if abort. If abort, you may"); send_string("\nchoose to erase the flash memory."); // Check the memory image, if OK, program flash memory if (check_before_program(last_addr) == 'y') { rptr = FPGA_FLASH_SELECT; *rptr = FLASH_SEL; sram_to_flash(last_addr); send_string("\nFlash loader finished.\n"); } else { send_string("\nDo you want to do a chip erase? (Y to erase)\n"); checkval = get_console_char(); if (checkval != 'Y') send_string("\nFlash loader aborted by user.\n"); else { send_string("\nAre you VERY SURE do a full chip erase? (Y to erase)\n"); checkval = get_console_char(); if (checkval != 'Y') send_string("\nFlash loader aborted by user.\n"); else { rptr = FPGA_FLASH_SELECT; *rptr = FLASH_SEL; send_string("\Erasing entire chip now.\n"); send_string("DO NOT RESET OR POWER DOWN!.\n"); send_string("Please wait 5 minutes, until this finishes!\n"); flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_WE_DATA1; flash_addr = (short *)FLASH_WE_ADDR2; *flash_addr = (short)FLASH_WE_DATA2; flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_ERASE_DATA; flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_WE_DATA1; flash_addr = (short *)FLASH_WE_ADDR2; *flash_addr = (short)FLASH_WE_DATA2; flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_CONFIRM_ERASE_DATA; // wait for programming to complete flash_busy = TRUE; while (flash_busy == TRUE) { if (*flash_addr == 0xff) flash_busy = FALSE; } send_string("\nFlash chip successfully erased.\n"); } } } *rptr = 0; // Restore flash select so wont accidentally write send_string("\nPlease reset now.\n"); while (TRUE) {} } void init_sram() { short *sram_addr; int offset; sram_addr = (short *)EXT_SRAM_ADDR; send_string("\nInitializing External SRAM..."); while ((int)sram_addr < 0x800000) { *sram_addr = 0xffff; sram_addr += 1; } send_string("\nDone initializing External SRAM..."); return; } void sram_to_flash(int last_addr) { int memory_offset; char no_fails; no_fails = TRUE; memory_offset = 0; // memory offset counts words, last_addr is actual (bytes) // so to get the right compare number, halve the last_addr // NOTE: FLASH LOADER MAXIMUM SIZE FILE is 1 MBYTE! This prevents totally spurious // file writes--HCS_C is too new and needs a little idiot protection.. while ((no_fails == TRUE) && (memory_offset < ((last_addr & MAX_FILE_SIZE)/2))) { no_fails = program_byte(memory_offset); memory_offset += 1; if ((memory_offset & 0x1f) == 0) char_to_console('+'); } if (no_fails == TRUE) send_string("\nFlash load successful.\n"); else send_string("\nFlash load FAILED!\n"); // should also do checksum here } // Check SRAM checksum char check_before_program(int addr) { char checkval; send_string("\nDownload successful.\n"); send_string("\nAre you sure you want to program?\n"); checkval = get_console_char(); return(checkval); } char program_byte(int offset) { short *flash_addr; short *sram_addr; short data_to_write; char flash_busy; sram_addr = (short *)EXT_SRAM_ADDR + offset; data_to_write = *sram_addr; flash_addr = (short *)FLASH_ADDR + offset; // If data is unchanged, or if no bits are to be written, skip the word if ((data_to_write == *flash_addr) || (data_to_write == -1)) return(TRUE); // Already programmed if ((data_to_write & (~*flash_addr)) != 0) { char_to_console('-'); return(FALSE); // cannot program that byte } // OK, is programmable and is changing, so program it flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_WE_DATA1; flash_addr = (short *)FLASH_WE_ADDR2; *flash_addr = (short)FLASH_WE_DATA2; flash_addr = (short *)FLASH_WE_ADDR1; *flash_addr = (short)FLASH_PROGRAM_DATA; flash_addr = (short *)FLASH_ADDR + offset; *flash_addr = data_to_write; // wait for programming to complete flash_busy = TRUE; while (flash_busy == TRUE) { if (*flash_addr == *flash_addr) flash_busy = FALSE; } return(TRUE); } #include "hcs_flash_utils.h" __gccmain() { } exit() { while(1); }