Firmware: uPD77c25 program download, reset

This commit is contained in:
ikari 2011-06-11 03:33:49 +02:00
parent 56538dc5e1
commit 344fa362be
14 changed files with 176 additions and 15 deletions

View File

@ -5,6 +5,8 @@
// #define DEBUG_IRQ
// #define DEBUG_MSU1
// #define DEBUG_UART
#ifdef DEBUG_UART
#define DBG_UART
#else

View File

@ -151,6 +151,7 @@ FLASH_RES flash_file(uint8_t *filename) {
uint32_t res;
writeled(1);
DBG_BL printf("erasing flash...\n");
if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
DBG_BL printf("error %ld while preparing for erase\n", res);
@ -172,7 +173,6 @@ FLASH_RES flash_file(uint8_t *filename) {
: (flash_addr >> 12);
DBG_BL printf("current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr);
DBG_UART uart_putc('.');
toggle_rdy_led();
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
DBG_BL printf("error %ld while preparing sector %d for write\n", res, current_sec);
@ -188,6 +188,7 @@ FLASH_RES flash_file(uint8_t *filename) {
DBG_UART uart_putc('X');
return ERR_FILECHK;
}
writeled(0);
} else {
DBG_UART uart_putc('n');
DBG_BL printf("flash content is ok, no version mismatch, no forced upgrade. No need to flash\n");

View File

@ -45,7 +45,7 @@ int main(void) {
DBG_UART uart_init();
led_init();
readled(0);
rdyled(0);
rdyled(1);
writeled(0);
/* do this last because the peripheral init()s change PCLK dividers */
clock_init();
@ -63,9 +63,11 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
FLASH_RES res = flash_file((uint8_t*)"/sd2snes/firmware.img");
if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
rdyled(0);
writeled(1);
}
if(res == ERR_FILEHD || res == ERR_FILECHK) {
rdyled(0);
readled(1);
}
DBG_BL printf("flash result = %d\n", res);

View File

@ -6,7 +6,7 @@
#flash info 0
reset init
flash write_image erase unlock obj/firmware.img 8192
flash write_image erase unlock obj/firmware.img 12288
reset run
shutdown

View File

@ -74,6 +74,11 @@
eg 0x20111210094816 is 2011-12-10, 9:48:16
E6 ssrr set/reset BS-X status register [7:0]
E7 - reset SRTC state
E8 - reset DSP program and data ROM write pointers
E9 hhmmllxxxx write+incr. DSP program ROM (xxxx=dummy writes)
EA hhllxxxx write+incr. DSP data ROM (xxxx=dummy writes)
EB - put DSP into reset
EC - release DSP from reset
F0 - receive test token (to see if FPGA is alive)
F1 - receive status (16bit, MSB first), see below
@ -345,3 +350,39 @@ void fpga_reset_srtc_state() {
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_reset_dspx_addr() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe8);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_write_dspx_pgm(uint32_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xe9);
FPGA_TX_BYTE((data>>16)&0xff);
FPGA_TX_BYTE((data>>8)&0xff);
FPGA_TX_BYTE((data)&0xff);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_write_dspx_dat(uint16_t data) {
FPGA_SELECT();
FPGA_TX_BYTE(0xea);
FPGA_TX_BYTE((data>>8)&0xff);
FPGA_TX_BYTE((data)&0xff);
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}
void fpga_dspx_reset(uint8_t reset) {
FPGA_SELECT();
FPGA_TX_BYTE(reset ? 0xeb : 0xec);
FPGA_TX_BYTE(0x00);
FPGA_DESELECT();
}

View File

@ -75,5 +75,8 @@ uint32_t get_snes_sysclk(void);
void set_bsx_regs(uint8_t set, uint8_t reset);
void set_fpga_time(uint64_t time);
void fpga_reset_srtc_state(void);
void fpga_reset_dspx_addr(void);
void fpga_write_dspx_pgm(uint32_t data);
void fpga_write_dspx_dat(uint16_t data);
void fpga_dspx_reset(uint8_t reset);
#endif

View File

@ -4,6 +4,7 @@
#include "bits.h"
#include "timer.h"
#include "led.h"
#include "cli.h"
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
@ -92,6 +93,7 @@ void led_panic() {
LPC_GPIO2->FIODIR &= ~(BV(4) | BV(5));
LPC_GPIO1->FIODIR &= ~BV(23);
delay_ms(350);
cli_entrycheck();
}
}

View File

@ -10,7 +10,7 @@ ENTRY(_start)
MEMORY
{
flash (rx) : ORIGIN = 0x00002100, LENGTH = 0x1df00 /* leave room for bootldr + metadata */
flash (rx) : ORIGIN = 0x00003100, LENGTH = 0x1cf00 /* leave room for bootldr + metadata */
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 0x04000
ahbram (rwx) : ORIGIN = 0x2007C000, LENGTH = 0x04000
}

View File

@ -131,7 +131,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
snes_bootprint(" Loading ... \0");
if(get_cic_state() == CIC_PAIR) {
printf("PAIR MODE ENGAGED!\n");
cic_pair(CIC_PAL, CIC_NTSC);
cic_pair(CIC_NTSC, CIC_NTSC);
}
rdyled(1);
readled(0);
@ -189,6 +189,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
/* load menu */
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
fpga_dspx_reset(1);
uart_putc('(');
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
/* force memory size + mapper */
@ -224,7 +225,7 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
uint32_t filesize=0;
sram_writebyte(32, SRAM_CMD_ADDR);
printf("test sram\n");
while(!sram_reliable());
while(!sram_reliable()) cli_entrycheck();
printf("ok\n");
sram_hexdump(SRAM_DIR_ADDR, 0x300);
//while(1) {
@ -237,13 +238,14 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300);
cmd=menu_main_loop();
// cmd = 1;
printf("cmd: %d\n", cmd);
sleep_ms(50);
sleep_ms(500);
uart_putc('-');
switch(cmd) {
case SNES_CMD_LOADROM:
get_selected_name(file_lfn);
set_mcu_ovr(1);
// strcpy((char*)file_lfn, "/bs3-1.smc");
// strcpy((char*)file_lfn, "/mon.smc");
printf("Selected name: %s\n", file_lfn);
filesize = load_rom(file_lfn, SRAM_ROM_ADDR);
if(romprops.ramsize_bytes) {
@ -257,6 +259,7 @@ sram_hexdump(SRAM_DIR_ADDR, 0x300);
snes_reset(1);
delay_ms(10);
snes_reset(0);
fpga_dspx_reset(0);
break;
case SNES_CMD_SETRTC:
/* get time from RAM */

View File

@ -229,6 +229,10 @@ ticks_total=getticks()-ticksstart;
sram_writebyte(0xfc, rombase+0xd5);
set_fpga_time(0x0220110301180530LL);
}
if(romprops.mapper_id == 4 || romprops.mapper_id == 5) {
printf("DSPx game. Loading firmware image %s...\n", romprops.necdsp_fw);
load_dspx(romprops.necdsp_fw);
}
uint32_t rammask;
uint32_t rommask;
@ -448,3 +452,67 @@ uint64_t sram_gettime(uint32_t base_addr) {
FPGA_DESELECT();
return result & 0x00ffffffffffffffLL;
}
void load_dspx(const uint8_t *filename) {
UINT bytes_read;
DWORD filesize;
uint16_t word_cnt;
uint8_t wordsize_cnt = 0;
uint16_t sector_remaining = 0;
uint16_t sector_cnt = 0;
uint16_t pgmsize = 2048;
uint16_t datsize = 1024;
uint32_t pgmdata = 0;
uint16_t datdata = 0;
file_open((uint8_t*)filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) {
printf("Could not read %s: error %d\n", filename, file_res);
return;
}
fpga_reset_dspx_addr();
for(word_cnt = 0; word_cnt < pgmsize;) {
if(!sector_remaining) {
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
pgmdata = (pgmdata << 8) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 3){
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_pgm(pgmdata);
printf("%06lx ", pgmdata&0xffffff);
}
}
wordsize_cnt = 0;
for(word_cnt = 0; word_cnt < datsize;) {
if(!sector_remaining) {
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
datdata = (datdata << 8) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 2){
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_dat(datdata);
printf("%04x ",datdata&0xffff);
}
}
fpga_reset_dspx_addr();
file_close();
}

View File

@ -49,6 +49,7 @@ uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr);
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr);
uint32_t load_bootrle(uint32_t base_addr);
void load_dspx(const uint8_t* filename);
void sram_hexdump(uint32_t addr, uint32_t len);
uint8_t sram_readbyte(uint32_t addr);
uint16_t sram_readshort(uint32_t addr);

