EverDrive-64 v3: Difference between revisions

describe USB Serial Communication
No edit summary
(describe USB Serial Communication)
Line 336:
=== Common Code ===
Before communication, you must enable ED64 registers.
*(volatile uint32_t *)0xA8040000;
 
<syntaxhighlight lang=c>
*(volatile uint32_t *)0xA8040020 = 0x1234;
#include <stdint.h>
 
*(volatile uint32_t *)0xA8040000; /* dummy read */
*(volatile uint32_t *)0xA8040020 = 0x1234; /* enable ED64 registers */
</syntaxhighlight>
 
=== 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.
 
TBA
<syntaxhighlight lang=c>
/* 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 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 */
</syntaxhighlight>
 
=== Reading Data from the Host ===
You should use USB->Cart DMA on ED64 first, then transfer data from cart ROM area to RDRAM.
 
TBA
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.
 
<syntaxhighlight lang=c>
/* 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;
 
/* invalidate D-cache (primary data hit invalidate; 16 bytes per 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 */
while(*(volatile uint32_t *)0xA8040004 & 4) /* busyloop */ ; /* wait until REG_STATUS & RXE# becomes zero = data is arriving */
*(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 0;
}
 
...
uint8_t __attribute((aligned(8)) buffer[512];
host_to_rdram(buffer, 0x00400000 - 2048, 512); /* using last ROM area for communication */
/* "buffer" is modified */
</syntaxhighlight>
 
[[Category:Flash Carts]]
24

edits