mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
removed task subsystem + huge cleanup
This commit is contained in:
parent
f7eb6a73b4
commit
7d6e2bc5ee
@ -382,7 +382,7 @@ module n64_si (
|
||||
4'd1: {rtc_time_wp, rtc_backup_wp} <= rx_byte_data[1:0];
|
||||
4'd2: begin
|
||||
rtc_stopped <= rx_byte_data[2:1];
|
||||
if (rx_byte_data[2:1] == 2'b00) begin
|
||||
if ((|rtc_stopped) && (rx_byte_data[2:1] == 2'b00)) begin
|
||||
n64_scb.rtc_pending <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
@ -14,14 +14,12 @@ SRC_FILES = \
|
||||
flash.c \
|
||||
flashram.c \
|
||||
fpga.c \
|
||||
gvr.c \
|
||||
hw.c \
|
||||
isv.c \
|
||||
lcmxo2.c \
|
||||
led.c \
|
||||
rtc.c \
|
||||
sd.c \
|
||||
task.c \
|
||||
timer.c \
|
||||
update.c \
|
||||
usb.c \
|
||||
|
@ -1,34 +1,46 @@
|
||||
#include "app.h"
|
||||
#include "gvr.h"
|
||||
#include "button.h"
|
||||
#include "cfg.h"
|
||||
#include "cic.h"
|
||||
#include "dd.h"
|
||||
#include "flashram.h"
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "led.h"
|
||||
#include "isv.h"
|
||||
#include "rtc.h"
|
||||
#include "task.h"
|
||||
#include "sd.h"
|
||||
#include "timer.h"
|
||||
#include "usb.h"
|
||||
#include "writeback.h"
|
||||
|
||||
|
||||
#define RTC_STACK_SIZE (256)
|
||||
#define LED_STACK_SIZE (256)
|
||||
#define GVR_STACK_SIZE (2048)
|
||||
|
||||
|
||||
uint8_t rtc_stack[RTC_STACK_SIZE] __attribute__((aligned(8)));
|
||||
uint8_t led_stack[LED_STACK_SIZE] __attribute__((aligned(8)));
|
||||
uint8_t gvr_stack[GVR_STACK_SIZE] __attribute__((aligned(8)));
|
||||
|
||||
|
||||
void app_get_stack_usage (uint32_t *usage) {
|
||||
*usage++ = 0;
|
||||
*usage++ = task_get_stack_usage(rtc_stack, RTC_STACK_SIZE);
|
||||
*usage++ = task_get_stack_usage(led_stack, LED_STACK_SIZE);
|
||||
*usage++ = task_get_stack_usage(gvr_stack, GVR_STACK_SIZE);
|
||||
}
|
||||
|
||||
void app (void) {
|
||||
hw_init();
|
||||
hw_app_init();
|
||||
|
||||
task_create(TASK_ID_RTC, rtc_task, rtc_stack, RTC_STACK_SIZE);
|
||||
task_create(TASK_ID_LED, led_task, led_stack, LED_STACK_SIZE);
|
||||
task_create(TASK_ID_GVR, gvr_task, gvr_stack, GVR_STACK_SIZE);
|
||||
timer_init();
|
||||
rtc_init();
|
||||
|
||||
task_scheduler_start();
|
||||
while (fpga_id_get() != FPGA_ID);
|
||||
|
||||
button_init();
|
||||
cfg_init();
|
||||
cic_init();
|
||||
dd_init();
|
||||
flashram_init();
|
||||
isv_init();
|
||||
sd_init();
|
||||
usb_init();
|
||||
writeback_init();
|
||||
|
||||
while (1) {
|
||||
button_process();
|
||||
cfg_process();
|
||||
cic_process();
|
||||
dd_process();
|
||||
flashram_process();
|
||||
isv_process();
|
||||
rtc_process();
|
||||
sd_process();
|
||||
usb_process();
|
||||
writeback_process();
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
#ifndef APP_H__
|
||||
#define APP_H__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void app_get_stack_usage (uint32_t *usage);
|
||||
|
||||
|
||||
#endif
|
@ -39,6 +39,7 @@ button_mode_t button_get_mode (void) {
|
||||
return p.mode;
|
||||
}
|
||||
|
||||
|
||||
void button_init (void) {
|
||||
p.counter = 0;
|
||||
p.state = false;
|
||||
@ -46,9 +47,12 @@ void button_init (void) {
|
||||
p.trigger = false;
|
||||
}
|
||||
|
||||
|
||||
void button_process (void) {
|
||||
usb_tx_info_t packet_info;
|
||||
|
||||
uint32_t status = fpga_reg_get(REG_CFG_SCR);
|
||||
|
||||
if (status & CFG_SCR_BUTTON_STATE) {
|
||||
if (p.counter < BUTTON_COUNTER_TRIGGER_ON) {
|
||||
p.counter += 1;
|
||||
@ -58,13 +62,16 @@ void button_process (void) {
|
||||
p.counter -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p.state && p.counter == BUTTON_COUNTER_TRIGGER_ON) {
|
||||
p.state = true;
|
||||
p.trigger = true;
|
||||
}
|
||||
|
||||
if (p.state && p.counter == BUTTON_COUNTER_TRIGGER_OFF) {
|
||||
p.state = false;
|
||||
}
|
||||
|
||||
if (p.trigger) {
|
||||
switch (p.mode) {
|
||||
case BUTTON_MODE_N64_IRQ:
|
||||
|
@ -16,7 +16,9 @@ typedef enum {
|
||||
bool button_get_state (void);
|
||||
bool button_set_mode (button_mode_t mode);
|
||||
button_mode_t button_get_mode (void);
|
||||
|
||||
void button_init (void);
|
||||
|
||||
void button_process (void);
|
||||
|
||||
|
||||
|
@ -373,11 +373,11 @@ bool cfg_update (uint32_t *args) {
|
||||
}
|
||||
|
||||
bool cfg_query_setting (uint32_t *args) {
|
||||
rtc_settings_t settings = (*rtc_get_settings());
|
||||
rtc_settings_t *settings = rtc_get_settings();
|
||||
|
||||
switch (args[0]) {
|
||||
case SETTING_ID_LED_ENABLE:
|
||||
args[1] = settings.led_enabled;
|
||||
args[1] = settings->led_enabled;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
@ -387,17 +387,17 @@ bool cfg_query_setting (uint32_t *args) {
|
||||
}
|
||||
|
||||
bool cfg_update_setting (uint32_t *args) {
|
||||
rtc_settings_t settings = (*rtc_get_settings());
|
||||
rtc_settings_t *settings = rtc_get_settings();
|
||||
|
||||
switch (args[0]) {
|
||||
case SETTING_ID_LED_ENABLE:
|
||||
settings.led_enabled = args[1];
|
||||
settings->led_enabled = args[1];
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
rtc_set_settings(&settings);
|
||||
rtc_save_settings();
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -450,12 +450,14 @@ void cfg_reset_state (void) {
|
||||
p.boot_mode = BOOT_MODE_MENU;
|
||||
}
|
||||
|
||||
|
||||
void cfg_init (void) {
|
||||
fpga_reg_set(REG_CFG_SCR, CFG_SCR_BOOTLOADER_ENABLED);
|
||||
cfg_reset_state();
|
||||
p.usb_output_ready = true;
|
||||
}
|
||||
|
||||
|
||||
void cfg_process (void) {
|
||||
uint32_t reg;
|
||||
uint32_t args[2];
|
||||
|
@ -27,7 +27,9 @@ save_type_t cfg_get_save_type (void);
|
||||
void cfg_get_time (uint32_t *args);
|
||||
void cfg_set_time (uint32_t *args);
|
||||
void cfg_reset_state (void);
|
||||
|
||||
void cfg_init (void);
|
||||
|
||||
void cfg_process (void);
|
||||
|
||||
|
||||
|
@ -12,12 +12,7 @@ typedef enum {
|
||||
} cic_region_t;
|
||||
|
||||
|
||||
static bool cic_initialized = false;
|
||||
|
||||
|
||||
static void cic_irq_reset_falling (void) {
|
||||
led_clear_error(LED_ERROR_CIC);
|
||||
}
|
||||
static bool cic_error_active = false;
|
||||
|
||||
|
||||
void cic_reset_parameters (void) {
|
||||
@ -26,72 +21,70 @@ void cic_reset_parameters (void) {
|
||||
const uint8_t default_seed = 0x3F;
|
||||
const uint64_t default_checksum = 0xA536C0F1D859ULL;
|
||||
|
||||
uint32_t cic_config_0 = (default_seed << CIC_SEED_BIT) | ((default_checksum >> 32) & 0xFFFF);
|
||||
uint32_t cic_config_1 = (default_checksum & 0xFFFFFFFFUL);
|
||||
uint32_t cfg[2] = {
|
||||
(default_seed << CIC_SEED_BIT) | ((default_checksum >> 32) & 0xFFFF),
|
||||
(default_checksum & 0xFFFFFFFFUL)
|
||||
};
|
||||
|
||||
if (region == REGION_PAL) {
|
||||
cic_config_0 |= CIC_REGION;
|
||||
cfg[0] |= CIC_REGION;
|
||||
}
|
||||
|
||||
fpga_reg_set(REG_CIC_0, cic_config_0);
|
||||
fpga_reg_set(REG_CIC_1, cic_config_1);
|
||||
fpga_reg_set(REG_CIC_0, cfg[0]);
|
||||
fpga_reg_set(REG_CIC_1, cfg[1]);
|
||||
}
|
||||
|
||||
void cic_set_parameters (uint32_t *args) {
|
||||
uint32_t cic_config_0 = args[0] & (0x00FFFFFF);
|
||||
uint32_t cic_config_1 = args[1];
|
||||
uint32_t cfg[2] = {
|
||||
args[0] & (0x00FFFFFF),
|
||||
args[1]
|
||||
};
|
||||
|
||||
cic_config_0 |= fpga_reg_get(REG_CIC_0) & (CIC_64DD_MODE | CIC_REGION);
|
||||
cfg[0] |= fpga_reg_get(REG_CIC_0) & (CIC_64DD_MODE | CIC_REGION);
|
||||
|
||||
if (args[0] & (1 << 24)) {
|
||||
cic_config_0 |= CIC_DISABLED;
|
||||
cfg[0] |= CIC_DISABLED;
|
||||
}
|
||||
|
||||
fpga_reg_set(REG_CIC_0, cic_config_0);
|
||||
fpga_reg_set(REG_CIC_1, cic_config_1);
|
||||
fpga_reg_set(REG_CIC_0, cfg[0]);
|
||||
fpga_reg_set(REG_CIC_1, cfg[1]);
|
||||
}
|
||||
|
||||
void cic_set_dd_mode (bool enabled) {
|
||||
uint32_t cic_config_0 = fpga_reg_get(REG_CIC_0);
|
||||
uint32_t cfg = fpga_reg_get(REG_CIC_0);
|
||||
|
||||
if (enabled) {
|
||||
cic_config_0 |= CIC_64DD_MODE;
|
||||
cfg |= CIC_64DD_MODE;
|
||||
} else {
|
||||
cic_config_0 &= ~(CIC_64DD_MODE);
|
||||
cfg &= ~(CIC_64DD_MODE);
|
||||
}
|
||||
|
||||
fpga_reg_set(REG_CIC_0, cic_config_0);
|
||||
fpga_reg_set(REG_CIC_0, cfg);
|
||||
}
|
||||
|
||||
|
||||
void cic_init (void) {
|
||||
hw_gpio_irq_setup(GPIO_ID_N64_RESET, GPIO_IRQ_FALLING, cic_irq_reset_falling);
|
||||
cic_reset_parameters();
|
||||
}
|
||||
|
||||
|
||||
void cic_process (void) {
|
||||
if (!cic_initialized) {
|
||||
if (rtc_is_initialized()) {
|
||||
cic_reset_parameters();
|
||||
cic_initialized = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
uint32_t cfg = fpga_reg_get(REG_CIC_0);
|
||||
|
||||
uint32_t cic_config_0 = fpga_reg_get(REG_CIC_0);
|
||||
if (cfg & CIC_INVALID_REGION_DETECTED) {
|
||||
cfg ^= CIC_REGION;
|
||||
cfg |= CIC_INVALID_REGION_RESET;
|
||||
fpga_reg_set(REG_CIC_0, cfg);
|
||||
|
||||
if (cic_config_0 & CIC_INVALID_REGION_DETECTED) {
|
||||
cic_config_0 ^= CIC_REGION;
|
||||
cic_config_0 |= CIC_INVALID_REGION_RESET;
|
||||
fpga_reg_set(REG_CIC_0, cic_config_0);
|
||||
|
||||
if (cic_config_0 & CIC_REGION) {
|
||||
rtc_set_region(REGION_PAL);
|
||||
} else {
|
||||
rtc_set_region(REGION_NTSC);
|
||||
}
|
||||
cic_region_t region = (cfg & CIC_REGION) ? REGION_PAL : REGION_NTSC;
|
||||
rtc_set_region(region);
|
||||
|
||||
cic_error_active = true;
|
||||
led_blink_error(LED_ERROR_CIC);
|
||||
}
|
||||
|
||||
if (cic_error_active && (!hw_gpio_get(GPIO_ID_N64_RESET))) {
|
||||
cic_error_active = false;
|
||||
led_clear_error(LED_ERROR_CIC);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,9 @@
|
||||
void cic_reset_parameters (void);
|
||||
void cic_set_parameters (uint32_t *args);
|
||||
void cic_set_dd_mode (bool enabled);
|
||||
|
||||
void cic_init (void);
|
||||
|
||||
void cic_process (void);
|
||||
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
#include <stdint.h>
|
||||
#include "dd.h"
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "led.h"
|
||||
#include "rtc.h"
|
||||
#include "sd.h"
|
||||
#include "timer.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
@ -20,7 +19,7 @@
|
||||
#define DD_DRIVE_ID_DEVELOPMENT (0x0004)
|
||||
#define DD_VERSION_RETAIL (0x0114)
|
||||
|
||||
#define DD_SPIN_UP_TIME (2000)
|
||||
#define DD_SPIN_UP_TIME_MS (2000)
|
||||
|
||||
#define DD_THB_UNMAPPED (0xFFFFFFFF)
|
||||
#define DD_THB_WRITABLE_FLAG (1 << 31)
|
||||
@ -75,7 +74,6 @@ struct process {
|
||||
rtc_time_t time;
|
||||
bool disk_spinning;
|
||||
bool cmd_response_delayed;
|
||||
bool cmd_response_ready;
|
||||
bool bm_running;
|
||||
bool transfer_mode;
|
||||
bool full_track_transfer;
|
||||
@ -178,10 +176,6 @@ static bool dd_block_write_request (void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dd_set_cmd_response_ready (void) {
|
||||
p.cmd_response_ready = true;
|
||||
}
|
||||
|
||||
|
||||
void dd_set_block_ready (bool valid) {
|
||||
p.block_ready = true;
|
||||
@ -284,13 +278,13 @@ void dd_handle_button (void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dd_init (void) {
|
||||
fpga_reg_set(REG_DD_SCR, 0);
|
||||
fpga_reg_set(REG_DD_HEAD_TRACK, 0);
|
||||
fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL);
|
||||
p.state = STATE_IDLE;
|
||||
p.cmd_response_delayed = false;
|
||||
p.cmd_response_ready = false;
|
||||
p.disk_spinning = false;
|
||||
p.bm_running = false;
|
||||
p.drive_type = DD_DRIVE_TYPE_RETAIL;
|
||||
@ -299,6 +293,7 @@ void dd_init (void) {
|
||||
dd_set_disk_mapping(0, 0);
|
||||
}
|
||||
|
||||
|
||||
void dd_process (void) {
|
||||
uint32_t starting_scr = fpga_reg_get(REG_DD_SCR);
|
||||
uint32_t scr = starting_scr;
|
||||
@ -306,7 +301,6 @@ void dd_process (void) {
|
||||
if (scr & DD_SCR_HARD_RESET) {
|
||||
p.state = STATE_IDLE;
|
||||
p.cmd_response_delayed = false;
|
||||
p.cmd_response_ready = false;
|
||||
p.disk_spinning = false;
|
||||
p.bm_running = false;
|
||||
p.head_track = 0;
|
||||
@ -319,19 +313,16 @@ void dd_process (void) {
|
||||
uint16_t data = cmd_data & 0xFFFF;
|
||||
|
||||
if (p.cmd_response_delayed) {
|
||||
if (p.cmd_response_ready) {
|
||||
if (timer_countdown_elapsed(TIMER_ID_DD)) {
|
||||
p.cmd_response_delayed = false;
|
||||
fpga_reg_set(REG_DD_HEAD_TRACK, DD_HEAD_TRACK_INDEX_LOCK | data);
|
||||
scr |= DD_SCR_CMD_READY;
|
||||
}
|
||||
} else if ((cmd == DD_CMD_SEEK_READ) || (cmd == DD_CMD_SEEK_WRITE)) {
|
||||
p.cmd_response_delayed = true;
|
||||
p.cmd_response_ready = false;
|
||||
if (!p.disk_spinning) {
|
||||
p.disk_spinning = true;
|
||||
hw_tim_setup(TIM_ID_DD, DD_SPIN_UP_TIME, dd_set_cmd_response_ready);
|
||||
} else {
|
||||
p.cmd_response_ready = true;
|
||||
timer_countdown_start(TIMER_ID_DD, DD_SPIN_UP_TIME_MS);
|
||||
}
|
||||
fpga_reg_set(REG_DD_HEAD_TRACK, p.head_track & ~(DD_HEAD_TRACK_INDEX_LOCK));
|
||||
p.head_track = data & DD_HEAD_TRACK_MASK;
|
||||
|
@ -27,7 +27,9 @@ bool dd_get_sd_mode (void);
|
||||
void dd_set_sd_mode (bool value);
|
||||
void dd_set_disk_mapping (uint32_t address, uint32_t length);
|
||||
void dd_handle_button (void);
|
||||
|
||||
void dd_init (void);
|
||||
|
||||
void dd_process (void);
|
||||
|
||||
|
||||
|
@ -40,10 +40,11 @@ void flashram_init (void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void flashram_process (void) {
|
||||
uint32_t scr = fpga_reg_get(REG_FLASHRAM_SCR);
|
||||
enum operation op = flashram_operation_type(scr);
|
||||
uint8_t read_buffer[FLASHRAM_PAGE_SIZE];
|
||||
uint8_t page_buffer[FLASHRAM_PAGE_SIZE];
|
||||
uint8_t write_buffer[FLASHRAM_PAGE_SIZE];
|
||||
uint32_t address = FLASHRAM_ADDRESS;
|
||||
uint32_t erase_size = (op == OP_ERASE_SECTOR) ? FLASHRAM_SECTOR_SIZE : FLASHRAM_SIZE;
|
||||
@ -63,10 +64,10 @@ void flashram_process (void) {
|
||||
break;
|
||||
|
||||
case OP_WRITE_PAGE:
|
||||
fpga_mem_read(FLASHRAM_BUFFER_ADDRESS, FLASHRAM_PAGE_SIZE, read_buffer);
|
||||
fpga_mem_read(FLASHRAM_BUFFER_ADDRESS, FLASHRAM_PAGE_SIZE, page_buffer);
|
||||
fpga_mem_read(address, FLASHRAM_PAGE_SIZE, write_buffer);
|
||||
for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) {
|
||||
write_buffer[i] &= read_buffer[i];
|
||||
write_buffer[i] &= page_buffer[i];
|
||||
}
|
||||
fpga_mem_write(address, FLASHRAM_PAGE_SIZE, write_buffer);
|
||||
fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
void flashram_init (void);
|
||||
|
||||
void flashram_process (void);
|
||||
|
||||
|
||||
|
@ -7,8 +7,8 @@ uint8_t fpga_id_get (void) {
|
||||
uint8_t id;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&id, 1, SPI_RX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_rx(&id, 1);
|
||||
hw_spi_stop();
|
||||
|
||||
return id;
|
||||
@ -19,9 +19,9 @@ uint32_t fpga_reg_get (fpga_reg_t reg) {
|
||||
uint32_t value;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(®, 1, SPI_TX);
|
||||
hw_spi_trx((uint8_t *) (&value), 4, SPI_RX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_tx(®, 1);
|
||||
hw_spi_rx((uint8_t *) (&value), 4);
|
||||
hw_spi_stop();
|
||||
|
||||
return value;
|
||||
@ -31,9 +31,9 @@ void fpga_reg_set (fpga_reg_t reg, uint32_t value) {
|
||||
fpga_cmd_t cmd = CMD_REG_WRITE;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(®, 1, SPI_TX);
|
||||
hw_spi_trx((uint8_t *) (&value), 4, SPI_TX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_tx(®, 1);
|
||||
hw_spi_tx((uint8_t *) (&value), 4);
|
||||
hw_spi_stop();
|
||||
}
|
||||
|
||||
@ -50,9 +50,9 @@ void fpga_mem_read (uint32_t address, size_t length, uint8_t *buffer) {
|
||||
while (fpga_reg_get(REG_MEM_SCR) & MEM_SCR_BUSY);
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&buffer_address, 1, SPI_TX);
|
||||
hw_spi_trx(buffer, length, SPI_RX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_tx(&buffer_address, 1);
|
||||
hw_spi_rx(buffer, length);
|
||||
hw_spi_stop();
|
||||
}
|
||||
|
||||
@ -65,9 +65,9 @@ void fpga_mem_write (uint32_t address, size_t length, uint8_t *buffer) {
|
||||
}
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&buffer_address, 1, SPI_TX);
|
||||
hw_spi_trx(buffer, length, SPI_TX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_tx(&buffer_address, 1);
|
||||
hw_spi_tx(buffer, length);
|
||||
hw_spi_stop();
|
||||
|
||||
fpga_reg_set(REG_MEM_ADDRESS, address);
|
||||
@ -95,8 +95,8 @@ uint8_t fpga_usb_status_get (void) {
|
||||
uint8_t status;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&status, 1, SPI_RX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_rx(&status, 1);
|
||||
hw_spi_stop();
|
||||
|
||||
return status;
|
||||
@ -107,8 +107,8 @@ uint8_t fpga_usb_pop (void) {
|
||||
uint8_t data;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&data, 1, SPI_RX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_rx(&data, 1);
|
||||
hw_spi_stop();
|
||||
|
||||
return data;
|
||||
@ -118,7 +118,7 @@ void fpga_usb_push (uint8_t data) {
|
||||
fpga_cmd_t cmd = CMD_USB_WRITE;
|
||||
|
||||
hw_spi_start();
|
||||
hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX);
|
||||
hw_spi_trx(&data, 1, SPI_TX);
|
||||
hw_spi_tx((uint8_t *) (&cmd), 1);
|
||||
hw_spi_tx(&data, 1);
|
||||
hw_spi_stop();
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
#include "button.h"
|
||||
#include "cfg.h"
|
||||
#include "cic.h"
|
||||
#include "dd.h"
|
||||
#include "flashram.h"
|
||||
#include "fpga.h"
|
||||
#include "isv.h"
|
||||
#include "rtc.h"
|
||||
#include "sd.h"
|
||||
#include "usb.h"
|
||||
#include "writeback.h"
|
||||
|
||||
|
||||
void gvr_task (void) {
|
||||
while (fpga_id_get() != FPGA_ID);
|
||||
|
||||
button_init();
|
||||
cfg_init();
|
||||
cic_init();
|
||||
dd_init();
|
||||
flashram_init();
|
||||
isv_init();
|
||||
sd_init();
|
||||
usb_init();
|
||||
writeback_init();
|
||||
|
||||
while (1) {
|
||||
button_process();
|
||||
cfg_process();
|
||||
cic_process();
|
||||
dd_process();
|
||||
flashram_process();
|
||||
isv_process();
|
||||
rtc_process();
|
||||
sd_process();
|
||||
usb_process();
|
||||
writeback_process();
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef GVR_H__
|
||||
#define GVR_H__
|
||||
|
||||
|
||||
void gvr_task (void);
|
||||
|
||||
|
||||
#endif
|
@ -3,7 +3,70 @@
|
||||
#include "hw.h"
|
||||
|
||||
|
||||
#define UART_BAUD (115200)
|
||||
#define CPU_FREQ (64000000UL)
|
||||
#define UART_BAUD (115200UL)
|
||||
|
||||
|
||||
void hw_set_vector_table (uint32_t offset) {
|
||||
SCB->VTOR = (__IOM uint32_t) (offset);
|
||||
}
|
||||
|
||||
|
||||
void hw_enter_critical (void) {
|
||||
__disable_irq();
|
||||
}
|
||||
|
||||
void hw_exit_critical (void) {
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
static void hw_clock_init (void) {
|
||||
FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos));
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos));
|
||||
|
||||
RCC->PLLCFGR = (
|
||||
((2 - 1) << RCC_PLLCFGR_PLLR_Pos)
|
||||
| RCC_PLLCFGR_PLLREN
|
||||
| (16 << RCC_PLLCFGR_PLLN_Pos)
|
||||
| ((2 - 1) << RCC_PLLCFGR_PLLM_Pos)
|
||||
| RCC_PLLCFGR_PLLSRC_HSI
|
||||
);
|
||||
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
while ((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY);
|
||||
|
||||
RCC->CFGR = RCC_CFGR_SW_1;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1);
|
||||
}
|
||||
|
||||
|
||||
static void hw_delay_init (void) {
|
||||
SysTick->LOAD = (((CPU_FREQ / 1000)) - 1);
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk);
|
||||
}
|
||||
|
||||
void hw_delay_ms (uint32_t ms) {
|
||||
SysTick->VAL = 0;
|
||||
for (uint32_t i = 0; i < ms; i++) {
|
||||
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void (*systick_callback) (void) = NULL;
|
||||
|
||||
void hw_systick_config (uint32_t period_ms, void (*callback) (void)) {
|
||||
SysTick_Config((CPU_FREQ / 1000) * period_ms);
|
||||
systick_callback = callback;
|
||||
}
|
||||
|
||||
void SysTick_Handler (void) {
|
||||
if (systick_callback) {
|
||||
systick_callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
@ -42,22 +105,7 @@ typedef enum {
|
||||
GPIO_AF_7 = 0x07
|
||||
} gpio_af_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
void (*volatile falling)(void);
|
||||
void (*volatile rising)(void);
|
||||
} gpio_irq_callback_t;
|
||||
|
||||
|
||||
static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB, 0, 0, 0, 0, 0, 0 };
|
||||
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, TIM1 };
|
||||
static void (*volatile tim_callbacks[5])(void);
|
||||
|
||||
|
||||
static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_ospeed_t ospeed, gpio_pupd_t pupd, gpio_af_t af, int value) {
|
||||
GPIO_TypeDef tmp;
|
||||
@ -65,6 +113,8 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp
|
||||
uint8_t pin = (id & 0x0F);
|
||||
uint8_t afr = ((pin < 8) ? 0 : 1);
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;
|
||||
|
||||
tmp.MODER = (gpio->MODER & ~(GPIO_MODER_MODE0_Msk << (pin * 2)));
|
||||
tmp.OTYPER = (gpio->OTYPER & ~(GPIO_OTYPER_OT0_Msk << pin));
|
||||
tmp.OSPEEDR = (gpio->OSPEEDR & ~(GPIO_OSPEEDR_OSPEED0_Msk << (pin * 2)));
|
||||
@ -80,22 +130,6 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp
|
||||
gpio->MODER = (tmp.MODER | (mode << (pin * 2)));
|
||||
}
|
||||
|
||||
void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void)) {
|
||||
uint8_t port = ((id >> 4) & 0x07);
|
||||
uint8_t pin = (id & 0x0F);
|
||||
__disable_irq();
|
||||
if (irq == GPIO_IRQ_FALLING) {
|
||||
EXTI->FTSR1 |= (EXTI_FTSR1_FT0 << pin);
|
||||
gpio_irq_callbacks[pin].falling = callback;
|
||||
} else {
|
||||
EXTI->RTSR1 |= (EXTI_RTSR1_RT0 << pin);
|
||||
gpio_irq_callbacks[pin].rising = callback;
|
||||
}
|
||||
EXTI->EXTICR[pin / 4] |= (port << (8 * (pin % 4)));
|
||||
EXTI->IMR1 |= (EXTI_IMR1_IM0 << pin);
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
uint32_t hw_gpio_get (gpio_id_t id) {
|
||||
GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07]));
|
||||
uint8_t pin = (id & 0x0F);
|
||||
@ -114,6 +148,20 @@ void hw_gpio_reset (gpio_id_t id) {
|
||||
gpio->BSRR = (GPIO_BSRR_BR0 << pin);
|
||||
}
|
||||
|
||||
|
||||
static void hw_uart_init (void) {
|
||||
RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN);
|
||||
|
||||
SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP);
|
||||
|
||||
hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0);
|
||||
hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0);
|
||||
|
||||
USART1->BRR = CPU_FREQ / UART_BAUD;
|
||||
USART1->RQR = USART_RQR_TXFRQ | USART_RQR_RXFRQ;
|
||||
USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
}
|
||||
|
||||
void hw_uart_read (uint8_t *data, int length) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
while (!(USART1->ISR & USART_ISR_RXNE_RXFNE));
|
||||
@ -128,10 +176,42 @@ void hw_uart_write (uint8_t *data, int length) {
|
||||
}
|
||||
}
|
||||
|
||||
void hw_uart_wait_busy (void) {
|
||||
void hw_uart_write_wait_busy (void) {
|
||||
while (!(USART1->ISR & USART_ISR_TC));
|
||||
}
|
||||
|
||||
|
||||
static void hw_spi_init (void) {
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||
RCC->APBENR2 |= RCC_APBENR2_SPI1EN;
|
||||
|
||||
DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos);
|
||||
DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos);
|
||||
|
||||
DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR);
|
||||
DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR);
|
||||
|
||||
SPI1->CR2 = (
|
||||
SPI_CR2_FRXTH |
|
||||
(8 - 1) << SPI_CR2_DS_Pos |
|
||||
SPI_CR2_TXDMAEN |
|
||||
SPI_CR2_RXDMAEN
|
||||
);
|
||||
SPI1->CR1 = (
|
||||
SPI_CR1_SSM |
|
||||
SPI_CR1_SSI |
|
||||
SPI_CR1_BR_1 |
|
||||
SPI_CR1_SPE |
|
||||
SPI_CR1_MSTR |
|
||||
SPI_CR1_CPHA
|
||||
);
|
||||
|
||||
hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1);
|
||||
hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
||||
}
|
||||
|
||||
void hw_spi_start (void) {
|
||||
hw_gpio_reset(GPIO_ID_SPI_CS);
|
||||
}
|
||||
@ -141,25 +221,17 @@ void hw_spi_stop (void) {
|
||||
hw_gpio_set(GPIO_ID_SPI_CS);
|
||||
}
|
||||
|
||||
void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction) {
|
||||
volatile uint8_t dummy __attribute__((unused));
|
||||
void hw_spi_rx (uint8_t *data, int length) {
|
||||
volatile uint8_t dummy = 0x00;
|
||||
|
||||
DMA1_Channel1->CNDTR = length;
|
||||
DMA1_Channel2->CNDTR = length;
|
||||
|
||||
if (direction == SPI_TX) {
|
||||
DMA1_Channel1->CMAR = (uint32_t) (&dummy);
|
||||
DMA1_Channel1->CCR = DMA_CCR_EN;
|
||||
DMA1_Channel1->CMAR = (uint32_t) (data);
|
||||
DMA1_Channel1->CCR = (DMA_CCR_MINC | DMA_CCR_EN);
|
||||
|
||||
DMA1_Channel2->CMAR = (uint32_t) (data);
|
||||
DMA1_Channel2->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN);
|
||||
} else {
|
||||
DMA1_Channel1->CMAR = (uint32_t) (data);
|
||||
DMA1_Channel1->CCR = (DMA_CCR_MINC | DMA_CCR_EN);
|
||||
|
||||
DMA1_Channel2->CMAR = (uint32_t) (&dummy);
|
||||
DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_EN);
|
||||
}
|
||||
DMA1_Channel2->CMAR = (uint32_t) (&dummy);
|
||||
DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_EN);
|
||||
|
||||
while (DMA1_Channel1->CNDTR || DMA1_Channel2->CNDTR);
|
||||
|
||||
@ -167,57 +239,69 @@ void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction) {
|
||||
DMA1_Channel2->CCR = 0;
|
||||
}
|
||||
|
||||
void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) {
|
||||
i2c_data_rxptr = data;
|
||||
i2c_callback = callback;
|
||||
I2C1->TXDR = address;
|
||||
i2c_next_cr2 = (
|
||||
I2C_CR2_AUTOEND |
|
||||
(length << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_START |
|
||||
I2C_CR2_RD_WRN |
|
||||
(i2c_address << I2C_CR2_SADD_Pos)
|
||||
);
|
||||
I2C1->CR2 = (
|
||||
(1 << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_START |
|
||||
(i2c_address << I2C_CR2_SADD_Pos)
|
||||
);
|
||||
void hw_spi_tx (uint8_t *data, int length) {
|
||||
volatile uint8_t dummy __attribute__((unused));
|
||||
|
||||
DMA1_Channel1->CNDTR = length;
|
||||
DMA1_Channel2->CNDTR = length;
|
||||
|
||||
DMA1_Channel1->CMAR = (uint32_t) (&dummy);
|
||||
DMA1_Channel1->CCR = DMA_CCR_EN;
|
||||
|
||||
DMA1_Channel2->CMAR = (uint32_t) (data);
|
||||
DMA1_Channel2->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN);
|
||||
|
||||
while (DMA1_Channel1->CNDTR || DMA1_Channel2->CNDTR);
|
||||
|
||||
DMA1_Channel1->CCR = 0;
|
||||
DMA1_Channel2->CCR = 0;
|
||||
}
|
||||
|
||||
void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) {
|
||||
i2c_data_txptr = data;
|
||||
i2c_callback = callback;
|
||||
I2C1->TXDR = address;
|
||||
I2C1->CR2 = (
|
||||
I2C_CR2_AUTOEND |
|
||||
((length + 1) << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_START |
|
||||
(i2c_address << I2C_CR2_SADD_Pos)
|
||||
);
|
||||
|
||||
static void hw_i2c_init (void) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_I2C1EN;
|
||||
|
||||
I2C1->CR1 &= ~(I2C_CR1_PE);
|
||||
I2C1->TIMINGR = 0x10901032UL;
|
||||
I2C1->CR1 |= I2C_CR1_PE;
|
||||
|
||||
hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0);
|
||||
hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0);
|
||||
}
|
||||
|
||||
uint32_t hw_i2c_get_error (void) {
|
||||
return (I2C1->ISR & I2C_ISR_NACKF);
|
||||
}
|
||||
|
||||
void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) {
|
||||
i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) {
|
||||
while (I2C1->ISR & I2C_ISR_BUSY);
|
||||
|
||||
if (tx_length > 0) {
|
||||
I2C1->ICR = I2C_ICR_NACKCF;
|
||||
I2C1->CR2 = (
|
||||
((rx_length == 0) ? I2C_CR2_AUTOEND : 0) |
|
||||
((rx_length > 0) ? 0 : I2C_CR2_AUTOEND) |
|
||||
(tx_length << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_START |
|
||||
(i2c_address << I2C_CR2_SADD_Pos)
|
||||
(address << I2C_CR2_SADD_Pos)
|
||||
);
|
||||
for (int i = 0; i < tx_length; i++) {
|
||||
while (!(I2C1->ISR & I2C_ISR_TXIS));
|
||||
I2C1->TXDR = *tx_data++;
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
|
||||
uint8_t left = tx_length;
|
||||
|
||||
while (left > 0) {
|
||||
uint32_t isr = I2C1->ISR;
|
||||
|
||||
if (isr & I2C_ISR_TXIS) {
|
||||
I2C1->TXDR = *tx_data++;
|
||||
left -= 1;
|
||||
}
|
||||
|
||||
if (isr & I2C_ISR_NACKF) {
|
||||
return I2C_ERR_NACK;
|
||||
}
|
||||
}
|
||||
if (!(I2C1->CR2 & I2C_CR2_AUTOEND)) {
|
||||
while (!(I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_TC)));
|
||||
|
||||
if (rx_length == 0) {
|
||||
return I2C_OK;
|
||||
}
|
||||
|
||||
if (left == 0) {
|
||||
while (!(I2C1->ISR & I2C_ISR_TC));
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,102 +309,31 @@ void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8
|
||||
I2C1->CR2 = (
|
||||
I2C_CR2_AUTOEND |
|
||||
(rx_length << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_START |
|
||||
I2C_CR2_RD_WRN |
|
||||
(i2c_address << I2C_CR2_SADD_Pos)
|
||||
(address << I2C_CR2_SADD_Pos)
|
||||
);
|
||||
for (int i = 0; i < rx_length; i++) {
|
||||
while (!(I2C1->ISR & I2C_ISR_RXNE));
|
||||
*rx_data++ = I2C1->RXDR;
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
|
||||
uint8_t left = rx_length;
|
||||
|
||||
while (left > 0) {
|
||||
uint32_t isr = I2C1->ISR;
|
||||
|
||||
if (isr & I2C_ISR_RXNE) {
|
||||
*rx_data++ = I2C1->RXDR;
|
||||
left -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((tx_length > 0) || (rx_length > 0)) {
|
||||
while (!(I2C1->ISR & I2C_ISR_STOPF));
|
||||
}
|
||||
return I2C_OK;
|
||||
}
|
||||
|
||||
void hw_i2c_disable_irq (void) {
|
||||
NVIC_DisableIRQ(I2C1_IRQn);
|
||||
}
|
||||
|
||||
void hw_i2c_enable_irq (void) {
|
||||
NVIC_EnableIRQ(I2C1_IRQn);
|
||||
}
|
||||
static void hw_crc32_init (void) {
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
|
||||
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);
|
||||
tim->ARR = delay;
|
||||
tim->DIER = TIM_DIER_UIE;
|
||||
tim->EGR = TIM_EGR_UG;
|
||||
tim->SR = 0;
|
||||
tim->CR1 |= TIM_CR1_CEN;
|
||||
tim_callbacks[id] = callback;
|
||||
}
|
||||
|
||||
void hw_tim_stop (tim_id_t id) {
|
||||
TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id]));
|
||||
tim->CR1 &= ~(TIM_CR1_CEN);
|
||||
tim_callbacks[id] = 0;
|
||||
}
|
||||
|
||||
void hw_tim_disable_irq (tim_id_t id) {
|
||||
switch (id) {
|
||||
case TIM_ID_CIC:
|
||||
NVIC_DisableIRQ(TIM14_IRQn);
|
||||
break;
|
||||
case TIM_ID_RTC:
|
||||
NVIC_DisableIRQ(TIM16_IRQn);
|
||||
break;
|
||||
case TIM_ID_SD:
|
||||
NVIC_DisableIRQ(TIM17_IRQn);
|
||||
break;
|
||||
case TIM_ID_DD:
|
||||
NVIC_DisableIRQ(TIM3_IRQn);
|
||||
break;
|
||||
case TIM_ID_LED:
|
||||
NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hw_tim_enable_irq (tim_id_t id) {
|
||||
switch (id) {
|
||||
case TIM_ID_CIC:
|
||||
NVIC_EnableIRQ(TIM14_IRQn);
|
||||
break;
|
||||
case TIM_ID_RTC:
|
||||
NVIC_EnableIRQ(TIM16_IRQn);
|
||||
break;
|
||||
case TIM_ID_SD:
|
||||
NVIC_EnableIRQ(TIM17_IRQn);
|
||||
break;
|
||||
case TIM_ID_DD:
|
||||
NVIC_EnableIRQ(TIM3_IRQn);
|
||||
break;
|
||||
case TIM_ID_LED:
|
||||
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hw_delay_ms (uint32_t ms) {
|
||||
SysTick->VAL = 0;
|
||||
for (uint32_t i = 0; i < ms; i++) {
|
||||
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
|
||||
}
|
||||
CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0);
|
||||
}
|
||||
|
||||
void hw_crc32_reset (void) {
|
||||
@ -334,10 +347,15 @@ uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length) {
|
||||
return (CRC->DR ^ 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
uint32_t hw_flash_size (void) {
|
||||
return FLASH_SIZE;
|
||||
}
|
||||
|
||||
hw_flash_t hw_flash_read (uint32_t offset) {
|
||||
return *(uint64_t *) (FLASH_BASE + offset);
|
||||
}
|
||||
|
||||
static void hw_flash_unlock (void) {
|
||||
while (FLASH->SR & FLASH_SR_BSY1);
|
||||
if (FLASH->CR & FLASH_CR_LOCK) {
|
||||
@ -363,9 +381,6 @@ void hw_flash_program (uint32_t offset, hw_flash_t value) {
|
||||
FLASH->CR &= ~(FLASH_CR_PG);
|
||||
}
|
||||
|
||||
hw_flash_t hw_flash_read (uint32_t offset) {
|
||||
return *(uint64_t *) (FLASH_BASE + offset);
|
||||
}
|
||||
|
||||
void hw_reset (loader_parameters_t *parameters) {
|
||||
if (parameters != NULL) {
|
||||
@ -382,6 +397,7 @@ void hw_reset (loader_parameters_t *parameters) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
|
||||
void hw_loader_get_parameters (loader_parameters_t *parameters) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN;
|
||||
parameters->magic = TAMP->BKP0R;
|
||||
@ -399,280 +415,44 @@ void hw_loader_get_parameters (loader_parameters_t *parameters) {
|
||||
RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN);
|
||||
}
|
||||
|
||||
static void hw_init_mcu (void) {
|
||||
FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos));
|
||||
while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos));
|
||||
|
||||
RCC->PLLCFGR = (
|
||||
((2 - 1) << RCC_PLLCFGR_PLLR_Pos)
|
||||
| RCC_PLLCFGR_PLLREN
|
||||
| (16 << RCC_PLLCFGR_PLLN_Pos)
|
||||
| ((2 - 1) << RCC_PLLCFGR_PLLM_Pos)
|
||||
| RCC_PLLCFGR_PLLSRC_HSI
|
||||
);
|
||||
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
while ((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY);
|
||||
|
||||
RCC->CFGR = RCC_CFGR_SW_1;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1);
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN;
|
||||
|
||||
SysTick->LOAD = (((64000000 / 1000)) - 1);
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk);
|
||||
|
||||
static void hw_led_init (void) {
|
||||
hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0);
|
||||
}
|
||||
|
||||
static void hw_init_spi (void) {
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||
RCC->APBENR2 |= RCC_APBENR2_SPI1EN;
|
||||
|
||||
DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos);
|
||||
DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos);
|
||||
|
||||
DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR);
|
||||
DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR);
|
||||
|
||||
SPI1->CR2 = (
|
||||
SPI_CR2_FRXTH |
|
||||
(8 - 1) << SPI_CR2_DS_Pos |
|
||||
SPI_CR2_TXDMAEN |
|
||||
SPI_CR2_RXDMAEN
|
||||
);
|
||||
SPI1->CR1 = (
|
||||
SPI_CR1_SSM |
|
||||
SPI_CR1_SSI |
|
||||
SPI_CR1_BR_1 |
|
||||
SPI_CR1_SPE |
|
||||
SPI_CR1_MSTR |
|
||||
SPI_CR1_CPHA
|
||||
);
|
||||
|
||||
hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1);
|
||||
hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0);
|
||||
}
|
||||
|
||||
static void hw_init_i2c (void) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_I2C1EN;
|
||||
|
||||
I2C1->TIMINGR = 0x80821B20UL;
|
||||
I2C1->CR1 |= (I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE | I2C_CR1_PE);
|
||||
|
||||
hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0);
|
||||
hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0);
|
||||
}
|
||||
|
||||
static void hw_init_uart (void) {
|
||||
RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN);
|
||||
|
||||
SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP);
|
||||
|
||||
hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0);
|
||||
hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0);
|
||||
|
||||
USART1->BRR = (64000000UL) / UART_BAUD;
|
||||
USART1->RQR = USART_RQR_TXFRQ | USART_RQR_RXFRQ;
|
||||
USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
}
|
||||
|
||||
static void hw_init_tim (void) {
|
||||
RCC->APBENR1 |= (
|
||||
RCC_APBENR1_DBGEN |
|
||||
RCC_APBENR1_TIM3EN
|
||||
);
|
||||
RCC->APBENR2 |= (
|
||||
RCC_APBENR2_TIM17EN |
|
||||
RCC_APBENR2_TIM16EN |
|
||||
RCC_APBENR2_TIM14EN |
|
||||
RCC_APBENR2_USART1EN |
|
||||
RCC_APBENR2_TIM1EN
|
||||
);
|
||||
|
||||
DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP;
|
||||
DBG->APBFZ2 |= (
|
||||
DBG_APB_FZ2_DBG_TIM17_STOP |
|
||||
DBG_APB_FZ2_DBG_TIM16_STOP |
|
||||
DBG_APB_FZ2_DBG_TIM14_STOP |
|
||||
DBG_APB_FZ2_DBG_TIM1_STOP
|
||||
);
|
||||
}
|
||||
|
||||
static void hw_init_crc (void) {
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
|
||||
CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0);
|
||||
}
|
||||
|
||||
static void hw_init_misc (void) {
|
||||
hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
static void hw_misc_init (void) {
|
||||
hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 1);
|
||||
hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||
}
|
||||
|
||||
void hw_set_vector_table (uint32_t offset) {
|
||||
SCB->VTOR = (__IOM uint32_t) (offset);
|
||||
}
|
||||
|
||||
void hw_init (void) {
|
||||
hw_init_mcu();
|
||||
hw_init_spi();
|
||||
hw_init_i2c();
|
||||
hw_init_uart();
|
||||
hw_init_tim();
|
||||
hw_init_crc();
|
||||
hw_init_misc();
|
||||
|
||||
NVIC_SetPriority(EXTI0_1_IRQn, 0);
|
||||
NVIC_SetPriority(EXTI2_3_IRQn, 0);
|
||||
NVIC_SetPriority(EXTI4_15_IRQn, 0);
|
||||
NVIC_SetPriority(I2C1_IRQn, 0);
|
||||
NVIC_SetPriority(TIM14_IRQn, 0);
|
||||
NVIC_SetPriority(TIM16_IRQn, 0);
|
||||
NVIC_SetPriority(TIM17_IRQn, 0);
|
||||
NVIC_SetPriority(TIM3_IRQn, 0);
|
||||
NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0);
|
||||
|
||||
NVIC_EnableIRQ(EXTI0_1_IRQn);
|
||||
NVIC_EnableIRQ(EXTI2_3_IRQn);
|
||||
NVIC_EnableIRQ(EXTI4_15_IRQn);
|
||||
NVIC_EnableIRQ(I2C1_IRQn);
|
||||
NVIC_EnableIRQ(TIM14_IRQn);
|
||||
NVIC_EnableIRQ(TIM16_IRQn);
|
||||
NVIC_EnableIRQ(TIM17_IRQn);
|
||||
NVIC_EnableIRQ(TIM3_IRQn);
|
||||
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
|
||||
void hw_primer_init (void) {
|
||||
hw_clock_init();
|
||||
hw_delay_init();
|
||||
hw_led_init();
|
||||
hw_uart_init();
|
||||
hw_spi_init();
|
||||
hw_i2c_init();
|
||||
hw_crc32_init();
|
||||
}
|
||||
|
||||
void hw_loader_init (void) {
|
||||
hw_init_mcu();
|
||||
hw_init_spi();
|
||||
hw_clock_init();
|
||||
hw_delay_init();
|
||||
hw_led_init();
|
||||
hw_spi_init();
|
||||
}
|
||||
|
||||
void hw_primer_init (void) {
|
||||
hw_init_mcu();
|
||||
hw_init_spi();
|
||||
hw_init_i2c();
|
||||
hw_init_uart();
|
||||
hw_init_crc();
|
||||
}
|
||||
|
||||
|
||||
void EXTI0_1_IRQHandler (void) {
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) {
|
||||
EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].falling) {
|
||||
gpio_irq_callbacks[i].falling();
|
||||
}
|
||||
}
|
||||
if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) {
|
||||
EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].rising) {
|
||||
gpio_irq_callbacks[i].rising();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI2_3_IRQHandler (void) {
|
||||
for (int i = 2; i <= 3; i++) {
|
||||
if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) {
|
||||
EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].falling) {
|
||||
gpio_irq_callbacks[i].falling();
|
||||
}
|
||||
}
|
||||
if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) {
|
||||
EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].rising) {
|
||||
gpio_irq_callbacks[i].rising();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI4_15_IRQHandler (void) {
|
||||
for (int i = 4; i <= 15; i++) {
|
||||
if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) {
|
||||
EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].falling) {
|
||||
gpio_irq_callbacks[i].falling();
|
||||
}
|
||||
}
|
||||
if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) {
|
||||
EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i);
|
||||
if (gpio_irq_callbacks[i].rising) {
|
||||
gpio_irq_callbacks[i].rising();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2C1_IRQHandler (void) {
|
||||
if (I2C1->ISR & I2C_ISR_TXIS) {
|
||||
I2C1->TXDR = *i2c_data_txptr++;
|
||||
}
|
||||
|
||||
if (I2C1->ISR & I2C_ISR_RXNE) {
|
||||
*i2c_data_rxptr++ = I2C1->RXDR;
|
||||
}
|
||||
|
||||
if (I2C1->ISR & I2C_ISR_TC) {
|
||||
I2C1->CR2 = i2c_next_cr2;
|
||||
}
|
||||
|
||||
if (I2C1->ISR & I2C_ISR_STOPF) {
|
||||
I2C1->ICR = I2C_ICR_STOPCF;
|
||||
if (i2c_callback) {
|
||||
i2c_callback();
|
||||
i2c_callback = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TIM14_IRQHandler (void) {
|
||||
TIM14->SR &= ~(TIM_SR_UIF);
|
||||
if (tim_callbacks[0]) {
|
||||
tim_callbacks[0]();
|
||||
tim_callbacks[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TIM16_IRQHandler (void) {
|
||||
TIM16->SR &= ~(TIM_SR_UIF);
|
||||
if (tim_callbacks[1]) {
|
||||
tim_callbacks[1]();
|
||||
tim_callbacks[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TIM17_IRQHandler (void) {
|
||||
TIM17->SR &= ~(TIM_SR_UIF);
|
||||
if (tim_callbacks[2]) {
|
||||
tim_callbacks[2]();
|
||||
tim_callbacks[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TIM3_IRQHandler (void) {
|
||||
TIM3->SR &= ~(TIM_SR_UIF);
|
||||
if (tim_callbacks[3]) {
|
||||
tim_callbacks[3]();
|
||||
tim_callbacks[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TIM1_BRK_UP_TRG_COM_IRQHandler (void) {
|
||||
TIM1->SR &= ~(TIM_SR_UIF);
|
||||
if (tim_callbacks[4]) {
|
||||
tim_callbacks[4]();
|
||||
tim_callbacks[4] = 0;
|
||||
}
|
||||
void hw_app_init (void) {
|
||||
hw_clock_init();
|
||||
hw_led_init();
|
||||
hw_uart_init();
|
||||
hw_spi_init();
|
||||
hw_i2c_init();
|
||||
hw_crc32_init();
|
||||
hw_misc_init();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#define GPIO_PORT_PIN(p, n) ((((p) & 0x07) << 4) | ((n) & 0x0F))
|
||||
|
||||
|
||||
typedef enum {
|
||||
GPIO_ID_N64_RESET = GPIO_PORT_PIN(0, 0),
|
||||
GPIO_ID_N64_CIC_CLK = GPIO_PORT_PIN(0, 1),
|
||||
@ -25,22 +26,9 @@ typedef enum {
|
||||
} gpio_id_t;
|
||||
|
||||
typedef enum {
|
||||
GPIO_IRQ_FALLING = 0b01,
|
||||
GPIO_IRQ_RISING = 0b10,
|
||||
} gpio_irq_t;
|
||||
|
||||
typedef enum {
|
||||
TIM_ID_CIC = 0,
|
||||
TIM_ID_RTC = 1,
|
||||
TIM_ID_SD = 2,
|
||||
TIM_ID_DD = 3,
|
||||
TIM_ID_LED = 4,
|
||||
} tim_id_t;
|
||||
|
||||
typedef enum {
|
||||
SPI_TX,
|
||||
SPI_RX,
|
||||
} spi_direction_t;
|
||||
I2C_OK,
|
||||
I2C_ERR_NACK,
|
||||
} i2c_err_t;
|
||||
|
||||
typedef uint64_t hw_flash_t;
|
||||
|
||||
@ -59,39 +47,45 @@ typedef struct {
|
||||
} loader_parameters_t;
|
||||
|
||||
|
||||
void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void));
|
||||
void hw_set_vector_table (uint32_t offset);
|
||||
|
||||
void hw_enter_critical (void);
|
||||
void hw_exit_critical (void);
|
||||
|
||||
void hw_delay_ms (uint32_t ms);
|
||||
|
||||
void hw_systick_config (uint32_t period_ms, void (*callback) (void));
|
||||
|
||||
uint32_t hw_gpio_get (gpio_id_t id);
|
||||
void hw_gpio_set (gpio_id_t id);
|
||||
void hw_gpio_reset (gpio_id_t id);
|
||||
|
||||
void hw_uart_read (uint8_t *data, int length);
|
||||
void hw_uart_write (uint8_t *data, int length);
|
||||
void hw_uart_wait_busy (void);
|
||||
void hw_uart_write_wait_busy (void);
|
||||
|
||||
void hw_spi_start (void);
|
||||
void hw_spi_stop (void);
|
||||
void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction);
|
||||
void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void));
|
||||
void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void));
|
||||
uint32_t hw_i2c_get_error (void);
|
||||
void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length);
|
||||
void hw_i2c_disable_irq (void);
|
||||
void hw_i2c_enable_irq (void);
|
||||
void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void));
|
||||
void hw_tim_stop (tim_id_t id);
|
||||
void hw_tim_disable_irq (tim_id_t id);
|
||||
void hw_tim_enable_irq (tim_id_t id);
|
||||
void hw_delay_ms (uint32_t ms);
|
||||
void hw_spi_rx (uint8_t *data, int length);
|
||||
void hw_spi_tx (uint8_t *data, int length);
|
||||
|
||||
i2c_err_t hw_i2c_trx (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length);
|
||||
|
||||
void hw_crc32_reset (void);
|
||||
uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length);
|
||||
|
||||
uint32_t hw_flash_size (void);
|
||||
hw_flash_t hw_flash_read (uint32_t offset);
|
||||
void hw_flash_erase (void);
|
||||
void hw_flash_program (uint32_t offset, hw_flash_t value);
|
||||
hw_flash_t hw_flash_read (uint32_t offset);
|
||||
|
||||
void hw_reset (loader_parameters_t *parameters);
|
||||
|
||||
void hw_loader_get_parameters (loader_parameters_t *parameters);
|
||||
void hw_set_vector_table (uint32_t offset);
|
||||
void hw_init (void);
|
||||
void hw_loader_init (void);
|
||||
|
||||
void hw_primer_init (void);
|
||||
void hw_loader_init (void);
|
||||
void hw_app_init (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -57,11 +57,13 @@ uint32_t isv_get_address (void) {
|
||||
return p.address;
|
||||
}
|
||||
|
||||
|
||||
void isv_init (void) {
|
||||
p.address = 0;
|
||||
p.ready = true;
|
||||
}
|
||||
|
||||
|
||||
void isv_process (void) {
|
||||
if ((p.address != 0) && p.ready) {
|
||||
if (isv_get_value(ISV_SETUP_TOKEN_ADDRESS) == ISV_TOKEN) {
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
bool isv_set_address (uint32_t address);
|
||||
uint32_t isv_get_address (void);
|
||||
|
||||
void isv_init (void);
|
||||
|
||||
void isv_process (void);
|
||||
|
||||
|
||||
|
@ -114,7 +114,7 @@ static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) {
|
||||
static void lcmxo2_reset_bus (void) {
|
||||
#ifdef LCMXO2_I2C
|
||||
uint8_t reset_data = 0;
|
||||
hw_i2c_raw(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), NULL, 0);
|
||||
hw_i2c_trx(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), NULL, 0);
|
||||
#else
|
||||
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE);
|
||||
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
||||
@ -131,7 +131,7 @@ static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint
|
||||
}
|
||||
packet_length += length;
|
||||
}
|
||||
hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
||||
hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
||||
#else
|
||||
uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF);
|
||||
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
||||
|
@ -1,148 +1,147 @@
|
||||
#include <stdbool.h>
|
||||
#include "hw.h"
|
||||
// #include "hw.h"
|
||||
#include "led.h"
|
||||
#include "rtc.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
// #include "rtc.h"
|
||||
// #include "timer.h"
|
||||
|
||||
|
||||
#define LED_MS_PER_TICK (10)
|
||||
#define LED_ERROR_TICKS_PERIOD (50)
|
||||
#define LED_ERROR_TICKS_ON (25)
|
||||
#define LED_ACT_TICKS_PERIOD (15)
|
||||
#define LED_ACT_TICKS_ON (6)
|
||||
// #define LED_MS_PER_TICK (10)
|
||||
// #define LED_ERROR_TICKS_PERIOD (50)
|
||||
// #define LED_ERROR_TICKS_ON (25)
|
||||
// #define LED_ACT_TICKS_PERIOD (15)
|
||||
// #define LED_ACT_TICKS_ON (6)
|
||||
|
||||
|
||||
static bool error_mode = false;
|
||||
static uint32_t error_timer = 0;
|
||||
static volatile bool cic_error = false;
|
||||
static volatile bool rtc_error = false;
|
||||
// static bool error_mode = false;
|
||||
// static uint32_t error_timer = 0;
|
||||
// static volatile bool cic_error = false;
|
||||
// static volatile bool rtc_error = false;
|
||||
|
||||
static uint32_t act_timer = 0;
|
||||
static uint32_t current_act_counter = 0;
|
||||
static volatile uint32_t next_act_counter = 0;
|
||||
// static uint32_t act_timer = 0;
|
||||
// static uint32_t current_act_counter = 0;
|
||||
// static volatile uint32_t next_act_counter = 0;
|
||||
|
||||
|
||||
static void led_task_resume (void) {
|
||||
task_set_ready(TASK_ID_LED);
|
||||
}
|
||||
// static void led_task_resume (void) {
|
||||
// task_set_ready(TASK_ID_LED);
|
||||
// }
|
||||
|
||||
static void led_set_state (bool state, bool force) {
|
||||
rtc_settings_t *settings = rtc_get_settings();
|
||||
if (settings->led_enabled || force) {
|
||||
if (state) {
|
||||
hw_gpio_set(GPIO_ID_LED);
|
||||
} else {
|
||||
hw_gpio_reset(GPIO_ID_LED);
|
||||
}
|
||||
} else {
|
||||
hw_gpio_reset(GPIO_ID_LED);
|
||||
}
|
||||
}
|
||||
// static void led_set_state (bool state, bool force) {
|
||||
// rtc_settings_t *settings = rtc_get_settings();
|
||||
// if (settings->led_enabled || force) {
|
||||
// if (state) {
|
||||
// hw_gpio_set(GPIO_ID_LED);
|
||||
// } else {
|
||||
// hw_gpio_reset(GPIO_ID_LED);
|
||||
// }
|
||||
// } else {
|
||||
// hw_gpio_reset(GPIO_ID_LED);
|
||||
// }
|
||||
// }
|
||||
|
||||
static void led_update_error_mode (void) {
|
||||
if (error_mode) {
|
||||
if (!(cic_error || rtc_error)) {
|
||||
led_set_state(false, true);
|
||||
error_mode = false;
|
||||
act_timer = 0;
|
||||
}
|
||||
} else {
|
||||
if (cic_error || rtc_error) {
|
||||
led_set_state(false, true);
|
||||
error_mode = true;
|
||||
error_timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// static void led_update_error_mode (void) {
|
||||
// if (error_mode) {
|
||||
// if (!(cic_error || rtc_error)) {
|
||||
// led_set_state(false, true);
|
||||
// error_mode = false;
|
||||
// act_timer = 0;
|
||||
// }
|
||||
// } else {
|
||||
// if (cic_error || rtc_error) {
|
||||
// led_set_state(false, true);
|
||||
// error_mode = true;
|
||||
// error_timer = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
static void led_process_errors (void) {
|
||||
if (error_timer == 0) {
|
||||
error_timer = LED_ERROR_TICKS_PERIOD;
|
||||
if (cic_error) {
|
||||
error_timer *= 1;
|
||||
} else if (rtc_error) {
|
||||
error_timer *= 2;
|
||||
}
|
||||
error_timer += LED_ERROR_TICKS_PERIOD;
|
||||
}
|
||||
// static void led_process_errors (void) {
|
||||
// if (error_timer == 0) {
|
||||
// error_timer = LED_ERROR_TICKS_PERIOD;
|
||||
// if (cic_error) {
|
||||
// error_timer *= 1;
|
||||
// } else if (rtc_error) {
|
||||
// error_timer *= 2;
|
||||
// }
|
||||
// error_timer += LED_ERROR_TICKS_PERIOD;
|
||||
// }
|
||||
|
||||
if (error_timer > 0) {
|
||||
error_timer -= 1;
|
||||
if (error_timer >= LED_ERROR_TICKS_PERIOD) {
|
||||
uint32_t error_cycle = (error_timer % LED_ERROR_TICKS_PERIOD);
|
||||
if (error_cycle == LED_ERROR_TICKS_ON) {
|
||||
led_set_state(true, true);
|
||||
}
|
||||
if (error_cycle == 0) {
|
||||
led_set_state(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (error_timer > 0) {
|
||||
// error_timer -= 1;
|
||||
// if (error_timer >= LED_ERROR_TICKS_PERIOD) {
|
||||
// uint32_t error_cycle = (error_timer % LED_ERROR_TICKS_PERIOD);
|
||||
// if (error_cycle == LED_ERROR_TICKS_ON) {
|
||||
// led_set_state(true, true);
|
||||
// }
|
||||
// if (error_cycle == 0) {
|
||||
// led_set_state(false, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
static void led_process_act (void) {
|
||||
if (act_timer == 0) {
|
||||
if (current_act_counter != next_act_counter) {
|
||||
current_act_counter = next_act_counter;
|
||||
act_timer = LED_ACT_TICKS_PERIOD;
|
||||
}
|
||||
}
|
||||
// static void led_process_act (void) {
|
||||
// if (act_timer == 0) {
|
||||
// if (current_act_counter != next_act_counter) {
|
||||
// current_act_counter = next_act_counter;
|
||||
// act_timer = LED_ACT_TICKS_PERIOD;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (act_timer > 0) {
|
||||
act_timer -= 1;
|
||||
if (act_timer == LED_ACT_TICKS_ON) {
|
||||
led_set_state(true, false);
|
||||
}
|
||||
if (act_timer == 0) {
|
||||
led_set_state(false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (act_timer > 0) {
|
||||
// act_timer -= 1;
|
||||
// if (act_timer == LED_ACT_TICKS_ON) {
|
||||
// led_set_state(true, false);
|
||||
// }
|
||||
// if (act_timer == 0) {
|
||||
// led_set_state(false, false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
void led_blink_error (led_error_t error) {
|
||||
switch (error) {
|
||||
case LED_ERROR_CIC:
|
||||
cic_error = true;
|
||||
break;
|
||||
case LED_ERROR_RTC:
|
||||
rtc_error = true;
|
||||
break;
|
||||
}
|
||||
// switch (error) {
|
||||
// case LED_ERROR_CIC:
|
||||
// cic_error = true;
|
||||
// break;
|
||||
// case LED_ERROR_RTC:
|
||||
// rtc_error = true;
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
void led_clear_error (led_error_t error) {
|
||||
switch (error) {
|
||||
case LED_ERROR_CIC:
|
||||
cic_error = false;
|
||||
break;
|
||||
case LED_ERROR_RTC:
|
||||
rtc_error = false;
|
||||
break;
|
||||
}
|
||||
// switch (error) {
|
||||
// case LED_ERROR_CIC:
|
||||
// cic_error = false;
|
||||
// break;
|
||||
// case LED_ERROR_RTC:
|
||||
// rtc_error = false;
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
void led_blink_act (void) {
|
||||
next_act_counter += 1;
|
||||
// next_act_counter += 1;
|
||||
}
|
||||
|
||||
void led_task (void) {
|
||||
timer_init();
|
||||
// void led_task (void) {
|
||||
// timer_init();
|
||||
|
||||
while (1) {
|
||||
hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume);
|
||||
// while (1) {
|
||||
// hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume);
|
||||
|
||||
led_update_error_mode();
|
||||
// led_update_error_mode();
|
||||
|
||||
if (error_mode) {
|
||||
led_process_errors();
|
||||
} else {
|
||||
led_process_act();
|
||||
}
|
||||
// if (error_mode) {
|
||||
// led_process_errors();
|
||||
// } else {
|
||||
// led_process_act();
|
||||
// }
|
||||
|
||||
timer_update();
|
||||
// timer_update();
|
||||
|
||||
task_yield();
|
||||
}
|
||||
}
|
||||
// task_yield();
|
||||
// }
|
||||
// }
|
||||
|
@ -11,7 +11,7 @@ typedef enum {
|
||||
void led_blink_error (led_error_t error);
|
||||
void led_clear_error (led_error_t error);
|
||||
void led_blink_act (void);
|
||||
void led_task (void);
|
||||
// void led_task (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,6 +9,7 @@ void no_valid_image (void) {
|
||||
hw_gpio_set(GPIO_ID_LED);
|
||||
}
|
||||
|
||||
|
||||
void loader (void) {
|
||||
if (update_check()) {
|
||||
hw_loader_init();
|
||||
|
@ -69,7 +69,10 @@ static void primer_send_response (uint8_t cmd, uint8_t *buffer, uint8_t tx_lengt
|
||||
|
||||
void primer (void) {
|
||||
hw_primer_init();
|
||||
|
||||
vendor_initial_configuration(primer_get_command, primer_send_response);
|
||||
hw_uart_wait_busy();
|
||||
|
||||
hw_uart_write_wait_busy();
|
||||
|
||||
hw_reset(NULL);
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include <string.h>
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "led.h"
|
||||
#include "rtc.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
#define RTC_I2C_ADDRESS (0xDE)
|
||||
@ -28,6 +29,8 @@
|
||||
|
||||
#define RTC_SETTINGS_VERSION (1)
|
||||
|
||||
#define RTC_TIME_REFRESH_PERIOD_MS (500)
|
||||
|
||||
|
||||
static rtc_time_t rtc_time = {
|
||||
.second = 0x00,
|
||||
@ -38,17 +41,15 @@ static rtc_time_t rtc_time = {
|
||||
.month = 0x03,
|
||||
.year = 0x22
|
||||
};
|
||||
static bool rtc_time_valid = false;
|
||||
static volatile bool rtc_time_pending = false;
|
||||
static bool rtc_time_pending = false;
|
||||
|
||||
static uint8_t rtc_region = 0xFF;
|
||||
static volatile bool rtc_region_pending = false;
|
||||
static bool rtc_region_pending = false;
|
||||
|
||||
static rtc_settings_t rtc_settings = {
|
||||
.led_enabled = true,
|
||||
};
|
||||
static volatile bool rtc_settings_pending = false;
|
||||
static volatile bool rtc_initialized = false;
|
||||
static bool rtc_settings_pending = false;
|
||||
|
||||
static const uint8_t rtc_regs_bit_mask[7] = {
|
||||
0b01111111,
|
||||
@ -61,29 +62,21 @@ static const uint8_t rtc_regs_bit_mask[7] = {
|
||||
};
|
||||
|
||||
|
||||
static void rtc_task_resume (void) {
|
||||
task_set_ready(TASK_ID_RTC);
|
||||
}
|
||||
|
||||
static void rtc_on_error (void) {
|
||||
rtc_time_valid = false;
|
||||
led_blink_error(LED_ERROR_RTC);
|
||||
task_yield();
|
||||
}
|
||||
|
||||
static void rtc_read (uint8_t address, uint8_t *data, uint8_t length) {
|
||||
hw_i2c_read(RTC_I2C_ADDRESS, address, data, length, rtc_task_resume);
|
||||
task_yield();
|
||||
if (hw_i2c_get_error()) {
|
||||
rtc_on_error();
|
||||
uint8_t tmp = address;
|
||||
if (hw_i2c_trx(RTC_I2C_ADDRESS, &tmp, 1, data, length) != I2C_OK) {
|
||||
led_blink_error(LED_ERROR_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_write (uint8_t address, uint8_t *data, uint8_t length) {
|
||||
hw_i2c_write(RTC_I2C_ADDRESS, address, data, length, rtc_task_resume);
|
||||
task_yield();
|
||||
if (hw_i2c_get_error()) {
|
||||
rtc_on_error();
|
||||
uint8_t tmp[16];
|
||||
tmp[0] = address;
|
||||
for (int i = 0; i < length; i++) {
|
||||
tmp[i + 1] = data[i];
|
||||
}
|
||||
if (hw_i2c_trx(RTC_I2C_ADDRESS, tmp, length + 1, NULL, 0) != I2C_OK) {
|
||||
led_blink_error(LED_ERROR_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,17 +103,13 @@ static void rtc_read_time (void) {
|
||||
|
||||
rtc_sanitize_time(regs);
|
||||
|
||||
if (!rtc_time_pending) {
|
||||
rtc_time.second = regs[0];
|
||||
rtc_time.minute = regs[1];
|
||||
rtc_time.hour = regs[2];
|
||||
rtc_time.weekday = regs[3];
|
||||
rtc_time.day = regs[4];
|
||||
rtc_time.month = regs[5];
|
||||
rtc_time.year = regs[6];
|
||||
|
||||
rtc_time_valid = true;
|
||||
}
|
||||
rtc_time.second = regs[0];
|
||||
rtc_time.minute = regs[1];
|
||||
rtc_time.hour = regs[2];
|
||||
rtc_time.weekday = regs[3];
|
||||
rtc_time.day = regs[4];
|
||||
rtc_time.month = regs[5];
|
||||
rtc_time.year = regs[6];
|
||||
}
|
||||
|
||||
static void rtc_write_time (void) {
|
||||
@ -161,12 +150,55 @@ static void rtc_write_settings (void) {
|
||||
rtc_write(RTC_ADDRESS_SRAM_SETTINGS, (uint8_t *) (&rtc_settings), sizeof(rtc_settings));
|
||||
}
|
||||
|
||||
static void rtc_init (void) {
|
||||
|
||||
void rtc_get_time (rtc_time_t *time) {
|
||||
time->second = rtc_time.second;
|
||||
time->minute = rtc_time.minute;
|
||||
time->hour = rtc_time.hour;
|
||||
time->weekday = rtc_time.weekday;
|
||||
time->day = rtc_time.day;
|
||||
time->month = rtc_time.month;
|
||||
time->year = rtc_time.year;
|
||||
}
|
||||
|
||||
void rtc_set_time (rtc_time_t *time) {
|
||||
rtc_time.second = time->second;
|
||||
rtc_time.minute = time->minute;
|
||||
rtc_time.hour = time->hour;
|
||||
rtc_time.weekday = time->weekday;
|
||||
rtc_time.day = time->day;
|
||||
rtc_time.month = time->month;
|
||||
rtc_time.year = time->year;
|
||||
rtc_time_pending = true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t rtc_get_region (void) {
|
||||
return rtc_region;
|
||||
}
|
||||
|
||||
void rtc_set_region (uint8_t region) {
|
||||
rtc_region = region;
|
||||
rtc_region_pending = true;
|
||||
}
|
||||
|
||||
|
||||
rtc_settings_t *rtc_get_settings (void) {
|
||||
return (&rtc_settings);
|
||||
}
|
||||
|
||||
void rtc_save_settings (void) {
|
||||
rtc_settings_pending = true;
|
||||
}
|
||||
|
||||
|
||||
void rtc_init (void) {
|
||||
bool uninitialized = false;
|
||||
const char *magic = "SC64";
|
||||
uint8_t buffer[4];
|
||||
uint32_t settings_version;
|
||||
|
||||
memset(buffer, 0, 4);
|
||||
rtc_read(RTC_ADDRESS_SRAM_MAGIC, buffer, 4);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@ -192,143 +224,73 @@ static void rtc_init (void) {
|
||||
rtc_write(RTC_ADDRESS_SRAM_VERSION, (uint8_t *) (&settings_version), 4);
|
||||
rtc_write_settings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool rtc_is_initialized (void) {
|
||||
return rtc_initialized;
|
||||
}
|
||||
|
||||
bool rtc_get_time (rtc_time_t *time) {
|
||||
bool vaild;
|
||||
|
||||
hw_i2c_disable_irq();
|
||||
hw_tim_disable_irq(TIM_ID_RTC);
|
||||
|
||||
time->second = rtc_time.second;
|
||||
time->minute = rtc_time.minute;
|
||||
time->hour = rtc_time.hour;
|
||||
time->weekday = rtc_time.weekday;
|
||||
time->day = rtc_time.day;
|
||||
time->month = rtc_time.month;
|
||||
time->year = rtc_time.year;
|
||||
vaild = rtc_time_valid;
|
||||
|
||||
hw_tim_enable_irq(TIM_ID_RTC);
|
||||
hw_i2c_enable_irq();
|
||||
|
||||
return vaild;
|
||||
}
|
||||
|
||||
void rtc_set_time (rtc_time_t *time) {
|
||||
hw_i2c_disable_irq();
|
||||
hw_tim_disable_irq(TIM_ID_RTC);
|
||||
|
||||
rtc_time.second = time->second;
|
||||
rtc_time.minute = time->minute;
|
||||
rtc_time.hour = time->hour;
|
||||
rtc_time.weekday = time->weekday;
|
||||
rtc_time.day = time->day;
|
||||
rtc_time.month = time->month;
|
||||
rtc_time.year = time->year;
|
||||
rtc_time_pending = true;
|
||||
|
||||
hw_tim_enable_irq(TIM_ID_RTC);
|
||||
hw_i2c_enable_irq();
|
||||
}
|
||||
|
||||
uint8_t rtc_get_region (void) {
|
||||
return rtc_region;
|
||||
}
|
||||
|
||||
void rtc_set_region (uint8_t region) {
|
||||
rtc_region = region;
|
||||
rtc_region_pending = true;
|
||||
}
|
||||
|
||||
rtc_settings_t *rtc_get_settings (void) {
|
||||
return (&rtc_settings);
|
||||
}
|
||||
|
||||
void rtc_set_settings (rtc_settings_t *settings) {
|
||||
hw_tim_disable_irq(TIM_ID_LED);
|
||||
|
||||
rtc_settings = *settings;
|
||||
rtc_settings_pending = true;
|
||||
|
||||
hw_tim_enable_irq(TIM_ID_LED);
|
||||
}
|
||||
|
||||
void rtc_task (void) {
|
||||
rtc_init();
|
||||
|
||||
rtc_read_time();
|
||||
rtc_read_region();
|
||||
rtc_read_settings();
|
||||
|
||||
rtc_initialized = true;
|
||||
|
||||
while (1) {
|
||||
if (rtc_time_pending) {
|
||||
rtc_time_pending = false;
|
||||
rtc_write_time();
|
||||
}
|
||||
|
||||
if (rtc_region_pending) {
|
||||
rtc_region_pending = false;
|
||||
rtc_write_region();
|
||||
}
|
||||
|
||||
if (rtc_settings_pending) {
|
||||
rtc_settings_pending = false;
|
||||
rtc_write_settings();
|
||||
}
|
||||
|
||||
rtc_read_time();
|
||||
|
||||
hw_tim_setup(TIM_ID_RTC, 50, rtc_task_resume);
|
||||
|
||||
task_yield();
|
||||
}
|
||||
timer_countdown_start(TIMER_ID_RTC, RTC_TIME_REFRESH_PERIOD_MS);
|
||||
}
|
||||
|
||||
|
||||
void rtc_process (void) {
|
||||
rtc_time_t time;
|
||||
uint32_t data[2];
|
||||
uint32_t scr = fpga_reg_get(REG_RTC_SCR);
|
||||
|
||||
if ((scr & RTC_SCR_PENDING) && ((scr & RTC_SCR_MAGIC_MASK) == RTC_SCR_MAGIC)) {
|
||||
uint32_t data[2];
|
||||
|
||||
data[0] = fpga_reg_get(REG_RTC_TIME_0);
|
||||
data[1] = fpga_reg_get(REG_RTC_TIME_1);
|
||||
|
||||
time.weekday = ((data[0] >> 24) & 0xFF) + 1;
|
||||
time.hour = ((data[0] >> 16) & 0xFF);
|
||||
time.minute = ((data[0] >> 8) & 0xFF);
|
||||
time.second = ((data[0] >> 0) & 0xFF);
|
||||
time.year = ((data[1] >> 16) & 0xFF);
|
||||
time.month = ((data[1] >> 8) & 0xFF);
|
||||
time.day = ((data[1] >> 0) & 0xFF);
|
||||
|
||||
rtc_set_time(&time);
|
||||
rtc_time.weekday = ((data[0] >> 24) & 0xFF) + 1;
|
||||
rtc_time.hour = ((data[0] >> 16) & 0xFF);
|
||||
rtc_time.minute = ((data[0] >> 8) & 0xFF);
|
||||
rtc_time.second = ((data[0] >> 0) & 0xFF);
|
||||
rtc_time.year = ((data[1] >> 16) & 0xFF);
|
||||
rtc_time.month = ((data[1] >> 8) & 0xFF);
|
||||
rtc_time.day = ((data[1] >> 0) & 0xFF);
|
||||
rtc_time_pending = true;
|
||||
|
||||
fpga_reg_set(REG_RTC_TIME_0, data[0]);
|
||||
fpga_reg_set(REG_RTC_TIME_1, data[1]);
|
||||
fpga_reg_set(REG_RTC_SCR, RTC_SCR_DONE);
|
||||
}
|
||||
|
||||
rtc_get_time(&time);
|
||||
if (rtc_time_pending) {
|
||||
rtc_time_pending = false;
|
||||
rtc_write_time();
|
||||
}
|
||||
|
||||
data[0] = (
|
||||
((time.weekday - 1) << 24) |
|
||||
(time.hour << 16) |
|
||||
(time.minute << 8) |
|
||||
(time.second << 0)
|
||||
);
|
||||
data[1] = (
|
||||
(time.year << 16) |
|
||||
(time.month << 8) |
|
||||
(time.day << 0)
|
||||
);
|
||||
if (rtc_region_pending) {
|
||||
rtc_region_pending = false;
|
||||
rtc_write_region();
|
||||
}
|
||||
|
||||
fpga_reg_set(REG_RTC_TIME_0, data[0]);
|
||||
fpga_reg_set(REG_RTC_TIME_1, data[1]);
|
||||
if (rtc_settings_pending) {
|
||||
rtc_settings_pending = false;
|
||||
rtc_write_settings();
|
||||
}
|
||||
|
||||
if (timer_countdown_elapsed(TIMER_ID_RTC)) {
|
||||
timer_countdown_start(TIMER_ID_RTC, RTC_TIME_REFRESH_PERIOD_MS);
|
||||
|
||||
rtc_read_time();
|
||||
|
||||
uint32_t data[2];
|
||||
|
||||
data[0] = (
|
||||
((rtc_time.weekday - 1) << 24) |
|
||||
(rtc_time.hour << 16) |
|
||||
(rtc_time.minute << 8) |
|
||||
(rtc_time.second << 0)
|
||||
);
|
||||
data[1] = (
|
||||
(rtc_time.year << 16) |
|
||||
(rtc_time.month << 8) |
|
||||
(rtc_time.day << 0)
|
||||
);
|
||||
|
||||
fpga_reg_set(REG_RTC_TIME_0, data[0]);
|
||||
fpga_reg_set(REG_RTC_TIME_1, data[1]);
|
||||
}
|
||||
}
|
||||
|
@ -7,28 +7,31 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile uint8_t second;
|
||||
volatile uint8_t minute;
|
||||
volatile uint8_t hour;
|
||||
volatile uint8_t weekday;
|
||||
volatile uint8_t day;
|
||||
volatile uint8_t month;
|
||||
volatile uint8_t year;
|
||||
uint8_t second;
|
||||
uint8_t minute;
|
||||
uint8_t hour;
|
||||
uint8_t weekday;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
} rtc_time_t;
|
||||
|
||||
typedef struct {
|
||||
volatile bool led_enabled;
|
||||
bool led_enabled;
|
||||
} rtc_settings_t;
|
||||
|
||||
|
||||
bool rtc_is_initialized (void);
|
||||
bool rtc_get_time (rtc_time_t *time);
|
||||
void rtc_get_time (rtc_time_t *time);
|
||||
void rtc_set_time (rtc_time_t *time);
|
||||
|
||||
uint8_t rtc_get_region (void);
|
||||
void rtc_set_region (uint8_t region);
|
||||
|
||||
rtc_settings_t *rtc_get_settings (void);
|
||||
void rtc_set_settings (rtc_settings_t *settings);
|
||||
void rtc_task (void);
|
||||
void rtc_save_settings (void);
|
||||
|
||||
void rtc_init (void);
|
||||
|
||||
void rtc_process (void);
|
||||
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "led.h"
|
||||
#include "sd.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
#define SD_INIT_BUFFER_ADDRESS (0x05002800UL)
|
||||
@ -33,6 +32,8 @@
|
||||
#define SWITCH_FUNCTION_GROUP_1 (SD_INIT_BUFFER_ADDRESS + 12)
|
||||
#define SWITCH_FUNCTION_GROUP_1_HS (1 << 1)
|
||||
|
||||
#define TIMEOUT_INIT_MS (1000)
|
||||
|
||||
#define DAT_BLOCK_MAX_COUNT (256)
|
||||
#define DAT_TIMEOUT_INIT_MS (2000)
|
||||
#define DAT_TIMEOUT_DATA_MS (5000)
|
||||
@ -60,6 +61,12 @@ typedef enum {
|
||||
DAT_WRITE,
|
||||
} dat_mode_t;
|
||||
|
||||
typedef enum {
|
||||
DAT_OK,
|
||||
DAT_ERR_IO,
|
||||
DAT_ERR_TIMEOUT,
|
||||
} dat_err_t;
|
||||
|
||||
|
||||
struct process {
|
||||
bool card_initialized;
|
||||
@ -67,7 +74,6 @@ struct process {
|
||||
uint32_t rca;
|
||||
uint8_t csd[16];
|
||||
uint8_t cid[16];
|
||||
volatile bool timeout;
|
||||
bool byte_swap;
|
||||
};
|
||||
|
||||
@ -75,24 +81,6 @@ struct process {
|
||||
static struct process p;
|
||||
|
||||
|
||||
static void sd_trigger_timeout (void) {
|
||||
p.timeout = true;
|
||||
}
|
||||
|
||||
static void sd_prepare_timeout (uint16_t value) {
|
||||
p.timeout = false;
|
||||
hw_tim_setup(TIM_ID_SD, value, sd_trigger_timeout);
|
||||
}
|
||||
|
||||
static bool sd_did_timeout (void) {
|
||||
return p.timeout;
|
||||
}
|
||||
|
||||
static void sd_clear_timeout (void) {
|
||||
hw_tim_stop(TIM_ID_SD);
|
||||
p.timeout = false;
|
||||
}
|
||||
|
||||
static void sd_set_clock (sd_clock_t mode) {
|
||||
fpga_reg_set(REG_SD_SCR, SD_SCR_CLOCK_MODE_OFF);
|
||||
|
||||
@ -198,22 +186,25 @@ static void sd_dat_abort (void) {
|
||||
fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH);
|
||||
}
|
||||
|
||||
static bool sd_dat_wait (uint16_t timeout) {
|
||||
sd_prepare_timeout(timeout);
|
||||
static dat_err_t sd_dat_wait (uint16_t timeout_ms) {
|
||||
timer_countdown_start(TIMER_ID_SD, timeout_ms);
|
||||
|
||||
do {
|
||||
uint32_t sd_dat = fpga_reg_get(REG_SD_DAT);
|
||||
uint32_t sd_dma_scr = fpga_reg_get(REG_SD_DMA_SCR);
|
||||
led_blink_act();
|
||||
if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) {
|
||||
sd_clear_timeout();
|
||||
return (sd_dat & SD_DAT_ERROR);
|
||||
if (sd_dat & SD_DAT_ERROR) {
|
||||
sd_dat_abort();
|
||||
return DAT_ERR_IO;
|
||||
}
|
||||
return DAT_OK;
|
||||
}
|
||||
} while (!sd_did_timeout());
|
||||
} while (!timer_countdown_elapsed(TIMER_ID_SD));
|
||||
|
||||
sd_dat_abort();
|
||||
|
||||
return true;
|
||||
return DAT_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
@ -248,9 +239,9 @@ bool sd_card_init (void) {
|
||||
arg = (ACMD41_ARG_HCS | ACMD41_ARG_OCR);
|
||||
}
|
||||
|
||||
sd_prepare_timeout(1000);
|
||||
timer_countdown_start(TIMER_ID_SD, TIMEOUT_INIT_MS);
|
||||
do {
|
||||
if (sd_did_timeout()) {
|
||||
if (timer_countdown_elapsed(TIMER_ID_SD)) {
|
||||
sd_card_deinit();
|
||||
return true;
|
||||
}
|
||||
@ -266,8 +257,7 @@ bool sd_card_init (void) {
|
||||
p.card_type_block = (rsp & R3_CCS);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
sd_clear_timeout();
|
||||
} while (true);
|
||||
|
||||
if (sd_cmd(2, 0, RSP_R2, NULL)) {
|
||||
sd_card_deinit();
|
||||
@ -308,8 +298,7 @@ bool sd_card_init (void) {
|
||||
sd_card_deinit();
|
||||
return true;
|
||||
}
|
||||
sd_dat_wait(DAT_TIMEOUT_INIT_MS);
|
||||
if (sd_did_timeout()) {
|
||||
if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) {
|
||||
sd_card_deinit();
|
||||
return true;
|
||||
}
|
||||
@ -326,8 +315,7 @@ bool sd_card_init (void) {
|
||||
sd_card_deinit();
|
||||
return true;
|
||||
}
|
||||
sd_dat_wait(DAT_TIMEOUT_INIT_MS);
|
||||
if (sd_did_timeout()) {
|
||||
if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) {
|
||||
sd_card_deinit();
|
||||
return true;
|
||||
}
|
||||
@ -389,6 +377,7 @@ bool sd_set_byte_swap (bool enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||
if (!p.card_initialized || (count == 0)) {
|
||||
return true;
|
||||
@ -405,8 +394,7 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||
return true;
|
||||
}
|
||||
sd_dat_prepare(address, blocks, DAT_WRITE);
|
||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS)) {
|
||||
sd_dat_abort();
|
||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) {
|
||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||
return true;
|
||||
}
|
||||
@ -440,10 +428,8 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||
sd_dat_abort();
|
||||
return true;
|
||||
}
|
||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS)) {
|
||||
if (sd_did_timeout()) {
|
||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||
}
|
||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) {
|
||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||
return true;
|
||||
}
|
||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||
@ -455,6 +441,7 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors) {
|
||||
uint32_t starting_sector = 0;
|
||||
uint32_t sectors_to_process = 0;
|
||||
@ -483,12 +470,14 @@ bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t cou
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void sd_init (void) {
|
||||
p.card_initialized = false;
|
||||
p.byte_swap = false;
|
||||
sd_set_clock(CLOCK_STOP);
|
||||
}
|
||||
|
||||
|
||||
void sd_process (void) {
|
||||
if (p.card_initialized && !sd_card_is_inserted()) {
|
||||
sd_card_deinit();
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define SD_SECTOR_SIZE (512)
|
||||
@ -18,10 +19,14 @@ bool sd_card_is_inserted (void);
|
||||
uint32_t sd_card_get_status (void);
|
||||
bool sd_card_get_info (uint32_t address);
|
||||
bool sd_set_byte_swap (bool enabled);
|
||||
|
||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
||||
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
||||
|
||||
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
|
||||
|
||||
void sd_init (void);
|
||||
|
||||
void sd_process (void);
|
||||
|
||||
|
||||
|
@ -1,135 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stm32g0xx.h>
|
||||
#include "task.h"
|
||||
|
||||
|
||||
#define TASK_INITIAL_XPSR (0x21000000UL)
|
||||
#define TASK_CONTEXT_SWITCH() { SCB->ICSR = (1 << SCB_ICSR_PENDSVSET_Pos); }
|
||||
#define TASK_STACK_FILL_VALUE (0xDEADBEEF)
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t sp;
|
||||
volatile bool ready;
|
||||
} task_t;
|
||||
|
||||
|
||||
static task_t task_table[__TASK_ID_MAX];
|
||||
static volatile task_id_t task_current = 0;
|
||||
|
||||
|
||||
static void task_exit (void) {
|
||||
while (1) {
|
||||
task_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t task_switch_context (uint32_t sp) {
|
||||
task_table[task_current].sp = sp;
|
||||
|
||||
for (task_id_t id = 0; id < __TASK_ID_MAX; id++) {
|
||||
if (task_table[id].ready) {
|
||||
task_current = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
for (size_t i = 0; i < stack_size; i += sizeof(uint32_t)) {
|
||||
(*(uint32_t *) (stack + i)) = TASK_STACK_FILL_VALUE;
|
||||
}
|
||||
uint32_t *sp = ((uint32_t *) ((uint32_t) (stack) + stack_size));
|
||||
*--sp = TASK_INITIAL_XPSR;
|
||||
*--sp = (uint32_t) (code);
|
||||
*--sp = ((uint32_t) (task_exit));
|
||||
for (int i = 0; i < 13; i++) {
|
||||
*--sp = 0;
|
||||
}
|
||||
task_t *task = &task_table[id];
|
||||
task->sp = ((uint32_t) (sp));
|
||||
task->ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
void task_yield (void) {
|
||||
__disable_irq();
|
||||
task_table[task_current].ready = false;
|
||||
__enable_irq();
|
||||
TASK_CONTEXT_SWITCH();
|
||||
}
|
||||
|
||||
void task_set_ready (task_id_t id) {
|
||||
__disable_irq();
|
||||
task_table[id].ready = true;
|
||||
__enable_irq();
|
||||
TASK_CONTEXT_SWITCH();
|
||||
}
|
||||
|
||||
size_t task_get_stack_usage (void *stack, size_t stack_size) {
|
||||
for (size_t i = 0; i < stack_size; i += sizeof(uint32_t)) {
|
||||
if ((*(uint32_t *) (stack + i)) != TASK_STACK_FILL_VALUE) {
|
||||
return (stack_size - i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((naked)) void task_scheduler_start (void) {
|
||||
uint32_t sp = task_table[task_current].sp;
|
||||
|
||||
NVIC_SetPriority(PendSV_IRQn, 3);
|
||||
|
||||
asm volatile (
|
||||
"add %[sp], #32 \n"
|
||||
"msr psp, %[sp] \n"
|
||||
"movs r0, #2 \n"
|
||||
"msr CONTROL, r0 \n"
|
||||
"isb \n"
|
||||
"pop {r0-r5} \n"
|
||||
"mov lr, r5 \n"
|
||||
"pop {r3} \n"
|
||||
"pop {r2} \n"
|
||||
"cpsie i \n"
|
||||
"bx r3 \n"
|
||||
:: [sp] "r" (sp)
|
||||
);
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
__attribute__((naked)) void PendSV_Handler (void) {
|
||||
asm volatile (
|
||||
"mrs r1, psp \n"
|
||||
"sub r1, r1, #32 \n"
|
||||
"mov r0, r1 \n"
|
||||
"stmia r1!, {r4-r7} \n"
|
||||
"mov r4, r8 \n"
|
||||
"mov r5, r9 \n"
|
||||
"mov r6, r10 \n"
|
||||
"mov r7, r11 \n"
|
||||
"stmia r1!, {r4-r7} \n"
|
||||
"push {lr} \n"
|
||||
"cpsid i \n"
|
||||
"blx %[task_switch_context] \n"
|
||||
"cpsie i \n"
|
||||
"pop {r2} \n"
|
||||
"add r0, #16 \n"
|
||||
"ldmia r0!, {r4-r7} \n"
|
||||
"mov r8, r4 \n"
|
||||
"mov r9, r5 \n"
|
||||
"mov r10, r6 \n"
|
||||
"mov r11, r7 \n"
|
||||
"msr psp, r0 \n"
|
||||
"sub r0, #32 \n"
|
||||
"ldmia r0!, {r4-r7} \n"
|
||||
"bx r2 \n"
|
||||
:: [task_switch_context] "r" (task_switch_context)
|
||||
);
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#ifndef TASK_H__
|
||||
#define TASK_H__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
TASK_ID_RTC,
|
||||
TASK_ID_LED,
|
||||
TASK_ID_GVR,
|
||||
__TASK_ID_MAX
|
||||
} task_id_t;
|
||||
|
||||
|
||||
void task_create (task_id_t id, void (*code)(void), void *stack, size_t stack_size);
|
||||
void task_yield (void);
|
||||
void task_set_ready (task_id_t id);
|
||||
size_t task_get_stack_usage (void *stack, size_t stack_size);
|
||||
void task_scheduler_start (void);
|
||||
|
||||
|
||||
#endif
|
@ -2,29 +2,55 @@
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
static volatile uint32_t timer[__TIMER_ID_COUNT];
|
||||
#define TIMER_PERIOD_MS (50)
|
||||
|
||||
|
||||
uint32_t timer_get (timer_id_t id) {
|
||||
return (uint32_t) (timer[id]);
|
||||
}
|
||||
typedef struct {
|
||||
volatile bool pending;
|
||||
volatile bool running;
|
||||
volatile uint32_t value;
|
||||
} timer_t;
|
||||
|
||||
void timer_set (timer_id_t id, uint32_t ticks) {
|
||||
hw_tim_disable_irq(TIM_ID_LED);
|
||||
timer[id] = ticks;
|
||||
hw_tim_enable_irq(TIM_ID_LED);
|
||||
}
|
||||
static timer_t timer[__TIMER_ID_COUNT];
|
||||
|
||||
void timer_init (void) {
|
||||
|
||||
static void timer_update (void) {
|
||||
for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) {
|
||||
timer[id] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_update (void) {
|
||||
for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) {
|
||||
if (timer[id] > 0) {
|
||||
timer[id] -= 1;
|
||||
if (timer[id].value > 0) {
|
||||
timer[id].value -= 1;
|
||||
}
|
||||
if (timer[id].pending) {
|
||||
timer[id].pending = false;
|
||||
} else if(timer[id].value == 0) {
|
||||
timer[id].running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void timer_countdown_start (timer_id_t id, uint32_t value_ms) {
|
||||
hw_enter_critical();
|
||||
if (value_ms > 0) {
|
||||
timer[id].pending = true;
|
||||
timer[id].running = true;
|
||||
timer[id].value = ((value_ms + (TIMER_PERIOD_MS - 1)) / TIMER_PERIOD_MS);
|
||||
}
|
||||
hw_exit_critical();
|
||||
}
|
||||
|
||||
void timer_countdown_abort (timer_id_t id) {
|
||||
hw_enter_critical();
|
||||
timer[id].pending = false;
|
||||
timer[id].running = false;
|
||||
timer[id].value = 0;
|
||||
hw_exit_critical();
|
||||
}
|
||||
|
||||
bool timer_countdown_elapsed (timer_id_t id) {
|
||||
return (!timer[id].running);
|
||||
}
|
||||
|
||||
|
||||
void timer_init (void) {
|
||||
hw_systick_config(TIMER_PERIOD_MS, timer_update);
|
||||
}
|
||||
|
@ -2,20 +2,25 @@
|
||||
#define TIMER_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
TIMER_ID_DD,
|
||||
TIMER_ID_RTC,
|
||||
TIMER_ID_SD,
|
||||
TIMER_ID_USB,
|
||||
TIMER_ID_WRITEBACK,
|
||||
__TIMER_ID_COUNT
|
||||
} timer_id_t;
|
||||
|
||||
|
||||
uint32_t timer_get (timer_id_t id);
|
||||
void timer_set (timer_id_t id, uint32_t ticks);
|
||||
void timer_countdown_start (timer_id_t id, uint32_t value_ms);
|
||||
void timer_countdown_abort (timer_id_t id);
|
||||
bool timer_countdown_elapsed (timer_id_t id);
|
||||
|
||||
void timer_init (void);
|
||||
void timer_update (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -312,7 +312,7 @@ void update_perform (void) {
|
||||
fpga_mem_read(parameters.mcu_address - 4, sizeof(length), (uint8_t *) (&length));
|
||||
if (mcu_update(parameters.mcu_address, length)) {
|
||||
update_status_notify(UPDATE_STATUS_ERROR);
|
||||
while (1);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,7 +321,7 @@ void update_perform (void) {
|
||||
fpga_mem_read(parameters.fpga_address - 4, sizeof(length), (uint8_t *) (&length));
|
||||
if (vendor_update(parameters.fpga_address, length) != VENDOR_OK) {
|
||||
update_status_notify(UPDATE_STATUS_ERROR);
|
||||
while (1);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ void update_perform (void) {
|
||||
fpga_mem_read(parameters.bootloader_address - 4, sizeof(length), (uint8_t *) (&length));
|
||||
if (bootloader_update(parameters.bootloader_address, length)) {
|
||||
update_status_notify(UPDATE_STATUS_ERROR);
|
||||
while (1);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include "app.h"
|
||||
#include "cfg.h"
|
||||
#include "cic.h"
|
||||
#include "dd.h"
|
||||
@ -12,15 +11,15 @@
|
||||
#include "writeback.h"
|
||||
|
||||
|
||||
#define BOOTLOADER_ADDRESS (0x04E00000UL)
|
||||
#define BOOTLOADER_LENGTH (1920 * 1024)
|
||||
#define BOOTLOADER_ADDRESS (0x04E00000UL)
|
||||
#define BOOTLOADER_LENGTH (1920 * 1024)
|
||||
|
||||
#define MEMORY_LENGTH (0x05002980UL)
|
||||
#define MEMORY_LENGTH (0x05002980UL)
|
||||
|
||||
#define RX_FLUSH_ADDRESS (0x07F00000UL)
|
||||
#define RX_FLUSH_LENGTH (1 * 1024 * 1024)
|
||||
#define RX_FLUSH_ADDRESS (0x07F00000UL)
|
||||
#define RX_FLUSH_LENGTH (1 * 1024 * 1024)
|
||||
|
||||
#define DEBUG_WRITE_TIMEOUT_TICKS (100)
|
||||
#define DEBUG_WRITE_TIMEOUT_MS (1000)
|
||||
|
||||
|
||||
enum rx_state {
|
||||
@ -175,7 +174,7 @@ static void usb_rx_process (void) {
|
||||
p.response_info.dma_length = 0;
|
||||
p.response_info.done_callback = NULL;
|
||||
if (p.rx_cmd == 'U') {
|
||||
timer_set(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_TICKS);
|
||||
timer_countdown_start(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -311,9 +310,9 @@ static void usb_rx_process (void) {
|
||||
p.read_length -= length;
|
||||
p.read_address += length;
|
||||
p.read_ready = true;
|
||||
timer_set(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_TICKS);
|
||||
timer_countdown_start(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_MS);
|
||||
}
|
||||
} else if (timer_get(TIMER_ID_USB) == 0) {
|
||||
} else if (timer_countdown_elapsed(TIMER_ID_USB)) {
|
||||
p.rx_state = RX_STATE_FLUSH;
|
||||
p.flush_packet = true;
|
||||
}
|
||||
@ -386,7 +385,10 @@ static void usb_rx_process (void) {
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 16;
|
||||
app_get_stack_usage(p.response_info.data);
|
||||
p.response_info.data[0] = 0;
|
||||
p.response_info.data[1] = 0;
|
||||
p.response_info.data[2] = 0;
|
||||
p.response_info.data[3] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -521,6 +523,7 @@ bool usb_enqueue_packet (usb_tx_info_t *info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool usb_prepare_read (uint32_t *args) {
|
||||
if (!p.read_ready) {
|
||||
return false;
|
||||
@ -543,6 +546,7 @@ void usb_get_read_info (uint32_t *args) {
|
||||
args[0] |= (scr & USB_SCR_PWRSAV) ? (1 << 29) : 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);
|
||||
@ -563,6 +567,7 @@ void usb_init (void) {
|
||||
usb_rx_cmd_counter = 0;
|
||||
}
|
||||
|
||||
|
||||
void usb_process (void) {
|
||||
uint32_t scr = fpga_reg_get(REG_USB_SCR);
|
||||
if (scr & (USB_SCR_PWRSAV | USB_SCR_RESET_STATE | USB_SCR_RESET_PENDING)) {
|
||||
|
@ -7,13 +7,13 @@
|
||||
|
||||
|
||||
typedef enum packet_cmd {
|
||||
PACKET_CMD_BUTTON_TRIGGER = 'B',
|
||||
PACKET_CMD_DATA_FLUSHED = 'G',
|
||||
PACKET_CMD_DEBUG_OUTPUT = 'U',
|
||||
PACKET_CMD_DD_REQUEST = 'D',
|
||||
PACKET_CMD_ISV_OUTPUT = 'I',
|
||||
PACKET_CMD_SAVE_WRITEBACK = 'S',
|
||||
PACKET_CMD_UPDATE_STATUS = 'F',
|
||||
PACKET_CMD_BUTTON_TRIGGER = 'B',
|
||||
PACKET_CMD_DATA_FLUSHED = 'G',
|
||||
PACKET_CMD_DEBUG_OUTPUT = 'U',
|
||||
PACKET_CMD_DD_REQUEST = 'D',
|
||||
PACKET_CMD_ISV_OUTPUT = 'I',
|
||||
PACKET_CMD_SAVE_WRITEBACK = 'S',
|
||||
PACKET_CMD_UPDATE_STATUS = 'F',
|
||||
} usb_packet_cmd_e;
|
||||
|
||||
|
||||
@ -29,9 +29,12 @@ typedef struct usb_tx_info {
|
||||
|
||||
void usb_create_packet (usb_tx_info_t *info, usb_packet_cmd_e 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);
|
||||
|
||||
|
||||
|
@ -6,16 +6,19 @@
|
||||
#include "writeback.h"
|
||||
|
||||
|
||||
#define SAVE_MAX_SECTOR_COUNT (256)
|
||||
#define EEPROM_ADDRESS (0x05002000)
|
||||
#define SRAM_FLASHRAM_ADDRESS (0x03FE0000)
|
||||
#define EEPROM_4K_LENGTH (512)
|
||||
#define EEPROM_16K_LENGTH (2048)
|
||||
#define SRAM_LENGTH (32 * 1024)
|
||||
#define FLASHRAM_LENGTH (128 * 1024)
|
||||
#define SRAM_BANKED_LENGTH (3 * 32 * 1024)
|
||||
#define SRAM_1M_LENGTH (128 * 1024)
|
||||
#define WRITEBACK_DELAY_TICKS (100)
|
||||
#define SAVE_MAX_SECTOR_COUNT (256)
|
||||
|
||||
#define EEPROM_ADDRESS (0x05002000)
|
||||
#define SRAM_FLASHRAM_ADDRESS (0x03FE0000)
|
||||
|
||||
#define EEPROM_4K_LENGTH (512)
|
||||
#define EEPROM_16K_LENGTH (2048)
|
||||
#define SRAM_LENGTH (32 * 1024)
|
||||
#define FLASHRAM_LENGTH (128 * 1024)
|
||||
#define SRAM_BANKED_LENGTH (3 * 32 * 1024)
|
||||
#define SRAM_1M_LENGTH (128 * 1024)
|
||||
|
||||
#define WRITEBACK_DELAY_MS (1000)
|
||||
|
||||
|
||||
struct process {
|
||||
@ -111,6 +114,7 @@ void writeback_load_sector_table (uint32_t address) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeback_enable (writeback_mode_t mode) {
|
||||
p.enabled = true;
|
||||
p.pending = false;
|
||||
@ -121,13 +125,14 @@ void writeback_enable (writeback_mode_t mode) {
|
||||
void writeback_disable (void) {
|
||||
p.enabled = false;
|
||||
p.pending = false;
|
||||
timer_set(TIMER_ID_WRITEBACK, 0);
|
||||
timer_countdown_abort(TIMER_ID_WRITEBACK);
|
||||
}
|
||||
|
||||
bool writeback_pending (void) {
|
||||
return p.enabled && p.pending;
|
||||
}
|
||||
|
||||
|
||||
void writeback_init (void) {
|
||||
p.enabled = false;
|
||||
p.pending = false;
|
||||
@ -137,6 +142,7 @@ void writeback_init (void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeback_process (void) {
|
||||
if (p.enabled && (p.mode == WRITEBACK_SD) && !sd_card_is_inserted()) {
|
||||
writeback_disable();
|
||||
@ -144,24 +150,27 @@ void writeback_process (void) {
|
||||
|
||||
if (p.enabled) {
|
||||
uint16_t save_count = fpga_reg_get(REG_SAVE_COUNT);
|
||||
|
||||
if (save_count != p.last_save_count) {
|
||||
p.pending = true;
|
||||
p.last_save_count = save_count;
|
||||
timer_set(TIMER_ID_WRITEBACK, WRITEBACK_DELAY_TICKS);
|
||||
timer_countdown_start(TIMER_ID_WRITEBACK, WRITEBACK_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
if (p.pending && (timer_get(TIMER_ID_WRITEBACK) == 0)) {
|
||||
if (p.pending && timer_countdown_elapsed(TIMER_ID_WRITEBACK)) {
|
||||
switch (p.mode) {
|
||||
case WRITEBACK_SD:
|
||||
writeback_save_to_sd();
|
||||
p.pending = false;
|
||||
break;
|
||||
|
||||
case WRITEBACK_USB:
|
||||
if (writeback_save_to_usb()) {
|
||||
p.pending = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
writeback_disable();
|
||||
break;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define WRITEBACK_SECTOR_TABLE_SIZE (1024)
|
||||
#define WRITEBACK_SECTOR_TABLE_SIZE (1024)
|
||||
|
||||
|
||||
typedef enum {
|
||||
@ -16,10 +16,13 @@ typedef enum {
|
||||
|
||||
|
||||
void writeback_load_sector_table (uint32_t address);
|
||||
|
||||
void writeback_enable (writeback_mode_t mode);
|
||||
void writeback_disable (void);
|
||||
bool writeback_pending (void);
|
||||
|
||||
void writeback_init (void);
|
||||
|
||||
void writeback_process (void);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user