Firmware: uPD77c25 program download, reset
This commit is contained in:
parent
56538dc5e1
commit
344fa362be
@ -5,6 +5,8 @@
|
||||
// #define DEBUG_IRQ
|
||||
// #define DEBUG_MSU1
|
||||
|
||||
// #define DEBUG_UART
|
||||
|
||||
#ifdef DEBUG_UART
|
||||
#define DBG_UART
|
||||
#else
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
11
src/main.c
11
src/main.c
@ -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 */
|
||||
|
||||
68
src/memory.c
68
src/memory.c
@ -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();
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
46
src/smc.c
46
src/smc.c
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ void prepare_reset() {
|
||||
snes_reset(0);
|
||||
while(get_snes_reset());
|
||||
snes_reset(1);
|
||||
fpga_dspx_reset(1);
|
||||
delay_ms(200);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user