huge cleanup

This commit is contained in:
Polprzewodnikowy 2021-09-01 17:21:41 +02:00
parent 975a98c03e
commit 5671e20c3f
48 changed files with 850 additions and 909 deletions

View File

@ -1,41 +0,0 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64_PCB"
FILES=(
"./hw/v1/CAMOutputs"
# Manually created files
"./hw/v1/SummerCart64_sch.pdf"
"./hw/v1/SummerCart64_brd_top.pdf"
"./hw/v1/SummerCart64_brd_bot.pdf"
"./hw/v1/SummerCart64_brd_place_top.pdf"
)
# Add version to zip file name if provided
if [[ $1 ]]; then
PACKAGE_FILE_NAME="${PACKAGE_FILE_NAME}-${1}"
fi
# Generate Gerbers
pushd hw/v1
if [[ -e CAMOutputs ]]; then
rm -rf CAMOutputs
fi
echo "Generating Gerbers"
eaglecon.exe -X -dCAMJOB -jSummerCart64.cam SummerCart64.brd
popd
# Create packages directory
echo "Creating ${PACKAGES_FOLDER_NAME} directory"
mkdir -p "${PACKAGES_FOLDER_NAME}"
# ZIP files for release
echo "Zipping PCB files"
if [[ -e "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ]]; then
rm -f "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip"
fi
zip -r "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ${FILES[@]}

View File

@ -1,59 +0,0 @@
#!/bin/bash
PACKAGES_FOLDER_NAME="packages"
PACKAGE_FILE_NAME="SummerCart64"
FILES=(
"./fw/output_files/SummerCart64.pof"
"./hw/v1/ftdi-template.xml"
"./sw/cic/UltraCIC-III.hex"
"./sw/cic/UltraCIC-III.eep.hex"
)
# Add version to zip file name if provided
if [[ $1 ]]; then
PACKAGE_FILE_NAME="${PACKAGE_FILE_NAME}-${1}"
fi
# Build libsc64
echo "Building libsc64"
pushd sw/libsc64
./build.sh
popd
# Build bootloader
echo "Building bootloader"
pushd sw/bootloader
./build.sh
popd
# Cleanup docker space
docker image prune -a -f
# Build UltraCIC-III
pushd sw/cic
echo "Building UltraCIC-III"
avra UltraCIC-III.asm -D attiny45
popd
# Build FPGA firmware
echo "Building FPGA firmware"
docker run -t --mount type=bind,src="$(pwd)",target="/build" chriz2600/quartus-lite:20.1.0 /usr/local/bin/quartus_wrapper quartus_sh --flow compile /build/fw/SummerCart64.qpf
# Create packages directory
echo "Creating ${PACKAGES_FOLDER_NAME} directory"
mkdir -p "${PACKAGES_FOLDER_NAME}"
# ZIP files for release
echo "Zipping files"
if [[ -e "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ]]; then
rm -f "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip"
fi
zip -r "${PACKAGES_FOLDER_NAME}/${PACKAGE_FILE_NAME}.zip" ${FILES[@]}

View File

@ -83,7 +83,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
set_global_assignment -name SIGNALTAP_FILE output_files/signaltap.stp
set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
# Pin & Location Assignments
# ==========================
@ -302,7 +301,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)
# -------------------------
@ -327,3 +325,5 @@ 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

View File

@ -1,36 +0,0 @@
CROSS=riscv64-unknown-elf-
FLAGS=\
-mabi=ilp32 \
-march=rv32i \
-std=c11 \
-Os \
-Wall \
-Wstrict-prototypes \
-fverbose-asm \
-ffunction-sections \
-fdata-sections \
-Tprv32_rx.ld \
-Wl,--gc-sections \
-ffreestanding \
-nostartfiles \
-nostdlib
all: bootloader.bin cpu_bootloader.sv print_size
bootloader.elf: prv32_rx.ld main.c
@$(CROSS)gcc $(FLAGS) main.c -o bootloader.elf
bootloader.bin: bootloader.elf
@$(CROSS)objcopy -O binary bootloader.elf bootloader.bin
cpu_bootloader.sv: bootloader.bin
@python3 bin2sv.py bootloader.bin cpu_bootloader_template.sv ../../rtl/cpu/cpu_bootloader.sv
print_size:
@echo 'Size of target .elf file:'
$(CROSS)size -B bootloader.elf
clean:
@rm -f bootloader.bin bootloader.elf
.PHONY: clean

View File

@ -1,40 +0,0 @@
#include "sys.h"
int reset_handler (void) {
#ifdef BOOT_UART
io8_t pointer = &RAM;
#else
#ifdef BOOT_N64
io32_t pointer = &RAM;
#endif
#endif
uint32_t length = 0;
#ifdef BOOT_UART
for (int i = 0; i < 4; i++) {
while (!(UART_SR & UART_SR_RXNE));
length |= (UART_DR << (i * 8));
}
#else
#ifdef BOOT_N64
while (!(CFG_SCR & CFG_SCR_BOOTSTRAP_PENDING));
length = CFG_BOOTSTRAP;
#endif
#endif
while (1) {
#ifdef BOOT_UART
while (!(UART_SR & UART_SR_RXNE));
*pointer++ = UART_DR;
#else
#ifdef BOOT_N64
while (!(CFG_SCR & CFG_SCR_BOOTSTRAP_PENDING));
*pointer++ = CFG_BOOTSTRAP;
#endif
#endif
if (((uint32_t) pointer) == length) {
CFG_SCR |= CFG_SCR_CPU_BOOTSTRAPPED;
__asm__("call 0");
}
}
}

View File

@ -1,16 +0,0 @@
MEMORY
{
rom (rx) : org = 0x10000000, len = 128
}
ENTRY(reset_handler)
SECTIONS
{
.rom :
{
. = ALIGN(4);
*(.text .text* .rodata .rodata* .srodata .srodata*)
. = ALIGN(4);
} > rom AT > rom
}

View File

@ -1,35 +0,0 @@
#ifndef BTLDR_H__
#define BTLDR_H__
#include <stdint.h>
#define BOOT_UART
// #define BOOT_N64
typedef volatile uint8_t * io8_t;
typedef volatile uint32_t * io32_t;
#ifdef BOOT_UART
#define RAM (*((io8_t) 0x00000000))
#else
#ifdef BOOT_N64
#define RAM (*((io32_t) 0x00000000))
#endif
#endif
#define UART_SR (*((io8_t) 0x50000000))
#define UART_DR (*((io8_t) 0x50000004))
#define UART_SR_RXNE (1 << 0)
#define UART_SR_TXE (1 << 1)
#define CFG_SCR (*((io32_t) 0x70000000))
#define CFG_BOOTSTRAP (*((io32_t) 0x7000001C))
#define CFG_SCR_CPU_BOOTSTRAPPED (1 << 31)
#define CFG_SCR_BOOTSTRAP_PENDING (1 << 29)
#endif

View File

@ -1,36 +0,0 @@
CROSS=riscv64-unknown-elf-
FLAGS=\
-mabi=ilp32 \
-march=rv32i \
-std=c11 \
-Os \
-Wall \
-Wstrict-prototypes \
-fverbose-asm \
-ffunction-sections \
-fdata-sections \
-Tprv32_rwx.ld \
-Wl,--gc-sections \
-ffreestanding \
-nostartfiles \
-nostdlib
all: controller.bin print_size
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
@python3 bin2rom.py tmp.bin controller.bin
@rm -f tmp.bin
print_size:
@echo 'Size of target .elf file:'
@$(CROSS)size -B controller.elf
@echo $(shell $(CROSS)size -B controller.elf | awk 'NR==2 { printf "\nTotal memory used: %.2f%%\n",(100/(16*1024))*($$4) }')
clean:
@rm -f controller.bin controller.elf
.PHONY: clean

View File

@ -1,25 +0,0 @@
#!/usr/bin/env python3
import os
import sys
binary = None
rom = None
binary_name = sys.argv[1] or 'binary.bin'
rom_name = sys.argv[2] or 'rom.bin'
try:
binary = open(binary_name, mode='rb')
rom = open(rom_name, mode='wb')
length = os.path.getsize(binary_name)
rom.write(length.to_bytes(4, byteorder='little'))
rom.write(binary.read())
except Exception as e:
print(f'Unable to convert the rom: {e}', file=sys.stderr)
sys.exit(-1)
finally:
if (binary): binary.close()
if (rom): rom.close()

View File

@ -1,17 +0,0 @@
#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 = DEFAULT_DD_OFFSET;
CFG->SAVE_OFFSET = DEFAULT_SAVE_OFFSET;
while (!(UART->SCR & UART_SCR_TXE));
UART->DR = '$';
}

View File

@ -1,8 +0,0 @@
#ifndef INIT_H__
#define INIT_H__
void init (void);
#endif

View File

@ -1,9 +0,0 @@
#include "init.h"
#include "process.h"
__attribute__((naked)) void main (void) {
__asm__("la sp, __stack_pointer");
init();
process();
}

View File

@ -1,350 +0,0 @@
#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;
static uint32_t *save_pointer = (uint32_t *) (SDRAM_BASE + DEFAULT_SAVE_OFFSET);
void process_usb (void);
void process_cfg (void);
void process_dd (void);
void process_si (void);
void process_uart (void);
void process_rtc (void);
void process_flashram (void);
void cfg_set_save_type (uint8_t type);
void cfg_update_config (uint32_t *args);
// void print (const char *text);
// void print_02hex (unsigned char number);
void process (void) {
while (1) {
process_usb();
process_cfg();
process_dd();
process_si();
process_uart();
process_rtc();
process_flashram();
}
}
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 if (cmd == 'Q') {
if (USB->SCR & USB_SCR_TXE) {
switch (current_byte) {
case 0: USB->DR = cic_type >> 8; break;
case 1: USB->DR = cic_type; break;
case 2: USB->DR = ((tv_type & 0x3) << 4) | (save_type & 0x7); break;
case 3: USB->DR = CFG->SCR; break;
case 4: USB->DR = (CFG->SAVE_OFFSET >> 24); break;
case 5: USB->DR = (CFG->SAVE_OFFSET >> 16); break;
case 6: USB->DR = (CFG->SAVE_OFFSET >> 8); break;
case 7: USB->DR = (CFG->SAVE_OFFSET >> 0); break;
case 8: USB->DR = (CFG->DD_OFFSET >> 24); break;
case 9: USB->DR = (CFG->DD_OFFSET >> 16); break;
case 10: USB->DR = (CFG->DD_OFFSET >> 8); break;
case 11: USB->DR = (CFG->DD_OFFSET >> 0); break;
}
current_byte += 1;
if (current_byte == 12) {
state = 3;
current_byte = 0;
}
}
} 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 process_rtc (void) {
}
void process_flashram (void) {
uint32_t scr = FLASHRAM->SCR;
volatile uint32_t *offset_pointer = save_pointer;
size_t length;
if (scr & FLASHRAM_OPERATION_PENDING) {
if (scr & FLASHRAM_WRITE_OR_ERASE) {
if (scr & FLASHRAM_SECTOR_OR_ALL) {
length = 128 * 1024;
} else {
offset_pointer += 32 * (scr >> FLASHRAM_SECTOR_BIT);
length = 16 * 1024;
}
for (size_t i = 0; i < (length / 4); i++) {
offset_pointer[i] = 0xFFFFFFFF;
}
} else {
offset_pointer += 32 * (scr >> FLASHRAM_SECTOR_BIT);
for (size_t i = 0; i < 32; i++) {
offset_pointer[i] &= FLASHRAM->BUFFER[i];
}
}
FLASHRAM->SCR = FLASHRAM_OPERATION_DONE;
}
}
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;
}
}
}
void cfg_set_save_type (uint8_t type) {
CFG->SCR &= ~(CFG_SCR_FLASHRAM_EN | CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN);
uint32_t save_offset = DEFAULT_SAVE_OFFSET;
switch (type) {
case 0: {
break;
}
case 1: {
save_offset = SDRAM_SIZE - 512;
break;
}
case 2: {
save_offset = SDRAM_SIZE - 2048;
break;
}
case 3: {
save_offset = SDRAM_SIZE - (32 * 1024);
CFG->SCR |= CFG_SCR_SRAM_EN;
break;
}
case 4: {
save_offset = SDRAM_SIZE - (256 * 1024);
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
}
case 5: {
save_offset = SDRAM_SIZE - (3 * 32 * 1024);
CFG->SCR |= CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN;
break;
}
case 6: {
save_offset = 0x01608000;
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
}
default: {
return;
}
}
save_pointer = (uint32_t *) (SDRAM_BASE + save_offset);
save_type = type;
CFG->SAVE_OFFSET = save_offset;
}
// void print (const char *text) {
// while (*text != '\0') {
// while (!(UART->SCR & UART_SCR_TXE));
// UART->DR = *text++;
// }
// }
// 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);
// }

