From 73a6f0f311102fd35f905034c07b0560ccdc444c Mon Sep 17 00:00:00 2001 From: logicog Date: Wed, 14 May 2025 20:40:44 +0200 Subject: [PATCH] Adding more flash functionality and image documentation --- README.md | 8 ++- rtl837x_flash.c | 170 +++++++++++++++++++++++++----------------------- rtl837x_flash.h | 7 +- rtl837x_sfr.h | 2 +- rtlplayground.c | 27 +++++--- 5 files changed, 120 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index dbeafaa..7d7cb5a 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,13 @@ Overlay 1 Overlay 2 Overlay n --------- 0xffff --------- -------- 0xffff -------- -------- 0xffff ``` -The RTL837x firmware images are organized as follows: common code starts at +The RTL837x firmware images are organized as follows: +The first 2 bytes of the image give the size of the prefetched data at the +start of the CPU power up. The default is 0x4000 (bytes: 0x00 0x40), which +means that the entire shared area of the code memory in all banks, +0x4000 bytes is read immediately into the code RAM. + +Common code starts at 0x0002 in the image and has length 0x3ffd, the first bank starts at 0x4000 in the image, is mapped to 0x4000 and has length 0xc000. The second bank starts at 0x10000, is mapped to 0x4000 and has length 0xc000. The third diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 3918725..3f429b3 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -7,43 +7,28 @@ #include "rtl837x_stdio.h" #include "rtl837x_sfr.h" - -// DE62B415D3155829 -// JEDEC-ID: ef 40 16 +__xdata unsigned char dio_enabled; /* - * Initializes the flash controller for programmed control - * The configuration options are not really understood, the SPI speed - * seems to be directly linked to the CPU frequency - * This configures uses fast double IO at 20.8 MHz when the CPU clock is at 20.8MHz - * and 62.5MHz when the CPU clock is configured at 125MHz + * Configure Memory Managed IO */ -void flash_init_dio() +void flash_configure_mmio(void) { - // Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio) - SFR_FLASH_CONFIG = 9; // There may be a chip-select in here - SFR_FLASH_CONF_RCMD = 0xbb; - SFR_FLASH_CONF_DIV = 4; + // Set configuration for MMIO access by controller + if (dio_enabled) { + SFR_FLASH_MODEB = 0x18; + SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed + SFR_FLASH_DUMMYCICLES = 4; + return; + } - // Test Controller Busy - while(SFR_FLASH_EXEC_BUSY); - - // Write 0 to status register - SFR_FLASH_DUMMYCICLES = 0; - SFR_FLASH_MODEB = 0; - SFR_FLASH_TLEN = 0x19; - SFR_FLASH_CMD = 1; - SFR_FLASH_DATA0 = 0; - SFR_FLASH_EXEC_GO = 1; - while(SFR_FLASH_EXEC_BUSY); - - // Set some idle mode - SFR_FLASH_MODEB = 0x18; - SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed - SFR_FLASH_DUMMYCICLES = 4; + SFR_FLASH_MODEB = 0x0; + SFR_FLASH_CMD_R = 0xb; // By default we read with single speed + SFR_FLASH_DUMMYCICLES = 8; } + /* * Initializes the flash controller for programmed control * The configuration options are not really understood, the SPI speed @@ -51,29 +36,33 @@ void flash_init_dio() * This configures uses fast single IO at 20.8 MHz when the CPU clock is at 20.8MHz * and 62.5MHz when the CPU clock is configured at 125MHz */ -void flash_init(void) +void flash_init(unsigned char enable_dio) { - // Configure fast read via divider = 8 and read-cmd being 0xb (for mmio) - SFR_FLASH_CONFIG = 9; - SFR_FLASH_CONF_RCMD = 0xb; - SFR_FLASH_CONF_DIV = 8; - + if (enable_dio) { + // Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio) + SFR_FLASH_CONFIG = 9; // There may be a chip-select in here + SFR_FLASH_CONF_RCMD = 0xbb; + SFR_FLASH_CONF_DIV = 4; + } else { + // Configure fast read via divider = 8 and read-cmd being 0xb (for mmio) + SFR_FLASH_CONFIG = 9; + SFR_FLASH_CONF_RCMD = 0xb; + SFR_FLASH_CONF_DIV = 8; + } // Test Controller Busy while(SFR_FLASH_EXEC_BUSY); // Write 0 to status register SFR_FLASH_DUMMYCICLES = 8; SFR_FLASH_MODEB = 0; - SFR_FLASH_TLEN = 0x19; + SFR_FLASH_TCONF = 0x19; SFR_FLASH_CMD = 1; SFR_FLASH_DATA0 = 0; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); - // Set some idle mode - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = 0xb; // By default we read with single speed - SFR_FLASH_DUMMYCICLES = 8; + dio_enabled = enable_dio; + flash_configure_mmio(); } uint8_t flash_read_status(void) @@ -82,7 +71,7 @@ uint8_t flash_read_status(void) while(SFR_FLASH_EXEC_BUSY); // setup status read command - SFR_FLASH_TLEN = 0x11; + SFR_FLASH_TCONF = 0x11; SFR_FLASH_CMD_R = 5; // execute and wait for controller done @@ -103,7 +92,7 @@ void flash_read_uid(void) SFR_FLASH_DUMMYCICLES = 8; // Transfer 4 bytes (command + 3 dummy bytes) - SFR_FLASH_TLEN = 4; + SFR_FLASH_TCONF = 4; SFR_FLASH_ADDR16 = 0; SFR_FLASH_ADDR8 = 0; SFR_FLASH_ADDR0 = 0; @@ -125,10 +114,7 @@ void flash_read_uid(void) print_byte(SFR_FLASH_DATA16); print_byte(SFR_FLASH_DATA24); - // Reset slow read mode - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = 0xb; - SFR_FLASH_DUMMYCICLES = 8; + flash_configure_mmio(); } @@ -142,7 +128,7 @@ void flash_read_jedecid(void) SFR_FLASH_DUMMYCICLES = 0; // Transfer 3 bytes back - SFR_FLASH_TLEN = 0x13; + SFR_FLASH_TCONF = 0x13; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); @@ -166,23 +152,25 @@ void flash_write_enable(void) // Wait until busy bit clear do { status = flash_read_status(); - print_short(status); } while (status & 0x1); // while (flash_read_status() & 0x1); - print_string("\r\n -setting- \r\n"); - SFR_FLASH_TLEN = 0x18; + SFR_FLASH_TCONF = 0x18; SFR_FLASH_CMD = 6; +/* The following is explicitly set for SIO, is this necessary?: + SFR_FLASH_DUMMYCYCLES = 0; + SFR_FLASH_MODEB = 0; +*/ SFR_FLASH_EXEC_GO = 1; + // Wait for write status enabled do { status = flash_read_status(); - print_short(status); } while (!(status & 0x2)); } -void flash_dump_dio(uint32_t addr, uint8_t len) +void flash_dump(uint32_t addr, uint8_t len) { short status; do { @@ -191,12 +179,17 @@ void flash_dump_dio(uint32_t addr, uint8_t len) } while (status & 0x1); // Set fast read mode - SFR_FLASH_MODEB = 0x18; - SFR_FLASH_CMD_R = 0xbb; - SFR_FLASH_DUMMYCICLES = 4; - + if (dio_enabled) { + SFR_FLASH_MODEB = 0x18; + SFR_FLASH_CMD_R = 0xbb; + SFR_FLASH_DUMMYCICLES = 4; + } else { + SFR_FLASH_MODEB = 0x0; + SFR_FLASH_CMD_R = 0xb; // Fast read + SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read? + } // Read 4 bytes - SFR_FLASH_TLEN = 4; + SFR_FLASH_TCONF = 4; while (len) { SFR_FLASH_ADDR16 = addr >> 16; SFR_FLASH_ADDR8 = addr >> 8; @@ -232,7 +225,7 @@ void flash_read_security(uint32_t addr, uint8_t len) SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks as for fast read // Transfer 4 bytes (command + 3byte address) - SFR_FLASH_TLEN = 4; + SFR_FLASH_TCONF = 4; while (len) { SFR_FLASH_ADDR16 = addr >> 16; SFR_FLASH_ADDR8 = addr >> 8; @@ -258,37 +251,54 @@ void flash_read_security(uint32_t addr, uint8_t len) } -void flash_dump(uint32_t addr, uint8_t len) +void flash_block_erase(uint32_t addr) { + flash_write_enable(); + SFR_FLASH_TCONF = 8; + SFR_FLASH_CMD = 0x20; + + SFR_FLASH_ADDR16 = addr >> 16; + SFR_FLASH_ADDR8 = addr >> 8; + SFR_FLASH_ADDR0 = addr; + + SFR_FLASH_EXEC_GO = 1; while (flash_read_status() & 0x1); - // Set slow read mode - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = 0xb; // Fast read - SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read? + flash_configure_mmio(); + +} + + +void flash_write_bytes(uint32_t addr, __xdata uint8_t *ptr, uint8_t len) +{ + unsigned char exit_loop = 0; + + while(1) { + flash_write_enable(); + SFR_FLASH_CMD = 2; + SFR_FLASH_TCONF = 0x40 | 8 | 2; // Bytes written is is 4, 8 enables write, 0x2 is unkown + // Last transfer? + if (len < 5) { + SFR_FLASH_TCONF = 8 | len; + exit_loop = 1; + } - // Transfer 4 bytes (command + 3byte address) - SFR_FLASH_TLEN = 4; - while (len) { SFR_FLASH_ADDR16 = addr >> 16; SFR_FLASH_ADDR8 = addr >> 8; SFR_FLASH_ADDR0 = addr; - addr += 4; + SFR_FLASH_DATA0 = *ptr++; + SFR_FLASH_DATA8 = *ptr++; + SFR_FLASH_DATA16 = *ptr++; + SFR_FLASH_DATA24 = *ptr++; + // Execute transfer, we wait for completion at top of loop SFR_FLASH_EXEC_GO = 1; - while(SFR_FLASH_EXEC_BUSY); - - print_byte(SFR_FLASH_DATA0); - if (len == 1) - return; - print_byte(SFR_FLASH_DATA8); - if (len == 2) - return; - print_byte(SFR_FLASH_DATA16); - if (len == 3) - return; - print_byte(SFR_FLASH_DATA24); - + if (exit_loop) + break; len -= 4; + addr += 4; } + + while (flash_read_status() & 0x1); + flash_configure_mmio(); } diff --git a/rtl837x_flash.h b/rtl837x_flash.h index 37bf501..8e20c22 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -3,13 +3,12 @@ #include uint8_t flash_read_status(void); -void flash_init(void); -void flash_init_dio(void); +void flash_init(unsigned char enable_dio); void flash_read_uid(void); void flash_write_enable(void); void flash_dump(uint32_t addr, uint8_t len); -void flash_dump_dio(uint32_t addr, uint8_t len); void flash_read_jedecid(void); void flash_read_security(uint32_t addr, uint8_t len); - +void flash_block_erase(uint32_t addr); +void flash_write_bytes(uint32_t addr, __xdata uint8_t *ptr, uint8_t len); #endif diff --git a/rtl837x_sfr.h b/rtl837x_sfr.h index 269b762..35f5266 100644 --- a/rtl837x_sfr.h +++ b/rtl837x_sfr.h @@ -56,7 +56,7 @@ __sfr __at(0x9c) SFR_FLASH_CONF_RCMD; __sfr __at(0x9d) SFR_FLASH_DUMMYCICLES; __sfr __at(0x9a) SFR_FLASH_MODEB; -__sfr __at(0x9e) SFR_FLASH_TLEN; +__sfr __at(0x9e) SFR_FLASH_TCONF; __sfr __at(0xaf) SFR_FLASH_DATA24; __sfr __at(0xae) SFR_FLASH_DATA16; diff --git a/rtlplayground.c b/rtlplayground.c index b28d42b..01021a6 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -53,6 +53,7 @@ __xdata unsigned sbuf[SBUF_SIZE]; __code unsigned char * __code greeting = "HI! This is a minimal prompt to explore the RTL8372!\r\n"; __code unsigned char * __code hex = "0123456789abcdef"; +__xdata uint8_t flash_buf[256]; #define N_COMMANDS 1 struct command { @@ -707,7 +708,7 @@ void bootloader(void) // port_leds_on(); print_string("\r\nStarting up...\r\n"); print_string(" Flash controller\r\n"); - flash_init(); + flash_init(0); print_string(" > OK\r\n current status: "); print_short(flash_read_status()); @@ -787,23 +788,33 @@ void bootloader(void) reset_chip(); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'd') { - print_string("\r\nDUMPING FLASH\n\n"); + print_string("\r\nDUMPING FLASH\r\n"); flash_dump(0, 255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'j') { - print_string("\r\nJEDEC ID\n\n"); + print_string("\r\nJEDEC ID\r\n"); flash_read_jedecid(); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'u') { - print_string("\r\nUNIQUE ID\n\n"); + print_string("\r\nUNIQUE ID\r\n"); flash_read_uid(); } // Switch to flash 62.5 MHz mode if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 's') { - print_string("\r\nFLASH FAST MODE\n\n"); - flash_init_fast(); - print_string("\r\nNow dumping flash\n\n"); - flash_dump_fast(0, 255); + print_string("\r\nFLASH FAST MODE\r\n"); + flash_init(1); + print_string("\r\nNow dumping flash\r\n"); + flash_dump(0, 255); + } + if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'e') { + print_string("\r\nFLASH erase\r\n"); + flash_block_erase(0x20000); + } + if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'w') { + print_string("\r\nFLASH write\r\n"); + for (unsigned char i = 0; i < 20; i++) + flash_buf[i] = greeting[i]; + flash_write_bytes(0x20000, flash_buf, 20); } } print_string("\r\n> ");