[sw/bootloader] TWI fix for bootloader (#1229)

This commit is contained in:
stnolting 2025-04-17 18:44:32 +02:00 committed by GitHub
commit 9ab5f6225b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 73 additions and 20 deletions

View file

@ -42,6 +42,11 @@
#define UART_HW_HANDSHAKE_EN 0
#endif
// Print splash screen
#ifndef UART_PRINT_SPLASH_EN
#define UART_PRINT_SPLASH_EN 1
#endif
/**********************************************************************
* Status LED
**********************************************************************/
@ -120,7 +125,12 @@
// TWI clock divider
#ifndef TWI_CLK_DIV
#define TWI_CLK_DIV 1
#define TWI_CLK_DIV 3
#endif
// TWI allow clock stretching
#ifndef TWI_CLK_STRECH_EN
#define TWI_CLK_STRECH_EN 0
#endif
// TWI device ID (write address; R/W cleared)
@ -138,4 +148,9 @@
#define TWI_FLASH_ADDR_BYTES 2
#endif
// TWI flash bulk write enable
#ifndef TWI_FLASH_BULK_WRITE_EN
#define TWI_FLASH_BULK_WRITE_EN 0
#endif
#endif // CONFIG_H

View file

@ -18,5 +18,6 @@
int twi_flash_read_word(uint32_t addr, uint32_t* rdata);
int twi_flash_write_word(uint32_t addr, uint32_t wdata);
void twi_flash_delay_twi_tick(int tick_count);
#endif // TWI_FLASH_H

View file

@ -84,10 +84,10 @@ int twi_flash_read_word(uint32_t addr, uint32_t* rdata) {
for (i = 0; i < 4; i++) {
transfer = 0xFF;
if (i == 3) {
device_nack |= neorv32_twi_transfer(&transfer, 1); // NACK by host
neorv32_twi_transfer(&transfer, 0); // NACK by host
}
else {
neorv32_twi_transfer(&transfer, 0);
neorv32_twi_transfer(&transfer, 1); // ACK by Host
}
data.uint8[i] = transfer;
}
@ -96,14 +96,10 @@ int twi_flash_read_word(uint32_t addr, uint32_t* rdata) {
// send stop condition
neorv32_twi_generate_stop();
if (device_nack) {
neorv32_uart0_puts("\nTWI_R ERR\n");
return 1;
}
else {
neorv32_uart0_puts("\nTWI_R OK\n");
return 0;
}
// delay next read
twi_flash_delay_twi_tick(1000);
return device_nack;
#else
return 1;
#endif
@ -115,9 +111,10 @@ int twi_flash_read_word(uint32_t addr, uint32_t* rdata) {
*
* @param addr TWI flash write address.
* @param wdata TWI flash write data.
* @param stop Send TWI stop command at end of transmission
* @return 0 if success, !=0 if error
**************************************************************************/
int twi_flash_write_byte(uint32_t addr, uint8_t wdata) {
int twi_flash_write_byte(uint32_t addr, uint8_t wdata, int stop) {
int device_nack = 0;
uint8_t transfer;
@ -165,7 +162,13 @@ int twi_flash_write_byte(uint32_t addr, uint8_t wdata) {
device_nack |= neorv32_twi_transfer(&transfer, 0);
// send stop condition
neorv32_twi_generate_stop();
if (stop) {
neorv32_twi_generate_stop();
// delay next send for EEPROM write cycle
neorv32_aux_delay_ms(NEORV32_SYSINFO->CLK,5); // t_wr(max) = 5ms
}
return device_nack;
}
@ -191,11 +194,28 @@ int twi_flash_write_word(uint32_t addr, uint32_t wdata) {
// write four bytes
data.uint32 = wdata;
device_nack += twi_flash_write_byte(addr+0, data.uint8[0]);
device_nack += twi_flash_write_byte(addr+1, data.uint8[1]);
device_nack += twi_flash_write_byte(addr+2, data.uint8[2]);
device_nack += twi_flash_write_byte(addr+3, data.uint8[3]);
#if(TWI_FLASH_BULK_WRITE_EN != 0)
// send data
uint8_t transfer = 0;
device_nack += twi_flash_write_byte(addr, data.uint8[0], 0); // Start + addr + first byte
transfer = data.uint8[1];
device_nack += neorv32_twi_transfer(&transfer, 0);
transfer = data.uint8[2];
device_nack += neorv32_twi_transfer(&transfer, 0);
transfer = data.uint8[3];
device_nack += neorv32_twi_transfer(&transfer, 0);
// send stop condition
neorv32_twi_generate_stop();
// delay next send for EEPROM write cycle
neorv32_aux_delay_ms(NEORV32_SYSINFO->CLK,5); // t_wr(max) = 5ms
#else
device_nack += twi_flash_write_byte(addr+0, data.uint8[0], 1);
device_nack += twi_flash_write_byte(addr+1, data.uint8[1], 1);
device_nack += twi_flash_write_byte(addr+2, data.uint8[2], 1);
device_nack += twi_flash_write_byte(addr+3, data.uint8[3], 1);
#endif
if (device_nack) {
return 1;
}
@ -206,3 +226,19 @@ int twi_flash_write_word(uint32_t addr, uint32_t wdata) {
return 1;
#endif
}
/**
* @brief Keeps TWI Peripheral in IDLE for 'tick_count' TWI clock ticks
*
* @param tick_count Amount of TWI NOP ticks to wait
*
*/
void twi_flash_delay_twi_tick(int tick_count){
for(int i = 0; i < tick_count; i++)
{
while (NEORV32_TWI->CTRL & (1<<TWI_CTRL_TX_FULL)); // wait for free TX entry
NEORV32_TWI->DCMD = (uint32_t)(TWI_CMD_NOP << TWI_DCMD_CMD_LO); // IDLE for 1 twi tick
}
while (NEORV32_TWI->CTRL & (1 << TWI_CTRL_BUSY)); // wait until FIFO empty
}

View file

@ -86,8 +86,8 @@ int main(void) {
// setup TWI
#if (TWI_EN != 0)
if (neorv32_uart0_available()) {
neorv32_twi_available();
if (neorv32_twi_available()) {
neorv32_twi_setup(TWI_CLK_PRSC, TWI_CLK_DIV, TWI_CLK_STRECH_EN);
}
#endif
@ -104,7 +104,7 @@ int main(void) {
// ------------------------------------------------
// Splash screen
// ------------------------------------------------
#if (UART_PRINT_SPLASH_EN != 0)
uart_puts("\n\n\nNEORV32 Bootloader\n\n"
"BLDV: "
__DATE__
@ -123,6 +123,7 @@ int main(void) {
uart_puts("\nDMEM: ");
uart_puth((uint32_t)(1 << NEORV32_SYSINFO->MISC[SYSINFO_MISC_DMEM]) & 0xFFFFFFFCU);
uart_puts("\n\n");
#endif
// ------------------------------------------------
// Auto boot sequence