View File

@ -1,8 +0,0 @@
#ifndef PROCESS_H__
#define PROCESS_H__
void process (void);
#endif

View File

@ -1,27 +0,0 @@
MEMORY
{
ram (rwx) : org = 0x00000000, len = 16k
bootloader (rx) : org = 0x10000000, len = 128
sdram (rwx) : org = 0x80000000, len = 64M
}
__ram_size = LENGTH(ram);
__stack_pointer = ORIGIN(ram) + LENGTH(ram) - 4;
ENTRY(main)
SECTIONS
{
.ram :
{
. = ALIGN(4);
*(.text.main);
. = ALIGN(4);
*(.text .text* .rodata .rodata* .srodata .srodata*);
. = ALIGN(4);
*(.data .data.* .sdata .sdata.*);
. = ALIGN(4);
*(.bss .bss.* .sbss .sbss.*);
. = ALIGN(4);
} > ram AT > ram
}

View File

@ -1,128 +0,0 @@
#include "sys.h"
#include "rtc.h"
static const uint8_t rtc_bit_mask[7] = {
0b01111111,
0b01111111,
0b00111111,
0b00000111,
0b00111111,
0b00011111,
0b11111111
};
static uint8_t i2c_is_busy (void) {
return (I2C_SCR & I2C_SCR_BUSY);
}
static void i2c_wait_busy (void) {
while (i2c_is_busy());
}
static uint8_t i2c_has_ack (void) {
return (I2C_SCR & I2C_SCR_ACK);
}
static void i2c_start (void) {
i2c_wait_busy();
I2C_SCR = I2C_SCR_START;
}
static void i2c_stop (void) {
i2c_wait_busy();
I2C_SCR = I2C_SCR_STOP;
}
static uint8_t i2c_write (uint8_t data) {
i2c_wait_busy();
I2C_SCR = 0;
I2C_DR = data;
i2c_wait_busy();
return i2c_has_ack();
}
static void i2c_read (uint8_t *data, uint8_t cfg) {
i2c_wait_busy();
I2C_SCR = cfg;
I2C_DR = 0xFF;
i2c_wait_busy();
*data = I2C_DR;
}
static uint8_t i2c_tx (uint8_t address, uint8_t *data, size_t length) {
uint8_t result = 0;
i2c_start();
result |= i2c_write(RTC_ADDR);
result |= i2c_write(address);
for (size_t i = 0; i < length; i++) {
result |= i2c_write(*data++);
}
i2c_stop();
return result;
}
static uint8_t i2c_rx (uint8_t address, uint8_t *data, size_t length) {
uint8_t result = 0;
i2c_start();
result |= i2c_write(RTC_ADDR);
result |= i2c_write(address);
i2c_start();
result |= i2c_write(RTC_ADDR | I2C_ADDR_READ);
for (size_t i = 0; i < length; i++) {
i2c_read(data++, (i == (length - 1)) ? 0 : I2C_SCR_MACK);
}
i2c_stop();
return result;
}
static void rtc_sanitize_data (uint8_t *rtc_data) {
for (int i = 0; i < 7; i++) {
rtc_data[i] &= rtc_bit_mask[i];
}
}
uint8_t rtc_set_time (uint8_t *rtc_data) {
uint8_t result = 0;
uint8_t tmp;
rtc_sanitize_data(rtc_data);
rtc_data[RTC_RTCSEC] |= RTC_RTCSEC_ST;
rtc_data[RTC_RTCWKDAY] |= RTC_RTCWKDAY_VBAT;
result |= i2c_tx(RTC_RTCSEC, 0x00, 1);
result |= i2c_tx(RTC_RTCMIN, rtc_data + 1, 6);
result |= i2c_tx(RTC_RTCSEC, rtc_data, 1);
do {
result |= i2c_rx(RTC_RTCWKDAY, &tmp, 7);
} while ((!(tmp & RTC_RTCWKDAY_OSCRUN)) || !result);
return result;
}
uint8_t rtc_get_time (uint8_t *rtc_data) {
uint8_t result = i2c_rx(RTC_RTCSEC, rtc_data, 7);
rtc_sanitize_data(rtc_data);
return result;
}
void rtc_init (void) {
uint8_t result;
uint8_t rtc_data[7];
result = i2c_rx(RTC_RTCSEC, rtc_data, 1);
if ((!(rtc_data[0] & RTC_RTCSEC_ST)) && (!result)) {
rtc_get_time(rtc_data);
rtc_set_time(rtc_data);
}
}

