EverDrive-64 v3

From N64brew Wiki
Jump to navigation Jump to search

The EverDrive-64 v3 is a flash cart made by Krikzz.

Basic information

ROM: Max 64MiB

RTC: supported

Save: 4ki/16ki bit EEPROM, 32KiB/128KiB SRAM, 128KiB Flash

USB Serial: 512-bytes block read-write

SD: SD or SDHC

Registers

All registers must be accessed by 32bit word, but it seems only lower 16bits are valid.

High 16bits of all registers seems REG_STATUS on read.

Base PI address for registers is 0x08040000 (Cartridge Domain 2, SRAM area +0x40000)

You should access these registers from CPU through no-cached segment, i.e. +0xA0000000, ex. 0xA8040020 for REG_KEY.

PI address name R/W description
0x08040000 REG_CFG R/W ED64 general configurations
0x08040004 REG_STATUS R ED64 registers, SPI, DMA statuses
0x08040008 REG_DMA_LEN W SD/USB DMA length in 512bytes blocks - 1 (ex. 0 = 0x200 bytes)
0x0804000C REG_DMA_RAM_ADDR W SD/USB Cart address in 2048bytes blocks (ex. 1 = 0x00000800)
0x08040010 REG_MSG R/W 16bit general storage? used to remember last used save type by ED64 OS (menu)
0x08040014 REG_DMA_CFG W Invoke SD/USB DMA
0x08040018 REG_SPI R/W SPI (SD card) DAT/CMD (write invoke CLK)
0x0804001C REG_SPI_CFG R/W SPI (SD card) configurations
0x08040020 REG_KEY W Enable or disable ED64 registers
0x08040024 REG_SAV_CFG R/W Save configurations (EEPROM/SRAM/FLASH)
0x08040028 REG_SEC ? ?
0x0804002C REG_VER R Firmware version
0x08040030 ? R/W I2C to access RTC
0x08040034 ? ? ?
0x08040038 ? ? ?
0x0804003C ? ? ?
0x08040040 REG_CFG_CNT R/W FPGA configuration control
0x08040044 REG_CFG_DAT W FPGA configuration data
0x08040048 MAX_MSG R/W Some configurations
0x0804004C REG_CRC ? ?
0x08040050 ? ? Flash?
0x08040054 ? ? Flash?

0x08040000 (REG_CFG)

Read/Write

bit from lsb description
15 1=finish FPGA configuration? (after REG_CFG_* writes)
9-8 D64 specific??
6-5 RTC (00=disable, 01=RTC emulation enabled through Cart EEPROM command 06/07, 11=RTC access enabled via I2C)
3 WR_ADDR_MASK??
2 WR_MOD??
1 1=16bit swap on SD DMA read
0 1=enable SDRAM on cart (usually set to 1)

0x08040004 (REG_STATUS)

Read only

bit from lsb description
15 1=SDRAM enabled?
4 1=SPI is busy (REG_SPI <-> SD is transferring)
3 RXF# on USB FIFO (0=some data from Host exists)
2 TXE# on USB FIFO (0=able to send some data to Host)
1 DMATOUT (1=last DMA was timed out, i.e. last transfer is less than 512bytes)
0 DMABUSY (1=DMA is ongoing)

0x08040008 (REG_DMA_LEN)

Write only

bit from lsb description
15-0 Next SD/USB DMA transfer size in 512 bytes step, minus 1.

ex. 0 = 0x200 bytes, 1 = 0x400 bytes, 2 = 0x600 bytes...

0x0804000C (REG_DMA_RAM_ADDR)

Write only

bit from lsb description
15-0 Next SD/DMA DMA transfer size in 2048 bytes step.

ex. 0 = 0x00000000, 1 = 0x00000800, 2 = 0x00001000...

This is in ED64 ROM address space, ex. 0xB0000000 on CPU = 0x10000000 on PI = 0x00000000 on ED64 ROM.

0x08040010 (REG_MSG)

Read/Write

It seems generic 16bit storage.

In ED64 OS v2.12, this register used as following:

bit from lsb description
4 last ROM is 64DD image
3-0 last ROM's savetype (0=none, 1=EEPROM 4kibit, ... same as /ED64/save_db.txt)

0x08040014 (REG_DMA_CFG)

Write only

value description
1 SD -> Cart
2 Cart -> SD
3 USB -> Cart
4 Cart -> USB

Note that above table numbers are value, not "bit from lsb".

You must set REG_DMA_LEN and REG_DMA_RAM_ADDR before writing this register.

0x08040018 (REG_SPI)

Read/Write

bit from lsb description
7-0 dat/cmd value. Bits are shifted in from lsb if 1bit mode.

Writing value to this invokes clock CLK on SD card.

You should also write this to read. (write value is ignored)

0x0804001C (REG_SPI_CFG)

Read/Write

