mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-25 04:21:56 +01:00
huge cleanup
This commit is contained in:
parent
975a98c03e
commit
5671e20c3f
41
build_pcb.sh
41
build_pcb.sh
@ -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[@]}
|
@ -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[@]}
|
@ -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
|
@ -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
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
@ -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
|
@ -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()
|
@ -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 = '$';
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef INIT_H__
|
||||
#define INIT_H__
|
||||
|
||||
|
||||
void init (void);
|
||||
|
||||
|
||||
#endif
|
@ -1,9 +0,0 @@
|
||||
#include "init.h"
|
||||
#include "process.h"
|
||||
|
||||
|
||||
__attribute__((naked)) void main (void) {
|
||||
__asm__("la sp, __stack_pointer");
|
||||
init();
|
||||
process();
|
||||
}
|
@ -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);
|
||||
// }
|
@ -1,8 +0,0 @@
|
||||
#ifndef PROCESS_H__
|
||||
#define PROCESS_H__
|
||||
|
||||
|
||||
void process (void);
|
||||
|
||||
|
||||
#endif
|
@ -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
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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" />
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
0
sw/bootloader/build.sh → sw/n64/build.sh
Executable file → Normal 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) {
|
0
sw/dumpy/.gitignore → sw/pc/.gitignore
vendored
0
sw/dumpy/.gitignore → sw/pc/.gitignore
vendored
@ -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
1
sw/riscv/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
50
sw/riscv/Makefile
Normal file
50
sw/riscv/Makefile
Normal 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
52
sw/riscv/SC64.ld
Normal 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
248
sw/riscv/src/controller.c
Normal 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
257
sw/riscv/src/driver.c
Normal 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
95
sw/riscv/src/driver.h
Normal 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
51
sw/riscv/src/handlers.c
Normal 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"
|
||||
);
|
||||
}
|
@ -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
22
sw/riscv/tools/bin2rom.py
Normal 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()
|
@ -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()
|
Loading…
Reference in New Issue
Block a user