Adding more flash functionality and image documentation

This commit is contained in:
logicog
2025-05-14 20:40:44 +02:00
parent 7493089c39
commit 73a6f0f311
5 changed files with 120 additions and 94 deletions
+7 -1
View File
@@ -64,7 +64,13 @@ Overlay 1 Overlay 2 Overlay n
--------- 0xffff --------- -------- 0xffff -------- -------- 0xffff --------- 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 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 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 starts at 0x10000, is mapped to 0x4000 and has length 0xc000. The third
+90 -80
View File
@@ -7,43 +7,28 @@
#include "rtl837x_stdio.h" #include "rtl837x_stdio.h"
#include "rtl837x_sfr.h" #include "rtl837x_sfr.h"
__xdata unsigned char dio_enabled;
// DE62B415D3155829
// JEDEC-ID: ef 40 16
/* /*
* Initializes the flash controller for programmed control * Configure Memory Managed IO
* 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
*/ */
void flash_init_dio() void flash_configure_mmio(void)
{ {
// Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio) // Set configuration for MMIO access by controller
SFR_FLASH_CONFIG = 9; // There may be a chip-select in here if (dio_enabled) {
SFR_FLASH_CONF_RCMD = 0xbb; SFR_FLASH_MODEB = 0x18;
SFR_FLASH_CONF_DIV = 4; SFR_FLASH_CMD_R = 0xbb; // By default we read with Dual speed
SFR_FLASH_DUMMYCICLES = 4;
return;
}
// Test Controller Busy SFR_FLASH_MODEB = 0x0;
while(SFR_FLASH_EXEC_BUSY); SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
SFR_FLASH_DUMMYCICLES = 8;
// 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;
} }
/* /*
* Initializes the flash controller for programmed control * Initializes the flash controller for programmed control
* The configuration options are not really understood, the SPI speed * 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 * 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 * 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) if (enable_dio) {
SFR_FLASH_CONFIG = 9; // Configure fast DIO via divider/DIO/SIOconfig = 4 and read-cmd being 0xbb (for mmio)
SFR_FLASH_CONF_RCMD = 0xb; SFR_FLASH_CONFIG = 9; // There may be a chip-select in here
SFR_FLASH_CONF_DIV = 8; 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 // Test Controller Busy
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
// Write 0 to status register // Write 0 to status register
SFR_FLASH_DUMMYCICLES = 8; SFR_FLASH_DUMMYCICLES = 8;
SFR_FLASH_MODEB = 0; SFR_FLASH_MODEB = 0;
SFR_FLASH_TLEN = 0x19; SFR_FLASH_TCONF = 0x19;
SFR_FLASH_CMD = 1; SFR_FLASH_CMD = 1;
SFR_FLASH_DATA0 = 0; SFR_FLASH_DATA0 = 0;
SFR_FLASH_EXEC_GO = 1; SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
// Set some idle mode dio_enabled = enable_dio;
SFR_FLASH_MODEB = 0x0; flash_configure_mmio();
SFR_FLASH_CMD_R = 0xb; // By default we read with single speed
SFR_FLASH_DUMMYCICLES = 8;
} }
uint8_t flash_read_status(void) uint8_t flash_read_status(void)
@@ -82,7 +71,7 @@ uint8_t flash_read_status(void)
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
// setup status read command // setup status read command
SFR_FLASH_TLEN = 0x11; SFR_FLASH_TCONF = 0x11;
SFR_FLASH_CMD_R = 5; SFR_FLASH_CMD_R = 5;
// execute and wait for controller done // execute and wait for controller done
@@ -103,7 +92,7 @@ void flash_read_uid(void)
SFR_FLASH_DUMMYCICLES = 8; SFR_FLASH_DUMMYCICLES = 8;
// Transfer 4 bytes (command + 3 dummy bytes) // Transfer 4 bytes (command + 3 dummy bytes)
SFR_FLASH_TLEN = 4; SFR_FLASH_TCONF = 4;
SFR_FLASH_ADDR16 = 0; SFR_FLASH_ADDR16 = 0;
SFR_FLASH_ADDR8 = 0; SFR_FLASH_ADDR8 = 0;
SFR_FLASH_ADDR0 = 0; SFR_FLASH_ADDR0 = 0;
@@ -125,10 +114,7 @@ void flash_read_uid(void)
print_byte(SFR_FLASH_DATA16); print_byte(SFR_FLASH_DATA16);
print_byte(SFR_FLASH_DATA24); print_byte(SFR_FLASH_DATA24);
// Reset slow read mode flash_configure_mmio();
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = 0xb;
SFR_FLASH_DUMMYCICLES = 8;
} }
@@ -142,7 +128,7 @@ void flash_read_jedecid(void)
SFR_FLASH_DUMMYCICLES = 0; SFR_FLASH_DUMMYCICLES = 0;
// Transfer 3 bytes back // Transfer 3 bytes back
SFR_FLASH_TLEN = 0x13; SFR_FLASH_TCONF = 0x13;
SFR_FLASH_EXEC_GO = 1; SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY); while(SFR_FLASH_EXEC_BUSY);
@@ -166,23 +152,25 @@ void flash_write_enable(void)
// Wait until busy bit clear // Wait until busy bit clear
do { do {
status = flash_read_status(); status = flash_read_status();
print_short(status);
} while (status & 0x1); } while (status & 0x1);
// while (flash_read_status() & 0x1); // while (flash_read_status() & 0x1);
print_string("\r\n -setting- \r\n"); SFR_FLASH_TCONF = 0x18;
SFR_FLASH_TLEN = 0x18;
SFR_FLASH_CMD = 6; 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; SFR_FLASH_EXEC_GO = 1;
// Wait for write status enabled
do { do {
status = flash_read_status(); status = flash_read_status();
print_short(status);
} while (!(status & 0x2)); } while (!(status & 0x2));
} }
void flash_dump_dio(uint32_t addr, uint8_t len) void flash_dump(uint32_t addr, uint8_t len)
{ {
short status; short status;
do { do {
@@ -191,12 +179,17 @@ void flash_dump_dio(uint32_t addr, uint8_t len)
} while (status & 0x1); } while (status & 0x1);
// Set fast read mode // Set fast read mode
SFR_FLASH_MODEB = 0x18; if (dio_enabled) {
SFR_FLASH_CMD_R = 0xbb; SFR_FLASH_MODEB = 0x18;
SFR_FLASH_DUMMYCICLES = 4; 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 // Read 4 bytes
SFR_FLASH_TLEN = 4; SFR_FLASH_TCONF = 4;
while (len) { while (len) {
SFR_FLASH_ADDR16 = addr >> 16; SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8; 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 SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks as for fast read
// Transfer 4 bytes (command + 3byte address) // Transfer 4 bytes (command + 3byte address)
SFR_FLASH_TLEN = 4; SFR_FLASH_TCONF = 4;
while (len) { while (len) {
SFR_FLASH_ADDR16 = addr >> 16; SFR_FLASH_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8; 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); while (flash_read_status() & 0x1);
// Set slow read mode flash_configure_mmio();
SFR_FLASH_MODEB = 0x0;
SFR_FLASH_CMD_R = 0xb; // Fast read }
SFR_FLASH_DUMMYCICLES = 8; // Add 8 dummy clocks after read?
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_ADDR16 = addr >> 16;
SFR_FLASH_ADDR8 = addr >> 8; SFR_FLASH_ADDR8 = addr >> 8;
SFR_FLASH_ADDR0 = addr; 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; SFR_FLASH_EXEC_GO = 1;
while(SFR_FLASH_EXEC_BUSY); if (exit_loop)
break;
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);
len -= 4; len -= 4;
addr += 4;
} }
while (flash_read_status() & 0x1);
flash_configure_mmio();
} }
+3 -4
View File
@@ -3,13 +3,12 @@
#include <stdint.h> #include <stdint.h>
uint8_t flash_read_status(void); uint8_t flash_read_status(void);
void flash_init(void); void flash_init(unsigned char enable_dio);
void flash_init_dio(void);
void flash_read_uid(void); void flash_read_uid(void);
void flash_write_enable(void); void flash_write_enable(void);
void flash_dump(uint32_t addr, uint8_t len); 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_jedecid(void);
void flash_read_security(uint32_t addr, uint8_t len); 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 #endif
+1 -1
View File
@@ -56,7 +56,7 @@ __sfr __at(0x9c) SFR_FLASH_CONF_RCMD;
__sfr __at(0x9d) SFR_FLASH_DUMMYCICLES; __sfr __at(0x9d) SFR_FLASH_DUMMYCICLES;
__sfr __at(0x9a) SFR_FLASH_MODEB; __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(0xaf) SFR_FLASH_DATA24;
__sfr __at(0xae) SFR_FLASH_DATA16; __sfr __at(0xae) SFR_FLASH_DATA16;
+19 -8
View File
@@ -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 greeting = "HI! This is a minimal prompt to explore the RTL8372!\r\n";
__code unsigned char * __code hex = "0123456789abcdef"; __code unsigned char * __code hex = "0123456789abcdef";
__xdata uint8_t flash_buf[256];
#define N_COMMANDS 1 #define N_COMMANDS 1
struct command { struct command {
@@ -707,7 +708,7 @@ void bootloader(void)
// port_leds_on(); // port_leds_on();
print_string("\r\nStarting up...\r\n"); print_string("\r\nStarting up...\r\n");
print_string(" Flash controller\r\n"); print_string(" Flash controller\r\n");
flash_init(); flash_init(0);
print_string(" > OK\r\n current status: "); print_string(" > OK\r\n current status: ");
print_short(flash_read_status()); print_short(flash_read_status());
@@ -787,23 +788,33 @@ void bootloader(void)
reset_chip(); reset_chip();
} }
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'd') { 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); flash_dump(0, 255);
} }
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'j') { 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(); flash_read_jedecid();
} }
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 'u') { 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(); flash_read_uid();
} }
// Switch to flash 62.5 MHz mode // Switch to flash 62.5 MHz mode
if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 's') { if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && sbuf[cmd_words_b[1]] == 's') {
print_string("\r\nFLASH FAST MODE\n\n"); print_string("\r\nFLASH FAST MODE\r\n");
flash_init_fast(); flash_init(1);
print_string("\r\nNow dumping flash\n\n"); print_string("\r\nNow dumping flash\r\n");
flash_dump_fast(0, 255); 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> "); print_string("\r\n> ");