mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-01-11 12:09:08 +01:00
yee
This commit is contained in:
parent
7fa3302299
commit
b297bd3f25
@ -298,7 +298,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
|
||||
# end DESIGN_PARTITION(Top)
|
||||
# -------------------------
|
||||
@ -322,4 +321,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
# ========================
|
||||
|
||||
# end ENTITY(intel_gpio_ddro)
|
||||
# ---------------------------
|
||||
# ---------------------------
|
||||
set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
@ -17,8 +17,8 @@ FLAGS=\
|
||||
|
||||
all: controller.bin print_size
|
||||
|
||||
controller.elf: prv32_rwx.ld main.c rtc.c startup.S
|
||||
@$(CROSS)gcc $(FLAGS) main.c rtc.c startup.S -o controller.elf
|
||||
controller.elf: prv32_rwx.ld main.c init.c process.c
|
||||
@$(CROSS)gcc $(FLAGS) main.c init.c process.c -o controller.elf
|
||||
|
||||
controller.bin: controller.elf
|
||||
@$(CROSS)objcopy -O binary controller.elf tmp.bin
|
||||
|
17
fw/cpu/controller/init.c
Normal file
17
fw/cpu/controller/init.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
void init (void) {
|
||||
DMA->SCR = DMA_SCR_STOP;
|
||||
USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
|
||||
|
||||
GPIO->ODR = 0;
|
||||
GPIO->OER = (1 << 0);
|
||||
|
||||
CFG->SCR = CFG_SCR_SDRAM_SWITCH;
|
||||
CFG->DD_OFFSET = 0x3BE0000;
|
||||
CFG->SAVE_OFFSET = 0x3FE0000;
|
||||
|
||||
while (!(UART->SCR & UART_SCR_TXE));
|
||||
UART->DR = '$';
|
||||
}
|
8
fw/cpu/controller/init.h
Normal file
8
fw/cpu/controller/init.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef INIT_H__
|
||||
#define INIT_H__
|
||||
|
||||
|
||||
void init (void);
|
||||
|
||||
|
||||
#endif
|
@ -1,227 +1,9 @@
|
||||
#include "sys.h"
|
||||
#include "rtc.h"
|
||||
#include "init.h"
|
||||
#include "process.h"
|
||||
|
||||
|
||||
volatile int counter = 0;
|
||||
|
||||
|
||||
void print (const char *text) {
|
||||
while (*text != '\0') {
|
||||
while (!(UART_SCR & UART_SCR_TXE));
|
||||
UART_DR = *text++;
|
||||
}
|
||||
__attribute__((naked)) void main (void) {
|
||||
__asm__("la sp, __stack_pointer");
|
||||
init();
|
||||
process();
|
||||
}
|
||||
|
||||
const char hex_char_map[16] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
void print_02hex (unsigned char number) {
|
||||
char buffer[3];
|
||||
buffer[0] = hex_char_map[number >> 4];
|
||||
buffer[1] = hex_char_map[number & 0x0F];
|
||||
buffer[2] = '\0';
|
||||
print(buffer);
|
||||
}
|
||||
|
||||
const char *weekday_names[7] = {
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
"Sunday"
|
||||
};
|
||||
|
||||
void print_nice_date(uint8_t *date) {
|
||||
print_02hex(date[4]);
|
||||
print(".");
|
||||
print_02hex(date[5]);
|
||||
print(".20");
|
||||
print_02hex(date[6]);
|
||||
print(" (");
|
||||
print(weekday_names[date[3] - 1]);
|
||||
print(") ");
|
||||
print_02hex(date[2]);
|
||||
print(":");
|
||||
print_02hex(date[1]);
|
||||
print(":");
|
||||
print_02hex(date[0]);
|
||||
}
|
||||
|
||||
const char CMD[3] = {'C', 'M', 'D'};
|
||||
const char CMD_R = 'R';
|
||||
const char CMD_W = 'W';
|
||||
|
||||
const char CMP[3] = {'C', 'M', 'P'};
|
||||
|
||||
__NAKED__ int main (void) {
|
||||
uint8_t data;
|
||||
uint8_t cmd = '-';
|
||||
uint32_t arg1, arg2;
|
||||
char tmp[2];
|
||||
|
||||
tmp[1] = 0;
|
||||
|
||||
GPIO_OE = (1 << 0);
|
||||
GPIO_O = 0; // (1 << 0);
|
||||
|
||||
CFG_SCR |= CFG_SCR_SRAM_EN | CFG_SCR_SDRAM_SWITCH | CFG_SCR_DD_EN;
|
||||
CFG_DD_OFFSET = 0;//0x3BE0000;
|
||||
CFG_SAVE_OFFSET = 0x3FE0000;
|
||||
|
||||
DMA_SCR = DMA_SCR_STOP;
|
||||
USB_SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
|
||||
|
||||
print("CPU START\r\n");
|
||||
|
||||
while (1) {
|
||||
arg1 = 0;
|
||||
arg2 = 0;
|
||||
|
||||
|
||||
if (USB_SCR & USB_SCR_RXNE) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
data = USB_DR;
|
||||
if (i < 3 && data != CMD[i]) {
|
||||
i = 0;
|
||||
print("Wrong data ");
|
||||
print_02hex(data);
|
||||
print("\r\n");
|
||||
} else {
|
||||
cmd = data;
|
||||
}
|
||||
}
|
||||
|
||||
print("Received CMD");
|
||||
tmp[0] = cmd;
|
||||
print(tmp);
|
||||
print("\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
arg1 = (arg1 << 8) | USB_DR;
|
||||
}
|
||||
|
||||
print("Received ARG_1 0x");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
print_02hex((uint8_t) (arg1 >> ((3 - i) * 8)));
|
||||
}
|
||||
print("\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_RXNE));
|
||||
arg2 = (arg2 << 8) | USB_DR;
|
||||
}
|
||||
|
||||
print("Received ARG_2 0x");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
print_02hex((uint8_t) (arg2 >> ((3 - i) * 8)));
|
||||
}
|
||||
print("\r\n");
|
||||
|
||||
DMA_MADDR = arg1;
|
||||
DMA_ID_LEN = arg2;
|
||||
DMA_SCR = (cmd == CMD_W ? DMA_SCR_DIR : 0) | DMA_SCR_START;
|
||||
|
||||
print("Started DMA\r\n");
|
||||
|
||||
while (DMA_SCR & DMA_SCR_BUSY);
|
||||
|
||||
print("Finished DMA\r\n");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
while (!(USB_SCR & USB_SCR_TXE));
|
||||
if (i < 3) {
|
||||
USB_DR = CMP[i];
|
||||
} else {
|
||||
USB_DR = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
print("Sent response CMP");
|
||||
tmp[0] = cmd;
|
||||
print(tmp);
|
||||
print("\r\n\r\n");
|
||||
} else if (CFG_SCR & CFG_SCR_CPU_BUSY) {
|
||||
uint8_t cmd = CFG_COMMAND;
|
||||
arg1 = CFG_ARG_1;
|
||||
arg2 = CFG_ARG_2;
|
||||
print("Received N64 CMD");
|
||||
tmp[0] = cmd;
|
||||
print(tmp);
|
||||
print("\r\n");
|
||||
if (cmd == 'S') {
|
||||
if (arg1) {
|
||||
CFG_SCR |= CFG_SCR_SDRAM_SWITCH;
|
||||
} else {
|
||||
CFG_SCR &= ~CFG_SCR_SDRAM_SWITCH;
|
||||
}
|
||||
}
|
||||
if (cmd == 'D') {
|
||||
print_02hex(arg1 >> 24);
|
||||
print_02hex(arg1 >> 16);
|
||||
print_02hex(arg1 >> 8);
|
||||
print_02hex(arg1 >> 0);
|
||||
print(" ");
|
||||
print_02hex(arg2 >> 24);
|
||||
print_02hex(arg2 >> 16);
|
||||
print_02hex(arg2 >> 8);
|
||||
print_02hex(arg2 >> 0);
|
||||
print("\r\n");
|
||||
}
|
||||
print("\r\n");
|
||||
CFG_RESPONSE = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __NAKED__ int main (void) {
|
||||
// uint8_t rtc_data[7];
|
||||
// uint8_t rtc_new_data[7];
|
||||
// int index = 0;
|
||||
|
||||
// GPIO_OE = (1 << 0);
|
||||
// GPIO_O = (1 << 0);
|
||||
|
||||
// rtc_init();
|
||||
|
||||
// while (!(USB_SR & USB_SR_TXE));
|
||||
// USB_DR = 0x55;
|
||||
// USB_DR = 0xAA;
|
||||
// USB_DR = 0x00;
|
||||
// USB_DR = 'D';
|
||||
// USB_DR = 'E';
|
||||
// USB_DR = 'A';
|
||||
// USB_DR = 'D';
|
||||
// USB_DR = 0xFF;
|
||||
// USB_DR = 0xAA;
|
||||
// USB_DR = 0x55;
|
||||
|
||||
// while (1) {
|
||||
// GPIO_O = (1 << 0);
|
||||
|
||||
// print("\033[2J\033[H\r\n --- Hello --- \r\n\r\n");
|
||||
// print(" RTC Data:\r\n\r\n ");
|
||||
|
||||
// rtc_get_time(rtc_data);
|
||||
|
||||
// print_nice_date(rtc_data);
|
||||
|
||||
// print("\r\n");
|
||||
// GPIO_O = 0x00;
|
||||
|
||||
// while (counter++ < 0x0003FFFF);
|
||||
// counter = 0;
|
||||
|
||||
// if (USB_SR & USB_SR_RXNE) {
|
||||
// rtc_new_data[index++] = USB_DR;
|
||||
// if (index == 7) {
|
||||
// index = 0;
|
||||
// rtc_set_time(rtc_new_data);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
267
fw/cpu/controller/process.c
Normal file
267
fw/cpu/controller/process.c
Normal file
@ -0,0 +1,267 @@
|
||||
#include "sys.h"
|
||||
#include "process.h"
|
||||
|
||||
static const uint8_t cmd_token[3] = { 'C', 'M', 'D' };
|
||||
static const uint8_t cmp_token[3] = { 'C', 'M', 'P' };
|
||||
static const uint8_t err_token[3] = { 'E', 'R', 'R' };
|
||||
|
||||
static uint8_t save_type = 0;
|
||||
static uint16_t cic_type = 0xFFFF;
|
||||
static uint8_t tv_type = 0xFF;
|
||||
|
||||
void process_usb (void);
|
||||
void process_cfg (void);
|
||||
void process_dd (void);
|
||||
void process_si (void);
|
||||
void process_uart (void);
|
||||
void cfg_set_save_type (uint8_t type);
|
||||
void cfg_update_config (uint32_t *args);
|
||||
|
||||
void process (void) {
|
||||
while (1) {
|
||||
process_usb();
|
||||
process_cfg();
|
||||
process_dd();
|
||||
process_si();
|
||||
process_uart();
|
||||
}
|
||||
}
|
||||
|
||||
void process_usb (void) {
|
||||
static int state = 0;
|
||||
static uint8_t current_byte = 0;
|
||||
static uint8_t cmd;
|
||||
static uint32_t args[2];
|
||||
static uint8_t is_error;
|
||||
static uint8_t dma_started;
|
||||
|
||||
uint8_t data;
|
||||
|
||||
switch (state) {
|
||||
case 0: {
|
||||
if (USB->SCR & USB_SCR_RXNE) {
|
||||
data = USB->DR;
|
||||
if (current_byte == 3) {
|
||||
state = 1;
|
||||
current_byte = 0;
|
||||
cmd = data;
|
||||
args[0] = 0;
|
||||
args[1] = 0;
|
||||
is_error = 0;
|
||||
dma_started = 0;
|
||||
break;
|
||||
}
|
||||
if (data != cmd_token[current_byte]) {
|
||||
current_byte = 0;
|
||||
break;
|
||||
}
|
||||
current_byte += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
if (USB->SCR & USB_SCR_RXNE) {
|
||||
data = USB->DR;
|
||||
uint32_t *p = args + (current_byte >= 4 ? 1 : 0);
|
||||
*p = (*p << 8) | data;
|
||||
current_byte += 1;
|
||||
if (current_byte == 8) {
|
||||
state = 2;
|
||||
current_byte = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
if (cmd == 'R' || cmd == 'W') {
|
||||
if (!dma_started) {
|
||||
if (!(DMA->SCR & DMA_SCR_BUSY)) {
|
||||
DMA->MADDR = args[0];
|
||||
DMA->ID_LEN = args[1];
|
||||
DMA->SCR = (cmd == 'W' ? DMA_SCR_DIR : 0) | DMA_SCR_START;
|
||||
dma_started = 1;
|
||||
}
|
||||
} else {
|
||||
if (!(DMA->SCR & DMA_SCR_BUSY)) {
|
||||
state = 3;
|
||||
}
|
||||
}
|
||||
} else if (cmd == 'C') {
|
||||
cfg_update_config(args);
|
||||
state = 3;
|
||||
} else {
|
||||
state = 3;
|
||||
is_error = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
if (USB->SCR & USB_SCR_TXE) {
|
||||
const uint8_t *p = is_error ? err_token : cmp_token;
|
||||
USB->DR = (current_byte < 3) ? p[current_byte] : cmd;
|
||||
current_byte += 1;
|
||||
if (current_byte == 4) {
|
||||
state = 0;
|
||||
current_byte = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_cfg (void) {
|
||||
static uint8_t state = 0;
|
||||
static uint8_t cmd;
|
||||
static uint32_t args[3];
|
||||
|
||||
switch (state) {
|
||||
case 0: {
|
||||
if (CFG->SCR & CFG_SCR_CPU_BUSY) {
|
||||
state = 1;
|
||||
cmd = CFG->CMD;
|
||||
args[0] = CFG->DATA[0];
|
||||
args[1] = CFG->DATA[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
if (cmd == 'C') {
|
||||
cfg_update_config(args);
|
||||
CFG->DATA[0] = (save_type << 8) | (CFG->SCR & 0x07);
|
||||
CFG->DATA[1] = (tv_type << 16) | cic_type;
|
||||
state = 2;
|
||||
} else {
|
||||
CFG->DATA[0] = 0xFFFFFFFF;
|
||||
CFG->DATA[1] = 0xFFFFFFFF;
|
||||
state = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
CFG->SCR &= ~(CFG_SCR_CPU_BUSY);
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_dd (void) {
|
||||
|
||||
}
|
||||
|
||||
void process_si (void) {
|
||||
|
||||
}
|
||||
|
||||
void process_uart (void) {
|
||||
if (UART->SCR & UART_SCR_RXNE) {
|
||||
uint8_t data = UART->DR;
|
||||
if (data == '/') {
|
||||
while (!(UART->SCR & UART_SCR_TXE));
|
||||
UART->DR = '>';
|
||||
void (*bootloader) (void) = (void *) &BOOTLOADER;
|
||||
bootloader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cfg_set_save_type (uint8_t type) {
|
||||
CFG->SCR &= ~(CFG_SCR_FLASHRAM_EN | CFG_SCR_SRAM_EN);
|
||||
|
||||
switch (type) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
CFG->SAVE_OFFSET = SDRAM_SIZE - 512;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
CFG->SAVE_OFFSET = SDRAM_SIZE - 2048;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
CFG->SAVE_OFFSET = SDRAM_SIZE - (32 * 1024);
|
||||
CFG->SCR |= CFG_SCR_SRAM_EN;
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
CFG->SAVE_OFFSET = SDRAM_SIZE - (256 * 1024);
|
||||
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
CFG->SAVE_OFFSET = SDRAM_SIZE - (3 * 32 * 1024);
|
||||
CFG->SCR |= CFG_SCR_SRAM_EN;
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
CFG->SAVE_OFFSET = 0x01618000;
|
||||
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
save_type = type;
|
||||
}
|
||||
|
||||
void cfg_update_config (uint32_t *args) {
|
||||
switch (args[0]) {
|
||||
case 0: {
|
||||
if (args[1]) {
|
||||
CFG->SCR |= CFG_SCR_SDRAM_SWITCH;
|
||||
} else {
|
||||
CFG->SCR &= ~CFG_SCR_SDRAM_SWITCH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (args[1]) {
|
||||
CFG->SCR |= CFG_SCR_SDRAM_WRITABLE;
|
||||
} else {
|
||||
CFG->SCR &= ~CFG_SCR_SDRAM_WRITABLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
if (args[1]) {
|
||||
CFG->SCR |= CFG_SCR_DD_EN;
|
||||
} else {
|
||||
CFG->SCR &= ~CFG_SCR_DD_EN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
cfg_set_save_type(args[1] & 0xFF);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
cic_type = args[1] & 0xFFFF;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
tv_type = args[1] & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
8
fw/cpu/controller/process.h
Normal file
8
fw/cpu/controller/process.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef PROCESS_H__
|
||||
#define PROCESS_H__
|
||||
|
||||
|
||||
void process (void);
|
||||
|
||||
|
||||
#endif
|
@ -6,14 +6,14 @@ MEMORY
|
||||
__ram_size = LENGTH(ram);
|
||||
__stack_pointer = ORIGIN(ram) + LENGTH(ram) - 16;
|
||||
|
||||
ENTRY(reset_handler)
|
||||
ENTRY(main)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.ram :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text.startup);
|
||||
*(.text.main);
|
||||
. = ALIGN(4);
|
||||
*(.text .text* .rodata .rodata* .srodata .srodata*);
|
||||
. = ALIGN(4);
|
||||
|
@ -1,5 +0,0 @@
|
||||
.section .text.startup
|
||||
.global reset_handler
|
||||
reset_handler:
|
||||
la sp, __stack_pointer
|
||||
j main
|
@ -6,25 +6,36 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define __NAKED__ __attribute__((naked))
|
||||
|
||||
typedef volatile uint8_t * io8_t;
|
||||
typedef volatile uint32_t * io32_t;
|
||||
|
||||
#define RAM (*((io32_t) 0x00000000))
|
||||
typedef volatile uint8_t io8_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
|
||||
|
||||
#define BOOTLOADER (*((io32_t) 0x10000000))
|
||||
#define RAM_BASE (0x00000000)
|
||||
#define RAM (*((io32_t *) RAM_BASE))
|
||||
|
||||
|
||||
#define GPIO (*((io32_t) 0x20000000))
|
||||
#define GPIO_O (*((io8_t) 0x20000000))
|
||||
#define GPIO_I (*((io8_t) 0x20000001))
|
||||
#define GPIO_OE (*((io8_t) 0x20000002))
|
||||
#define BOOTLOADER_BASE (0x10000000)
|
||||
#define BOOTLOADER (*((io32_t *) BOOTLOADER_BASE))
|
||||
|
||||
|
||||
#define I2C_SCR (*((io8_t) 0x30000000))
|
||||
#define I2C_DR (*((io8_t) 0x30000004))
|
||||
typedef volatile struct gpio_regs {
|
||||
io8_t ODR;
|
||||
io8_t IDR;
|
||||
io8_t OER;
|
||||
io8_t __padding;
|
||||
} gpio_regs_t;
|
||||
|
||||
#define GPIO_BASE (0x20000000)
|
||||
#define GPIO ((gpio_regs_t *) GPIO_BASE)
|
||||
|
||||
|
||||
typedef volatile struct i2c_regs {
|
||||
io32_t SCR;
|
||||
io32_t DR;
|
||||
} i2c_regs_t;
|
||||
|
||||
#define I2C_BASE (0x30000000)
|
||||
#define I2C ((i2c_regs_t *) I2C_BASE)
|
||||
|
||||
#define I2C_SCR_START (1 << 0)
|
||||
#define I2C_SCR_STOP (1 << 1)
|
||||
@ -34,8 +45,14 @@ typedef volatile uint32_t * io32_t;
|
||||
#define I2C_ADDR_READ (1 << 0)
|
||||
|
||||
|
||||
#define USB_SCR (*((io8_t) 0x40000000))
|
||||
#define USB_DR (*((io8_t) 0x40000004))
|
||||
typedef volatile struct usb_regs {
|
||||
io32_t SCR;
|
||||
io8_t DR;
|
||||
io8_t __padding[3];
|
||||
} usb_regs_t;
|
||||
|
||||
#define USB_BASE (0x40000000)
|
||||
#define USB ((usb_regs_t *) USB_BASE)
|
||||
|
||||
#define USB_SCR_RXNE (1 << 0)
|
||||
#define USB_SCR_TXE (1 << 1)
|
||||
@ -43,16 +60,27 @@ typedef volatile uint32_t * io32_t;
|
||||
#define USB_SCR_FLUSH_TX (1 << 3)
|
||||
|
||||
|
||||
#define UART_SCR (*((io8_t) 0x50000000))
|
||||
#define UART_DR (*((io8_t) 0x50000004))
|
||||
typedef volatile struct uart_regs {
|
||||
io32_t SCR;
|
||||
io8_t DR;
|
||||
io8_t __padding[3];
|
||||
} uart_regs_t;
|
||||
|
||||
#define UART_BASE (0x50000000)
|
||||
#define UART ((uart_regs_t *) UART_BASE)
|
||||
|
||||
#define UART_SCR_RXNE (1 << 0)
|
||||
#define UART_SCR_TXE (1 << 1)
|
||||
|
||||
|
||||
#define DMA_SCR (*((io8_t) 0x60000000))
|
||||
#define DMA_MADDR (*((io32_t) 0x60000004))
|
||||
#define DMA_ID_LEN (*((io32_t) 0x60000008))
|
||||
typedef volatile struct dma_regs {
|
||||
io32_t SCR;
|
||||
io32_t MADDR;
|
||||
io32_t ID_LEN;
|
||||
} dma_regs_t;
|
||||
|
||||
#define DMA_BASE (0x60000000)
|
||||
#define DMA ((dma_regs_t *) DMA_BASE)
|
||||
|
||||
#define DMA_SCR_START (1 << 0)
|
||||
#define DMA_SCR_STOP (1 << 1)
|
||||
@ -60,16 +88,17 @@ typedef volatile uint32_t * io32_t;
|
||||
#define DMA_SCR_BUSY (1 << 3)
|
||||
|
||||
|
||||
#define SDRAM (*((io32_t) 0x68000000))
|
||||
typedef volatile struct cfg_regs {
|
||||
io32_t SCR;
|
||||
io32_t DD_OFFSET;
|
||||
io32_t SAVE_OFFSET;
|
||||
io8_t CMD;
|
||||
io8_t __padding[3];
|
||||
io32_t DATA[3];
|
||||
} cfg_regs_t;
|
||||
|
||||
|
||||
#define CFG_SCR (*((io32_t) 0x70000000))
|
||||
#define CFG_DD_OFFSET (*((io32_t) 0x70000004))
|
||||
#define CFG_SAVE_OFFSET (*((io32_t) 0x70000008))
|
||||
#define CFG_COMMAND (*((io8_t) 0x7000000C))
|
||||
#define CFG_ARG_1 (*((io32_t) 0x70000010))
|
||||
#define CFG_ARG_2 (*((io32_t) 0x70000014))
|
||||
#define CFG_RESPONSE (*((io32_t) 0x70000018))
|
||||
#define CFG_BASE (0x70000000)
|
||||
#define CFG ((cfg_regs_t *) CFG_BASE)
|
||||
|
||||
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
|
||||
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
|
||||
@ -77,7 +106,12 @@ typedef volatile uint32_t * io32_t;
|
||||
#define CFG_SCR_SRAM_EN (1 << 3)
|
||||
#define CFG_SCR_FLASHRAM_EN (1 << 4)
|
||||
#define CFG_SCR_CPU_BUSY (1 << 30)
|
||||
#define CFG_SCR_CPU_RUNNING (1 << 31)
|
||||
#define CFG_SCR_CPU_READY (1 << 31)
|
||||
|
||||
|
||||
#define SDRAM_BASE (0x80000000)
|
||||
#define SDRAM (*((io32_t *) SDRAM_BASE)
|
||||
#define SDRAM_SIZE (64 * 1024 * 1024)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,14 +9,10 @@ module cpu_cfg (
|
||||
R_DD_OFFSET,
|
||||
R_SAVE_OFFSET,
|
||||
R_COMMAND,
|
||||
R_ARG_1,
|
||||
R_ARG_2,
|
||||
R_RESPONSE,
|
||||
R_BOOTSTRAP
|
||||
R_DATA_0,
|
||||
R_DATA_1
|
||||
} e_reg_id;
|
||||
|
||||
logic bootstrap_pending;
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
if (bus.request) begin
|
||||
@ -29,10 +25,9 @@ module cpu_cfg (
|
||||
if (bus.ack) begin
|
||||
case (bus.address[4:2])
|
||||
R_SCR: bus.rdata = {
|
||||
cfg.cpu_bootstrapped,
|
||||
cfg.cpu_ready,
|
||||
cfg.cpu_busy,
|
||||
bootstrap_pending,
|
||||
24'd0,
|
||||
25'd0,
|
||||
cfg.flashram_enabled,
|
||||
cfg.sram_enabled,
|
||||
cfg.dd_enabled,
|
||||
@ -41,18 +36,26 @@ module cpu_cfg (
|
||||
};
|
||||
R_DD_OFFSET: bus.rdata = {6'd0, cfg.dd_offset};
|
||||
R_SAVE_OFFSET: bus.rdata = {6'd0, cfg.save_offset};
|
||||
R_COMMAND: bus.rdata = {24'd0, cfg.command};
|
||||
R_ARG_1: bus.rdata = cfg.arg[0];
|
||||
R_ARG_2: bus.rdata = cfg.arg[1];
|
||||
R_RESPONSE: bus.rdata = cfg.response;
|
||||
R_BOOTSTRAP: bus.rdata = cfg.arg[0];
|
||||
R_COMMAND: bus.rdata = {24'd0, cfg.cmd};
|
||||
R_DATA_0: bus.rdata = cfg.data[0];
|
||||
R_DATA_1: bus.rdata = cfg.data[1];
|
||||
default: bus.rdata = 32'd0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
cfg.wdata = bus.wdata;
|
||||
cfg.data_write = 2'b00;
|
||||
if (bus.request && (&bus.wmask)) begin
|
||||
cfg.data_write[0] = bus.address[4:2] == R_DATA_0;
|
||||
cfg.data_write[1] = bus.address[4:2] == R_DATA_1;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (sys.reset) begin
|
||||
cfg.cpu_bootstrapped <= 1'b0;
|
||||
cfg.cpu_ready <= 1'b0;
|
||||
cfg.cpu_busy <= 1'b0;
|
||||
cfg.sdram_switch <= 1'b0;
|
||||
cfg.sdram_writable <= 1'b0;
|
||||
@ -61,22 +64,20 @@ module cpu_cfg (
|
||||
cfg.flashram_enabled <= 1'b0;
|
||||
cfg.dd_offset <= 26'h3BE_0000;
|
||||
cfg.save_offset <= 26'h3FE_0000;
|
||||
bootstrap_pending <= 1'b0;
|
||||
end else begin
|
||||
if (sys.n64_soft_reset) begin
|
||||
cfg.sdram_switch <= 1'b0;
|
||||
cfg.sdram_writable <= 1'b0;
|
||||
end
|
||||
if (cfg.request) begin
|
||||
if (cfg.cmd_request) begin
|
||||
cfg.cpu_busy <= 1'b1;
|
||||
end
|
||||
if (cfg.boot_write) begin
|
||||
bootstrap_pending <= 1'b1;
|
||||
end
|
||||
if (bus.request) begin
|
||||
case (bus.address[4:2])
|
||||
R_SCR: begin
|
||||
if (bus.wmask[3]) begin
|
||||
cfg.cpu_bootstrapped <= bus.wdata[31];
|
||||
cfg.cpu_ready <= bus.wdata[31];
|
||||
cfg.cpu_busy <= bus.wdata[30];
|
||||
end
|
||||
if (bus.wmask[0]) begin
|
||||
{
|
||||
@ -100,19 +101,6 @@ module cpu_cfg (
|
||||
cfg.save_offset <= bus.wdata[25:0];
|
||||
end
|
||||
end
|
||||
|
||||
R_RESPONSE: begin
|
||||
if (&bus.wmask) begin
|
||||
cfg.cpu_busy <= 1'b0;
|
||||
cfg.response <= bus.wdata;
|
||||
end
|
||||
end
|
||||
|
||||
R_BOOTSTRAP: begin
|
||||
if (!(|bus.wmask)) begin
|
||||
bootstrap_pending <= 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -101,6 +101,7 @@ module cpu_dma (
|
||||
} e_state;
|
||||
|
||||
e_state state;
|
||||
logic pending_stop;
|
||||
logic direction;
|
||||
logic [27:0] length;
|
||||
logic [15:0] rdata_buffer;
|
||||
@ -129,10 +130,17 @@ module cpu_dma (
|
||||
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
pending_stop <= 1'b0;
|
||||
dma.request <= 1'b0;
|
||||
end else begin
|
||||
if (bus.request && bus.address[3:2] == 0 && bus.wmask[0]) begin
|
||||
pending_stop <= bus.wdata[1];
|
||||
end
|
||||
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
pending_stop <= 1'b0;
|
||||
|
||||
if (bus.request) begin
|
||||
case (bus.address[3:2])
|
||||
0: if (bus.wmask[0]) begin
|
||||
@ -155,7 +163,7 @@ module cpu_dma (
|
||||
end
|
||||
|
||||
S_FETCH: begin
|
||||
if (length != 28'd0) begin
|
||||
if (length != 28'd0 && !pending_stop) begin
|
||||
if (direction) begin
|
||||
if (!dma.rx_empty && !dma.rx_read) begin
|
||||
dma.rx_read <= 1'b1;
|
||||
|
@ -4,6 +4,17 @@ module n64_cfg (
|
||||
if_config.n64 cfg
|
||||
);
|
||||
|
||||
typedef enum bit [3:0] {
|
||||
R_SR,
|
||||
R_COMMAND,
|
||||
R_DATA_0_H,
|
||||
R_DATA_0_L,
|
||||
R_DATA_1_H,
|
||||
R_DATA_1_L,
|
||||
R_VERSION_H,
|
||||
R_VERSION_L
|
||||
} e_reg_id;
|
||||
|
||||
typedef enum bit [0:0] {
|
||||
S_IDLE,
|
||||
S_WAIT
|
||||
@ -15,20 +26,14 @@ module n64_cfg (
|
||||
bus.rdata = 16'd0;
|
||||
if (bus.ack) begin
|
||||
case (bus.address[4:1])
|
||||
0: bus.rdata = {cfg.cpu_bootstrapped, cfg.cpu_busy, 14'd0};
|
||||
// ...
|
||||
3: bus.rdata = {8'd0, cfg.command};
|
||||
4: bus.rdata = cfg.arg[0][31:16];
|
||||
5: bus.rdata = cfg.arg[0][15:0];
|
||||
6: bus.rdata = cfg.arg[1][31:16];
|
||||
7: bus.rdata = cfg.arg[1][15:0];
|
||||
8: bus.rdata = cfg.response[31:16];
|
||||
9: bus.rdata = cfg.response[15:0];
|
||||
10: bus.rdata = cfg.arg[0][31:16];
|
||||
11: bus.rdata = cfg.arg[0][15:0];
|
||||
// ...
|
||||
14: bus.rdata = 16'h5343;
|
||||
15: bus.rdata = 16'h7632;
|
||||
R_SR: bus.rdata = {cfg.cpu_ready, cfg.cpu_busy, 14'd0};
|
||||
R_COMMAND: bus.rdata = {8'd0, cfg.cmd};
|
||||
R_DATA_0_H: bus.rdata = cfg.data[0][31:16];
|
||||
R_DATA_0_L: bus.rdata = cfg.data[0][15:0];
|
||||
R_DATA_1_H: bus.rdata = cfg.data[1][31:16];
|
||||
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
|
||||
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
|
||||
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
|
||||
default: bus.rdata = 16'd0;
|
||||
endcase
|
||||
end
|
||||
@ -36,8 +41,10 @@ module n64_cfg (
|
||||
|
||||
always_ff @(posedge sys.clk) begin
|
||||
bus.ack <= 1'b0;
|
||||
cfg.request <= 1'b0;
|
||||
cfg.boot_write <= 1'b0;
|
||||
cfg.cmd_request <= 1'b0;
|
||||
|
||||
if (cfg.data_write[0]) cfg.data[0] <= cfg.wdata;
|
||||
if (cfg.data_write[1]) cfg.data[1] <= cfg.wdata;
|
||||
|
||||
if (sys.reset) begin
|
||||
state <= S_IDLE;
|
||||
@ -49,21 +56,14 @@ module n64_cfg (
|
||||
bus.ack <= 1'b1;
|
||||
if (bus.write) begin
|
||||
case (bus.address[4:1])
|
||||
// ...
|
||||
3: begin
|
||||
cfg.command <= bus.wdata[7:0];
|
||||
cfg.request <= 1'b1;
|
||||
end
|
||||
4: cfg.arg[0][31:16] <= bus.wdata;
|
||||
5: cfg.arg[0][15:0] <= bus.wdata;
|
||||
6: cfg.arg[1][31:16] <= bus.wdata;
|
||||
7: cfg.arg[1][15:0] <= bus.wdata;
|
||||
// ...
|
||||
10: cfg.arg[0][31:16] <= bus.wdata;
|
||||
11: begin
|
||||
cfg.arg[0][15:0] <= bus.wdata;
|
||||
cfg.boot_write <= 1'b1;
|
||||
R_COMMAND: begin
|
||||
cfg.cmd <= bus.wdata[7:0];
|
||||
cfg.cmd_request <= 1'b1;
|
||||
end
|
||||
R_DATA_0_H: cfg.data[0][31:16] <= bus.wdata;
|
||||
R_DATA_0_L: cfg.data[0][15:0] <= bus.wdata;
|
||||
R_DATA_1_H: cfg.data[1][31:16] <= bus.wdata;
|
||||
R_DATA_1_L: cfg.data[1][15:0] <= bus.wdata;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
@ -88,7 +88,7 @@ module n64_dummy (
|
||||
always_comb begin
|
||||
bus.rdata = 16'h0000;
|
||||
if (bus.ack) begin
|
||||
bus.rdata = !bus.address[1] ? 16'h0180 : 16'h0000;
|
||||
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
interface if_config ();
|
||||
|
||||
logic cpu_bootstrapped;
|
||||
logic cpu_ready;
|
||||
logic cpu_busy;
|
||||
logic request;
|
||||
logic [7:0] command;
|
||||
logic [31:0] arg [0:1];
|
||||
logic [31:0] response;
|
||||
logic boot_write;
|
||||
logic cmd_request;
|
||||
logic [7:0] cmd;
|
||||
logic [31:0] data [0:1];
|
||||
logic [1:0] data_write;
|
||||
logic [31:0] wdata;
|
||||
logic sdram_switch;
|
||||
logic sdram_writable;
|
||||
logic dd_enabled;
|
||||
@ -32,23 +32,23 @@ interface if_config ();
|
||||
);
|
||||
|
||||
modport n64 (
|
||||
input cpu_bootstrapped,
|
||||
input cpu_ready,
|
||||
input cpu_busy,
|
||||
output request,
|
||||
output command,
|
||||
output arg,
|
||||
input response,
|
||||
output boot_write
|
||||
output cmd_request,
|
||||
output cmd,
|
||||
output data,
|
||||
input data_write,
|
||||
input wdata
|
||||
);
|
||||
|
||||
modport cpu (
|
||||
output cpu_bootstrapped,
|
||||
output cpu_ready,
|
||||
output cpu_busy,
|
||||
input request,
|
||||
input command,
|
||||
input arg,
|
||||
output response,
|
||||
input boot_write,
|
||||
input cmd_request,
|
||||
input cmd,
|
||||
input data,
|
||||
output data_write,
|
||||
output wdata,
|
||||
output sdram_switch,
|
||||
output sdram_writable,
|
||||
output dd_enabled,
|
||||
|
40
fw/rtl/system/dd.sv
Normal file
40
fw/rtl/system/dd.sv
Normal file
@ -0,0 +1,40 @@
|
||||
interface if_dd();
|
||||
|
||||
logic hard_reset;
|
||||
logic cmd_request;
|
||||
logic cmd_ack;
|
||||
logic [7:0] command;
|
||||
logic [15:0] status;
|
||||
logic [15:0] data_input;
|
||||
logic [15:0] data_output;
|
||||
logic bm_request;
|
||||
logic [15:0] bm_control;
|
||||
logic [15:0] bm_status;
|
||||
|
||||
modport n64 (
|
||||
output hard_reset,
|
||||
output cmd_request,
|
||||
input cmd_ack,
|
||||
output command,
|
||||
input status,
|
||||
output data_input,
|
||||
input data_output,
|
||||
output bm_request,
|
||||
output bm_control,
|
||||
input bm_status
|
||||
);
|
||||
|
||||
modport cpu (
|
||||
input hard_reset,
|
||||
input cmd_request,
|
||||
output cmd_ack,
|
||||
input command,
|
||||
output status,
|
||||
input data_input,
|
||||
output data_output,
|
||||
input bm_request,
|
||||
input bm_control,
|
||||
output bm_status
|
||||
);
|
||||
|
||||
endinterface
|
@ -27,6 +27,8 @@ package sc64;
|
||||
__ID_DMA_END
|
||||
} e_dma_id;
|
||||
|
||||
parameter bit [31:0] SC64_VER = 32'h53437632;
|
||||
|
||||
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
||||
|
||||
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "boot.h"
|
||||
#include "crc32.h"
|
||||
#include "n64_regs.h"
|
||||
// #include "sc64.h"
|
||||
|
||||
|
||||
static const struct crc32_to_cic_seed {
|
||||
@ -140,10 +141,9 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) {
|
||||
gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
|
||||
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == TV_PAL) ? 341 : 340]);
|
||||
|
||||
print_debug((uint32_t) gpr_regs[CPU_REG_T3], (uint32_t) gpr_regs[CPU_REG_S3]);
|
||||
print_debug((uint32_t) gpr_regs[CPU_REG_S4], (uint32_t) gpr_regs[CPU_REG_S5]);
|
||||
print_debug((uint32_t) gpr_regs[CPU_REG_S6], (uint32_t) gpr_regs[CPU_REG_S7]);
|
||||
print_debug((uint32_t) gpr_regs[CPU_REG_SP], (uint32_t) gpr_regs[CPU_REG_RA]);
|
||||
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_T3], (uint32_t) gpr_regs[CPU_REG_S3], (uint32_t) gpr_regs[CPU_REG_S4]);
|
||||
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_S5], (uint32_t) gpr_regs[CPU_REG_S6], (uint32_t) gpr_regs[CPU_REG_S7]);
|
||||
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_SP], (uint32_t) gpr_regs[CPU_REG_RA], 0);
|
||||
|
||||
__asm__ (
|
||||
".set noat \n\t"
|
||||
|
@ -1,62 +1,21 @@
|
||||
#include "sc64.h"
|
||||
#include "boot/boot.h"
|
||||
|
||||
typedef struct sc64_cart_registers {
|
||||
__IO reg_t SCR;
|
||||
__IO reg_t COMMAND;
|
||||
__IO reg_t ARG[2];
|
||||
__IO reg_t RESPONSE;
|
||||
__IO reg_t BOOTSTRAP;
|
||||
__IO reg_t ___unused;
|
||||
__IO reg_t VERSION;
|
||||
} sc64_cfg_registers_t;
|
||||
|
||||
#define SC64_CFG_BASE (0x1FFF0000)
|
||||
|
||||
#define SC64_CFG ((__IO sc64_cfg_registers_t *) SC64_CFG_BASE)
|
||||
|
||||
#define SC64_CFG_SCR_CPU_BOOTSTRAPPED (1 << 31)
|
||||
#define SC64_CFG_SCR_CPU_BUSY (1 << 30)
|
||||
|
||||
#define CMD_SDRAM_SWITCH 'S'
|
||||
#define CMD_DEBUG 'D'
|
||||
|
||||
void print_debug(uint32_t a1, uint32_t a2) {
|
||||
|
||||
uint32_t scr = 0;
|
||||
do {
|
||||
scr = platform_pi_io_read(&SC64_CFG->SCR);
|
||||
} while (scr & SC64_CFG_SCR_CPU_BUSY);
|
||||
|
||||
platform_pi_io_write(&SC64_CFG->ARG[0], a1);
|
||||
platform_pi_io_write(&SC64_CFG->ARG[1], a2);
|
||||
platform_pi_io_write(&SC64_CFG->COMMAND, (uint32_t) CMD_DEBUG);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
OS_BOOT_CONFIG->tv_type = TV_NTSC;
|
||||
|
||||
uint32_t scr = 0;
|
||||
while (!sc64_check_presence());
|
||||
|
||||
do {
|
||||
scr = platform_pi_io_read(&SC64_CFG->SCR);
|
||||
} while (!(scr & SC64_CFG_SCR_CPU_BOOTSTRAPPED));
|
||||
sc64_wait_cpu_ready();
|
||||
|
||||
do {
|
||||
scr = platform_pi_io_read(&SC64_CFG->SCR);
|
||||
} while (scr & SC64_CFG_SCR_CPU_BUSY);
|
||||
|
||||
platform_pi_io_write(&SC64_CFG->ARG[0], 1);
|
||||
platform_pi_io_write(&SC64_CFG->COMMAND, (uint32_t) CMD_SDRAM_SWITCH);
|
||||
|
||||
do {
|
||||
scr = platform_pi_io_read(&SC64_CFG->SCR);
|
||||
} while (scr & SC64_CFG_SCR_CPU_BUSY);
|
||||
sc64_set_config(SC64_CONFIG_SDRAM_SWITCH, true);
|
||||
|
||||
cart_header_t *cart_header = boot_load_cart_header();
|
||||
uint16_t cic_seed = boot_get_cic_seed(cart_header);
|
||||
tv_type_t tv_type = boot_get_tv_type(cart_header);
|
||||
|
||||
print_debug(cic_seed << 16 | (tv_type & 0x03), cart_header->pi_conf);
|
||||
// sc64_print_debug(cic_seed << 16 | (tv_type & 0x03), cart_header->pi_conf, cart_header->boot_addr);
|
||||
|
||||
boot(cart_header, cic_seed, tv_type);
|
||||
}
|
||||
|
60
sw/bootloader/src/sc64.c
Normal file
60
sw/bootloader/src/sc64.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
typedef struct sc64_cart_registers {
|
||||
__IO reg_t SR_CMD;
|
||||
__IO reg_t DATA[2];
|
||||
__IO reg_t VERSION;
|
||||
} sc64_cfg_registers_t;
|
||||
|
||||
#define SC64_CFG_BASE (0x1FFF0000)
|
||||
#define SC64_CFG ((__IO sc64_cfg_registers_t *) SC64_CFG_BASE)
|
||||
|
||||
|
||||
|
||||
bool sc64_check_presence(void) {
|
||||
uint32_t version = platform_pi_io_read(&SC64_CFG->VERSION);
|
||||
return (version == 0x53437632);
|
||||
}
|
||||
|
||||
void sc64_wait_cpu_ready(void) {
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = platform_pi_io_read(&SC64_CFG->SR_CMD);
|
||||
} while (sr & SC64_CFG_SCR_CPU_READY);
|
||||
}
|
||||
|
||||
void sc64_wait_cpu_busy(void) {
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = platform_pi_io_read(&SC64_CFG->SR_CMD);
|
||||
} while (sr & SC64_CFG_SCR_CPU_BUSY);
|
||||
}
|
||||
|
||||
void sc64_perform_cmd(uint8_t cmd, uint32_t *args) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
platform_pi_io_write(&SC64_CFG->DATA[i], args[i]);
|
||||
}
|
||||
platform_pi_io_write(&SC64_CFG->SR_CMD, (uint32_t) cmd);
|
||||
sc64_wait_cpu_busy();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
args[i] = platform_pi_io_read(&SC64_CFG->DATA[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void sc64_set_config(uint32_t type, uint32_t value) {
|
||||
uint32_t args[2] = { type, value };
|
||||
sc64_perform_cmd(SC64_CMD_CONFIG, args);
|
||||
}
|
||||
|
||||
void sc64_get_config(sc64_config_t *config) {
|
||||
uint32_t args[2] = { SC64_CONFIG_NOP, 0 };
|
||||
sc64_perform_cmd(SC64_CMD_CONFIG, args);
|
||||
config->___raw_data[0] = args[0];
|
||||
config->___raw_data[1] = args[1];
|
||||
}
|
||||
|
||||
void sc64_print_debug(uint32_t a1, uint32_t a2, uint32_t a3) {
|
||||
// uint32_t args[3] = { a1, a2, a3 };
|
||||
// sc64_perform_cmd(SC64_CMD_DEBUG, args);
|
||||
}
|
50
sw/bootloader/src/sc64.h
Normal file
50
sw/bootloader/src/sc64.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef SC64_H__
|
||||
#define SC64_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
#define SC64_CFG_SCR_CPU_READY (1 << 31)
|
||||
#define SC64_CFG_SCR_CPU_BUSY (1 << 30)
|
||||
|
||||
#define SC64_CMD_CONFIG 'C'
|
||||
#define SC64_CMD_DEBUG 'D'
|
||||
|
||||
#define SC64_CONFIG_SDRAM_SWITCH 0
|
||||
#define SC64_CONFIG_SDRAM_WRITABLE 1
|
||||
#define SC64_CONFIG_DD_ENABLE 2
|
||||
#define SC64_CONFIG_SAVE_TYPE 3
|
||||
#define SC64_CONFIG_CIC_TYPE 4
|
||||
#define SC64_CONFIG_TV_TYPE 5
|
||||
#define SC64_CONFIG_NOP 0xFFFFFFFF
|
||||
|
||||
|
||||
typedef struct sc64_config {
|
||||
union {
|
||||
uint32_t ___raw_data[2];
|
||||
struct {
|
||||
uint8_t ___unused_1[2];
|
||||
uint8_t save_type;
|
||||
uint8_t ___unused_2: 1;
|
||||
uint8_t dd_enable: 1;
|
||||
uint8_t sdram_writable: 1;
|
||||
uint8_t sdram_switch: 1;
|
||||
uint8_t ___unused_3;
|
||||
uint8_t tv_type;
|
||||
uint16_t cic_type;
|
||||
};
|
||||
};
|
||||
} sc64_config_t;
|
||||
|
||||
|
||||
bool sc64_check_presence(void);
|
||||
void sc64_wait_cpu_ready(void);
|
||||
void sc64_wait_cpu_busy(void);
|
||||
void sc64_perform_cmd(uint8_t cmd, uint32_t *args);
|
||||
void sc64_set_config(uint32_t type, uint32_t value);
|
||||
void sc64_get_config(sc64_config_t *config);
|
||||
void sc64_print_debug(uint32_t a1, uint32_t a2, uint32_t a3);
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user