mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
more bug fixes and improvements
This commit is contained in:
parent
980d28d94d
commit
2dd8613794
2
build.sh
2
build.sh
@ -83,6 +83,8 @@ build_cic () {
|
|||||||
build_fpga () {
|
build_fpga () {
|
||||||
if [ "$BUILT_FPGA" = true ]; then return; fi
|
if [ "$BUILT_FPGA" = true ]; then return; fi
|
||||||
|
|
||||||
|
build_cic
|
||||||
|
|
||||||
pushd fw/project/lcmxo2 > /dev/null
|
pushd fw/project/lcmxo2 > /dev/null
|
||||||
if [ "$FORCE_CLEAN" = true ]; then
|
if [ "$FORCE_CLEAN" = true ]; then
|
||||||
rm -rf ./impl1/
|
rm -rf ./impl1/
|
||||||
|
@ -305,8 +305,8 @@ void hw_spi_tx (uint8_t *data, int length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define I2C_TIMEOUT_US_BUSY (1000)
|
#define I2C_TIMEOUT_US_BUSY (10000)
|
||||||
#define I2C_TIMEOUT_US_PER_BYTE (100)
|
#define I2C_TIMEOUT_US_PER_BYTE (1000)
|
||||||
|
|
||||||
static void hw_i2c_init (void) {
|
static void hw_i2c_init (void) {
|
||||||
RCC->APBENR1 |= RCC_APBENR1_I2C1EN;
|
RCC->APBENR1 |= RCC_APBENR1_I2C1EN;
|
||||||
@ -331,18 +331,18 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t timeout = ((tx_length + rx_length) * I2C_TIMEOUT_US_PER_BYTE);
|
|
||||||
|
|
||||||
hw_timeout_start();
|
|
||||||
|
|
||||||
if (tx_length > 0) {
|
if (tx_length > 0) {
|
||||||
|
uint32_t tx_timeout = ((tx_length + 1) * I2C_TIMEOUT_US_PER_BYTE);
|
||||||
|
|
||||||
|
hw_timeout_start();
|
||||||
|
|
||||||
I2C1->ICR = I2C_ICR_NACKCF;
|
I2C1->ICR = I2C_ICR_NACKCF;
|
||||||
I2C1->CR2 = (
|
I2C1->CR2 = (
|
||||||
((rx_length > 0) ? 0 : I2C_CR2_AUTOEND) |
|
((rx_length > 0) ? 0 : I2C_CR2_AUTOEND) |
|
||||||
(tx_length << I2C_CR2_NBYTES_Pos) |
|
(tx_length << I2C_CR2_NBYTES_Pos) |
|
||||||
|
I2C_CR2_START |
|
||||||
(address << I2C_CR2_SADD_Pos)
|
(address << I2C_CR2_SADD_Pos)
|
||||||
);
|
);
|
||||||
I2C1->CR2 |= I2C_CR2_START;
|
|
||||||
|
|
||||||
uint8_t left = tx_length;
|
uint8_t left = tx_length;
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
return I2C_ERR_NACK;
|
return I2C_ERR_NACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw_timeout_occured(timeout)) {
|
if (hw_timeout_occured(tx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,20 +368,24 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!(I2C1->ISR & I2C_ISR_TC)) {
|
while (!(I2C1->ISR & I2C_ISR_TC)) {
|
||||||
if (hw_timeout_occured(timeout)) {
|
if (hw_timeout_occured(tx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_length > 0) {
|
if (rx_length > 0) {
|
||||||
|
uint32_t rx_timeout = ((rx_length + 1) * I2C_TIMEOUT_US_PER_BYTE);
|
||||||
|
|
||||||
|
hw_timeout_start();
|
||||||
|
|
||||||
I2C1->CR2 = (
|
I2C1->CR2 = (
|
||||||
I2C_CR2_AUTOEND |
|
I2C_CR2_AUTOEND |
|
||||||
(rx_length << I2C_CR2_NBYTES_Pos) |
|
(rx_length << I2C_CR2_NBYTES_Pos) |
|
||||||
|
I2C_CR2_START |
|
||||||
I2C_CR2_RD_WRN |
|
I2C_CR2_RD_WRN |
|
||||||
(address << I2C_CR2_SADD_Pos)
|
(address << I2C_CR2_SADD_Pos)
|
||||||
);
|
);
|
||||||
I2C1->CR2 |= I2C_CR2_START;
|
|
||||||
|
|
||||||
uint8_t left = rx_length;
|
uint8_t left = rx_length;
|
||||||
|
|
||||||
@ -393,7 +397,7 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
left -= 1;
|
left -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw_timeout_occured(timeout)) {
|
if (hw_timeout_occured(rx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,20 +121,26 @@ static void lcmxo2_reset_bus (void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint8_t *buffer, uint8_t length, bool write) {
|
static bool lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint8_t *buffer, uint8_t length, bool write) {
|
||||||
#ifdef LCMXO2_I2C
|
#ifdef LCMXO2_I2C
|
||||||
uint8_t packet[20] = { cmd, ((arg >> 16) & 0xFF), ((arg >> 8) & 0xFF), (arg & 0xFF) };
|
uint8_t packet[20] = { cmd, ((arg >> 16) & 0xFF), ((arg >> 8) & 0xFF), (arg & 0xFF) };
|
||||||
int packet_length = ((type == CMD_TWO_OP) ? 3 : 4);
|
int packet_length = ((type == CMD_TWO_OP) ? 3 : 4);
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
packet[packet_length + i] = buffer[i];
|
packet[packet_length + i] = buffer[i];
|
||||||
}
|
}
|
||||||
packet_length += length;
|
packet_length += length;
|
||||||
}
|
}
|
||||||
hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
|
||||||
|
i2c_err_t err = hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
||||||
|
|
||||||
|
return (err != I2C_OK);
|
||||||
#else
|
#else
|
||||||
uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF);
|
|
||||||
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
||||||
|
|
||||||
|
uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF);
|
||||||
|
|
||||||
fpga_reg_set(REG_VENDOR_DATA, data);
|
fpga_reg_set(REG_VENDOR_DATA, data);
|
||||||
fpga_reg_set(REG_VENDOR_SCR,
|
fpga_reg_set(REG_VENDOR_SCR,
|
||||||
(LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) |
|
(LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) |
|
||||||
@ -143,7 +149,9 @@ static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint
|
|||||||
VENDOR_SCR_WRITE |
|
VENDOR_SCR_WRITE |
|
||||||
VENDOR_SCR_START
|
VENDOR_SCR_START
|
||||||
);
|
);
|
||||||
|
|
||||||
while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY);
|
while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY);
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
if (write) {
|
if (write) {
|
||||||
lcmxo2_write_data(buffer, length);
|
lcmxo2_write_data(buffer, length);
|
||||||
@ -151,82 +159,105 @@ static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint
|
|||||||
lcmxo2_read_data(buffer, length);
|
lcmxo2_read_data(buffer, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
lcmxo2_reg_set(LCMXO2_CFGCR, 0);
|
||||||
|
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_read_device_id (uint8_t *id) {
|
static bool lcmxo2_read_device_id (uint8_t *id) {
|
||||||
lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL, id, DEVICE_ID_SIZE, false);
|
return lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL, id, DEVICE_ID_SIZE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t lcmxo2_read_status (void) {
|
static uint32_t lcmxo2_read_status (uint32_t *status) {
|
||||||
uint32_t status = 0;
|
uint32_t tmp = 0;
|
||||||
lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL, (uint8_t *) (&status), 4, false);
|
bool error = lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL, (uint8_t *) (&tmp), 4, false);
|
||||||
return SWAP32(status);
|
*status = SWAP32(tmp);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_wait_busy (void) {
|
static bool lcmxo2_wait_busy (void) {
|
||||||
|
bool error;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
do {
|
do {
|
||||||
status = lcmxo2_read_status();
|
error = lcmxo2_read_status(&status);
|
||||||
} while (status & LSC_STATUS_BUSY);
|
} while ((!error) && (status & LSC_STATUS_BUSY));
|
||||||
return (status & LSC_STATUS_FAIL);
|
return (error) || (status & LSC_STATUS_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_enable_flash (void) {
|
static bool lcmxo2_enable_flash (void) {
|
||||||
#ifdef LCMXO2_I2C
|
#ifdef LCMXO2_I2C
|
||||||
lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_TWO_OP, NULL, 0, false);
|
if (lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_TWO_OP, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL, NULL, 0, false);
|
if (lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_disable_flash (void) {
|
static bool lcmxo2_disable_flash (void) {
|
||||||
lcmxo2_wait_busy();
|
if (lcmxo2_wait_busy()) {
|
||||||
lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP, NULL, 0, false);
|
return true;
|
||||||
lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL, NULL, 0, false);
|
}
|
||||||
|
if (lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL, NULL, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_erase_featbits (void) {
|
static bool lcmxo2_erase_featbits (void) {
|
||||||
lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_FEATURE, CMD_NORMAL, NULL, 0, false);
|
if (lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_FEATURE, CMD_NORMAL, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_erase_flash (void) {
|
static bool lcmxo2_erase_flash (void) {
|
||||||
lcmxo2_execute_cmd(ISC_ERASE, (ISC_ERASE_UFM | ISC_ERASE_CFG), CMD_NORMAL, NULL, 0, false);
|
if (lcmxo2_execute_cmd(ISC_ERASE, (ISC_ERASE_UFM | ISC_ERASE_CFG), CMD_NORMAL, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_reset_flash_address (void) {
|
static bool lcmxo2_reset_flash_address (void) {
|
||||||
lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL, NULL, 0, false);
|
return lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL, NULL, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_write_flash_page (uint8_t *buffer) {
|
static bool lcmxo2_write_flash_page (uint8_t *buffer) {
|
||||||
lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL, buffer, FLASH_PAGE_SIZE, true);
|
if (lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL, buffer, FLASH_PAGE_SIZE, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_read_flash_page (uint8_t *buffer) {
|
static bool lcmxo2_read_flash_page (uint8_t *buffer) {
|
||||||
lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED, buffer, FLASH_PAGE_SIZE, false);
|
return lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED, buffer, FLASH_PAGE_SIZE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_program_done (void) {
|
static bool lcmxo2_program_done (void) {
|
||||||
lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL, NULL, 0, false);
|
if (lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL, NULL, 0, false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool lcmxo2_write_featbits (uint8_t *buffer) {
|
static bool lcmxo2_write_featbits (uint8_t *buffer) {
|
||||||
lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, true);
|
if (lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return lcmxo2_wait_busy();
|
return lcmxo2_wait_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_read_featbits (uint8_t *buffer) {
|
static bool lcmxo2_read_featbits (uint8_t *buffer) {
|
||||||
lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, false);
|
return lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcmxo2_refresh (void) {
|
static bool lcmxo2_refresh (void) {
|
||||||
lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP, NULL, 0, false);
|
return lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP, NULL, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vendor_error_t lcmxo2_fail (vendor_error_t error) {
|
static vendor_error_t lcmxo2_fail (vendor_error_t error) {
|
||||||
@ -346,20 +377,29 @@ static bool primer_check_rx_length (primer_cmd_e cmd, size_t rx_length) {
|
|||||||
static bool lcmxo2_init_featbits (void) {
|
static bool lcmxo2_init_featbits (void) {
|
||||||
uint8_t programmed[2] = { 0x00, 0x00 };
|
uint8_t programmed[2] = { 0x00, 0x00 };
|
||||||
uint8_t target[2] = { FEATBITS_0_SPI_OFF, FEATBITS_1_PROGRAMN_OFF };
|
uint8_t target[2] = { FEATBITS_0_SPI_OFF, FEATBITS_1_PROGRAMN_OFF };
|
||||||
lcmxo2_read_featbits(programmed);
|
|
||||||
|
if (lcmxo2_read_featbits(programmed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((programmed[0] == target[0]) && (programmed[1] == target[1])) {
|
if ((programmed[0] == target[0]) && (programmed[1] == target[1])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lcmxo2_erase_featbits()) {
|
if (lcmxo2_erase_featbits()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (lcmxo2_write_featbits(target)) {
|
if (lcmxo2_write_featbits(target)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
lcmxo2_read_featbits(programmed);
|
if (lcmxo2_read_featbits(programmed)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((programmed[0] != target[0]) || (programmed[1] != target[1])) {
|
if ((programmed[0] != target[0]) || (programmed[1] != target[1])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +443,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_GET_DEVICE_ID:
|
case CMD_GET_DEVICE_ID:
|
||||||
lcmxo2_read_device_id(buffer);
|
error = lcmxo2_read_device_id(buffer);
|
||||||
tx_length = 4;
|
tx_length = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -416,7 +456,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_RESET_ADDRESS:
|
case CMD_RESET_ADDRESS:
|
||||||
lcmxo2_reset_flash_address();
|
error = lcmxo2_reset_flash_address();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_WRITE_PAGE:
|
case CMD_WRITE_PAGE:
|
||||||
@ -424,7 +464,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_READ_PAGE:
|
case CMD_READ_PAGE:
|
||||||
lcmxo2_read_flash_page(buffer);
|
error = lcmxo2_read_flash_page(buffer);
|
||||||
tx_length = FLASH_PAGE_SIZE;
|
tx_length = FLASH_PAGE_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -437,7 +477,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_REFRESH:
|
case CMD_REFRESH:
|
||||||
lcmxo2_refresh();
|
error = lcmxo2_refresh();
|
||||||
hw_delay_ms(200);
|
hw_delay_ms(200);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -204,9 +204,16 @@ class STM32Bootloader:
|
|||||||
|
|
||||||
__connected = False
|
__connected = False
|
||||||
|
|
||||||
def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]):
|
def __init__(
|
||||||
|
self,
|
||||||
|
write: Callable[[bytes], None],
|
||||||
|
read: Callable[[int], bytes],
|
||||||
|
flush: Callable[[None], None],
|
||||||
|
progress: Callable[[int, int, str], None]
|
||||||
|
):
|
||||||
self.__write = write
|
self.__write = write
|
||||||
self.__read = read
|
self.__read = read
|
||||||
|
self.__flush = flush
|
||||||
self.__progress = progress
|
self.__progress = progress
|
||||||
|
|
||||||
def __append_xor(self, data: bytes) -> bytes:
|
def __append_xor(self, data: bytes) -> bytes:
|
||||||
@ -217,7 +224,7 @@ class STM32Bootloader:
|
|||||||
|
|
||||||
def __check_ack(self) -> None:
|
def __check_ack(self) -> None:
|
||||||
response = self.__read(1)
|
response = self.__read(1)
|
||||||
if (response == None):
|
if (len(response) != 1):
|
||||||
raise STM32BootloaderException('No ACK/NACK byte received')
|
raise STM32BootloaderException('No ACK/NACK byte received')
|
||||||
if (response == self.__NACK):
|
if (response == self.__NACK):
|
||||||
raise STM32BootloaderException('NACK byte received')
|
raise STM32BootloaderException('NACK byte received')
|
||||||
@ -228,18 +235,22 @@ class STM32Bootloader:
|
|||||||
if (len(cmd) != 1):
|
if (len(cmd) != 1):
|
||||||
raise ValueError('Command must contain only one byte')
|
raise ValueError('Command must contain only one byte')
|
||||||
self.__write(self.__append_xor(cmd))
|
self.__write(self.__append_xor(cmd))
|
||||||
|
self.__flush()
|
||||||
self.__check_ack()
|
self.__check_ack()
|
||||||
|
|
||||||
def __data_write(self, data: bytes) -> None:
|
def __data_write(self, data: bytes) -> None:
|
||||||
self.__write(self.__append_xor(data))
|
self.__write(self.__append_xor(data))
|
||||||
|
self.__flush()
|
||||||
self.__check_ack()
|
self.__check_ack()
|
||||||
|
|
||||||
def __data_read(self) -> bytes:
|
def __data_read(self) -> bytes:
|
||||||
length = self.__read(1)
|
length = self.__read(1)
|
||||||
if (len(length) != 1):
|
if (len(length) != 1):
|
||||||
raise STM32BootloaderException('Did not receive length byte')
|
raise STM32BootloaderException('Did not receive length byte')
|
||||||
length = length[0]
|
length = (length[0] + 1)
|
||||||
data = self.__read(length + 1)
|
data = self.__read(length)
|
||||||
|
if (len(data) != length):
|
||||||
|
raise STM32BootloaderException('Did not receive requested data bytes')
|
||||||
self.__check_ack()
|
self.__check_ack()
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -253,7 +264,10 @@ class STM32Bootloader:
|
|||||||
self.__cmd_send(b'\x11')
|
self.__cmd_send(b'\x11')
|
||||||
self.__data_write(address.to_bytes(4, byteorder='big'))
|
self.__data_write(address.to_bytes(4, byteorder='big'))
|
||||||
self.__data_write(bytes([length - 1]))
|
self.__data_write(bytes([length - 1]))
|
||||||
return self.__read(length)
|
data = self.__read(length)
|
||||||
|
if (len(data) != length):
|
||||||
|
raise STM32BootloaderException(f'Did not receive requested memory bytes')
|
||||||
|
return data
|
||||||
|
|
||||||
def __go(self, address: int) -> None:
|
def __go(self, address: int) -> None:
|
||||||
self.__cmd_send(b'\x21')
|
self.__cmd_send(b'\x21')
|
||||||
@ -288,8 +302,12 @@ class STM32Bootloader:
|
|||||||
|
|
||||||
def connect(self, id: int) -> None:
|
def connect(self, id: int) -> None:
|
||||||
if (not self.__connected):
|
if (not self.__connected):
|
||||||
self.__write(self.__INIT)
|
try:
|
||||||
self.__check_ack()
|
self.__write(self.__INIT)
|
||||||
|
self.__flush()
|
||||||
|
self.__check_ack()
|
||||||
|
except STM32BootloaderException as e:
|
||||||
|
raise STM32BootloaderException(f'Could not connect to the STM32 ({e})')
|
||||||
self.__connected = True
|
self.__connected = True
|
||||||
dev_id = self.__get_id()
|
dev_id = self.__get_id()
|
||||||
if (dev_id != id):
|
if (dev_id != id):
|
||||||
@ -339,9 +357,16 @@ class LCMXO2Primer:
|
|||||||
|
|
||||||
DEV_ID_LCMXO2_7000HC = b'\x01\x2B\xD0\x43'
|
DEV_ID_LCMXO2_7000HC = b'\x01\x2B\xD0\x43'
|
||||||
|
|
||||||
def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]):
|
def __init__(
|
||||||
|
self,
|
||||||
|
write: Callable[[bytes], None],
|
||||||
|
read: Callable[[int], bytes],
|
||||||
|
flush: Callable[[None], None],
|
||||||
|
progress: Callable[[int, int, str], None]
|
||||||
|
):
|
||||||
self.__write = write
|
self.__write = write
|
||||||
self.__read = read
|
self.__read = read
|
||||||
|
self.__flush = flush
|
||||||
self.__progress = progress
|
self.__progress = progress
|
||||||
|
|
||||||
def __cmd_execute(self, cmd: bytes, data: bytes=b'') -> bytes:
|
def __cmd_execute(self, cmd: bytes, data: bytes=b'') -> bytes:
|
||||||
@ -355,14 +380,20 @@ class LCMXO2Primer:
|
|||||||
packet += data
|
packet += data
|
||||||
packet += crc32(packet).to_bytes(4, byteorder='little')
|
packet += crc32(packet).to_bytes(4, byteorder='little')
|
||||||
self.__write(packet)
|
self.__write(packet)
|
||||||
|
self.__flush()
|
||||||
|
|
||||||
response = self.__read(5)
|
response = self.__read(5)
|
||||||
if (len(response) != 5):
|
if (len(response) != 5):
|
||||||
raise LCMXO2PrimerException(f'No response received [{cmd}]')
|
raise LCMXO2PrimerException(f'No response received [{cmd}]')
|
||||||
length = int.from_bytes(response[4:5], byteorder='little')
|
length = int.from_bytes(response[4:5], byteorder='little')
|
||||||
response += self.__read(length)
|
response_data = self.__read(length)
|
||||||
calculated_checksum = crc32(response)
|
if (len(response_data) != length):
|
||||||
received_checksum = int.from_bytes(self.__read(4), byteorder='little')
|
raise LCMXO2PrimerException(f'No response data received [{cmd}]')
|
||||||
|
checksum = self.__read(4)
|
||||||
|
if (len(checksum) != 4):
|
||||||
|
raise LCMXO2PrimerException(f'No response data checksum received [{cmd}]')
|
||||||
|
calculated_checksum = crc32(response + response_data)
|
||||||
|
received_checksum = int.from_bytes(checksum, byteorder='little')
|
||||||
|
|
||||||
if (response[0:3] != b'RSP'):
|
if (response[0:3] != b'RSP'):
|
||||||
raise LCMXO2PrimerException(f'Invalid response token [{response[0:3]} / {cmd}]')
|
raise LCMXO2PrimerException(f'Invalid response token [{response[0:3]} / {cmd}]')
|
||||||
@ -371,16 +402,19 @@ class LCMXO2Primer:
|
|||||||
if (calculated_checksum != received_checksum):
|
if (calculated_checksum != received_checksum):
|
||||||
raise LCMXO2PrimerException(f'Invalid response checksum [{cmd}]')
|
raise LCMXO2PrimerException(f'Invalid response checksum [{cmd}]')
|
||||||
|
|
||||||
return response[5:]
|
return response_data
|
||||||
|
|
||||||
def connect(self, id: bytes) -> None:
|
def connect(self, id: bytes) -> None:
|
||||||
primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID)
|
try:
|
||||||
if (primer_id != self.__PRIMER_ID_LCMXO2):
|
primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID)
|
||||||
raise LCMXO2PrimerException('Invalid primer ID received')
|
if (primer_id != self.__PRIMER_ID_LCMXO2):
|
||||||
|
raise LCMXO2PrimerException('Invalid primer ID received')
|
||||||
|
|
||||||
dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID)
|
dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID)
|
||||||
if (dev_id != id):
|
if (dev_id != id):
|
||||||
raise LCMXO2PrimerException('Invalid FPGA device id received')
|
raise LCMXO2PrimerException('Invalid FPGA device id received')
|
||||||
|
except LCMXO2PrimerException as e:
|
||||||
|
raise LCMXO2PrimerException(f'Could not connect to the LCMXO2 primer ({e})')
|
||||||
|
|
||||||
def load_flash_and_run(self, data: bytes, description: str) -> None:
|
def load_flash_and_run(self, data: bytes, description: str) -> None:
|
||||||
erase_description = f'{description} / Erase'
|
erase_description = f'{description} / Erase'
|
||||||
@ -599,8 +633,8 @@ class SC64BringUp:
|
|||||||
write_timeout=self.__SERIAL_TIMEOUT
|
write_timeout=self.__SERIAL_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
stm32_bootloader = STM32Bootloader(link.write, link.read, self.__progress)
|
stm32_bootloader = STM32Bootloader(link.write, link.read, link.flush, self.__progress)
|
||||||
lcmxo2_primer = LCMXO2Primer(link.write, link.read, self.__progress)
|
lcmxo2_primer = LCMXO2Primer(link.write, link.read, link.flush, self.__progress)
|
||||||
|
|
||||||
stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX)
|
stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX)
|
||||||
stm32_bootloader.load_ram_and_run(self.__sc64_update_data.get_primer_data(), 'FPGA primer -> STM32 RAM')
|
stm32_bootloader.load_ram_and_run(self.__sc64_update_data.get_primer_data(), 'FPGA primer -> STM32 RAM')
|
||||||
@ -645,7 +679,7 @@ if __name__ == '__main__':
|
|||||||
sc64_bring_up = SC64BringUp(progress=utils.progress)
|
sc64_bring_up = SC64BringUp(progress=utils.progress)
|
||||||
|
|
||||||
Utils.log()
|
Utils.log()
|
||||||
Utils.info('[ Welcome to SC64 flashcart board bring-up! ]')
|
Utils.info('[ Welcome to SummerCart64 flashcart board bring-up! ]')
|
||||||
Utils.log()
|
Utils.log()
|
||||||
|
|
||||||
Utils.log(f'Serial port: {port}')
|
Utils.log(f'Serial port: {port}')
|
||||||
@ -683,6 +717,7 @@ if __name__ == '__main__':
|
|||||||
original_sigint_handler = signal.getsignal(signal.SIGINT)
|
original_sigint_handler = signal.getsignal(signal.SIGINT)
|
||||||
try:
|
try:
|
||||||
signal.signal(signal.SIGINT, lambda *kwargs: utils.exit_warning())
|
signal.signal(signal.SIGINT, lambda *kwargs: utils.exit_warning())
|
||||||
|
Utils.log('Starting SC64 flashcart board bring-up...')
|
||||||
sc64_bring_up.start_bring_up(port, bootloader_only)
|
sc64_bring_up.start_bring_up(port, bootloader_only)
|
||||||
except (serial.SerialException, STM32BootloaderException, LCMXO2PrimerException, SC64Exception) as e:
|
except (serial.SerialException, STM32BootloaderException, LCMXO2PrimerException, SC64Exception) as e:
|
||||||
if (utils.get_progress_active):
|
if (utils.get_progress_active):
|
||||||
|
Loading…
Reference in New Issue
Block a user