mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-27 05:21:55 +01:00
added usb read functionality, general cleanup
This commit is contained in:
parent
1374033733
commit
ea4470eaaa
@ -485,7 +485,8 @@ module mcu_top (
|
||||
|
||||
REG_RTC_SCR: begin
|
||||
reg_rdata <= {
|
||||
31'd0,
|
||||
24'h525443,
|
||||
7'd0,
|
||||
n64_scb.rtc_pending
|
||||
};
|
||||
end
|
||||
|
@ -180,7 +180,7 @@ static const char *exception_get_description (uint8_t exception_code) {
|
||||
|
||||
void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
|
||||
version_t *version = version_get();
|
||||
uint32_t sc64_version = pi_io_read(&SC64->VERSION);
|
||||
uint32_t sc64_version = pi_io_read(&SC64_REGS->VERSION);
|
||||
uint32_t *instruction_address = (((uint32_t *) (e->epc.u32)) + ((e->cr & C0_CR_BD) ? 1 : 0));
|
||||
|
||||
exception_init_screen();
|
||||
|
@ -3,45 +3,45 @@
|
||||
#include "../sc64.h"
|
||||
|
||||
|
||||
DSTATUS status[__DRIVE_COUNT] = { STA_NOINIT, STA_NOINIT };
|
||||
// DSTATUS status[__DRIVE_COUNT] = { STA_NOINIT, STA_NOINIT };
|
||||
|
||||
|
||||
DSTATUS disk_status (BYTE pdrv) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
// if (pdrv >= __DRIVE_COUNT) {
|
||||
return STA_NODISK;
|
||||
}
|
||||
return status[pdrv];
|
||||
// }
|
||||
// return status[pdrv];
|
||||
}
|
||||
|
||||
DSTATUS disk_initialize (BYTE pdrv) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
// if (pdrv >= __DRIVE_COUNT) {
|
||||
return STA_NODISK;
|
||||
}
|
||||
if (!sc64_storage_init((drive_id_t) (pdrv))) {
|
||||
status[pdrv] &= ~(STA_NOINIT);
|
||||
}
|
||||
return status[pdrv];
|
||||
// }
|
||||
// if (!sc64_storage_init((drive_id_t) (pdrv))) {
|
||||
// status[pdrv] &= ~(STA_NOINIT);
|
||||
// }
|
||||
// return status[pdrv];
|
||||
}
|
||||
|
||||
DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sc64_storage_read((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
// if (pdrv >= __DRIVE_COUNT) {
|
||||
// return RES_PARERR;
|
||||
// }
|
||||
// if (sc64_storage_read((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_OK;
|
||||
// }
|
||||
// return RES_OK;
|
||||
}
|
||||
|
||||
#if !FF_FS_READONLY
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sc64_storage_write((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
// if (pdrv >= __DRIVE_COUNT) {
|
||||
// return RES_PARERR;
|
||||
// }
|
||||
// if (sc64_storage_write((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_OK;
|
||||
// }
|
||||
// return RES_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -225,14 +225,28 @@ typedef struct {
|
||||
#define PIFRAM ((io8_t *) PIFRAM_BASE)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io8_t BUFFER[8192];
|
||||
io8_t EEPROM[2048];
|
||||
io8_t __unused_1[8192 - 2048];
|
||||
io8_t FLASHRAM[128];
|
||||
io8_t __unused_2[8192 - 128];
|
||||
io8_t DD_SECTOR[2048];
|
||||
io8_t __unused_3[8192 - 2048];
|
||||
} sc64_buffers_t;
|
||||
|
||||
#define SC64_BUFFERS_BASE (0x1FFE0000UL)
|
||||
#define SC64_BUFFERS ((sc64_buffers_t *) SC64_BUFFERS_BASE)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io32_t SR_CMD;
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
} sc64_regs_t;
|
||||
|
||||
#define SC64_BASE (0x1FFF0000UL)
|
||||
#define SC64 ((sc64_regs_t *) SC64_BASE)
|
||||
#define SC64_REGS_BASE (0x1FFF0000UL)
|
||||
#define SC64_REGS ((sc64_regs_t *) SC64_REGS_BASE)
|
||||
|
||||
#define SC64_SR_CMD_ERROR (1 << 30)
|
||||
#define SC64_SR_CPU_BUSY (1 << 31)
|
||||
|
@ -1,17 +1,18 @@
|
||||
#include "boot.h"
|
||||
#include "error.h"
|
||||
#include "init.h"
|
||||
#include "io.h"
|
||||
#include "sc64.h"
|
||||
#include "storage.h"
|
||||
|
||||
|
||||
void main (void) {
|
||||
boot_info_t boot_info;
|
||||
sc64_info_t sc64_info;
|
||||
sc64_boot_info_t sc64_boot_info;
|
||||
|
||||
sc64_get_info(&sc64_info);
|
||||
sc64_get_boot_info(&sc64_boot_info);
|
||||
|
||||
switch (sc64_info.boot_mode) {
|
||||
switch (sc64_boot_info.boot_mode) {
|
||||
case BOOT_MODE_MENU_SD:
|
||||
storage_run_menu(STORAGE_BACKEND_SD);
|
||||
break;
|
||||
@ -29,23 +30,23 @@ void main (void) {
|
||||
break;
|
||||
|
||||
default:
|
||||
error_display("Unknown boot mode selected [%d]\n", sc64_info.boot_mode);
|
||||
error_display("Unknown boot mode selected [%d]\n", sc64_boot_info.boot_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
boot_info.reset_type = OS_INFO->reset_type;
|
||||
|
||||
if (sc64_info.tv_type != TV_TYPE_UNKNOWN) {
|
||||
boot_info.tv_type = sc64_info.tv_type;
|
||||
if (sc64_boot_info.tv_type != TV_TYPE_UNKNOWN) {
|
||||
boot_info.tv_type = sc64_boot_info.tv_type;
|
||||
} else {
|
||||
if (!boot_get_tv_type(&boot_info)) {
|
||||
boot_info.tv_type = OS_INFO->tv_type;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc64_info.cic_seed != CIC_SEED_UNKNOWN) {
|
||||
boot_info.cic_seed = sc64_info.cic_seed & 0xFF;
|
||||
boot_info.version = (sc64_info.cic_seed >> 8) & 0x01;
|
||||
if (sc64_boot_info.cic_seed != CIC_SEED_UNKNOWN) {
|
||||
boot_info.cic_seed = sc64_boot_info.cic_seed & 0xFF;
|
||||
boot_info.version = (sc64_boot_info.cic_seed >> 8) & 0x01;
|
||||
} else {
|
||||
if (!boot_get_cic_seed_version(&boot_info)) {
|
||||
boot_info.cic_seed = 0x3F;
|
||||
|
@ -1,61 +1,75 @@
|
||||
#include "io.h"
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
#define SECTOR_SIZE (512)
|
||||
#define SC64_VERSION_2 (0x53437632)
|
||||
|
||||
|
||||
bool sc64_check_presence (void) {
|
||||
uint32_t version = pi_io_read(&SC64->VERSION);
|
||||
return (version == SC64_VERSION_2);
|
||||
}
|
||||
typedef enum {
|
||||
SC64_CMD_GET_VERSION = 'v',
|
||||
SC64_CMD_CONFIG_QUERY = 'c',
|
||||
SC64_CMD_CONFIG_CHANGE = 'C',
|
||||
SC64_CMD_TIME_GET = 't',
|
||||
SC64_CMD_TIME_SET = 'T',
|
||||
SC64_CMD_USB_READ = 'm',
|
||||
SC64_CMD_USB_WRITE = 'M',
|
||||
SC64_CMD_USB_READ_STATUS = 'u',
|
||||
SC64_CMD_USB_WRITE_STATUS = 'U',
|
||||
} cmd_id_t;
|
||||
|
||||
|
||||
static bool sc64_wait_cpu_busy (void) {
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = pi_io_read(&SC64->SR_CMD);
|
||||
sr = pi_io_read(&SC64_REGS->SR_CMD);
|
||||
} while (sr & SC64_SR_CPU_BUSY);
|
||||
return sr & SC64_SR_CMD_ERROR;
|
||||
}
|
||||
|
||||
static bool sc64_perform_cmd (uint8_t cmd, uint32_t *args, uint32_t *result) {
|
||||
static bool sc64_execute_cmd (uint8_t cmd, uint32_t *args, uint32_t *result) {
|
||||
if (args != NULL) {
|
||||
pi_io_write(&SC64->DATA[0], args[0]);
|
||||
pi_io_write(&SC64->DATA[1], args[1]);
|
||||
pi_io_write(&SC64_REGS->DATA[0], args[0]);
|
||||
pi_io_write(&SC64_REGS->DATA[1], args[1]);
|
||||
}
|
||||
pi_io_write(&SC64->SR_CMD, ((uint32_t) (cmd)) & 0xFF);
|
||||
pi_io_write(&SC64_REGS->SR_CMD, ((uint32_t) (cmd)) & 0xFF);
|
||||
bool error = sc64_wait_cpu_busy();
|
||||
if (result != NULL) {
|
||||
result[0] = pi_io_read(&SC64->DATA[0]);
|
||||
result[1] = pi_io_read(&SC64->DATA[1]);
|
||||
result[0] = pi_io_read(&SC64_REGS->DATA[0]);
|
||||
result[1] = pi_io_read(&SC64_REGS->DATA[1]);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t sc64_query_config (cfg_id_t id) {
|
||||
uint32_t args[2] = { id, 0 };
|
||||
uint32_t result[2];
|
||||
sc64_perform_cmd(SC64_CMD_QUERY, args, result);
|
||||
return result[1];
|
||||
}
|
||||
|
||||
void sc64_change_config (cfg_id_t id, uint32_t value) {
|
||||
uint32_t args[2] = { id, value };
|
||||
sc64_perform_cmd(SC64_CMD_CONFIG, args, NULL);
|
||||
}
|
||||
|
||||
void sc64_get_info (sc64_info_t *info) {
|
||||
info->cic_seed = (uint16_t) sc64_query_config(CFG_ID_CIC_SEED);
|
||||
info->tv_type = (tv_type_t) sc64_query_config(CFG_ID_TV_TYPE);
|
||||
info->boot_mode = (boot_mode_t) sc64_query_config(CFG_ID_BOOT_MODE);
|
||||
bool sc64_check_presence (void) {
|
||||
uint32_t version = pi_io_read(&SC64_REGS->VERSION);
|
||||
return (version == SC64_VERSION_2);
|
||||
}
|
||||
|
||||
void sc64_init (void) {
|
||||
sc64_change_config(CFG_ID_BOOTLOADER_SWITCH, false);
|
||||
}
|
||||
|
||||
uint32_t sc64_query_config (cfg_id_t id) {
|
||||
uint32_t args[2] = { id, 0 };
|
||||
uint32_t result[2];
|
||||
sc64_execute_cmd(SC64_CMD_CONFIG_QUERY, args, result);
|
||||
return result[1];
|
||||
}
|
||||
|
||||
void sc64_change_config (cfg_id_t id, uint32_t value) {
|
||||
uint32_t args[2] = { id, value };
|
||||
sc64_execute_cmd(SC64_CMD_CONFIG_CHANGE, args, NULL);
|
||||
}
|
||||
|
||||
void sc64_get_boot_info (sc64_boot_info_t *info) {
|
||||
info->cic_seed = (uint16_t) sc64_query_config(CFG_ID_CIC_SEED);
|
||||
info->tv_type = (tv_type_t) sc64_query_config(CFG_ID_TV_TYPE);
|
||||
info->boot_mode = (boot_mode_t) sc64_query_config(CFG_ID_BOOT_MODE);
|
||||
}
|
||||
|
||||
void sc64_get_time (rtc_time_t *t) {
|
||||
uint32_t result[2];
|
||||
sc64_perform_cmd(SC64_CMD_GET_TIME, NULL, result);
|
||||
sc64_execute_cmd(SC64_CMD_TIME_GET, NULL, result);
|
||||
t->second = (result[0] & 0xFF);
|
||||
t->minute = ((result[0] >> 8) & 0xFF);
|
||||
t->hour = ((result[0] >> 16) & 0xFF);
|
||||
@ -70,106 +84,38 @@ void sc64_set_time (rtc_time_t *t) {
|
||||
((t->hour << 16) | (t->minute << 8) | t->second),
|
||||
((t->weekday << 24) | (t->year << 16) | (t->month << 8) | t->day),
|
||||
};
|
||||
sc64_perform_cmd(SC64_CMD_SET_TIME, args, NULL);
|
||||
sc64_execute_cmd(SC64_CMD_TIME_SET, args, NULL);
|
||||
}
|
||||
|
||||
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
||||
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||
bool sc64_usb_write_ready (void) {
|
||||
uint32_t result[2];
|
||||
sc64_execute_cmd(SC64_CMD_USB_WRITE_STATUS, NULL, result);
|
||||
return result[0];
|
||||
}
|
||||
|
||||
void sc64_usb_write (uint32_t *address, uint32_t length) {
|
||||
while (!sc64_usb_write_ready());
|
||||
uint32_t args[2] = { (uint32_t) (address), length };
|
||||
sc64_execute_cmd(SC64_CMD_USB_WRITE, args, NULL);
|
||||
}
|
||||
|
||||
bool sc64_usb_read_ready (uint8_t *type, uint32_t *length) {
|
||||
uint32_t result[2];
|
||||
sc64_execute_cmd(SC64_CMD_USB_READ_STATUS, NULL, result);
|
||||
if (type != NULL) {
|
||||
*type = result[0] & 0xFF;
|
||||
}
|
||||
if (length != NULL) {
|
||||
*length = result[1];
|
||||
}
|
||||
return result[1] > 0;
|
||||
}
|
||||
|
||||
void sc64_usb_read (uint32_t *address, uint32_t length) {
|
||||
uint32_t args[2] = { (uint32_t) (address), length };
|
||||
uint32_t result[2];
|
||||
sc64_execute_cmd(SC64_CMD_USB_READ, args, NULL);
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
||||
} while (result[0]);
|
||||
return result[1];
|
||||
}
|
||||
|
||||
bool sc64_storage_init (drive_id_t drive) {
|
||||
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sc64_drive_start_rw (drive_id_t drive, bool write, uint32_t sector, uint32_t offset) {
|
||||
uint32_t args[2] = { (((drive & 0x01) << 31) | (offset & 0x7FFFFFFF)), sector };
|
||||
if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count) {
|
||||
io32_t *src;
|
||||
uint8_t *dst = (uint8_t *) (buffer);
|
||||
uint32_t current_offset = 0;
|
||||
uint32_t next_offset = SECTOR_SIZE;
|
||||
|
||||
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL)) {
|
||||
return true;
|
||||
}
|
||||
while (count > 0) {
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
if (count > 1) {
|
||||
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL + next_offset)) {
|
||||
return true;
|
||||
}
|
||||
next_offset = next_offset ? 0 : SECTOR_SIZE;
|
||||
}
|
||||
src = (io32_t *) (0x13FF0000UL + current_offset);
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
uint32_t data = pi_io_read(src + i);
|
||||
*dst++ = ((data >> 24) & 0xFF);
|
||||
*dst++ = ((data >> 16) & 0xFF);
|
||||
*dst++ = ((data >> 8) & 0xFF);
|
||||
*dst++ = ((data >> 0) & 0xFF);
|
||||
}
|
||||
current_offset = current_offset ? 0 : SECTOR_SIZE;
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
|
||||
uint8_t *src = (uint8_t *) (buffer);
|
||||
io32_t *dst = (io32_t *) (0x13FF0000UL);
|
||||
|
||||
while (count > 0) {
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
uint32_t data = 0;
|
||||
data |= ((*src++) << 24);
|
||||
data |= ((*src++) << 16);
|
||||
data |= ((*src++) << 8);
|
||||
data |= ((*src++) << 0);
|
||||
pi_io_write((dst + i), data);
|
||||
}
|
||||
if (sc64_drive_start_rw(drive, true, sector, 0x03FF0000UL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
sector += 1;
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void sc64_uart_put_char (char c) {
|
||||
#ifdef DEBUG
|
||||
uint32_t args[2] = { (uint32_t) (c), 0 };
|
||||
sc64_perform_cmd(SC64_CMD_UART_PUT, args, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sc64_uart_print_string (const char *text) {
|
||||
while (*text != '\0') {
|
||||
sc64_uart_put_char (*text++);
|
||||
}
|
||||
sc64_execute_cmd(SC64_CMD_USB_READ_STATUS, NULL, result);
|
||||
} while(result[0] & (1 << 24));
|
||||
}
|
||||
|
@ -4,61 +4,64 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "io.h"
|
||||
|
||||
|
||||
#define SC64_CMD_QUERY ('c')
|
||||
#define SC64_CMD_CONFIG ('C')
|
||||
#define SC64_CMD_GET_TIME ('t')
|
||||
#define SC64_CMD_SET_TIME ('T')
|
||||
#define SC64_CMD_DRIVE_INIT (0xF0)
|
||||
#define SC64_CMD_DRIVE_BUSY (0xF1)
|
||||
#define SC64_CMD_DRIVE_READ (0xF2)
|
||||
#define SC64_CMD_DRIVE_WRITE (0xF3)
|
||||
#define SC64_CMD_DRIVE_LOAD (0xF4)
|
||||
#define SC64_CMD_DRIVE_STORE (0xF5)
|
||||
#define SC64_CMD_UART_PUT ('U')
|
||||
|
||||
#define SC64_VERSION_2 (0x53437632)
|
||||
|
||||
|
||||
typedef enum {
|
||||
CFG_ID_BOOTLOADER_SWITCH,
|
||||
CFG_ID_ROM_WRITE_ENABLE,
|
||||
CFG_ID_ROM_SHADOW_ENABLE,
|
||||
CFG_ID_DD_ENABLE,
|
||||
CFG_ID_DD_MODE,
|
||||
CFG_ID_ISV_ENABLE,
|
||||
CFG_ID_BOOT_MODE,
|
||||
CFG_ID_SAVE_TYPE,
|
||||
CFG_ID_CIC_SEED,
|
||||
CFG_ID_TV_TYPE,
|
||||
CFG_ID_FLASH_ERASE_BLOCK,
|
||||
CFG_ID_DD_DRIVE_TYPE,
|
||||
CFG_ID_DD_DISK_STATE,
|
||||
} cfg_id_t;
|
||||
|
||||
typedef enum {
|
||||
CIC_SEED_UNKNOWN = 0xFFFF,
|
||||
} cic_seed_t;
|
||||
|
||||
typedef enum {
|
||||
TV_TYPE_PAL = 0,
|
||||
TV_TYPE_NTSC = 1,
|
||||
TV_TYPE_MPAL = 2,
|
||||
TV_TYPE_UNKNOWN = 3,
|
||||
} tv_type_t;
|
||||
DD_MODE_DISABLED = 0,
|
||||
DD_MODE_REGS = 1,
|
||||
DD_MODE_IPL = 2,
|
||||
DD_MODE_FULL = 3
|
||||
} dd_mode_t;
|
||||
|
||||
typedef enum {
|
||||
BOOT_MODE_MENU_SD = 0,
|
||||
BOOT_MODE_MENU_USB = 1,
|
||||
BOOT_MODE_ROM = 2,
|
||||
BOOT_MODE_DDIPL = 3,
|
||||
BOOT_MODE_DIRECT = 4,
|
||||
BOOT_MODE_DIRECT = 4
|
||||
} boot_mode_t;
|
||||
|
||||
typedef enum {
|
||||
SAVE_TYPE_NONE = 0,
|
||||
SAVE_TYPE_EEPROM_4K = 1,
|
||||
SAVE_TYPE_EEPROM_16K = 2,
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5
|
||||
} save_type_t;
|
||||
|
||||
typedef enum {
|
||||
CIC_SEED_UNKNOWN = 0xFFFF
|
||||
} cic_seed_t;
|
||||
|
||||
typedef enum {
|
||||
TV_TYPE_PAL = 0,
|
||||
TV_TYPE_NTSC = 1,
|
||||
TV_TYPE_MPAL = 2,
|
||||
TV_TYPE_UNKNOWN = 3
|
||||
} tv_type_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
boot_mode_t boot_mode;
|
||||
uint16_t cic_seed;
|
||||
tv_type_t tv_type;
|
||||
} sc64_info_t;
|
||||
} sc64_boot_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t second;
|
||||
@ -70,24 +73,18 @@ typedef struct {
|
||||
uint8_t year;
|
||||
} rtc_time_t;
|
||||
|
||||
typedef enum {
|
||||
DRIVE_SD = 0,
|
||||
DRIVE_USB = 1,
|
||||
__DRIVE_COUNT = 2
|
||||
} drive_id_t;
|
||||
|
||||
|
||||
bool sc64_check_presence (void);
|
||||
void sc64_init (void);
|
||||
uint32_t sc64_query_config (cfg_id_t id);
|
||||
void sc64_change_config (cfg_id_t id, uint32_t value);
|
||||
void sc64_get_info (sc64_info_t *info);
|
||||
void sc64_init (void);
|
||||
void sc64_get_boot_info (sc64_boot_info_t *info);
|
||||
void sc64_get_time (rtc_time_t *t);
|
||||
void sc64_set_time (rtc_time_t *t);
|
||||
bool sc64_storage_init (drive_id_t drive);
|
||||
bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count);
|
||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count);
|
||||
void sc64_uart_print_string (const char *text);
|
||||
bool sc64_write_usb_ready (void);
|
||||
void sc64_write_usb (uint32_t *address, uint32_t length);
|
||||
bool sc64_usb_read_ready (uint8_t *type, uint32_t *length);
|
||||
void sc64_usb_read (uint32_t *address, uint32_t length);
|
||||
|
||||
|
||||
#endif
|
||||
|
1
sw/controller/.gitattributes
vendored
Normal file
1
sw/controller/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
lib/** linguist-vendored
|
@ -5,13 +5,14 @@
|
||||
#include "fpga.h"
|
||||
#include "isv.h"
|
||||
#include "rtc.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
CFG_ID_BOOTLOADER_SWITCH,
|
||||
CFG_ID_ROM_WRITE_ENABLE,
|
||||
CFG_ID_ROM_SHADOW_ENABLE,
|
||||
CFG_ID_DD_ENABLE,
|
||||
CFG_ID_DD_MODE,
|
||||
CFG_ID_ISV_ENABLE,
|
||||
CFG_ID_BOOT_MODE,
|
||||
CFG_ID_SAVE_TYPE,
|
||||
@ -23,13 +24,11 @@ typedef enum {
|
||||
} cfg_id_t;
|
||||
|
||||
typedef enum {
|
||||
SAVE_TYPE_NONE = 0,
|
||||
SAVE_TYPE_EEPROM_4K = 1,
|
||||
SAVE_TYPE_EEPROM_16K = 2,
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5
|
||||
} save_type_t;
|
||||
DD_MODE_DISABLED = 0,
|
||||
DD_MODE_REGS = 1,
|
||||
DD_MODE_IPL = 2,
|
||||
DD_MODE_FULL = 3
|
||||
} dd_mode_t;
|
||||
|
||||
typedef enum {
|
||||
BOOT_MODE_MENU_SD = 0,
|
||||
@ -39,17 +38,43 @@ typedef enum {
|
||||
BOOT_MODE_DIRECT = 4
|
||||
} boot_mode_t;
|
||||
|
||||
typedef enum {
|
||||
SAVE_TYPE_NONE = 0,
|
||||
SAVE_TYPE_EEPROM_4K = 1,
|
||||
SAVE_TYPE_EEPROM_16K = 2,
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5
|
||||
} save_type_t;
|
||||
|
||||
typedef enum {
|
||||
CIC_SEED_UNKNOWN = 0xFFFF
|
||||
} cic_seed_t;
|
||||
|
||||
typedef enum {
|
||||
TV_TYPE_PAL = 0,
|
||||
TV_TYPE_NTSC = 1,
|
||||
TV_TYPE_MPAL = 2,
|
||||
TV_TYPE_UNKNOWN = 3
|
||||
} tv_type_t;
|
||||
|
||||
|
||||
struct process {
|
||||
boot_mode_t boot_mode;
|
||||
save_type_t save_type;
|
||||
uint16_t cic_seed;
|
||||
uint8_t tv_type;
|
||||
cic_seed_t cic_seed;
|
||||
tv_type_t tv_type;
|
||||
bool usb_output_ready;
|
||||
};
|
||||
|
||||
|
||||
static struct process p;
|
||||
|
||||
|
||||
static void cfg_set_usb_output_ready (void) {
|
||||
p.usb_output_ready = true;
|
||||
}
|
||||
|
||||
static void change_scr_bits (uint32_t mask, bool value) {
|
||||
if (value) {
|
||||
fpga_reg_set(REG_CFG_SCR, fpga_reg_get(REG_CFG_SCR) | mask);
|
||||
@ -101,18 +126,26 @@ uint32_t cfg_get_version (void) {
|
||||
}
|
||||
|
||||
void cfg_query (uint32_t *args) {
|
||||
uint32_t scr = fpga_reg_get(REG_CFG_SCR);
|
||||
|
||||
switch (args[0]) {
|
||||
case CFG_ID_BOOTLOADER_SWITCH:
|
||||
args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_BOOTLOADER_ENABLED);
|
||||
args[1] = (scr & CFG_SCR_BOOTLOADER_ENABLED);
|
||||
break;
|
||||
case CFG_ID_ROM_WRITE_ENABLE:
|
||||
args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_ROM_WRITE_ENABLED);
|
||||
args[1] = (scr & CFG_SCR_ROM_WRITE_ENABLED);
|
||||
break;
|
||||
case CFG_ID_ROM_SHADOW_ENABLE:
|
||||
args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_ROM_SHADOW_ENABLED);
|
||||
args[1] = (scr & CFG_SCR_ROM_SHADOW_ENABLED);
|
||||
break;
|
||||
case CFG_ID_DD_ENABLE:
|
||||
args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_DD_ENABLED);
|
||||
case CFG_ID_DD_MODE:
|
||||
args[1] = DD_MODE_DISABLED;
|
||||
if (scr & CFG_SCR_DDIPL_ENABLED) {
|
||||
args[1] |= DD_MODE_IPL;
|
||||
}
|
||||
if (scr & CFG_SCR_DD_ENABLED) {
|
||||
args[1] |= DD_MODE_REGS;
|
||||
}
|
||||
break;
|
||||
case CFG_ID_ISV_ENABLE:
|
||||
args[1] = isv_get_enabled();
|
||||
@ -130,10 +163,13 @@ void cfg_query (uint32_t *args) {
|
||||
args[1] = p.tv_type;
|
||||
break;
|
||||
case CFG_ID_FLASH_ERASE_BLOCK:
|
||||
args[1] = 0xFFFFFFFF;
|
||||
break;
|
||||
case CFG_ID_DD_DRIVE_TYPE:
|
||||
args[1] = dd_get_drive_type();
|
||||
break;
|
||||
case CFG_ID_DD_DISK_STATE:
|
||||
args[1] = dd_get_disk_state();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -149,8 +185,18 @@ void cfg_update (uint32_t *args) {
|
||||
case CFG_ID_ROM_SHADOW_ENABLE:
|
||||
change_scr_bits(CFG_SCR_ROM_SHADOW_ENABLED, args[1]);
|
||||
break;
|
||||
case CFG_ID_DD_ENABLE:
|
||||
change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, args[1]);
|
||||
case CFG_ID_DD_MODE:
|
||||
if (args[1] == DD_MODE_DISABLED) {
|
||||
change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, false);
|
||||
} else if (args[1] == DD_MODE_REGS) {
|
||||
change_scr_bits(CFG_SCR_DD_ENABLED, true);
|
||||
change_scr_bits(CFG_SCR_DDIPL_ENABLED, false);
|
||||
} else if (args[1] == DD_MODE_IPL) {
|
||||
change_scr_bits(CFG_SCR_DD_ENABLED, false);
|
||||
change_scr_bits(CFG_SCR_DDIPL_ENABLED, true);
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, true);
|
||||
}
|
||||
break;
|
||||
case CFG_ID_ISV_ENABLE:
|
||||
isv_set_enabled(args[1]);
|
||||
@ -163,10 +209,10 @@ void cfg_update (uint32_t *args) {
|
||||
set_save_type((save_type_t) (args[1]));
|
||||
break;
|
||||
case CFG_ID_CIC_SEED:
|
||||
p.cic_seed = (uint16_t) (args[1] & 0xFFFF);
|
||||
p.cic_seed = (cic_seed_t) (args[1] & 0xFFFF);
|
||||
break;
|
||||
case CFG_ID_TV_TYPE:
|
||||
p.tv_type = (uint8_t) (args[1] & 0x03);
|
||||
p.tv_type = (tv_type_t) (args[1] & 0x03);
|
||||
break;
|
||||
case CFG_ID_FLASH_ERASE_BLOCK:
|
||||
flash_erase_block(args[1]);
|
||||
@ -199,19 +245,19 @@ void cfg_set_time (uint32_t *args) {
|
||||
rtc_set_time(&t);
|
||||
}
|
||||
|
||||
|
||||
void cfg_init (void) {
|
||||
fpga_reg_set(REG_CFG_SCR, 0);
|
||||
set_save_type(SAVE_TYPE_NONE);
|
||||
|
||||
p.cic_seed = 0xFFFF;
|
||||
p.tv_type = 0x03;
|
||||
p.cic_seed = CIC_SEED_UNKNOWN;
|
||||
p.tv_type = TV_TYPE_UNKNOWN;
|
||||
p.boot_mode = BOOT_MODE_MENU_SD;
|
||||
p.usb_output_ready = true;
|
||||
}
|
||||
|
||||
|
||||
void cfg_process (void) {
|
||||
uint32_t args[2];
|
||||
usb_tx_info_t packet_info;
|
||||
|
||||
if (fpga_reg_get(REG_STATUS) & STATUS_CFG_PENDING) {
|
||||
args[0] = fpga_reg_get(REG_CFG_DATA_0);
|
||||
@ -239,6 +285,32 @@ void cfg_process (void) {
|
||||
cfg_set_time(args);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (!usb_prepare_read(args)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
usb_create_packet(&packet_info, PACKET_CMD_USB_OUTPUT);
|
||||
packet_info.dma_length = args[1];
|
||||
packet_info.dma_address = args[0];
|
||||
packet_info.done_callback = cfg_set_usb_output_ready;
|
||||
if (usb_enqueue_packet(&packet_info)) {
|
||||
p.usb_output_ready = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
usb_get_read_info(args);
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
args[0] = p.usb_output_ready ? 1 : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fpga_reg_set(REG_CFG_CMD, CFG_CMD_ERROR | CFG_CMD_DONE);
|
||||
return;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdbool.h>
|
||||
#include "cic.h"
|
||||
#include "hw.h"
|
||||
#include "rtc.h"
|
||||
@ -290,18 +291,16 @@ static void cic_soft_reset (void) {
|
||||
task_yield();
|
||||
}
|
||||
|
||||
void cic_set_dd_mode (bool enabled) {
|
||||
cic_dd_mode = enabled;
|
||||
}
|
||||
|
||||
void cic_set_seed (uint8_t seed) {
|
||||
cic_seed = seed;
|
||||
}
|
||||
|
||||
void cic_set_checksum (uint8_t *checksum) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cic_checksum[i] = checksum[i];
|
||||
}
|
||||
void cic_set_parameters (uint32_t *args) {
|
||||
cic_dd_mode = (args[0] >> 24) & 0x01;
|
||||
cic_seed = (args[0] >> 16) & 0xFF;
|
||||
cic_checksum[0] = (args[0] >> 8) & 0xFF;
|
||||
cic_checksum[1] = args[0] & 0xFF;
|
||||
cic_checksum[2] = (args[1] >> 24) & 0xFF;
|
||||
cic_checksum[3] = (args[1] >> 16) & 0xFF;
|
||||
cic_checksum[4] = (args[1] >> 8) & 0xFF;
|
||||
cic_checksum[5] = args[1] & 0xFF;
|
||||
}
|
||||
|
||||
void cic_hw_init (void) {
|
||||
|
@ -2,13 +2,10 @@
|
||||
#define CIC_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void cic_set_dd_mode (bool enabled);
|
||||
void cic_set_seed (uint8_t seed);
|
||||
void cic_set_checksum (uint8_t *checksum);
|
||||
void cic_set_parameters (uint32_t *args);
|
||||
void cic_hw_init (void);
|
||||
void cic_task (void);
|
||||
|
||||
|
@ -75,6 +75,7 @@ struct process {
|
||||
sector_info_t sector_info;
|
||||
bool block_ready;
|
||||
bool block_valid;
|
||||
dd_drive_type_t drive_type;
|
||||
};
|
||||
|
||||
|
||||
@ -90,19 +91,18 @@ static uint16_t dd_track_head_block (void) {
|
||||
|
||||
static bool dd_block_read_request (void) {
|
||||
usb_tx_info_t packet_info;
|
||||
packet_info.cmd = PACKET_CMD_DD_REQUEST;
|
||||
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
||||
packet_info.data_length = 12;
|
||||
packet_info.data[0] = 1;
|
||||
packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS;
|
||||
packet_info.data[2] = dd_track_head_block();
|
||||
packet_info.dma_length = 0;
|
||||
p.block_ready = false;
|
||||
return usb_enqueue_packet(&packet_info);
|
||||
}
|
||||
|
||||
static bool dd_block_write_request (void) {
|
||||
usb_tx_info_t packet_info;
|
||||
packet_info.cmd = PACKET_CMD_DD_REQUEST;
|
||||
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
||||
packet_info.data_length = 12;
|
||||
packet_info.data[0] = 2;
|
||||
packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS;
|
||||
@ -123,18 +123,35 @@ void dd_set_block_ready (bool valid) {
|
||||
p.block_valid = valid;
|
||||
}
|
||||
|
||||
dd_drive_type_t dd_get_drive_type (void) {
|
||||
return p.drive_type;
|
||||
}
|
||||
|
||||
void dd_set_drive_type (dd_drive_type_t type) {
|
||||
switch (type) {
|
||||
case DD_DRIVE_TYPE_RETAIL:
|
||||
fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL);
|
||||
p.drive_type = type;
|
||||
break;
|
||||
|
||||
case DD_DRIVE_TYPE_DEVELOPMENT:
|
||||
fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_DEVELOPMENT);
|
||||
p.drive_type = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dd_disk_state_t dd_get_disk_state (void) {
|
||||
uint32_t scr = fpga_reg_get(REG_DD_SCR);
|
||||
if (scr & DD_SCR_DISK_CHANGED) {
|
||||
return DD_DISK_STATE_CHANGED;
|
||||
}
|
||||
if (scr & DD_SCR_DISK_INSERTED) {
|
||||
return DD_DISK_STATE_INSERTED;
|
||||
}
|
||||
return DD_DISK_STATE_EJECTED;
|
||||
}
|
||||
|
||||
void dd_set_disk_state (dd_disk_state_t state) {
|
||||
uint32_t scr = fpga_reg_get(REG_DD_SCR);
|
||||
scr &= ~(DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED);
|
||||
@ -162,6 +179,7 @@ void dd_init (void) {
|
||||
p.cmd_response_ready = false;
|
||||
p.disk_spinning = false;
|
||||
p.bm_running = false;
|
||||
p.drive_type = DD_DRIVE_TYPE_RETAIL;
|
||||
}
|
||||
|
||||
void dd_process (void) {
|
||||
|
@ -17,7 +17,9 @@ typedef enum {
|
||||
} dd_disk_state_t;
|
||||
|
||||
|
||||
dd_drive_type_t dd_get_drive_type (void);
|
||||
void dd_set_drive_type (dd_drive_type_t type);
|
||||
dd_disk_state_t dd_get_disk_state (void);
|
||||
void dd_set_disk_state (dd_disk_state_t state);
|
||||
void dd_set_block_ready (bool valid);
|
||||
void dd_init (void);
|
||||
|
@ -6,9 +6,9 @@
|
||||
#define FLASHRAM_SIZE (128 * 1024)
|
||||
#define FLASHRAM_SECTOR_SIZE (16 * 1024)
|
||||
#define FLASHRAM_PAGE_SIZE (128)
|
||||
#define FLASHRAM_OFFSET (0x03FE0000UL)
|
||||
#define FLASHRAM_BUFFER_OFFSET (0x06004000UL)
|
||||
|
||||
#define FLASHRAM_OFFSET ((64 * 1024 * 1024) - (128 * 1024))
|
||||
#define FLASHRAM_BUFFER_OFFSET (((64 + 32) * 1024 * 1024) + ((8 + 8) * 1024))
|
||||
|
||||
enum operation {
|
||||
OP_NONE,
|
||||
@ -39,7 +39,6 @@ void flashram_init (void) {
|
||||
fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE);
|
||||
}
|
||||
|
||||
|
||||
void flashram_process (void) {
|
||||
uint32_t scr = fpga_reg_get(REG_FLASHRAM_SCR);
|
||||
enum operation op = flashram_operation_type(scr);
|
||||
|
@ -114,6 +114,8 @@ typedef enum {
|
||||
|
||||
#define RTC_SCR_PENDING (1 << 0)
|
||||
#define RTC_SCR_DONE (1 << 1)
|
||||
#define RTC_SCR_MAGIC (0x52544300)
|
||||
#define RTC_SCR_MAGIC_MASK (0xFFFFFF00)
|
||||
|
||||
#define SD_SCR_CLOCK_MODE_OFF (0 << 0)
|
||||
#define SD_SCR_CLOCK_MODE_400KHZ (1 << 0)
|
||||
|
@ -38,6 +38,7 @@ typedef enum {
|
||||
GPIO_AF_7 = 0x07
|
||||
} gpio_af_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
void (*volatile falling)(void);
|
||||
void (*volatile rising)(void);
|
||||
@ -46,12 +47,10 @@ typedef struct {
|
||||
|
||||
static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB };
|
||||
static gpio_irq_callback_t gpio_irq_callbacks[16];
|
||||
|
||||
static volatile uint8_t *i2c_data_txptr;
|
||||
static volatile uint8_t *i2c_data_rxptr;
|
||||
static volatile uint32_t i2c_next_cr2;
|
||||
static void (*volatile i2c_callback)(void);
|
||||
|
||||
static const TIM_TypeDef *tims[] = { TIM14, TIM16, TIM17, TIM3 };
|
||||
static void (*volatile tim_callbacks[4])(void);
|
||||
|
||||
@ -198,6 +197,12 @@ void hw_i2c_enable_irq (void) {
|
||||
}
|
||||
|
||||
void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)) {
|
||||
if (delay == 0) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id]));
|
||||
tim->CR1 = (TIM_CR1_OPM | TIM_CR1_URS);
|
||||
tim->PSC = (64000 - 1);
|
||||
@ -362,6 +367,7 @@ void hw_init (void) {
|
||||
NVIC_EnableIRQ(TIM3_IRQn);
|
||||
}
|
||||
|
||||
|
||||
void EXTI0_1_IRQHandler (void) {
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) {
|
||||
|
@ -13,6 +13,7 @@ struct process {
|
||||
uint32_t current_read_pointer;
|
||||
};
|
||||
|
||||
|
||||
static struct process p;
|
||||
|
||||
|
||||
@ -29,9 +30,11 @@ static uint32_t isv_get_read_pointer (void) {
|
||||
|
||||
|
||||
void isv_set_enabled (bool enabled) {
|
||||
uint32_t read_pointer = 0;
|
||||
if (enabled) {
|
||||
p.enabled = true;
|
||||
p.current_read_pointer = 0;
|
||||
fpga_mem_write(ISV_READ_POINTER_ADDRESS, 4, (uint8_t *) (&read_pointer));
|
||||
} else {
|
||||
p.enabled = false;
|
||||
}
|
||||
@ -55,8 +58,7 @@ void isv_process (void) {
|
||||
uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer;
|
||||
|
||||
usb_tx_info_t packet_info;
|
||||
packet_info.cmd = PACKET_CMD_ISV_OUTPUT;
|
||||
packet_info.data_length = 0;
|
||||
usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT);
|
||||
packet_info.dma_length = length;
|
||||
packet_info.dma_address = offset;
|
||||
if (usb_enqueue_packet(&packet_info)) {
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
static uint8_t rtc_region = 0xFF;
|
||||
static volatile bool rtc_region_pending = false;
|
||||
|
||||
static rtc_time_t rtc_time = {
|
||||
.second = 0x00,
|
||||
.minute = 0x00,
|
||||
@ -174,6 +173,7 @@ static void rtc_init (void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool rtc_get_time (rtc_time_t *time) {
|
||||
bool vaild;
|
||||
|
||||
@ -248,8 +248,9 @@ void rtc_task (void) {
|
||||
void rtc_process (void) {
|
||||
rtc_time_t time;
|
||||
uint32_t data[2];
|
||||
uint32_t scr = fpga_reg_get(REG_RTC_SCR);
|
||||
|
||||
if (fpga_reg_get(REG_RTC_SCR) & RTC_SCR_PENDING) {
|
||||
if ((scr & RTC_SCR_PENDING) && ((scr & RTC_SCR_MAGIC_MASK) == RTC_SCR_MAGIC)) {
|
||||
data[0] = fpga_reg_get(REG_RTC_TIME_0);
|
||||
data[1] = fpga_reg_get(REG_RTC_TIME_1);
|
||||
|
||||
|
@ -12,6 +12,7 @@ typedef enum {
|
||||
TASK_FLAG_RESET = (1 << 1),
|
||||
} task_flags_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t initial_pc;
|
||||
uint32_t initial_sp;
|
||||
@ -62,6 +63,7 @@ static uint32_t task_switch_context (uint32_t sp) {
|
||||
return task_table[task_current].sp;
|
||||
}
|
||||
|
||||
|
||||
void task_create (task_id_t id, void (*code)(void), void *stack, size_t stack_size) {
|
||||
if (id < __TASK_ID_MAX) {
|
||||
task_t *task = &task_table[id];
|
||||
@ -110,6 +112,7 @@ __attribute__((naked)) void task_scheduler_start (void) {
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
__attribute__((naked)) void PendSV_Handler (void) {
|
||||
asm volatile (
|
||||
"mrs r1, psp \n"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "cic.h"
|
||||
#include "dd.h"
|
||||
#include "cfg.h"
|
||||
#include "fpga.h"
|
||||
@ -42,6 +43,10 @@ struct process {
|
||||
|
||||
bool packet_pending;
|
||||
usb_tx_info_t packet_info;
|
||||
|
||||
bool read_ready;
|
||||
uint32_t read_length;
|
||||
uint32_t read_address;
|
||||
};
|
||||
|
||||
|
||||
@ -54,6 +59,10 @@ static const uint32_t ERR_TOKEN = (0x45525200UL);
|
||||
static const uint32_t PKT_TOKEN = (0x504B5400UL);
|
||||
|
||||
|
||||
static bool usb_dma_ready (void) {
|
||||
return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY));
|
||||
}
|
||||
|
||||
static bool usb_rx_byte (uint8_t *data) {
|
||||
if (fpga_usb_status_get() & USB_STATUS_RXNE) {
|
||||
*data = fpga_usb_pop();
|
||||
@ -119,7 +128,6 @@ static bool usb_rx_cmd (uint8_t *cmd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void usb_rx_process (void) {
|
||||
if (p.rx_state == RX_STATE_IDLE) {
|
||||
if (!p.response_pending && usb_rx_cmd(&p.rx_cmd)) {
|
||||
@ -130,6 +138,7 @@ static void usb_rx_process (void) {
|
||||
p.response_info.cmd = p.rx_cmd;
|
||||
p.response_info.data_length = 0;
|
||||
p.response_info.dma_length = 0;
|
||||
p.response_info.done_callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +162,12 @@ static void usb_rx_process (void) {
|
||||
p.response_info.data[0] = cfg_get_version();
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
cic_set_parameters(p.rx_args);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cfg_query(p.rx_args);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
@ -197,7 +212,7 @@ static void usb_rx_process (void) {
|
||||
|
||||
case 'M':
|
||||
case 'D':
|
||||
if (!((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY))) {
|
||||
if (usb_dma_ready()) {
|
||||
if (!p.rx_dma_running) {
|
||||
fpga_reg_set(REG_USB_DMA_ADDRESS, p.rx_args[0]);
|
||||
fpga_reg_set(REG_USB_DMA_LENGTH, p.rx_args[1]);
|
||||
@ -213,6 +228,27 @@ static void usb_rx_process (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
if ((p.read_length > 0) && usb_dma_ready()) {
|
||||
uint32_t length = (p.read_length > p.rx_args[1]) ? p.rx_args[1] : p.read_length;
|
||||
if (!p.rx_dma_running) {
|
||||
fpga_reg_set(REG_USB_DMA_ADDRESS, p.read_address);
|
||||
fpga_reg_set(REG_USB_DMA_LENGTH, length);
|
||||
fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START);
|
||||
p.rx_dma_running = true;
|
||||
p.read_ready = false;
|
||||
} else {
|
||||
p.rx_args[1] -= length;
|
||||
p.read_length -= length;
|
||||
p.read_address += length;
|
||||
p.read_ready = true;
|
||||
if (p.rx_args[1] == 0) {
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
@ -273,7 +309,7 @@ static void usb_tx_process (void) {
|
||||
|
||||
if (p.tx_state == TX_STATE_DMA) {
|
||||
if (p.tx_info.dma_length > 0) {
|
||||
if (!((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY))) {
|
||||
if (usb_dma_ready()) {
|
||||
if (!p.tx_dma_running) {
|
||||
p.tx_dma_running = true;
|
||||
fpga_reg_set(REG_USB_DMA_ADDRESS, p.tx_info.dma_address);
|
||||
@ -290,11 +326,25 @@ static void usb_tx_process (void) {
|
||||
|
||||
if (p.tx_state == TX_STATE_FLUSH) {
|
||||
fpga_reg_set(REG_USB_SCR, USB_SCR_WRITE_FLUSH);
|
||||
if (p.tx_info.done_callback) {
|
||||
p.tx_info.done_callback();
|
||||
}
|
||||
p.tx_state = TX_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usb_create_packet (usb_tx_info_t *info, uint8_t cmd) {
|
||||
info->cmd = cmd;
|
||||
info->data_length = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info->data[i] = 0;
|
||||
}
|
||||
info->dma_length = 0;
|
||||
info->dma_address = 0;
|
||||
info->done_callback = NULL;
|
||||
}
|
||||
|
||||
bool usb_enqueue_packet (usb_tx_info_t *info) {
|
||||
if (p.packet_pending) {
|
||||
return false;
|
||||
@ -306,6 +356,25 @@ bool usb_enqueue_packet (usb_tx_info_t *info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool usb_prepare_read (uint32_t *args) {
|
||||
if (!p.read_ready) {
|
||||
return false;
|
||||
}
|
||||
p.read_length = args[1];
|
||||
p.read_address = args[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void usb_get_read_info (uint32_t *args) {
|
||||
args[0] = 0;
|
||||
args[1] = 0;
|
||||
if (p.rx_state == RX_STATE_DATA && p.rx_cmd == 'U') {
|
||||
args[0] = p.rx_args[0] & 0xFF;
|
||||
args[1] = p.rx_args[1];
|
||||
}
|
||||
args[0] |= (p.read_length > 0) ? (1 << 24) : 0;
|
||||
}
|
||||
|
||||
void usb_init (void) {
|
||||
fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP);
|
||||
fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH);
|
||||
@ -316,6 +385,10 @@ void usb_init (void) {
|
||||
p.response_pending = false;
|
||||
p.packet_pending = false;
|
||||
|
||||
p.read_ready = true;
|
||||
p.read_length = 0;
|
||||
p.read_address = 0;
|
||||
|
||||
usb_rx_word_counter = 0;
|
||||
usb_rx_word_buffer = 0;
|
||||
usb_tx_word_counter = 0;
|
||||
@ -324,6 +397,9 @@ void usb_init (void) {
|
||||
|
||||
void usb_process (void) {
|
||||
if (fpga_reg_get(REG_USB_SCR) & USB_SCR_RESET_PENDING) {
|
||||
if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) {
|
||||
p.tx_info.done_callback();
|
||||
}
|
||||
usb_init();
|
||||
fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK);
|
||||
} else {
|
||||
|
@ -9,6 +9,7 @@
|
||||
typedef enum packet_cmd {
|
||||
PACKET_CMD_DD_REQUEST = 'D',
|
||||
PACKET_CMD_ISV_OUTPUT = 'I',
|
||||
PACKET_CMD_USB_OUTPUT = 'U',
|
||||
} usb_packet_cmd_e;
|
||||
|
||||
|
||||
@ -18,10 +19,14 @@ typedef struct usb_tx_info {
|
||||
uint32_t data[4];
|
||||
uint32_t dma_length;
|
||||
uint32_t dma_address;
|
||||
void (*done_callback)(void);
|
||||
} usb_tx_info_t;
|
||||
|
||||
|
||||
void usb_create_packet (usb_tx_info_t *info, uint8_t cmd);
|
||||
bool usb_enqueue_packet (usb_tx_info_t *info);
|
||||
bool usb_prepare_read (uint32_t *args);
|
||||
void usb_get_read_info (uint32_t *args);
|
||||
void usb_init (void);
|
||||
void usb_process (void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user