View File

@ -1,23 +0,0 @@
#ifndef RTC_H__
#define RTC_H__
#include "sys.h"
#define RTC_ADDR (0xDE)
#define RTC_RTCSEC (0x00)
#define RTC_RTCSEC_ST (1 << 7)
#define RTC_RTCMIN (0x01)
#define RTC_RTCWKDAY (0x03)
#define RTC_RTCWKDAY_OSCRUN (1 << 5)
#define RTC_RTCWKDAY_VBAT (1 << 3)
uint8_t rtc_set_time (uint8_t *rtc_data);
uint8_t rtc_get_time (uint8_t *rtc_data);
void rtc_init (void);
#endif

View File

@ -18,7 +18,7 @@ module cpu_bootloader (
1: bus.rdata = 32'h00000713;
2: bus.rdata = 32'h50000637;
3: bus.rdata = 32'h02000593;
4: bus.rdata = 32'h00064683;
4: bus.rdata = 32'h00062683;
5: bus.rdata = 32'h0016f693;
6: bus.rdata = 32'hfe068ce3;
7: bus.rdata = 32'h00464683;
@ -27,24 +27,20 @@ module cpu_bootloader (
10: bus.rdata = 32'h00d76733;
11: bus.rdata = 32'hfeb792e3;
12: bus.rdata = 32'h00000793;
13: bus.rdata = 32'h50000537;
14: bus.rdata = 32'h70000637;
15: bus.rdata = 32'h80000837;
16: bus.rdata = 32'h00054683;
17: bus.rdata = 32'h0016f693;
18: bus.rdata = 32'hfe068ce3;
19: bus.rdata = 32'h00454683;
20: bus.rdata = 32'h00178593;
21: bus.rdata = 32'h0ff6f693;
22: bus.rdata = 32'h00d78023;
23: bus.rdata = 32'h00e59c63;
24: bus.rdata = 32'h00062783;
25: bus.rdata = 32'h0107e7b3;
26: bus.rdata = 32'h00f62023;
27: bus.rdata = 32'hf0000097;
28: bus.rdata = 32'hf94080e7;
29: bus.rdata = 32'h00058793;
30: bus.rdata = 32'hfc9ff06f;
13: bus.rdata = 32'h500005b7;
14: bus.rdata = 32'h0005a683;
15: bus.rdata = 32'h0016f693;
16: bus.rdata = 32'hfe068ce3;
17: bus.rdata = 32'h0045c683;
18: bus.rdata = 32'h00178613;
19: bus.rdata = 32'h0ff6f693;
20: bus.rdata = 32'h00d78023;
21: bus.rdata = 32'h00e61863;
22: bus.rdata = 32'hf0000297;
23: bus.rdata = 32'hfa828293;
24: bus.rdata = 32'h00028067;
25: bus.rdata = 32'h00060793;
26: bus.rdata = 32'hfd1ff06f;
default: bus.rdata = 32'd0;
endcase
end

View File

@ -10,7 +10,8 @@ module cpu_cfg (
R_SAVE_OFFSET,
R_COMMAND,
R_DATA_0,
R_DATA_1
R_DATA_1,
R_VERSION
} e_reg_id;
always_ff @(posedge sys.clk) begin
@ -27,7 +28,9 @@ module cpu_cfg (
R_SCR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
24'd0,
cfg.usb_waiting,
cfg.cmd_error,
22'd0,
cfg.flashram_enabled,
cfg.sram_banked,
cfg.sram_enabled,
@ -40,6 +43,7 @@ module cpu_cfg (
R_COMMAND: bus.rdata = {24'd0, cfg.cmd};
R_DATA_0: bus.rdata = cfg.data[0];
R_DATA_1: bus.rdata = cfg.data[1];
R_VERSION: bus.rdata = sc64::SC64_VER;
default: bus.rdata = 32'd0;
endcase
end
@ -58,6 +62,8 @@ module cpu_cfg (
if (sys.reset) begin
cfg.cpu_ready <= 1'b0;
cfg.cpu_busy <= 1'b0;
cfg.usb_waiting <= 1'b0;
cfg.cmd_error <= 1'b0;
cfg.sdram_switch <= 1'b0;
cfg.sdram_writable <= 1'b0;
cfg.dd_enabled <= 1'b0;
@ -78,8 +84,12 @@ module cpu_cfg (
case (bus.address[4:2])
R_SCR: begin
if (bus.wmask[3]) begin
cfg.cpu_ready <= bus.wdata[31];
cfg.cpu_busy <= bus.wdata[30];
{
cfg.cpu_ready,
cfg.cpu_busy,
cfg.usb_waiting,
cfg.cmd_error
} <= bus.wdata[31:28];
end
if (bus.wmask[0]) begin
{

View File

@ -71,8 +71,8 @@
<parameter name="SECTOR_ACCESS_MODE">Read only,Read only,Hidden,Read only,Read only</parameter>
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
<parameter name="initFlashContent" value="true" />
<parameter name="initializationFileName">../sw/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="initializationFileNameForSim">../sw/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="initializationFileName">../sw/n64/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="initializationFileNameForSim">../sw/n64/bootloader/build/SummerLoader64.hex</parameter>
<parameter name="useNonDefaultInitFile" value="true" />
</module>
<interconnectRequirement for="$system" name="qsys_mm.clockCrossingAdapter" value="HANDSHAKE" />

View File

@ -26,7 +26,13 @@ module n64_cfg (
bus.rdata = 16'd0;
if (bus.ack) begin
case (bus.address[3:1])
R_SR: bus.rdata = {cfg.cpu_ready, cfg.cpu_busy, 14'd0};
R_SR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
cfg.usb_waiting,
cfg.cmd_error,
12'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];

View File

@ -169,12 +169,13 @@ module n64_flashram (
end
endcase
end
end else begin
if (flashram_state == FS_STATUS) begin
flashram_status[B_ERASE_DONE] <= bus.wdata[B_ERASE_DONE];
flashram_status[B_WRITE_DONE] <= bus.wdata[B_WRITE_DONE];
end
end
// else begin
// if (bus.address[1] && flashram_state == FS_STATUS) begin
// flashram_status[B_ERASE_DONE] <= bus.wdata[B_ERASE_DONE];
// flashram_status[B_WRITE_DONE] <= bus.wdata[B_WRITE_DONE];
// end
// end
end
end
end

View File

@ -2,6 +2,8 @@ interface if_config ();
logic cpu_ready;
logic cpu_busy;
logic usb_waiting;
logic cmd_error;
logic cmd_request;
logic [7:0] cmd;
logic [31:0] data [0:1];
@ -36,6 +38,8 @@ interface if_config ();
modport n64 (
input cpu_ready,
input cpu_busy,
input usb_waiting,
input cmd_error,
output cmd_request,
output cmd,
output data,
@ -46,6 +50,8 @@ interface if_config ();
modport cpu (
output cpu_ready,
output cpu_busy,
output usb_waiting,
output cmd_error,
input cmd_request,
input cmd,
input data,

0
sw/bootloader/build.sh → sw/n64/build.sh Executable file → Normal file
View File

View File

@ -21,7 +21,7 @@ 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);
} while (!(sr & SC64_CFG_SCR_CPU_READY));
}
void sc64_wait_cpu_busy(void) {

View File

@ -7,19 +7,25 @@ import sys
class SC64:
__SDRAM_SIZE = 64 * 1024 * 1024
__CONFIG_QUERY_SAVE_TYPE = 1
__CONFIG_QUERY_SAVE_OFFSET = 4
def __init__(self, port):
self.__serial = serial.Serial(port)
self.__query_config()
self.__save_type = self.__query_config(self.__CONFIG_QUERY_SAVE_TYPE)
self.__save_offset = self.__query_config(self.__CONFIG_QUERY_SAVE_OFFSET)
print('{:08X}'.format(self.__save_type))
print('{:08X}'.format(self.__save_offset))
def __query_config(self):
def __query_config(self, query):
self.__serial.write(b'CMDQ')
self.__serial.write(bytes(8))
config_raw = self.__serial.read(12)
self.__serial.write(query.to_bytes(4, byteorder='big'))
self.__serial.write(bytes(4))
value = self.__serial.read(4)
if (self.__serial.read(4).decode() != 'CMPQ'):
raise Exception('Bad query response')
self.__save_type = config_raw[2] & 0x07
self.__save_offset = int.from_bytes(config_raw[4:8], byteorder='big')
return int.from_bytes(value, byteorder='big')
def __save_length(self):
@ -83,7 +89,7 @@ class SC64:
mode = 'r'
file = 'save.dat'
port = 'COM5'
port = 'COM7'
if (len(sys.argv) >= 2):
mode = sys.argv[1]

1
sw/riscv/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

50
sw/riscv/Makefile Normal file
View File

@ -0,0 +1,50 @@
TOOLCHAIN = riscv64-unknown-elf-
CC = $(TOOLCHAIN)gcc
OBJCOPY = $(TOOLCHAIN)objcopy
SIZE = $(TOOLCHAIN)size
FLAGS = -mabi=ilp32 -march=rv32i
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
LDFLAGS = -nostartfiles -Wl,--gc-sections
SRC_DIR = src
BUILD_DIR = build
BOOTLOADER_DIR = ../../fw/rtl/cpu
SRCS = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIR)))
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRCS:.c=.o)))
DEPS = $(OBJS:.o=.d)
VPATH = $(SRC_DIR)
all: make_output_dir $(BOOTLOADER_DIR)/cpu_bootloader.sv $(BUILD_DIR)/controller.rom
$(BUILD_DIR)/%.o: %.c
$(CC) $(FLAGS) $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/uc.elf: $(OBJS) SC64.ld
$(CC) $(FLAGS) $(LDFLAGS) -TSC64.ld $(OBJS) -o $@
$(BUILD_DIR)/controller.rom: $(BUILD_DIR)/uc.elf
$(OBJCOPY) -R .bootloader $(BUILD_DIR)/uc.elf $(BUILD_DIR)/controller.elf
$(OBJCOPY) -O binary --set-section-flags .bss=alloc,contents $(BUILD_DIR)/controller.elf $(BUILD_DIR)/controller.bin
python3 tools/bin2rom.py $@ < $(BUILD_DIR)/controller.bin
@echo 'Size of controller:'
@$(SIZE) -B build/controller.elf
$(BOOTLOADER_DIR)/cpu_bootloader.sv: $(BUILD_DIR)/uc.elf
$(OBJCOPY) -j .bootloader $(BUILD_DIR)/uc.elf $(BUILD_DIR)/bootloader.elf
$(OBJCOPY) -O binary $(BUILD_DIR)/bootloader.elf $(BUILD_DIR)/bootloader.bin
python3 tools/bin2sv.py tools/cpu_bootloader_template.sv $@ < $(BUILD_DIR)/bootloader.bin
@echo 'Size of bootloader:'
@$(SIZE) -B build/bootloader.elf
make_output_dir:
@$(shell mkdir ./$(BUILD_DIR) 2> /dev/null)
clean:
rm -rf build
.PHONY: all make_output_dir clean
-include $(DEPS)

52
sw/riscv/SC64.ld Normal file
View File

@ -0,0 +1,52 @@
MEMORY {
RAM (rwx) : org = 0x00000000, len = 16k
ROM (rx) : org = 0x10000000, len = 128
}
__stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 4;
ENTRY(reset_handler)
SECTIONS {
.text : {
PROVIDE(__app_entry_point = .);
*(.text.app_handler)
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} > RAM
.rodata : {
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} > RAM
.data : {
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE(__global_pointer = . + 0x800);
*(.sdata .sdata.* .sdata2.*)
*(.gnu.linkonce.s.*)
} > RAM
.bss : ALIGN(8) {
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
} > RAM
.bootloader : {
*(.text.reset_handler)
} > ROM
}

248
sw/riscv/src/controller.c Normal file
View File

@ -0,0 +1,248 @@
#include "sys.h"
#include "driver.h"
static e_cfg_save_type_t save_type = CFG_SAVE_TYPE_NONE;
static uint16_t cic_seed = 0xFFFF;
static uint8_t tv_type = 0xFF;
void process_usb (void);
void process_cfg (void);
void process_flashram (void);
void config_update (uint32_t *args);
void config_query (uint32_t *args);
void main (void) {
UART->DR = 'X';
GPIO->ODR = 0;
GPIO->OER = (1 << 0);
dma_abort();
usb_flush_rx();
usb_flush_tx();
cfg_set_sdram_switch(true);
cfg_set_save_type(CFG_SAVE_TYPE_NONE);
cfg_set_dd_offset(CFG_DEFAULT_DD_OFFSET);
cfg_set_cpu_ready(true);
while (1) {
process_usb();
process_cfg();
process_flashram();
}
}
typedef enum {
USB_STATE_IDLE,
USB_STATE_ARGS,
USB_STATE_DATA,
USB_STATE_RESPONSE,
} e_usb_state_t;
#define USB_CMD_TOKEN (0x434D4400)
#define USB_CMP_TOKEN (0x434D5000)
#define USB_ERR_TOKEN (0x45525200)
void process_usb (void) {
static e_usb_state_t state = USB_STATE_IDLE;
static uint8_t cmd;
static uint32_t args[2];
static bool error = false;
static bool processing = false;
static uint8_t current_word = 0;
switch (state) {
case USB_STATE_IDLE:
if (usb_rx_word(&args[0])) {
if ((args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) {
state = USB_STATE_ARGS;
cmd = args[0] & 0xFF;
error = false;
processing = false;
current_word = 0;
} else {
state = USB_STATE_RESPONSE;
error = true;
}
}
break;
case USB_STATE_ARGS:
if (usb_rx_word(&args[current_word])) {
current_word += 1;
if (current_word == 2) {
state = USB_STATE_DATA;
}
}
break;
case USB_STATE_DATA:
switch (cmd) {
case 'C':
config_update(args);
state = USB_STATE_RESPONSE;
break;
case 'Q':
if (!processing) {
config_query(args);
processing = true;
} else if (usb_tx_word(args[1])) {
state = USB_STATE_RESPONSE;
}
break;
case 'R':
case 'W':
if (!dma_busy()) {
if (!processing) {
e_dma_id_t id = args[1] >> 30;
e_dma_dir_t dir = cmd == 'W' ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
dma_start(args[0], args[1], id, dir);
processing = true;
} else {
state = USB_STATE_RESPONSE;
}
}
break;
case 'D':
break;
default:
state = USB_STATE_RESPONSE;
error = true;
break;
}
break;
case USB_STATE_RESPONSE:
if (usb_tx_word(error ? USB_ERR_TOKEN : (USB_CMP_TOKEN | cmd))) {
state = USB_STATE_IDLE;
}
break;
default:
state = USB_STATE_IDLE;
break;
}
}
void process_cfg (void) {
uint8_t cmd;
uint32_t args[2];
if (cfg_get_command(&cmd, args)) {
switch (cmd) {
case 'C':
config_update(args);
cfg_set_response(args, false);
break;
case 'Q':
config_query(args);
cfg_set_response(args, false);
break;
case 'D':
break;
default:
cfg_set_response(args, true);
return;
}
}
}
void process_flashram (void) {
e_flashram_op_t op = flashram_get_pending_operation();
if (op != FLASHRAM_OP_NONE) {
uint32_t length = flashram_get_operation_length(op);
uint32_t page = flashram_get_page();
uint32_t offset = cfg_get_save_offset() + (page * FLASHRAM_PAGE_SIZE);
volatile uint32_t *src = flashram_get_page_buffer();
volatile uint32_t *dst = (uint32_t *) (SDRAM_BASE + offset);
for (uint32_t i = 0; i < (length / 4); i++) {
if (op == FLASHRAM_OP_WRITE_PAGE) {
dst[i] &= src[i];
} else {
dst[i] = FLASHRAM_ERASE_VALUE;
}
}
flashram_set_operation_done();
}
}
typedef enum {
CONFIG_UPDATE_SDRAM_SWITCH,
CONFIG_UPDATE_SDRAM_WRITABLE,
CONFIG_UPDATE_DD_ENABLE,
CONFIG_UPDATE_SAVE_TYPE,
CONFIG_UPDATE_CIC_SEED,
CONFIG_UPDATE_TV_TYPE
} e_config_update_t;
void config_update (uint32_t *args) {
switch (args[0]) {
case CONFIG_UPDATE_SDRAM_SWITCH:
cfg_set_sdram_switch(args[1]);
break;
case CONFIG_UPDATE_SDRAM_WRITABLE:
cfg_set_sdram_writable(args[1]);
break;
case CONFIG_UPDATE_DD_ENABLE:
cfg_set_dd_enable(args[1]);
break;
case CONFIG_UPDATE_SAVE_TYPE:
save_type = args[1] & 0x07;
cfg_set_save_type(save_type);
break;
case CONFIG_UPDATE_CIC_SEED:
cic_seed = args[1] & 0xFFFF;
break;
case CONFIG_UPDATE_TV_TYPE:
tv_type = args[1] & 0xFF;
break;
}
}
typedef enum {
CONFIG_QUERY_STATUS,
CONFIG_QUERY_SAVE_TYPE,
CONFIG_QUERY_CIC_SEED,
CONFIG_QUERY_TV_TYPE,
CONFIG_QUERY_SAVE_OFFSET,
CONFIG_QUERY_DD_OFFSET,
} e_config_query_t;
void config_query (uint32_t *args) {
switch (args[0]) {
case CONFIG_QUERY_STATUS:
args[1] = cfg_get_status();
break;
case CONFIG_QUERY_SAVE_TYPE:
args[1] = save_type;
break;
case CONFIG_QUERY_CIC_SEED:
args[1] = cic_seed;
break;
case CONFIG_QUERY_TV_TYPE:
args[1] = tv_type;
break;
case CONFIG_QUERY_SAVE_OFFSET:
args[1] = cfg_get_save_offset();
break;
case CONFIG_QUERY_DD_OFFSET:
args[1] = cfg_get_dd_offset();
break;
}
}

257
sw/riscv/src/driver.c Normal file
View File

@ -0,0 +1,257 @@
#include "driver.h"
#include "sys.h"
// DMA
bool dma_start (uint32_t address, uint32_t length, e_dma_id_t id, e_dma_dir_t dir) {
if (DMA->SCR & DMA_SCR_BUSY) {
return false;
}
DMA->MADDR = address;
DMA->ID_LEN = ((id & 0x03) << 30) | (length & 0x3FFFFFFF);
DMA->SCR = ((dir == DMA_DIR_TO_SDRAM) ? DMA_SCR_DIR : 0) | DMA_SCR_START;
return true;
}
void dma_abort (void) {
DMA->SCR = DMA_SCR_STOP;
}
bool dma_busy (void) {
return DMA->SCR & DMA_SCR_BUSY;
}
// FLASHRAM
e_flashram_op_t flashram_get_pending_operation (void) {
uint32_t scr = FLASHRAM->SCR;
if (!(scr & FLASHRAM_OPERATION_PENDING)) {
return FLASHRAM_OP_NONE;
}
if (scr & FLASHRAM_WRITE_OR_ERASE) {
if (scr & FLASHRAM_SECTOR_OR_ALL) {
return FLASHRAM_OP_ERASE_ALL;
} else {
return FLASHRAM_OP_ERASE_SECTOR;
}
} else {
return FLASHRAM_OP_WRITE_PAGE;
}
}
uint32_t flashram_get_operation_length (e_flashram_op_t op) {
switch (op) {
case FLASHRAM_OP_ERASE_ALL: return FLASHRAM_SIZE;
case FLASHRAM_OP_ERASE_SECTOR: return FLASHRAM_SECTOR_SIZE;
case FLASHRAM_OP_WRITE_PAGE: return FLASHRAM_PAGE_SIZE;
default: return 0;
}
}
void flashram_set_operation_done (void) {
FLASHRAM->SCR = FLASHRAM_OPERATION_DONE;
}
uint32_t flashram_get_page (void) {
return (FLASHRAM->SCR >> FLASHRAM_PAGE_BIT);
}
volatile uint32_t * flashram_get_page_buffer (void) {
return FLASHRAM->BUFFER;
}
// USB
bool usb_rx_byte (uint8_t *data) {
if (!(USB->SCR & USB_SCR_RXNE)) {
return false;
}
*data = USB->DR;
return true;
}
bool usb_rx_word (uint32_t *data) {
static uint8_t current_byte = 0;
static uint32_t buffer = 0;
uint8_t tmp;
while (usb_rx_byte(&tmp)) {
buffer = (buffer << 8) | tmp;
current_byte += 1;
if (current_byte == 4) {
current_byte = 0;
*data = buffer;
buffer = 0;
return true;
}
}
return false;
}
bool usb_tx_byte (uint8_t data) {
if (!(USB->SCR & USB_SCR_TXE)) {
return false;
}
USB->DR = data;
return true;
}
bool usb_tx_word (uint32_t data) {
static uint8_t current_byte = 0;
while (usb_tx_byte(data >> ((3 - current_byte) * 8))) {
current_byte += 1;
if (current_byte == 4) {
current_byte = 0;
return true;
}
}
return false;
}
void usb_flush_rx (void) {
USB->SCR = USB_SCR_FLUSH_RX;
}
void usb_flush_tx (void) {
USB->SCR = USB_SCR_FLUSH_TX;
}
// CFG
uint32_t cfg_get_status (void) {
return CFG->SCR;
}
void cfg_set_cpu_ready (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_CPU_READY;
} else {
CFG->SCR &= ~CFG_SCR_CPU_READY;
}
}
void cfg_set_sdram_switch (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_SDRAM_SWITCH;
} else {
CFG->SCR &= ~CFG_SCR_SDRAM_SWITCH;
}
}
void cfg_set_sdram_writable (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_SDRAM_WRITABLE;
} else {
CFG->SCR &= ~CFG_SCR_SDRAM_WRITABLE;
}
}
void cfg_set_dd_enable (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_DD_EN;
} else {
CFG->SCR &= ~CFG_SCR_DD_EN;
}
}
void cfg_set_usb_waiting (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_USB_WAITING;
} else {
CFG->SCR &= ~CFG_SCR_USB_WAITING;
}
}
void cfg_set_save_type (e_cfg_save_type_t save_type) {
uint32_t save_offset = 0;
CFG->SCR &= ~(CFG_SCR_FLASHRAM_EN | CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN);
switch (save_type) {
case CFG_SAVE_TYPE_NONE:
break;
case CFG_SAVE_TYPE_EEPROM_4K:
save_offset = SDRAM_SIZE - CFG_SAVE_SIZE_EEPROM_4K;
break;
case CFG_SAVE_TYPE_EEPROM_16K:
save_offset = SDRAM_SIZE - CFG_SAVE_SIZE_EEPROM_16K;
break;
case CFG_SAVE_TYPE_SRAM:
save_offset = SDRAM_SIZE - CFG_SAVE_SIZE_SRAM;
CFG->SCR |= CFG_SCR_SRAM_EN;
break;
case CFG_SAVE_TYPE_FLASHRAM:
save_offset = SDRAM_SIZE - CFG_SAVE_SIZE_FLASHRAM;
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
case CFG_SAVE_TYPE_SRAM_BANKED:
save_offset = SDRAM_SIZE - CFG_SAVE_SIZE_SRAM_BANKED;
CFG->SCR |= CFG_SCR_SRAM_BANKED | CFG_SCR_SRAM_EN;
break;
case CFG_SAVE_TYPE_FLASHRAM_PKST2:
save_offset = CFG_SAVE_OFFSET_PKST2;
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
default:
break;
}
CFG->SAVE_OFFSET = save_offset;
}
void cfg_set_save_offset (uint32_t offset) {
CFG->SAVE_OFFSET = offset;
}
uint32_t cfg_get_save_offset (void) {
return CFG->SAVE_OFFSET;
}
void cfg_set_dd_offset (uint32_t offset) {
CFG->DD_OFFSET = offset;
}
uint32_t cfg_get_dd_offset (void) {
return CFG->DD_OFFSET;
}
bool cfg_get_command (uint8_t *cmd, uint32_t *args) {
if (!(CFG->SCR & CFG_SCR_CPU_BUSY)) {
return false;
}
*cmd = CFG->CMD;
for (size_t i = 0; i < 2; i++) {
args[i] = CFG->DATA[i];
}
return true;
}
void cfg_set_response (uint32_t *args, bool error) {
for (size_t i = 0; i < 2; i++) {
CFG->DATA[i] = args[i];
}
if (error) {
CFG->SCR |= CFG_SCR_CMD_ERROR;
} else {
CFG->SCR &= ~CFG_SCR_CMD_ERROR;
}
CFG->SCR &= ~(CFG_SCR_CPU_BUSY);
}

95
sw/riscv/src/driver.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef DRIVER_H__
#define DRIVER_H__
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
// DMA
typedef enum {
DMA_DIR_TO_SDRAM,
DMA_DIR_FROM_SDRAM,
} e_dma_dir_t;
typedef enum {
DMA_ID_USB = 0,
DMA_ID_SD = 1,
} e_dma_id_t;
bool dma_start (uint32_t address, uint32_t length, e_dma_id_t id, e_dma_dir_t dir);
void dma_abort (void);
bool dma_busy (void);
// USB
bool usb_rx_byte (uint8_t *data);
bool usb_rx_word (uint32_t *data);
bool usb_tx_byte (uint8_t data);
bool usb_tx_word (uint32_t data);
void usb_flush_rx (void);
void usb_flush_tx (void);
// FLASHRAM
#define FLASHRAM_SIZE (128 * 1024)
#define FLASHRAM_SECTOR_SIZE (16 * 1024)
#define FLASHRAM_PAGE_SIZE (128)
#define FLASHRAM_ERASE_VALUE (0xFFFFFFFF)
typedef enum {
FLASHRAM_OP_NONE,
FLASHRAM_OP_ERASE_ALL,
FLASHRAM_OP_ERASE_SECTOR,
FLASHRAM_OP_WRITE_PAGE
} e_flashram_op_t;
e_flashram_op_t flashram_get_pending_operation (void);
uint32_t flashram_get_operation_length (e_flashram_op_t op);
void flashram_set_operation_done (void);
uint32_t flashram_get_page (void);
volatile uint32_t * flashram_get_page_buffer (void);
// CFG
#define CFG_SAVE_SIZE_EEPROM_4K (512)
#define CFG_SAVE_SIZE_EEPROM_16K (2048)
#define CFG_SAVE_SIZE_SRAM (32 * 1024)
#define CFG_SAVE_SIZE_FLASHRAM (128 * 1024)
#define CFG_SAVE_SIZE_SRAM_BANKED (3 * 32 * 1024)
#define CFG_SAVE_OFFSET_PKST2 (0x01608000UL)
#define CFG_DEFAULT_DD_OFFSET (0x03BE0000UL)
typedef enum {
CFG_SAVE_TYPE_NONE = 0,
CFG_SAVE_TYPE_EEPROM_4K = 1,
CFG_SAVE_TYPE_EEPROM_16K = 2,
CFG_SAVE_TYPE_SRAM = 3,
CFG_SAVE_TYPE_FLASHRAM = 4,
CFG_SAVE_TYPE_SRAM_BANKED = 5,
CFG_SAVE_TYPE_FLASHRAM_PKST2 = 6,
} e_cfg_save_type_t;
uint32_t cfg_get_status (void);
void cfg_set_cpu_ready (bool enabled);
void cfg_set_sdram_switch (bool enabled);
void cfg_set_sdram_writable (bool enabled);
void cfg_set_usb_waiting (bool value);
void cfg_set_dd_enable (bool enabled);
void cfg_set_save_type (e_cfg_save_type_t save_type);
void cfg_set_save_offset (uint32_t offset);
uint32_t cfg_get_save_offset (void);
void cfg_set_dd_offset (uint32_t offset);
uint32_t cfg_get_dd_offset (void);
bool cfg_get_command (uint8_t *cmd, uint32_t *args);
void cfg_set_response (uint32_t *args, bool error);
#endif

51
sw/riscv/src/handlers.c Normal file
View File

@ -0,0 +1,51 @@
#include <stdint.h>
#include "sys.h"
#define BOOT_UART
__attribute__ ((naked, section(".bootloader"))) int reset_handler (void) {
register uint32_t length = 0;
#if defined(BOOT_UART)
volatile uint8_t *pointer = (volatile uint8_t *) &RAM;
for (int i = 0; i < 4; i++) {
while (!(UART->SCR & UART_SCR_RXNE));
length |= (UART->DR << (i * 8));
}
#elif defined(BOOT_N64)
volatile uint32_t *pointer = (volatile uint32_t *) &RAM;
while (!(CFG->SCR & CFG_SCR_CPU_BUSY));
length = CFG->DATA[0];
CFG->SCR &= ~(CFG_SCR_CPU_READY);
#endif
while (1) {
#if defined(BOOT_UART)
while (!(UART->SCR & UART_SCR_RXNE));
*pointer++ = UART->DR;
length = length - 1;
#elif defined(BOOT_N64)
while (!(CFG->SCR & CFG_SCR_CPU_BUSY));
*pointer++ = CFG->DATA[0];
CFG->SCR &= ~(CFG_SCR_CPU_READY);
length = length - 4;
#endif
if (length == 0) {
__asm__ volatile (
"la t0, app_handler\n"
"jalr zero, t0\n"
);
}
}
}
__attribute__ ((naked)) void app_handler (void) {
__asm__ volatile (
"la sp, __stack_pointer\n"
"la gp, __global_pointer\n"
"jal zero, main\n"
);
}

View File

@ -98,7 +98,7 @@ typedef volatile struct cfg_regs {
io32_t SAVE_OFFSET;
io8_t CMD;
io8_t __padding[3];
io32_t DATA[3];
io32_t DATA[2];
} cfg_regs_t;
#define CFG_BASE (0x70000000UL)
@ -110,6 +110,8 @@ typedef volatile struct cfg_regs {
#define CFG_SCR_SRAM_EN (1 << 3)
#define CFG_SCR_SRAM_BANKED (1 << 4)
#define CFG_SCR_FLASHRAM_EN (1 << 5)
#define CFG_SCR_CMD_ERROR (1 << 28)
#define CFG_SCR_USB_WAITING (1 << 29)
#define CFG_SCR_CPU_BUSY (1 << 30)
#define CFG_SCR_CPU_READY (1 << 31)
@ -132,7 +134,7 @@ typedef volatile struct flashram_regs {
#define FLASHRAM_OPERATION_DONE (1 << 1)
#define FLASHRAM_WRITE_OR_ERASE (1 << 2)
#define FLASHRAM_SECTOR_OR_ALL (1 << 3)
#define FLASHRAM_SECTOR_BIT (8)
#define FLASHRAM_PAGE_BIT (8)
#endif

22
sw/riscv/tools/bin2rom.py Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python3
import os
import sys
rom = None
rom_name = sys.argv[1] or 'rom.bin'
try:
binary_data = sys.stdin.buffer.read()
if (os.path.exists(rom_name)):
os.remove(rom_name)
rom = open(rom_name, mode='wb')
rom.write(len(binary_data).to_bytes(4, byteorder='little'))
rom.write(binary_data)
except Exception as e:
print(f'Unable to convert the rom: {e}', file=sys.stderr)
sys.exit(-1)
finally:
if (rom): rom.close()

View File

@ -2,16 +2,13 @@
import struct
import sys
binary = None
sv_template = None
sv_code = None
binary_name = sys.argv[1] or 'binary.bin'
template_name = sys.argv[2] or 'binary_template.sv'
code_name = sys.argv[3] or 'binary.sv'
template_name = sys.argv[1] or 'template.sv'
code_name = sys.argv[2] or 'result.sv'
try:
binary = open(binary_name, mode='rb')
sv_template = open(template_name, mode='r')
sv_code = open(code_name, mode='w')
@ -19,7 +16,7 @@ try:
rom_formatted = ''
index = 0
for line in iter(lambda: binary.read(4), ''):
for line in iter(lambda: sys.stdin.buffer.read(4), ''):
if (not line):
break
value = format(struct.unpack('<I', line)[0], '08x')
@ -33,6 +30,5 @@ except Exception as e:
sys.exit(-1)
finally:
if (binary): binary.close()
if (sv_template): sv_template.close()
if (sv_code): sv_code.close()