bit from lsb description
5 Bits transferred on writing REG_SPI: 0=8bits 1=1bit
4 Which line to R/W: 0=CMD 1=DAT
3 Read or write (on writing REG_SPI): 0=write 1=read
2 Slave Select line on SD card
1-0 CLK speed: 10=init 01=25MHz 00=50MHz

0x08040020 (REG_KEY)

Write only

bit from lsb description
15-0 Enable or disable ED64 registers: 0=disable, 0x1234=enable

Note that you should dummy-read REG_CFG before writing to REG_KEY, or it may be ignored (glitch).

0x08040024 (REG_SAV_CFG)

Read/Write

bit from lsb description
15 1=enable ED64 save page
7 1=enable game save page (have priority than ED64 page)
3 SRAM size: 0=32KiB 1=128KiB
2 EEPROM size: 0=4kibit 1=16kibit
1 SRAM ON: 1=SRAM
0 EEPROM ON: 1=EEPROM

But this register should be treated as a value not bitfields (like REG_DMA_CFG)

value description
0x0080 Save is disabled
0x0082 32KiB SRAM enabled
0x008A 128KiB SRAM enabled
0x0081 4kibit EEPROM enabled
0x0085 16kibit EEPROM enabled
0x0088 128KiB Flash enabled (!?)
0x800A 128KiB ED64 save page enabled (mainly from 0x1E000)

0x08040028 (REG_SEC)

Write only?

0x0804002C (REG_VER)

Read only

bit from lsb description
15-8 Firmware major version
7-0 Firmware minor version

ex. 0x0304 for Firmware v3.04

0x08040030 (I2C/RTC)

Read/Write

bit from lsb description
2 CLK
0 DAT

You must set DAT=1 before read, or you'll get always DAT=0 (because of I2C's open-drain).

DS1337 (RTC) at address 0x58.

0x08040040 (REG_CFG_CNT)

Read/Write on REG_CFG&1==0

bit from lsb description
3 1=REG_CFG_DAT is transferring [R]
2 1=FPGA is configuring? [R]
0 0=unconfigure FPGA? [W]

SDRAM must be disabled (REG_CFG & 1 must be zero).

0x08040044 (REG_CFG_DAT)

Write only? on REG_CFG&1==0

bit from lsb description
15-0 configuration data (part of bitstream)

SDRAM must be disabled (REG_CFG & 1 must be zero).

0x08040048 (REG_MAX_MSG)

Read/Write on REG_CFG&1==0

bit from lsb description
14 1?
13 1=SDHC
12 1=SD card initialized
11-10 tvtype (value that IPL3 sets)
9 1=tvtype in REG_MAX_MSG is set
8 1=FPGA configured

SDRAM must be disabled (REG_CFG & 1 must be zero).

0x0804004C (REG_CRC)

Read only? on REG_CFG&1==0

bit from lsb description
15-12 HW major version?
11-0 ?

SDRAM must be disabled (REG_CFG & 1 must be zero).

This register seems not related to "Cyclic Redundancy Check".

0x08040050

Write only? on REG_CFG&1==0

TBA

SDRAM must be disabled (REG_CFG & 1 must be zero).

0x08040054

Write only on REG_CFG&1==0 ?

TBA

SDRAM must be disabled (REG_CFG & 1 must be zero).

ED64 Boot ROM Header

You can read boot ROM header by:

  • set REG_CFG &= ~1 (disable SDRAM)
  • read from cart usually (by *(uint32_t*)0xB0000000 etc, or use PI DMA)
PI address bytes description
0x10000020 12 "ED64 SD boot", can be used to identify SD is usable or not (=SPI)
0x10000038 2 assembly date in FAT style
0x1000003A 2 assembly time in 2-seconds from 00:00:00, ex. 0x5878 for 12:34:56
0x1000003C 2 serial number (16bit binary, hex)

They are, of course, big endian.

Date in FAT Style
bit from lsb description
15-9 year - 1980
8-5 month (start from 1)
4-0 day (start from 1)

USB Serial Communication

Common Code

Before communication, you must enable ED64 registers.

#include <stdint.h>

*(volatile uint32_t *)0xA8040000; /* dummy read */
*(volatile uint32_t *)0xA8040020 = 0x1234; /* enable ED64 registers */

Sending Data to the Host

You should transfer data from RDRAM to some area on cart "ROM" area first, then use Cart->USB DMA on ED64.

/* polling style */

