Made ROM programming more robust now that we are not using interrupts for the control

This commit is contained in:
Dreaded_X 2020-12-22 02:31:33 +01:00
parent 279a81716a
commit b638db4f95
4 changed files with 136 additions and 238 deletions

View File

@ -18,17 +18,6 @@ typedef enum {
CONTROL_CLOCK_HIGH
} ControlState;
typedef struct {
uint8_t programming;
uint16_t length;
uint8_t* data;
} Eeprom;
typedef struct {
uint8_t received;
uint8_t c;
} Input;
typedef struct {
uint8_t dirty;
uint8_t action;
@ -45,19 +34,14 @@ typedef struct {
ControlState state;
uint8_t memory_config;
Storage storage;
Input input;
Eeprom eeprom;
} Control;
uint16_t read_address();
void write_data(uint8_t value);
uint8_t read_data();
void control_program_eeprom(uint8_t* data, uint16_t length);
void control_execute_state();
void control_reset();
uint8_t control_receive_program(uint8_t byte);
void send_key(uint8_t c);
#endif

View File

@ -47,86 +47,47 @@ uint32_t calculate_lba() {
return temp;
}
void program_eeprom() {
static int address_counter = 0;
static int read_counter = 0;
static int write_counter = 0;
// Check if we are done
if (address_counter == control.eeprom.length) {
// Mark as done and trigger Z80 reset
control.eeprom.programming = 0;
control.state = CONTROL_RESET_BEGIN;
// Reset counters
address_counter = 0;
read_counter = 0;
write_counter = 0;
send_busrq(0);
// Reset signals
send_memrq(0);
send_wr(0);
send_rd(0);
// Free memory used to store program
free(control.eeprom.data);
control.eeprom.data = NULL;
control.eeprom.length = 0;
// Notify the user
printf("\nEEPROM Programmed!\n\r");
// Turn of the update light
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
return;
void control_program_eeprom(uint8_t* data, uint16_t length) {
// Take control of the bus
printf("Taking control of bus...\n\r");
send_busrq(1);
while (!has_busak()) {
control_execute_state();
}
// Turn on the update light
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
printf("Done!\n\r");
printf("Writing to ROM...\n\r");
// Check if the data is written
if (write_counter < 100) {
// Select correct device and address
select_device(memory_map_0[0]);
write_address(address_counter);
enable_address_out(1);
// Write the data
write_data(control.eeprom.data[address_counter]);
select_device(memory_map_0[0]);
for (uint16_t i = 0; i < length; ++i) {
write_address(i);
write_data(data[i]);
// Send write request
enable_data_out(1);
send_memrq(1);
send_wr(1);
write_counter++;
} else {
// Stop writing
enable_data_out(0);
send_memrq(1);
send_wr(0);
enable_data_out(0);
send_rd(1);
uint8_t d = read_data();
if (read_counter > 5 && d == control.eeprom.data[address_counter]) {
address_counter++;
write_counter = 0;
read_counter = 0;
printf("%i/%i\r", i+1, length);
send_rd(0);
printf("Progress: %i/%i\r", address_counter, control.eeprom.length);
} else if (read_counter > 4000) {
// In case we failed, try again
printf("Trying again! %x != %x (%i)\n\r", d, control.eeprom.data[address_counter], address_counter);
read_counter = 0;
write_counter = 0;
send_rd(0);
} else {
read_counter++;
for (;;) {
uint8_t d = read_data();
if (d == data[i]) {
break;
}
}
send_rd(0);
send_memrq(0);
}
printf("\n");
}
void handle_memrq() {
@ -139,6 +100,7 @@ void handle_io_read() {
uint8_t address = read_address() & 0xFF;
switch (address) {
// @todo This should be detected on startup
// Stand in for graphics hardware
/* case 0x03: */
/* write_data(0x01); */
@ -266,27 +228,13 @@ void handle_ioreq() {
}
void cycle() {
// Make sure data get reset as input
if (!control.eeprom.programming) {
enable_data_out(0);
}
// We need this not detect IO multiple times
static uint8_t had_ioreq = 0;
if (!has_ioreq()) {
had_ioreq = 0;
}
// @todo Enable this one we start doing things using interrupts again
/* send_int(control.interrupt.type != CONTROL_INT_NONE); */
if (control.eeprom.programming && has_busak()) {
if (control.eeprom.programming) {
program_eeprom();
}
} else if (control.eeprom.programming != has_busak()) {
send_busrq(control.eeprom.programming);
} else if (has_memrq()) {
if (has_memrq()) {
handle_memrq();
} else if (has_ioreq() && !has_m1()) {
had_ioreq++;
@ -347,39 +295,7 @@ void control_execute_state() {
// @todo Properly reset everything
void control_reset() {
free(control.storage.buffer);
Control temp = {CONTROL_RESET_BEGIN, 0, {1, 0, 0, 0, 0, 0, 0, 0, NULL}, {0,0}, {0, 0, NULL}};
Control temp = {CONTROL_RESET_BEGIN, 0, {1, 0, 0, 0, 0, 0, 0, 0, NULL}};
control = temp;
control.storage.buffer = (uint8_t*)malloc(SD_PAGES*SD_PAGE_SIZE);
}
uint8_t control_receive_program(uint8_t byte) {
static uint16_t i = 0;
static uint16_t c = 0;
if (c <= 1) {
control.eeprom.length += byte << c*8;
c++;
} else {
if (c == 2) {
control.eeprom.data = malloc(control.eeprom.length);
c++;
}
control.eeprom.data[i] = byte;
i++;
}
if (i >= control.eeprom.length) {
i = 0;
c = 0;
control.eeprom.programming = 1;
return 1;
}
return 0;
}
void send_key(uint8_t c) {
control.input.c = c;
control.input.received = 1;
}

View File

@ -1,7 +1,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "firmware.h"
#include "control.h"
#include "io.h"
extern I2C_HandleTypeDef hi2c1;
extern UART_HandleTypeDef huart2;
@ -34,29 +37,43 @@ void firmware_update() {
HAL_UART_Receive(&huart2, data, length, 1000);
printf("Firmware received!\n\r");
printf("Uploading to target...\n\r");
switch (target) {
case TARGET_ROM:
control_program_eeprom(data, length);
break;
case TARGET_I2C: {
// Upload the application
uint8_t upload_command[4 + length];
upload_command[0] = 0x02;
upload_command[1] = 0x01;
// Make sure tell the device to enter bootloader mode first
// Upload the application
printf("Uploading to target...\n\r");
uint8_t upload_command[4 + length];
upload_command[0] = 0x02;
upload_command[1] = 0x01;
for (uint16_t offset = 0; offset < 8; ++offset) {
upload_command[2] = ((offset*0x80) >> 8) & 0xFF;
upload_command[3] = (offset*0x80) & 0xFF;
printf("0/%i\r", length);
// We need to handle the last section properly
memcpy(&upload_command[4], &data[offset*0x80], 0x80);
uint16_t remaining = length;
for (uint8_t offset = 0; remaining > 0; ++offset) {
upload_command[2] = ((offset*0x80) >> 8) & 0xFF;
upload_command[3] = (offset*0x80) & 0xFF;
HAL_I2C_Master_Transmit(&hi2c1, address << 1, upload_command, sizeof(upload_command), 1000);
}
uint8_t amount = remaining > 0x80 ? 0x80 : remaining;
remaining -= amount;
// Start application
uint8_t start_command[] = {0x01, 0x80};
HAL_I2C_Master_Transmit(&hi2c1, address << 1, start_command, sizeof(start_command), 1000);
break;
// We need to handle the last section properly
memcpy(&upload_command[4], &data[offset*0x80], amount);
HAL_I2C_Master_Transmit(&hi2c1, address << 1, upload_command, sizeof(upload_command), 1000);
printf("%i/%i\r", length-remaining, length);
}
printf("\n");
// Start application
uint8_t start_command[] = {0x01, 0x80};
HAL_I2C_Master_Transmit(&hi2c1, address << 1, start_command, sizeof(start_command), 1000);
break;
}
default:

View File

@ -73,113 +73,94 @@ static void MX_SDIO_SD_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
typedef uint8_t (*upload_callback_t)(uint8_t byte);
upload_callback_t upload_callback = NULL;
uint8_t byte;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART2) {
if (upload_callback) {
if (upload_callback(byte)) {
upload_callback = NULL;
static uint8_t cmd_buffer[128];
static uint32_t cmd_buffer_len = 0;
printf("Done\n\r");
}
} else {
if (cmd_buffer_len+1 > 128) {
printf("\n\rCommand is too long!\n\r");
cmd_buffer_len = 0;
return;
}
static uint8_t cmd_buffer[128];
static uint32_t cmd_buffer_len = 0;
if (cmd_buffer_len+1 > 128) {
printf("\n\rCommand is too long!\n\r");
cmd_buffer_len = 0;
return;
}
int handle_command = 0;
static int is_command = 0;
switch (byte) {
// @todo Handle \t
// Backspace
case 0x08:
if (is_command) {
if (cmd_buffer_len) {
cmd_buffer_len--;
} else {
is_command = 0;
}
break;
}
// else falltrough
// Newline
case '\r':
case '\n':
if (is_command) {
handle_command = 1;
break;
}
// else falltrough
default:
if (!is_command && cmd_buffer_len == 0 && byte == '#') {
is_command = 1;
int handle_command = 0;
static int is_command = 0;
switch (byte) {
// @todo Handle \t
// Backspace
case 0x08:
if (is_command) {
if (cmd_buffer_len) {
cmd_buffer_len--;
} else {
cmd_buffer[cmd_buffer_len] = byte;
cmd_buffer_len++;
is_command = 0;
}
break;
}
if (!is_command) {
// ONLY SEND THE FIRST CHAR
if (cmd_buffer_len > 0) {
send_key(byte);
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
}
cmd_buffer_len = 0;
} else if (handle_command && is_command) {
if (cmd_buffer_len == 1) {
switch (cmd_buffer[0]) {
case 'r':
control_reset();
printf("Starting...\n\r");
break;
// else falltrough
case 'b':
request_restart_to_bootloader();
printf("Restarting... (bootloader)\n\r");
break;
// Newline
case '\r':
case '\n':
if (is_command) {
handle_command = 1;
break;
}
// else falltrough
case 'u':
printf("Receiving program...\n\r");
upload_callback = &control_receive_program;
break;
case 'h':
printf("#r - (Re)start program\n\r#b - Restart (Bootloader)\n\r#u - Update\n\r#m - Mount the sd card to pc\n\r#h - Show this menu\n\r");
break;
case '#':
send_key('#');
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
break;
case 'a':
firmware_update();
break;
default:
printf("Unknown command: %c!\n\r", cmd_buffer[0]);
break;
}
default:
if (!is_command && cmd_buffer_len == 0 && byte == '#') {
is_command = 1;
} else {
printf("Unknown command!\n\r");
cmd_buffer[cmd_buffer_len] = byte;
cmd_buffer_len++;
}
break;
}
cmd_buffer_len = 0;
is_command = 0;
if (!is_command) {
// ONLY SEND THE FIRST CHAR
if (cmd_buffer_len > 0) {
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
}
cmd_buffer_len = 0;
} else if (handle_command && is_command) {
if (cmd_buffer_len == 1) {
switch (cmd_buffer[0]) {
case 'r':
control_reset();
printf("Starting...\n\r");
break;
case 'b':
request_restart_to_bootloader();
printf("Restarting... (bootloader)\n\r");
break;
case 'u':
firmware_update();
break;
case 'h':
printf("#r - (Re)start program\n\r#b - Restart (Bootloader)\n\r#u - Update\n\r#m - Mount the sd card to pc\n\r#h - Show this menu\n\r");
break;
case '#':
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
break;
default:
printf("Unknown command: %c!\n\r", cmd_buffer[0]);
break;
}
} else {
printf("Unknown command!\n\r");
}
cmd_buffer_len = 0;
is_command = 0;
}
HAL_UART_Receive_IT(&huart2, &byte, 1);
}