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

View File

@ -47,86 +47,47 @@ uint32_t calculate_lba() {
return temp; return temp;
} }
void program_eeprom() { void control_program_eeprom(uint8_t* data, uint16_t length) {
static int address_counter = 0; // Take control of the bus
static int read_counter = 0; printf("Taking control of bus...\n\r");
static int write_counter = 0; send_busrq(1);
while (!has_busak()) {
// Check if we are done control_execute_state();
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;
} }
// Turn on the update light printf("Done!\n\r");
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET); printf("Writing to ROM...\n\r");
enable_address_out(1);
// Check if the data is written
if (write_counter < 100) {
// Select correct device and address
select_device(memory_map_0[0]); select_device(memory_map_0[0]);
write_address(address_counter);
// Write the data for (uint16_t i = 0; i < length; ++i) {
write_data(control.eeprom.data[address_counter]); write_address(i);
write_data(data[i]);
// Send write request
enable_data_out(1); enable_data_out(1);
send_memrq(1); send_memrq(1);
send_wr(1); send_wr(1);
write_counter++;
} else {
// Stop writing
enable_data_out(0);
send_memrq(1);
send_wr(0); send_wr(0);
enable_data_out(0);
send_rd(1); send_rd(1);
printf("%i/%i\r", i+1, length);
for (;;) {
uint8_t d = read_data(); uint8_t d = read_data();
if (read_counter > 5 && d == control.eeprom.data[address_counter]) { if (d == data[i]) {
address_counter++; break;
write_counter = 0;
read_counter = 0;
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++;
} }
} }
send_rd(0);
send_memrq(0);
}
printf("\n");
} }
void handle_memrq() { void handle_memrq() {
@ -139,6 +100,7 @@ void handle_io_read() {
uint8_t address = read_address() & 0xFF; uint8_t address = read_address() & 0xFF;
switch (address) { switch (address) {
// @todo This should be detected on startup
// Stand in for graphics hardware // Stand in for graphics hardware
/* case 0x03: */ /* case 0x03: */
/* write_data(0x01); */ /* write_data(0x01); */
@ -266,27 +228,13 @@ void handle_ioreq() {
} }
void cycle() { 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 // We need this not detect IO multiple times
static uint8_t had_ioreq = 0; static uint8_t had_ioreq = 0;
if (!has_ioreq()) { if (!has_ioreq()) {
had_ioreq = 0; had_ioreq = 0;
} }
// @todo Enable this one we start doing things using interrupts again if (has_memrq()) {
/* 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()) {
handle_memrq(); handle_memrq();
} else if (has_ioreq() && !has_m1()) { } else if (has_ioreq() && !has_m1()) {
had_ioreq++; had_ioreq++;
@ -347,39 +295,7 @@ void control_execute_state() {
// @todo Properly reset everything // @todo Properly reset everything
void control_reset() { void control_reset() {
free(control.storage.buffer); 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 = temp;
control.storage.buffer = (uint8_t*)malloc(SD_PAGES*SD_PAGE_SIZE); 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 <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "firmware.h" #include "firmware.h"
#include "control.h"
#include "io.h"
extern I2C_HandleTypeDef hi2c1; extern I2C_HandleTypeDef hi2c1;
extern UART_HandleTypeDef huart2; extern UART_HandleTypeDef huart2;
@ -34,25 +37,39 @@ void firmware_update() {
HAL_UART_Receive(&huart2, data, length, 1000); HAL_UART_Receive(&huart2, data, length, 1000);
printf("Firmware received!\n\r"); printf("Firmware received!\n\r");
printf("Uploading to target...\n\r");
switch (target) { switch (target) {
case TARGET_ROM:
control_program_eeprom(data, length);
break;
case TARGET_I2C: { case TARGET_I2C: {
// Make sure tell the device to enter bootloader mode first
// Upload the application // Upload the application
printf("Uploading to target...\n\r");
uint8_t upload_command[4 + length]; uint8_t upload_command[4 + length];
upload_command[0] = 0x02; upload_command[0] = 0x02;
upload_command[1] = 0x01; upload_command[1] = 0x01;
for (uint16_t offset = 0; offset < 8; ++offset) { printf("0/%i\r", length);
uint16_t remaining = length;
for (uint8_t offset = 0; remaining > 0; ++offset) {
upload_command[2] = ((offset*0x80) >> 8) & 0xFF; upload_command[2] = ((offset*0x80) >> 8) & 0xFF;
upload_command[3] = (offset*0x80) & 0xFF; upload_command[3] = (offset*0x80) & 0xFF;
uint8_t amount = remaining > 0x80 ? 0x80 : remaining;
remaining -= amount;
// We need to handle the last section properly // We need to handle the last section properly
memcpy(&upload_command[4], &data[offset*0x80], 0x80); memcpy(&upload_command[4], &data[offset*0x80], amount);
HAL_I2C_Master_Transmit(&hi2c1, address << 1, upload_command, sizeof(upload_command), 1000); HAL_I2C_Master_Transmit(&hi2c1, address << 1, upload_command, sizeof(upload_command), 1000);
printf("%i/%i\r", length-remaining, length);
} }
printf("\n");
// Start application // Start application
uint8_t start_command[] = {0x01, 0x80}; uint8_t start_command[] = {0x01, 0x80};
HAL_I2C_Master_Transmit(&hi2c1, address << 1, start_command, sizeof(start_command), 1000); HAL_I2C_Master_Transmit(&hi2c1, address << 1, start_command, sizeof(start_command), 1000);

View File

@ -73,20 +73,9 @@ static void MX_SDIO_SD_Init(void);
/* Private user code ---------------------------------------------------------*/ /* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */ /* USER CODE BEGIN 0 */
typedef uint8_t (*upload_callback_t)(uint8_t byte);
upload_callback_t upload_callback = NULL;
uint8_t byte; uint8_t byte;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART2) { if (huart->Instance == USART2) {
if (upload_callback) {
if (upload_callback(byte)) {
upload_callback = NULL;
printf("Done\n\r");
}
} else {
static uint8_t cmd_buffer[128]; static uint8_t cmd_buffer[128];
static uint32_t cmd_buffer_len = 0; static uint32_t cmd_buffer_len = 0;
@ -134,7 +123,6 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (!is_command) { if (!is_command) {
// ONLY SEND THE FIRST CHAR // ONLY SEND THE FIRST CHAR
if (cmd_buffer_len > 0) { if (cmd_buffer_len > 0) {
send_key(byte);
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000); HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
} }
cmd_buffer_len = 0; cmd_buffer_len = 0;
@ -152,8 +140,7 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
break; break;
case 'u': case 'u':
printf("Receiving program...\n\r"); firmware_update();
upload_callback = &control_receive_program;
break; break;
case 'h': case 'h':
@ -161,14 +148,9 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
break; break;
case '#': case '#':
send_key('#');
HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000); HAL_I2C_Master_Transmit(&hi2c1, 0x04 << 1, &byte, 1, 1000);
break; break;
case 'a':
firmware_update();
break;
default: default:
printf("Unknown command: %c!\n\r", cmd_buffer[0]); printf("Unknown command: %c!\n\r", cmd_buffer[0]);
break; break;
@ -180,7 +162,6 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
cmd_buffer_len = 0; cmd_buffer_len = 0;
is_command = 0; is_command = 0;
} }
}
HAL_UART_Receive_IT(&huart2, &byte, 1); HAL_UART_Receive_IT(&huart2, &byte, 1);
} }
} }