void rdram_to_host(
  void *src, /* pointer for data aligned by 64 bits (8 bytes) */
  uint32_t tmp_cart_addr, /* somewhere aligned by 2048 bytes */
  uint32_t len /* length aligned 512 bytes */
) {
  uintptr_t i;

  /* flush D-cache (primary data hit writeback invalidate; 16 bytes per D-cache-line on N64) */
  for(i = (uintptr_t)src & ~15; i < (uintptr_t)src + (uintptr_t)len; i += 16) {
    __asm volatile("cache 0x15, %0" :: "m"(*(uint32_t*)i));
  }

  *(volatile uint32_t *)0xA4600010 = 3; /* reset PI and clear interrupt */

  /* transfer (PI DMA) RDRAM to Cart */
  *(volatile uint32_t *)0xA4600000 = (uint32_t)src & 0x00FFffff; /* XXX: assuming src points to kseg0 or kseg1 */
  *(volatile uint32_t *)0xA4600004 = tmp_cart_addr;
  *(volatile uint32_t *)0xA4600008 = len - 1;
  while(*(volatile uint32_t *)0xA4600010 & 1) /* busyloop */ ; /* wait for PI DMA done */

  /* Cart->USB DMA on ED64 */
  while(*(volatile uint32_t *)0xA8040004 & 4) /* busyloop */ ; /* wait until REG_STATUS & TXE# becomes zero = able to tx */
  *(volatile uint32_t *)0xA8040008 = len / 512 - 1; /* set REG_DMA_LEN */
  *(volatile uint32_t *)0xA8040000; /* dummy read for previous PI write is done (REG_CFG is just because) */
  *(volatile uint32_t *)0xA804000C = tmp_cart_addr / 2048; /* set REG_DMA_ADDR */
  *(volatile uint32_t *)0xA8040000; /* dummy read for previous PI write is done (REG_CFG is just because) */
  *(volatile uint32_t *)0xA8040014 = 4; /* set REG_DMA_CFG to Cart->USB invokes DMA */
  while(*(volatile uint32_t *)0xA8040004 & 1) /* busyloop */ ; /* wait for Cart->USB DMA done */
}

...
uint8_t __attribute((aligned(8))) buffer[512];
/* ... some modification to "buffer" */
rdram_to_host(buffer, 0x00400000 - 2048, 512); /* using last ROM area for communication */

Reading Data from the Host

You should use USB->Cart DMA on ED64 first, then transfer data from cart ROM area to RDRAM.

At least on HW v3.04, it seems that USB->Cart transfer is done at 16-bit halfwords. If received data is NOT aligned at 16-bit, that last byte will be lost. Of course if received data is shorter than "len", DMA will be timed out, cause waiting ~500ms to DMA done until timeout, so you should send data from host by 512 bytes block for faster communication.

/* polling style */

int host_to_rdram(
  void *dst, /* pointer for data aligned by 64 bits (8 bytes) */
  uint32_t tmp_cart_addr, /* somewhere aligned by 2048 bytes */
  uint32_t len /* length aligned 512 bytes */
) {
  uintptr_t i;

  /* REG_STATUS & RXF# is zero = data is arriving, not zero = not arrived */
  if(*(volatile uint32_t *)0xA8040004 & 8) {
    /* no data is arrived now */
    return 0;
  }

  /* invalidate D-cache (primary data hit invalidate; 16 bytes per D-cache-line on N64) */
  for(i = (uintptr_t)dst & ~15; i < (uintptr_t)dst + (uintptr_t)len; i += 16) {
    __asm volatile("cache 0x11, %0" :: "m"(*(uint32_t*)i));
  }

  *(volatile uint32_t *)0xA4600010 = 3; /* reset PI and clear interrupt */

  /* USB->Cart DMA on ED64 */
  *(volatile uint32_t *)0xA8040008 = len / 512 - 1; /* set REG_DMA_LEN */
  *(volatile uint32_t *)0xA8040000; /* dummy read for previous PI write is done (REG_CFG is just because) */
  *(volatile uint32_t *)0xA804000C = tmp_cart_addr / 2048; /* set REG_DMA_ADDR */
  *(volatile uint32_t *)0xA8040000; /* dummy read for previous PI write is done (REG_CFG is just because) */
  *(volatile uint32_t *)0xA8040014 = 3; /* set REG_DMA_CFG to USB->Cart invokes DMA */
  while(*(volatile uint32_t *)0xA8040004 & 1) /* busyloop */ ; /* wait for USB->Cart DMA done */

  if(*(volatile uint32_t *)0xA8040004 & 2) {
    /* last DMA timed out... you may be treat this as error (or you can read partially transferred data, comment out next return) */
    return -1;
  }

  /* transfer (PI DMA) Cart to RDRAM */
  *(volatile uint32_t *)0xA4600000 = (uint32_t)dst & 0x00FFffff; /* XXX: assuming dst points to kseg0 or kseg1 */
  *(volatile uint32_t *)0xA4600004 = tmp_cart_addr;
  *(volatile uint32_t *)0xA460000C = len - 1;
  while(*(volatile uint32_t *)0xA4600010 & 1) /* busyloop */ ; /* wait for PI DMA done */

  /* success */
  return 1;
}

...
uint8_t __attribute((aligned(8))) buffer[512];
int result;
result = host_to_rdram(buffer, 0x00400000 - 2048, 512); /* using last ROM area for communication */
/* "buffer" is modified if 0 < result */