View File

@ -28,9 +28,16 @@
#include "config.h"
#include "uart.h"
#include "smc.h"
#include "string.h"
snes_romprops_t romprops;
const uint8_t* DSPFW_1 = (uint8_t*)"/sd2snes/dsp1.bin";
const uint8_t* DSPFW_1B = (uint8_t*)"/sd2snes/dsp1b.bin";
const uint8_t* DSPFW_2 = (uint8_t*)"/sd2snes/dsp2.bin";
const uint8_t* DSPFW_3 = (uint8_t*)"/sd2snes/dsp3.bin";
const uint8_t* DSPFW_4 = (uint8_t*)"/sd2snes/dsp4.bin";
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t countAllASCII(uint8_t* data, int size) {
uint8_t res = 0;
@ -77,7 +84,6 @@ uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
void smc_id(snes_romprops_t* props) {
uint8_t score, maxscore=1, score_idx=2; /* assume LoROM */
snes_header_t* header = &(props->header);
for(uint8_t num = 0; num < 6; num++) {
@ -122,7 +128,7 @@ void smc_id(snes_romprops_t* props) {
const uint8_t n15 = header->map;
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c
|| n15 == 0xbc || n15 == 0xfc) {
if(header->fixed_33 == 0x33 || header->fixed_33 == 0xff) {
if(header->licensee == 0x33 || header->licensee == 0xff) {
props->mapper_id = 0;
/*XXX do this properly */
props->ramsize_bytes = 0x8000;
@ -135,15 +141,44 @@ void smc_id(snes_romprops_t* props) {
}
}
switch(header->map & 0xef) {
case 0x21: /* HiROM */
props->mapper_id = 0;
if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) {
props->mapper_id = 4; /* DSPx HiROM */
props->necdsp_fw = DSPFW_1B;
} else {
props->mapper_id = 0; /* regular HiROM */
}
break;
case 0x20: /* LoROM */
props->mapper_id = 1;
if ((header->map == 0x20 && header->carttype == 0x03) ||
(header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) {
props->mapper_id = 5;
// Pilotwings uses DSP1 instead of DSP1B
if(!memcmp(header->name, "PILOTWINGS", 10)) {
props->necdsp_fw = DSPFW_1;
} else {
props->necdsp_fw = DSPFW_1B;
}
} else if (header->map == 0x20 && header->carttype == 0x05) {
props->mapper_id = 5; /* DSPx LoROM */
props->necdsp_fw = DSPFW_2;
} else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) {
props->mapper_id = 5; /* DSPx LoROM */
props->necdsp_fw = DSPFW_3;
} else if (header->map == 0x30 && header->carttype == 0x03) {
props->mapper_id = 5; /* DSPx LoROM */
props->necdsp_fw = DSPFW_4;
} else {
props->mapper_id = 1; /* regular LoROM */
}
break;
case 0x25: /* ExHiROM */
props->mapper_id = 2;
break;
case 0x22: /* ExLoROM */
if(file_handle.fsize > 0x400200) {
props->mapper_id = 6; /* SO96 */
@ -151,6 +186,7 @@ void smc_id(snes_romprops_t* props) {
props->mapper_id = 4;
}
break;
default: /* invalid/unsupported mapper, use header location */
switch(score_idx) {
case 0:
@ -194,7 +230,7 @@ uint8_t smc_headerscore(snes_header_t* header) {
score += countAllASCII(header->gamecode, sizeof(header->gamecode));
score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
score += countAllJISX0201(header->name, sizeof(header->name));
score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33);
score += 3*isFixed(&header->licensee, sizeof(header->licensee), 0x33);
score += checkChksum(header->cchk, header->chk);
return score;
}

View File

@ -40,7 +40,7 @@ typedef struct _snes_header {
uint8_t romsize; /* 0xD7 */
uint8_t ramsize; /* 0xD8 */
uint8_t destcode; /* 0xD9 */
uint8_t fixed_33; /* 0xDA */
uint8_t licensee; /* 0xDA */
uint8_t ver; /* 0xDB */
uint16_t cchk; /* 0xDC */
uint16_t chk; /* 0xDE */
@ -53,6 +53,7 @@ typedef struct _snes_romprops {
uint32_t expramsize_bytes; /* ExpRAM size in bytes */
uint32_t ramsize_bytes; /* CartRAM size in bytes */
uint32_t romsize_bytes; /* ROM size in bytes (rounded up) */
const uint8_t* necdsp_fw; /* NEC DSP ROM filename */
snes_header_t header; /* original header from ROM image */
} snes_romprops_t;

View File

@ -60,6 +60,7 @@ void prepare_reset() {
snes_reset(0);
while(get_snes_reset());
snes_reset(1);
fpga_dspx_reset(1);
delay_ms(200);
}