From 48d57dfb0f165a874a407c3232a1a272cb1dc23d Mon Sep 17 00:00:00 2001 From: logicog Date: Thu, 11 Sep 2025 06:43:30 +0200 Subject: [PATCH 01/12] Cleanup of flash code in installer --- installer/installer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/installer/installer.c b/installer/installer.c index c66f06f..3eeb61d 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -256,8 +256,7 @@ void flash_write_enable(void) SFR_FLASH_TCONF = 0x18; SFR_FLASH_CMD = 6; -// The following is explicitly set for SIO, is this necessary?: - SFR_FLASH_DUMMYCYCLES = 0; + SFR_FLASH_DUMMYCICLES = 0; SFR_FLASH_MODEB = 0; SFR_FLASH_EXEC_GO = 1; From 4a4abef9fdc5e6b045415b9315f4874eef338e56 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 29 Sep 2025 08:28:42 +0200 Subject: [PATCH 02/12] Add web-page for firmware update --- html/update.html | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 html/update.html diff --git a/html/update.html b/html/update.html new file mode 100644 index 0000000..ab99b67 --- /dev/null +++ b/html/update.html @@ -0,0 +1,20 @@ + + + + + Firmware update + + + +
+
+

Firmware Update

+
+ + Choose a firmware update file to upload:
+ +
+ + From f464be33688b10889e74e34afdf914d755e95b74 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 29 Sep 2025 08:29:39 +0200 Subject: [PATCH 03/12] Add POST code for firmware update --- httpd/httpd.c | 254 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 228 insertions(+), 26 deletions(-) diff --git a/httpd/httpd.c b/httpd/httpd.c index 57602f8..6d9fe5d 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -7,6 +7,9 @@ #include "uip.h" #include "../html_data.h" +// Upload Firmware to 1M +#define FIRMWARE_UPLOAD_START 0x100000 + #define CMARK_S 6 #pragma codeseg BANK1 @@ -15,6 +18,10 @@ extern __code struct f_data f_data[]; extern __code fcall_ptr f_calls[]; extern __code char * __code mime_strings[]; +// Flash buffer to optimize flash writing speed, write_len is the current filling position +extern __xdata uint8_t flash_buf[512]; +__xdata uint16_t write_len; + __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; __xdata uint8_t entry; __xdata uint16_t slen; @@ -22,11 +29,21 @@ __xdata uint16_t o_idx; __xdata uint16_t mpos; __xdata uint16_t len_left; +// HTTP header properties +__xdata uint8_t boundary[72]; +__xdata uint8_t *content_type = 0; + +// Global variables holding POST state +__xdata uint32_t uptr; // Current flash write position +__xdata uint16_t bindex; // Current index into the boundary + +__xdata uint16_t short_parsed; #define TSTATE_NONE 0 #define TSTATE_TX 1 #define TSTATE_ACKED 2 #define TSTATE_CLOSED 3 +#define TSTATE_POST 4 inline uint8_t is_separator(uint8_t c) @@ -46,7 +63,7 @@ void httpd_init(void) __banked uint8_t find_entry(__xdata uint8_t * __xdata e) { - register uint8_t i, j; + __xdata uint8_t i, j; for (i = 0; f_data[i].len; i++) { j = 0; @@ -65,9 +82,8 @@ char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) { register uint8_t i = 0; - while (d[i] && (d[i] == c[i])) { + while (d[i] && (d[i] == c[i])) i++; - } if (c[i] < d[i]) return -1; @@ -77,15 +93,47 @@ char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) } -uint8_t parse_short(register uint16_t *n, __xdata uint8_t * __xdata p) +char is_word(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) +{ + register uint8_t i = 0; + + while (d[i] && (d[i] == c[i])) + i++; + + if (d[i]) + return 0; + if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i]) + return 0; + return 1; +} + + +char is_word_x(__xdata uint8_t * __xdata c, __xdata uint8_t *d) +{ + register uint8_t i = 0; + + while (d[i] && (d[i] == c[i])) + i++; + + if (d[i]) + return 0; + if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i]) + return 0; + return 1; +} + + +uint8_t parse_short(__xdata uint8_t *p) { uint8_t err = 1; - *n = 0; + uint8_t c = 0; - while (*p >= '0' && *p <= '9') { + short_parsed = 0; + while(1) { + c = *p++ - '0'; + if (c > 9) { break; } err = 0; - *n = (*n * 10) + *p - '0'; - p++; + short_parsed = (short_parsed * 10) + c; } return err; } @@ -93,33 +141,180 @@ uint8_t parse_short(register uint16_t *n, __xdata uint8_t * __xdata p) void send_not_found(void) { - slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n"); - print_string("slen: "); print_short(slen); write_char('\n'); - slen += strtox(outbuf + slen, "\n404 Not Found\n

Not Found

\n"); + slen = strtox(outbuf, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n" \ + "\n404 Not Found\n

Not Found

\n"); } -void handle_post(void) + +void send_bad_request(void) { - __xdata uint8_t *p = uip_appdata; + slen = strtox(outbuf, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" \ + "\n400 Bad Request\n

Bad Request

\n"); +} + + +__xdata uint8_t *skip_boundary(__xdata uint8_t *p) +{ + while (*p) { + if (is_word_x(p, boundary)) + return p + strlen_x(boundary); + p++; + } + return p; +} + + +__xdata uint8_t *scan_header(__xdata uint8_t *p) +{ + content_type = 0; + while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') { write_char(*p); if (!*p++) break; + if (is_word(p, "\nContent-Type:")) + content_type = p + 15; } - if (!*p) { - print_string("No body found!\n"); + if (content_type && is_word(content_type, "multipart/form-data; boundary")) { + print_string("\nFound multiplart\n"); + content_type += 30; + uint8_t i = 0; + while (content_type[i] != '\r' && content_type[i] != '\n') { + boundary[i + 2] = content_type[i]; + i++; + } + // The boundary between parts is "--" + the boundary given in the header + boundary[0] = '-'; + boundary[1] = '-'; + boundary[i + 2] = 0; + } + return p; +} + + +/* + * Reads post data from the http stream and writes it into flash memory + * Input: the current position in the TCP buffer (uip_appdata) + * Returns 1: More data to read, 0: Upload complete, all parts reads + */ +uint8_t stream_upload(__xdata uint16_t bptr) +{ + __xdata uint8_t *p = uip_appdata; + __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); + + print_string("Stream_upload called: "); + print_short(bptr); write_char('\n'); + + do { + if (bptr >= uip_len) { + s->tstate = TSTATE_POST; + return 1; + } + // Have we reached the end of the part? + if (!boundary[bindex]) { + s->tstate = TSTATE_NONE; + print_string("len 2: "); print_short(write_len); write_char(' '); + flash_write_bytes(uptr, flash_buf, write_len); + uptr += write_len; + write_len = 0; + // TODO: This is a bit premature, what about a nice web-page saying the device will reset??? + reset_chip(); + if (bptr >= uip_len) + return 0; + return 1; + } + if (p[bptr] == boundary[bindex]) { + bptr++; + bindex++; + } else { + if (bindex) { + memcpy(flash_buf + write_len, boundary, bindex); + write_len += bindex; + bindex = 0; + } + flash_buf[write_len++] = p[bptr++]; + if (write_len >= 256) { + print_string("len: "); print_short(write_len); write_char(' '); + flash_write_bytes(uptr, flash_buf, write_len); + uptr += write_len; + write_len = 0; + } + bindex = 0; + } + } while(1); +} + + +void handle_post(void) +{ + __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); + __xdata uint8_t *p = uip_appdata; + __xdata uint8_t *request_path = p + 6; + + print_string("Is POST\n"); + p += 5; // Skip post + // Find end of request path + while (*p && !is_separator(*p)) + p++; + *p = '\0'; + + // Find end of request header + boundary[0] ='\0'; + p = scan_header(p + 1); + print_string("Boundary: >"); print_string_x(boundary); print_string("<\n"); + if (!*p || !content_type) { + print_string("Bad Request!\n"); send_not_found(); return; } - register uint8_t i = 0; - p += 4; - while (*p && *p != '\n' && *p != '\r') - cmd_buffer[i++] = *p++; - cmd_buffer[i] = '\0'; - if (i && !cmd_tokenize()) + if (is_word(request_path, "cmd")) { + register uint8_t i = 0; + p += 4; + while (*p && *p != '\n' && *p != '\r') + cmd_buffer[i++] = *p++; + cmd_buffer[i] = '\0'; + + if (i && !cmd_tokenize()) cmd_parser(); + } else if (is_word(request_path, "upload")) { + print_string("POST upload request\n"); + if (!boundary[0]) { + print_string("Bad request, no boundary!\n"); + send_bad_request(); + return; + } + // We skip the intial parts as part of the header + do { + p = skip_boundary(p); + if (!*p) + goto bad_request; + p = scan_header(p); + if (!*p) + goto bad_request; + if (!content_type) // We are waiting for the part with the octet stream + continue; + } while (!is_word(content_type, "application/octet-stream")); + print_string("Have content octets\n"); + p += 4; // Skip \r\n\r\n sequence at end of preamble of part + + uptr = FIRMWARE_UPLOAD_START; + bindex = 0; + write_len = 0; + stream_upload(p - uip_appdata); + + print_string("Done reading first fragment\n"); + return; + + } else { + send_not_found(); + return; + } slen = strtox(outbuf, "HTTP/1.1 200 OK\r\n\r\n"); + return; +bad_request: + send_bad_request(); + return; } @@ -168,20 +363,28 @@ void httpd_appcall(void) print_string("Sending B done\n"); s->tstate = TSTATE_TX; } + } else if (uip_newdata() && s->tstate == TSTATE_POST) { + stream_upload(0); } else if (uip_newdata() && s->tstate != TSTATE_TX) { write_char('<'); print_short(uip_len); write_char('\n'); __xdata uint8_t *p = uip_appdata; + // Mark end of request header with \0 p[uip_len] = 0; while (*p) write_char(*p++); write_char('\n'); p = uip_appdata; - if (p[0] == 'P' && p[1] == 'O' && p[2] == 'S' && p[3] == 'T' && p[4] == ' ') { + if (is_word(p, "POST")) { handle_post(); + // If this is an ongoing post stream, then wait for the next packet + if (s->tstate == TSTATE_POST) { + uip_len = 0; + return; + } goto do_send; } - if (p[0] == 'G' && p[1] == 'E' && p[2] == 'T' && p[3] == ' ') + if (is_word(p, "GET")) print_string("GET request "); p += 4; __xdata uint8_t *q = p; @@ -199,9 +402,8 @@ void httpd_appcall(void) if (!strcmp(q, "/status.json")) { send_status(); } else if (!strcmp(q, "/vlan.json")) { - __xdata uint16_t vlan; - parse_short(&vlan, q + 15); - send_vlan(vlan); + parse_short(q + 15); + send_vlan(short_parsed); } else if (!strcmp(q, "/counters.json")) { send_counters(q[19]-'0'); } else { From 6aa28b7385dfec17532f0bb11c3fd72c0e3adb61 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 29 Sep 2025 08:30:53 +0200 Subject: [PATCH 04/12] Cleanup and increase of flash_buf size for flash write buffer --- rtlplayground.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/rtlplayground.c b/rtlplayground.c index a657297..16816d3 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -70,7 +70,7 @@ extern __xdata uint8_t gpio_last_value[8]; __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code hex = "0123456789abcdef"; -__xdata uint8_t flash_buf[256]; +__xdata uint8_t flash_buf[512]; // NIC buffers for packet RX/TX __xdata uint8_t rx_headers[16]; // Packet header(s) on RX @@ -195,9 +195,6 @@ uint16_t strlen_x(register __xdata const char *s) uint16_t l = 0; while (s[l]) l++; - write_char(';'); - print_short(l); - write_char(';'); return l; } @@ -761,12 +758,14 @@ void tcpip_output(void) uint16_t ring_ptr = ((uint16_t)sfr_data[2]) << 8; ring_ptr |= sfr_data[3]; +#ifdef RXTXDBG print_string("TX: \n"); for (uint8_t i = 0; i < 120; i++) { print_byte(uip_buf[i]); write_char(' '); } write_char('\n'); +#endif // Move data over from xmem buffer to ASIC side using DMA nic_tx_packet(ring_ptr); From 110c4034433fa5ea87e54b5b4f7139d2e539f4c3 Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 29 Sep 2025 15:10:42 +0200 Subject: [PATCH 05/12] Adding firmware update at beginning of boot if a new image is found in second half of flash --- rtlplayground.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/rtlplayground.c b/rtlplayground.c index 16816d3..fe06a3d 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -16,6 +16,9 @@ #include "uip/uip.h" #include "uip/uip_arp.h" +// Upload Firmware to 1M +#define FIRMWARE_UPLOAD_START 0x100000 + #define SYS_TICK_HZ 100 #define SERIAL_BAUD_RATE 115200 @@ -1694,6 +1697,35 @@ void bootloader(void) print_string(" Flash controller\n"); flash_init(0); + // Check update in progress and move blocks + flash_read_bulk(flash_buf, FIRMWARE_UPLOAD_START, 0x100); + if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { + print_string("Update in progress, moving firmware to start of FLASH!\n"); + + __xdata uint32_t dest = 0x0; + __xdata uint32_t source = FIRMWARE_UPLOAD_START; + // A 512kByte = 4MBit Flash has 128*8=1024 512k blocks, we copy only 120 + for (__xdata uint16_t i=0; i < 960; i++) { + print_string("Writing block: "); + print_short(dest); + flash_read_bulk(flash_buf, source, 0x200); + write_char('\n'); + if (!(i & 0x7)) + flash_sector_erase(dest); + flash_write_bytes(dest, flash_buf, 0x200); + dest += 0x200; + source += 0x200; + } + print_string("Deleting uploaded flash image\n"); + dest = FIRMWARE_UPLOAD_START; + for (register uint8_t i=0; i < 120; i++) { + flash_sector_erase(dest); + dest += 0x1000; + } + print_string("Resetting now"); + reset_chip(); + } + // Reset NIC reg_bit_set(0x24, 2); do { From 05492e601ae7552894b51a4dac2854b102e68b2b Mon Sep 17 00:00:00 2001 From: logicog Date: Mon, 29 Sep 2025 15:08:52 +0200 Subject: [PATCH 06/12] Reducing IMEM footprint in flash routines --- cmd_parser.c | 19 +++++++++++------ httpd/httpd.c | 26 ++++++++++++---------- rtl837x_flash.c | 57 +++++++++++++++++++++++++------------------------ rtl837x_flash.h | 8 +++---- rtlplayground.c | 11 +++++++--- 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 68a01f4..41e4f3b 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -32,7 +32,9 @@ extern volatile __xdata uint8_t sfr_data[4]; extern __code uint8_t * __code greeting; extern __code uint8_t * __code hex; -extern __xdata uint8_t flash_buf[256]; +extern __xdata uint8_t flash_buf[512]; +extern __xdata uint32_t flash_addr; + __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint16_t vlan_ptr; __xdata uint8_t gpio_last_value[8] = { 0 }; @@ -495,7 +497,8 @@ void cmd_parser(void) __banked } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { print_string("\nDUMPING FLASH\n"); - flash_dump(0, 255); + flash_addr = 0; + flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { print_string("\nJEDEC ID\n"); @@ -510,7 +513,8 @@ void cmd_parser(void) __banked print_string("\nFLASH FAST MODE\n"); flash_init(1); print_string("\nNow dumping flash\n"); - flash_dump(0, 255); + flash_addr = 0; + flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { print_string("\nFLASH erase\n"); @@ -520,7 +524,8 @@ void cmd_parser(void) __banked print_string("\nFLASH write\n"); for (uint8_t i = 0; i < 20; i++) flash_buf[i] = greeting[i]; - flash_write_bytes(0x20000, flash_buf, 20); + flash_addr = 0x20000; + flash_write_bytes(flash_buf, 20); } if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { print_string("\nPORT "); @@ -625,10 +630,12 @@ void execute_config(void) __banked __xdata uint32_t pos = CONFIG_START; __xdata uint16_t len_left = CONFIG_LEN; do { - flash_find_mark(pos, len_left, "\n"); + flash_addr = pos; + flash_find_mark("\n", len_left); if (mpos != 0xffff) { __xdata uint16_t len = len_left - mpos; - flash_read_bulk(&cmd_buffer[0], pos, len > SBUF_SIZE ? SBUF_SIZE : len); + flash_addr = pos; + flash_read_bulk(&cmd_buffer[0], len > SBUF_SIZE ? SBUF_SIZE : len); cmd_buffer[len > SBUF_SIZE ? SBUF_SIZE : len] = '\0'; len++; pos += len; diff --git a/httpd/httpd.c b/httpd/httpd.c index 6d9fe5d..4436458 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -17,6 +17,7 @@ extern __code struct f_data f_data[]; extern __code fcall_ptr f_calls[]; extern __code char * __code mime_strings[]; +extern __xdata uint32_t flash_addr; // Flash buffer to optimize flash writing speed, write_len is the current filling position extern __xdata uint8_t flash_buf[512]; @@ -34,7 +35,6 @@ __xdata uint8_t boundary[72]; __xdata uint8_t *content_type = 0; // Global variables holding POST state -__xdata uint32_t uptr; // Current flash write position __xdata uint16_t bindex; // Current index into the boundary __xdata uint16_t short_parsed; @@ -214,10 +214,10 @@ uint8_t stream_upload(__xdata uint16_t bptr) if (!boundary[bindex]) { s->tstate = TSTATE_NONE; print_string("len 2: "); print_short(write_len); write_char(' '); - flash_write_bytes(uptr, flash_buf, write_len); - uptr += write_len; + flash_write_bytes(flash_buf, write_len); write_len = 0; // TODO: This is a bit premature, what about a nice web-page saying the device will reset??? + print_string("Upload to flash done, will reset!\n"); reset_chip(); if (bptr >= uip_len) return 0; @@ -235,8 +235,7 @@ uint8_t stream_upload(__xdata uint16_t bptr) flash_buf[write_len++] = p[bptr++]; if (write_len >= 256) { print_string("len: "); print_short(write_len); write_char(' '); - flash_write_bytes(uptr, flash_buf, write_len); - uptr += write_len; + flash_write_bytes(flash_buf, write_len); write_len = 0; } bindex = 0; @@ -298,7 +297,7 @@ void handle_post(void) print_string("Have content octets\n"); p += 4; // Skip \r\n\r\n sequence at end of preamble of part - uptr = FIRMWARE_UPLOAD_START; + flash_addr = FIRMWARE_UPLOAD_START; bindex = 0; write_len = 0; stream_upload(p - uip_appdata); @@ -419,13 +418,15 @@ void httpd_appcall(void) if (f_data[entry].mime == mime_HTML) { print_string("MIME is html len is "); print_short(len_left); write_char('\n'); mpos = 0; - flash_find_mark(f_data[entry].start, len_left, "#{"); + flash_addr = f_data[entry].start; + flash_find_mark("#{", len_left); print_string("mpos: "); print_short(mpos); write_char('\n'); while (mpos != 0xffff) { print_string("Entry-len:"); print_short(len_left); write_char('\n'); mpos = len_left - mpos; print_string("l/pos: "); print_short(mpos); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, mpos + CMARK_S); // call marker is e.g. #{001} + flash_addr = f_data[entry].start + f_data[entry].len - len_left; + flash_read_bulk(outbuf + slen, mpos + CMARK_S); // call marker is e.g. #{001} slen += mpos; write_char('@'); write_char(outbuf[slen + 2]); write_char(outbuf[slen + 3]); write_char(outbuf[slen + 4]); fcall_ptr ptr = f_calls[(outbuf[slen + 2] - '0') * 100 + (outbuf[slen + 3]-'0') * 10 + outbuf[slen + 4] - '0']; @@ -436,15 +437,18 @@ void httpd_appcall(void) print_string("call done\n"); mpos += CMARK_S; len_left -= mpos; - flash_find_mark(f_data[entry].start + mpos, len_left, "#{"); + flash_addr = f_data[entry].start + mpos; + flash_find_mark("#{", len_left); print_string("mpos now: "); print_short(mpos); write_char('\n'); } print_string("At end mpos: "); print_short(mpos); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start + f_data[entry].len - len_left, len_left); + flash_addr = f_data[entry].start + f_data[entry].len - len_left; + flash_read_bulk(outbuf + slen, len_left); slen += len_left; } else { print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); - flash_read_bulk(outbuf + slen, f_data[entry].start, len_left); + flash_addr = f_data[entry].start; + flash_read_bulk(outbuf + slen, len_left); slen += len_left; } } diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 471116f..674c735 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -10,6 +10,7 @@ __xdata uint8_t dio_enabled; __xdata uint8_t markbuf[16]; extern __xdata uint16_t mpos; +__xdata uint32_t flash_addr; // For the flash commands, see e.g. Windbond W25Q32JV datasheet #define CMD_WRITE_STATUS 0x01 @@ -36,7 +37,7 @@ void flash_configure_mmio(void) } SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = 0xb; // Default is Single IO + SFR_FLASH_CMD_R = CMD_FREAD; // Default is Single IO SFR_FLASH_DUMMYCYCLES = 8; } @@ -184,7 +185,7 @@ void flash_write_enable(void) } -void flash_dump(register uint32_t addr, register uint8_t len) +void flash_dump(uint8_t len) { short status; do { @@ -205,10 +206,10 @@ void flash_dump(register uint32_t addr, register uint8_t len) // Read 4 bytes SFR_FLASH_TCONF = 4; while (len) { - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; - addr += 4; + SFR_FLASH_ADDR16 = flash_addr >> 16; + SFR_FLASH_ADDR8 = flash_addr >> 8; + SFR_FLASH_ADDR0 = flash_addr; + flash_addr += 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); @@ -232,7 +233,7 @@ void flash_dump(register uint32_t addr, register uint8_t len) * Reads bulk data of length len from the flash memory starging at address src * and writes the data into a buffer pointed to by dst in XMEM */ -void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len) +void flash_read_bulk(__xdata uint8_t *dst, register uint16_t len) { short status; do { @@ -252,10 +253,10 @@ void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, regist // Read 4 bytes SFR_FLASH_TCONF = 4; while (len) { - SFR_FLASH_ADDR16 = src >> 16; - SFR_FLASH_ADDR8 = src >> 8; - SFR_FLASH_ADDR0 = src; - src += 4; + SFR_FLASH_ADDR16 = flash_addr >> 16; + SFR_FLASH_ADDR8 = flash_addr >> 8; + SFR_FLASH_ADDR0 = flash_addr; + flash_addr += 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); @@ -276,9 +277,9 @@ void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, regist } -void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark) +void flash_find_mark(__code uint8_t *mark, __xdata uint16_t len) { - uint16_t status; + __xdata uint16_t status; do { status = flash_read_status(); } while (status & 0x1); @@ -294,9 +295,9 @@ void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? } - uint8_t i = 0; - uint8_t l = 0; - uint8_t k; + __xdata uint8_t i = 0; + __xdata uint8_t l = 0; + __xdata uint8_t k; // Calculate the length while (mark[i++]) @@ -310,10 +311,10 @@ void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t i = 0; SFR_FLASH_TCONF = 4; while (len) { - SFR_FLASH_ADDR16 = src >> 16; - SFR_FLASH_ADDR8 = src >> 8; - SFR_FLASH_ADDR0 = src; - src += 4; + SFR_FLASH_ADDR16 = flash_addr >> 16; + SFR_FLASH_ADDR8 = flash_addr >> 8; + SFR_FLASH_ADDR0 = flash_addr; + flash_addr += 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); @@ -408,27 +409,27 @@ void flash_sector_erase(uint32_t addr) while (flash_read_status() & 0x1); flash_configure_mmio(); - } -void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len) +void flash_write_bytes(__xdata uint8_t *ptr, __xdata uint16_t len) { - uint8_t exit_loop = 0; + __xdata uint8_t exit_loop = 0; + write_char('>'); print_long(flash_addr); write_char(':'); print_short(len); write_char('-'); print_byte(*ptr); write_char('\n'); while(1) { flash_write_enable(); SFR_FLASH_CMD = CMD_PAGE_PROGRAM; - SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is is 4, 8 enables write, 0x40 is unkown + SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown // Last transfer? if (len < 5) { SFR_FLASH_TCONF = 8 | len; exit_loop = 1; } - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; + SFR_FLASH_ADDR16 = flash_addr >> 16; + SFR_FLASH_ADDR8 = flash_addr >> 8; + SFR_FLASH_ADDR0 = flash_addr; SFR_FLASH_DATA0 = *ptr++; SFR_FLASH_DATA8 = *ptr++; SFR_FLASH_DATA16 = *ptr++; @@ -439,7 +440,7 @@ void flash_write_bytes(__xdata uint32_t addr, __xdata uint8_t *ptr, uint16_t len if (exit_loop) break; len -= 4; - addr += 4; + flash_addr += 4; } while (flash_read_status() & 0x1); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index f891f97..de81bd2 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -4,11 +4,11 @@ void flash_init(uint8_t enable_dio); void flash_read_uid(void); void flash_write_enable(void); -void flash_dump(register uint32_t addr, register uint8_t len); +void flash_dump(register uint8_t len); void flash_read_jedecid(void); void flash_read_security(uint32_t addr, uint8_t len); void flash_sector_erase(uint32_t addr); -void flash_read_bulk(register __xdata uint8_t *dst, __xdata uint32_t src, register uint16_t len); -void flash_write_bytes(__xdata uint32_t addr, register __xdata uint8_t *ptr, register uint16_t len); -void flash_find_mark(__xdata uint32_t src, register uint16_t len, __code uint8_t *mark); +void flash_read_bulk(__xdata uint8_t *dst, __xdata uint16_t len); +void flash_write_bytes(__xdata uint8_t *ptr, __xdata uint16_t len); +void flash_find_mark( __code uint8_t *mark, __xdata uint16_t len); #endif diff --git a/rtlplayground.c b/rtlplayground.c index fe06a3d..d011dde 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -70,6 +70,8 @@ __xdata uint8_t sfr_data[4]; extern __xdata uint8_t cmd_buffer[SBUF_SIZE]; extern __xdata uint8_t gpio_last_value[8]; +extern __xdata uint32_t flash_addr; + __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code hex = "0123456789abcdef"; @@ -1698,7 +1700,8 @@ void bootloader(void) flash_init(0); // Check update in progress and move blocks - flash_read_bulk(flash_buf, FIRMWARE_UPLOAD_START, 0x100); + flash_addr = FIRMWARE_UPLOAD_START; + flash_read_bulk(flash_buf, 0x100); if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { print_string("Update in progress, moving firmware to start of FLASH!\n"); @@ -1708,11 +1711,13 @@ void bootloader(void) for (__xdata uint16_t i=0; i < 960; i++) { print_string("Writing block: "); print_short(dest); - flash_read_bulk(flash_buf, source, 0x200); + flash_addr = source; + flash_read_bulk(flash_buf, 0x200); write_char('\n'); if (!(i & 0x7)) flash_sector_erase(dest); - flash_write_bytes(dest, flash_buf, 0x200); + flash_addr = dest; + flash_write_bytes(flash_buf, 0x200); dest += 0x200; source += 0x200; } From 7a87b798713cf477c8e25899fd81fa475ea665c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 5 Oct 2025 15:36:08 +0200 Subject: [PATCH 07/12] Convert flash_addr to struct flash_region. flash_region storage flash address and length, which a operation is needed. --- cmd_parser.c | 13 +++++---- httpd/httpd.c | 23 +++++++++++----- rtl837x_common.h | 5 ++++ rtl837x_flash.c | 72 +++++++++++++++++++++++++----------------------- rtl837x_flash.h | 6 ++-- rtlplayground.c | 18 +++++++----- 6 files changed, 80 insertions(+), 57 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 41e4f3b..ee06b95 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -33,7 +33,7 @@ extern __code uint8_t * __code greeting; extern __code uint8_t * __code hex; extern __xdata uint8_t flash_buf[512]; -extern __xdata uint32_t flash_addr; +extern __xdata struct flash_region_t flash_region; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint16_t vlan_ptr; @@ -497,7 +497,8 @@ void cmd_parser(void) __banked } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { print_string("\nDUMPING FLASH\n"); - flash_addr = 0; + flash_region.addr = 0; + flash_region.len = 255; flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'j') { @@ -513,7 +514,8 @@ void cmd_parser(void) __banked print_string("\nFLASH FAST MODE\n"); flash_init(1); print_string("\nNow dumping flash\n"); - flash_addr = 0; + flash_region.addr = 0; + flash_region.len = 255; flash_dump(255); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { @@ -524,8 +526,9 @@ void cmd_parser(void) __banked print_string("\nFLASH write\n"); for (uint8_t i = 0; i < 20; i++) flash_buf[i] = greeting[i]; - flash_addr = 0x20000; - flash_write_bytes(flash_buf, 20); + flash_region.addr = 0x200000; + flash_region.len = 20; + flash_write_bytes(flash_buf); } if (cmd_compare(0, "port") && cmd_words_b[1] > 0) { print_string("\nPORT "); diff --git a/httpd/httpd.c b/httpd/httpd.c index 4436458..434ec2f 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -17,10 +17,11 @@ extern __code struct f_data f_data[]; extern __code fcall_ptr f_calls[]; extern __code char * __code mime_strings[]; -extern __xdata uint32_t flash_addr; +extern __xdata struct flash_region_t flash_region; // Flash buffer to optimize flash writing speed, write_len is the current filling position extern __xdata uint8_t flash_buf[512]; +__xdata uint32_t uptr; // Current flash write position __xdata uint16_t write_len; __xdata uint8_t outbuf[TCP_OUTBUF_SIZE]; @@ -214,7 +215,10 @@ uint8_t stream_upload(__xdata uint16_t bptr) if (!boundary[bindex]) { s->tstate = TSTATE_NONE; print_string("len 2: "); print_short(write_len); write_char(' '); - flash_write_bytes(flash_buf, write_len); + flash_region.addr = uptr; + flash_region.len = write_len; + flash_write_bytes(flash_buf); + uptr += write_len; write_len = 0; // TODO: This is a bit premature, what about a nice web-page saying the device will reset??? print_string("Upload to flash done, will reset!\n"); @@ -235,7 +239,10 @@ uint8_t stream_upload(__xdata uint16_t bptr) flash_buf[write_len++] = p[bptr++]; if (write_len >= 256) { print_string("len: "); print_short(write_len); write_char(' '); - flash_write_bytes(flash_buf, write_len); + flash_region.addr = uptr; + flash_region.len = write_len; + flash_write_bytes(flash_buf); + uptr += write_len; write_len = 0; } bindex = 0; @@ -297,7 +304,7 @@ void handle_post(void) print_string("Have content octets\n"); p += 4; // Skip \r\n\r\n sequence at end of preamble of part - flash_addr = FIRMWARE_UPLOAD_START; + uptr = FIRMWARE_UPLOAD_START; bindex = 0; write_len = 0; stream_upload(p - uip_appdata); @@ -437,8 +444,9 @@ void httpd_appcall(void) print_string("call done\n"); mpos += CMARK_S; len_left -= mpos; - flash_addr = f_data[entry].start + mpos; - flash_find_mark("#{", len_left); + flash_region.addr = f_data[entry].start + mpos; + flash_addr = f_data[entry].start + f_data[entry].len - len_left; + flash_find_mark("#{"); print_string("mpos now: "); print_short(mpos); write_char('\n'); } print_string("At end mpos: "); print_short(mpos); write_char('\n'); @@ -447,7 +455,8 @@ void httpd_appcall(void) slen += len_left; } else { print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); - flash_addr = f_data[entry].start; + flash_region.addr = f_data[entry].start; + flash_region.len = len_left; flash_read_bulk(outbuf + slen, len_left); slen += len_left; } diff --git a/rtl837x_common.h b/rtl837x_common.h index 35d1e49..c04fbb3 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -50,6 +50,11 @@ struct uip_eth_addr { uint8_t addr[6]; }; +struct flash_region_t { + uint32_t addr; + uint16_t len; +}; + extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 674c735..2530452 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -10,7 +10,8 @@ __xdata uint8_t dio_enabled; __xdata uint8_t markbuf[16]; extern __xdata uint16_t mpos; -__xdata uint32_t flash_addr; +__xdata struct flash_region_t flash_region; + // For the flash commands, see e.g. Windbond W25Q32JV datasheet #define CMD_WRITE_STATUS 0x01 @@ -206,10 +207,10 @@ void flash_dump(uint8_t len) // Read 4 bytes SFR_FLASH_TCONF = 4; while (len) { - SFR_FLASH_ADDR16 = flash_addr >> 16; - SFR_FLASH_ADDR8 = flash_addr >> 8; - SFR_FLASH_ADDR0 = flash_addr; - flash_addr += 4; + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; + flash_region.addr += 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); @@ -233,7 +234,7 @@ void flash_dump(uint8_t len) * Reads bulk data of length len from the flash memory starging at address src * and writes the data into a buffer pointed to by dst in XMEM */ -void flash_read_bulk(__xdata uint8_t *dst, register uint16_t len) +void flash_read_bulk(__xdata uint8_t *dst) { short status; do { @@ -251,28 +252,30 @@ void flash_read_bulk(__xdata uint8_t *dst, register uint16_t len) SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? } // Read 4 bytes - SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = flash_addr >> 16; - SFR_FLASH_ADDR8 = flash_addr >> 8; - SFR_FLASH_ADDR0 = flash_addr; - flash_addr += 4; + while (1) { + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; + flash_region.addr += 4; + + SFR_FLASH_TCONF = 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); *dst++ = SFR_FLASH_DATA0; - if (len == 1) - return; + if (flash_region.len == 1) + break; *dst++ = SFR_FLASH_DATA8; - if (len == 2) - return; + if (flash_region.len == 2) + break; *dst++ = SFR_FLASH_DATA16; - if (len == 3) - return; + if (flash_region.len == 3) + break; *dst++ = SFR_FLASH_DATA24; - - len -= 4; + if (flash_region.len == 4) + break; + flash_region.len -= 4; } } @@ -412,24 +415,21 @@ void flash_sector_erase(uint32_t addr) } -void flash_write_bytes(__xdata uint8_t *ptr, __xdata uint16_t len) +void flash_write_bytes(__xdata uint8_t *ptr) { - __xdata uint8_t exit_loop = 0; - - write_char('>'); print_long(flash_addr); write_char(':'); print_short(len); write_char('-'); print_byte(*ptr); write_char('\n'); - while(1) { + write_char('>'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('-'); print_byte(*ptr); write_char('\n'); + while(1) { flash_write_enable(); SFR_FLASH_CMD = CMD_PAGE_PROGRAM; SFR_FLASH_TCONF = 0x40 | 8 | 4; // Bytes written is 4, 8 enables write, 0x40 is unknown // Last transfer? - if (len < 5) { - SFR_FLASH_TCONF = 8 | len; - exit_loop = 1; + if (flash_region.len < 5) { + SFR_FLASH_TCONF = 8 | flash_region.len; } - SFR_FLASH_ADDR16 = flash_addr >> 16; - SFR_FLASH_ADDR8 = flash_addr >> 8; - SFR_FLASH_ADDR0 = flash_addr; + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; SFR_FLASH_DATA0 = *ptr++; SFR_FLASH_DATA8 = *ptr++; SFR_FLASH_DATA16 = *ptr++; @@ -437,11 +437,13 @@ void flash_write_bytes(__xdata uint8_t *ptr, __xdata uint16_t len) // Execute transfer, we wait for completion at top of loop SFR_FLASH_EXEC_GO = 1; - if (exit_loop) + + if (flash_region.len < 5) break; - len -= 4; - flash_addr += 4; - } + + flash_region.len -= 4; + flash_region.addr += 4; + }; while (flash_read_status() & 0x1); flash_configure_mmio(); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index de81bd2..43a1948 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -4,11 +4,11 @@ void flash_init(uint8_t enable_dio); void flash_read_uid(void); void flash_write_enable(void); -void flash_dump(register uint8_t len); +void flash_dump(uint8_t len); void flash_read_jedecid(void); void flash_read_security(uint32_t addr, uint8_t len); void flash_sector_erase(uint32_t addr); -void flash_read_bulk(__xdata uint8_t *dst, __xdata uint16_t len); -void flash_write_bytes(__xdata uint8_t *ptr, __xdata uint16_t len); +void flash_read_bulk(__xdata uint8_t *dst); +void flash_write_bytes(__xdata uint8_t *ptr); void flash_find_mark( __code uint8_t *mark, __xdata uint16_t len); #endif diff --git a/rtlplayground.c b/rtlplayground.c index d011dde..b4aeb73 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -70,7 +70,7 @@ __xdata uint8_t sfr_data[4]; extern __xdata uint8_t cmd_buffer[SBUF_SIZE]; extern __xdata uint8_t gpio_last_value[8]; -extern __xdata uint32_t flash_addr; +extern __xdata struct flash_region_t flash_region; __code uint8_t * __code greeting = "\nA minimal prompt to explore the RTL8372:\n"; __code uint8_t * __code hex = "0123456789abcdef"; @@ -1700,8 +1700,10 @@ void bootloader(void) flash_init(0); // Check update in progress and move blocks - flash_addr = FIRMWARE_UPLOAD_START; - flash_read_bulk(flash_buf, 0x100); + flash_region.addr = FIRMWARE_UPLOAD_START; + flash_region.len = 0x100; + flash_read_bulk(flash_buf); + if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { print_string("Update in progress, moving firmware to start of FLASH!\n"); @@ -1711,13 +1713,15 @@ void bootloader(void) for (__xdata uint16_t i=0; i < 960; i++) { print_string("Writing block: "); print_short(dest); - flash_addr = source; - flash_read_bulk(flash_buf, 0x200); + flash_region.addr = source; + flash_region.len = 0x200; + flash_read_bulk(flash_buf); write_char('\n'); if (!(i & 0x7)) flash_sector_erase(dest); - flash_addr = dest; - flash_write_bytes(flash_buf, 0x200); + flash_region.addr = dest; + flash_region.len = 0x200; + flash_write_bytes(flash_buf); dest += 0x200; source += 0x200; } From 884bc18a619afbef8bd2e0b8d325d3724d0a29a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 5 Oct 2025 15:47:14 +0200 Subject: [PATCH 08/12] Remove flash_read_bulk(), refactor website and execute_config(). flash_read_bulk() is kind of a printf function. But did not work as well. flash_read_bulk() was used in the http generation so this needed to be changed as well. For the website we decided that we are going to use CSR(Client Side Rendering). So every HTML and JS files are now static. Variables are fetched via json calls and output is render on the client side. Also usefull for the future when we want a REST like API. execute_config() was also using flash_read_bulk(). This have been replaced with flash_read_bulk() and parsing the flash_buf buffer. --- cmd_parser.c | 56 +++++++++++++++++++---------- html/index.html | 47 +++++++++++++++---------- html/main_info.js | 22 ++++++++++++ httpd/httpd.c | 50 +++++--------------------- httpd/page_impl.c | 25 ++++++------- httpd/page_impl.h | 1 + rtl837x_flash.c | 89 +++-------------------------------------------- rtl837x_flash.h | 1 - tools/fileadder.c | 6 ++-- tools/httpd_sim.c | 12 +++++++ 10 files changed, 132 insertions(+), 177 deletions(-) create mode 100644 html/main_info.js diff --git a/cmd_parser.c b/cmd_parser.c index ee06b95..1f9ad4c 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -628,24 +628,44 @@ void cmd_parser(void) __banked } } +#define FLASH_READ_BURST_SIZE 0x100; void execute_config(void) __banked { - __xdata uint32_t pos = CONFIG_START; - __xdata uint16_t len_left = CONFIG_LEN; - do { - flash_addr = pos; - flash_find_mark("\n", len_left); - if (mpos != 0xffff) { - __xdata uint16_t len = len_left - mpos; - flash_addr = pos; - flash_read_bulk(&cmd_buffer[0], len > SBUF_SIZE ? SBUF_SIZE : len); - cmd_buffer[len > SBUF_SIZE ? SBUF_SIZE : len] = '\0'; - len++; - pos += len; - len_left -= len; - if (len && !cmd_tokenize()) - cmd_parser(); - } - } while (mpos != 0xffff); -} + memcpyc(flash_buf, "test", 5); + print_string_x(flash_buf); + __xdata uint32_t pos = CONFIG_START; + __xdata uint16_t len_left = CONFIG_LEN; + do { + flash_region.addr = pos; + flash_region.len = FLASH_READ_BURST_SIZE; + write_char('-'); print_long(flash_region.addr); write_char(':'); print_short(flash_region.len); write_char('\n'); + + flash_read_bulk(flash_buf); + + uint8_t cfg_idx = 0; + uint8_t c = 0; + do { + for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) { + c = flash_buf[cfg_idx++]; + print_byte(c); + + if (c == 0 || c == '\n') { + cmd_buffer[cmd_idx] = '\0'; + write_char('\n'); write_char('#'); print_short(cfg_idx); write_char('-'); print_short(cmd_idx); write_char('-'); print_string_x(cmd_buffer); write_char('\n'); + if (cmd_idx && !cmd_tokenize()) + cmd_parser(); + if (c == 0) + return; + break; + } + + cmd_buffer[cmd_idx] = c; + } + write_char('N'); + } while(cfg_idx); + + len_left -= FLASH_READ_BURST_SIZE; + pos += FLASH_READ_BURST_SIZE; + } while(len_left); +} diff --git a/html/index.html b/html/index.html index 485e607..f9f94c6 100644 --- a/html/index.html +++ b/html/index.html @@ -1,24 +1,35 @@ - - - - - FreeSwitchOS Main Page - - - -
+ + + + + + + FreeSwitchOS Main Page + + + + +

Switch Configuration

- - - #{html_index} +
Setting
+ + + + +
Settings
-
- +
+ + diff --git a/html/main_info.js b/html/main_info.js new file mode 100644 index 0000000..1d9d7ee --- /dev/null +++ b/html/main_info.js @@ -0,0 +1,22 @@ +document.addEventListener("DOMContentLoaded", function () { + fetch('/information.json') + .then(response => response.json()) + .then(data => { + const tableBody = document.getElementById('infoTable').querySelector('tbody'); + + // Create table rows + for (const [key, value] of Object.entries(data)) { + const row = document.createElement('tr'); + const cellKey = document.createElement('td'); + const cellValue = document.createElement('td'); + + cellKey.textContent = key; + cellValue.textContent = value; + + row.appendChild(cellKey); + row.appendChild(cellValue); + tableBody.appendChild(row); + } + }) + .catch(error => console.error('Error fetching the data:', error)); +}); diff --git a/httpd/httpd.c b/httpd/httpd.c index 434ec2f..cf396a3 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -15,7 +15,6 @@ #pragma codeseg BANK1 extern __code struct f_data f_data[]; -extern __code fcall_ptr f_calls[]; extern __code char * __code mime_strings[]; extern __xdata struct flash_region_t flash_region; @@ -407,6 +406,8 @@ void httpd_appcall(void) print_string("Not file entry\n"); if (!strcmp(q, "/status.json")) { send_status(); + } else if (!strcmp(q, "/information.json")) { + send_basic_info(); } else if (!strcmp(q, "/vlan.json")) { parse_short(q + 15); send_vlan(short_parsed); @@ -419,47 +420,14 @@ void httpd_appcall(void) print_string("Have entry\n"); slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: "); slen += strtox(outbuf + slen, mime_strings[f_data[entry].mime]); - slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000"); - slen += strtox(outbuf + slen, "\r\n\r\n"); + slen += strtox(outbuf + slen, "\r\nCache-Control: max-age=2592000\r\n\r\n"); len_left = f_data[entry].len; - if (f_data[entry].mime == mime_HTML) { - print_string("MIME is html len is "); print_short(len_left); write_char('\n'); - mpos = 0; - flash_addr = f_data[entry].start; - flash_find_mark("#{", len_left); - print_string("mpos: "); print_short(mpos); write_char('\n'); - while (mpos != 0xffff) { - print_string("Entry-len:"); print_short(len_left); write_char('\n'); - mpos = len_left - mpos; - print_string("l/pos: "); print_short(mpos); write_char('\n'); - flash_addr = f_data[entry].start + f_data[entry].len - len_left; - flash_read_bulk(outbuf + slen, mpos + CMARK_S); // call marker is e.g. #{001} - slen += mpos; - write_char('@'); write_char(outbuf[slen + 2]); write_char(outbuf[slen + 3]); write_char(outbuf[slen + 4]); - fcall_ptr ptr = f_calls[(outbuf[slen + 2] - '0') * 100 + (outbuf[slen + 3]-'0') * 10 + outbuf[slen + 4] - '0']; - slen -= CMARK_S; // Overwrite marker with generated html - print_string("Call location is: "); print_short((uint16_t)ptr); write_char('\n'); -// f_calls[outbuf[slen + 2] * 100 + outbuf[slen + 3] * 10 + outbuf[slen + 4]](); - ptr(); - print_string("call done\n"); - mpos += CMARK_S; - len_left -= mpos; - flash_region.addr = f_data[entry].start + mpos; - flash_addr = f_data[entry].start + f_data[entry].len - len_left; - flash_find_mark("#{"); - print_string("mpos now: "); print_short(mpos); write_char('\n'); - } - print_string("At end mpos: "); print_short(mpos); write_char('\n'); - flash_addr = f_data[entry].start + f_data[entry].len - len_left; - flash_read_bulk(outbuf + slen, len_left); - slen += len_left; - } else { - print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); - flash_region.addr = f_data[entry].start; - flash_region.len = len_left; - flash_read_bulk(outbuf + slen, len_left); - slen += len_left; - } + + print_string("MIME: "); print_string(mime_strings[f_data[entry].mime]); write_char('\n'); + flash_region.addr = f_data[entry].start; + flash_region.len = len_left; + flash_read_bulk(outbuf + slen); + slen += len_left; } do_send: print_string("slen: "); print_short(slen); write_char('\n'); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 89ae166..3a66242 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -27,6 +27,7 @@ extern __xdata uint8_t isRTL8373; extern __xdata uint8_t sfp_pins_last; extern __xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; +__code uint8_t * __code HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"; /* Convert only the lower nibble to ascii HEX char. For convenience the upper nibble is masked out. @@ -133,40 +134,40 @@ void reg_to_html(register uint16_t reg) sfr_data_to_html(); } - -uint16_t html_index(void) +void send_basic_info(void) { - print_string("html_index called\n"); - slen += strtox(outbuf + slen, "IP Address"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); + print_string("send_basic_info called\n"); + slen += strtox(outbuf + slen, "{\"ip_address\":\""); itoa_html(uip_hostaddr[0]); char_to_html('.'); itoa_html(uip_hostaddr[0] >> 8); char_to_html('.'); itoa_html(uip_hostaddr[1]); char_to_html('.'); itoa_html(uip_hostaddr[1] >> 8); - slen += strtox(outbuf + slen, "Gateway"); + slen += strtox(outbuf + slen, "\",\"ip_gateway\":\""); itoa_html(uip_draddr[0]); char_to_html('.'); itoa_html(uip_draddr[0] >> 8); char_to_html('.'); itoa_html(uip_draddr[1]); char_to_html('.'); itoa_html(uip_draddr[1] >> 8); - slen += strtox(outbuf + slen, "Netmask"); + slen += strtox(outbuf + slen, "\",\"ip_netmask\":\""); itoa_html(uip_netmask[0]); char_to_html('.'); itoa_html(uip_netmask[0] >> 8); char_to_html('.'); itoa_html(uip_netmask[1]); char_to_html('.'); itoa_html(uip_netmask[1] >> 8); - slen += strtox(outbuf + slen, "MAC Address"); + slen += strtox(outbuf + slen, "\",\"mac_address\":\""); byte_to_html(uip_ethaddr.addr[0]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[1]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[2]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[3]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[4]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[5]); - slen += strtox(outbuf + slen, ""); - return 0; + slen += strtox(outbuf + slen, "\",\"sw_ver\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}"); + // slen += strtox(outbuf + slen, "\"}"); } void send_vlan(__xdata uint16_t vlan) { - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending VLAN\n"); //{"members":"0x00060011"} slen += strtox(outbuf + slen, "{\"members\":\"0x"); @@ -187,7 +188,7 @@ void send_vlan(__xdata uint16_t vlan) void send_counters(char port) { print_string("send_counters called: "); print_byte(port); write_char('\n'); - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending counters\n"); port--; @@ -209,7 +210,7 @@ void send_counters(char port) void send_status(void) { - slen = strtox(outbuf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); + slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending status\n"); char_to_html('['); diff --git a/httpd/page_impl.h b/httpd/page_impl.h index c643140..16f776e 100644 --- a/httpd/page_impl.h +++ b/httpd/page_impl.h @@ -4,5 +4,6 @@ void send_counters(char port); void send_status(void); void send_vlan(register uint16_t vlan); +void send_basic_info(void); #endif diff --git a/rtl837x_flash.c b/rtl837x_flash.c index 2530452..c4bf5af 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -16,6 +16,7 @@ __xdata struct flash_region_t flash_region; // For the flash commands, see e.g. Windbond W25Q32JV datasheet #define CMD_WRITE_STATUS 0x01 #define CMD_PAGE_PROGRAM 0x02 +#define CMD_READ 0x03 #define CMD_WRITE_ENABLE 0x06 #define CMD_FREAD 0x0b #define CMD_SECTOR_ERASE 0x20 @@ -248,9 +249,11 @@ void flash_read_bulk(__xdata uint8_t *dst) SFR_FLASH_DUMMYCYCLES = 4; } else { SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = CMD_FREAD; // Fast read - SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? + SFR_FLASH_CMD_R = CMD_READ; + SFR_FLASH_DUMMYCYCLES = 0; } + + // Read 4 bytes while (1) { SFR_FLASH_ADDR16 = flash_region.addr >> 16; @@ -280,88 +283,6 @@ void flash_read_bulk(__xdata uint8_t *dst) } -void flash_find_mark(__code uint8_t *mark, __xdata uint16_t len) -{ - __xdata uint16_t status; - do { - status = flash_read_status(); - } while (status & 0x1); - - // Set fast read mode - if (dio_enabled) { - SFR_FLASH_MODEB = 0x18; - SFR_FLASH_CMD_R = CMD_FREAD_DIO; - SFR_FLASH_DUMMYCYCLES = 4; - } else { - SFR_FLASH_MODEB = 0x0; - SFR_FLASH_CMD_R = CMD_FREAD; // Fast read - SFR_FLASH_DUMMYCYCLES = 8; // Add 8 dummy clocks after read? - } - - __xdata uint8_t i = 0; - __xdata uint8_t l = 0; - __xdata uint8_t k; - - // Calculate the length - while (mark[i++]) - l++; - - if (l >= 12) { - mpos = 0xffff; - return; - } - - i = 0; - SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = flash_addr >> 16; - SFR_FLASH_ADDR8 = flash_addr >> 8; - SFR_FLASH_ADDR0 = flash_addr; - flash_addr += 4; - - SFR_FLASH_EXEC_GO = 1; - while(SFR_FLASH_EXEC_BUSY); - markbuf[i++] = SFR_FLASH_DATA0; - if (len != 1) { - markbuf[i++] = SFR_FLASH_DATA8; - if (len != 2) { - markbuf[i++] = SFR_FLASH_DATA16; - if (len != 3) { - markbuf[i++] = SFR_FLASH_DATA24; - } else { - markbuf[i++] = 0; - } - } else { - markbuf[i++] = 0; - } - } else { - markbuf[i++] = 0; - } - - len -= len >= 4? 4 : len; - uint8_t j = 0; - k = (i + 13 - l) & 0xf; - i &= 0xf; - while (mark[j] && (k != ((i) & 0xf))) { - if (mark[j] != markbuf[k]) { - k = k - j + 17; - j = 0; - } else { - k++; - j++; - } - k &= 0xf; - } - if (!mark[j]) { - mpos = len + l + ((4 - ( k & 0x3)) & 0x3); - return; - } - } - mpos = 0xffff; - return; -} - - void flash_read_security(uint32_t addr, uint8_t len) { while (flash_read_status() & 0x1); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index 43a1948..fb0ada6 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -10,5 +10,4 @@ void flash_read_security(uint32_t addr, uint8_t len); void flash_sector_erase(uint32_t addr); void flash_read_bulk(__xdata uint8_t *dst); void flash_write_bytes(__xdata uint8_t *ptr); -void flash_find_mark( __code uint8_t *mark, __xdata uint16_t len); #endif diff --git a/tools/fileadder.c b/tools/fileadder.c index 84a2865..7b739d8 100644 --- a/tools/fileadder.c +++ b/tools/fileadder.c @@ -270,7 +270,7 @@ int main(int argc, char **argv) defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef enum mime_type_e {\n mime_HTML = 0,\n mime_SVG,\n mime_ICO,\n mime_PNG,\n mime_JS,\n mime_CSS,\n mime_TXT\n} mime_type_t;\n\n"); defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "struct f_data {\n __code char *file;\n uint32_t start;\n uint16_t len;\n mime_type_t mime;\n};\n\n"); - defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(void);\n\n"); + // defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "typedef uint16_t (* fcall_ptr)(void);\n\n"); ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "// This file is automatically generated, do not edit!\n\n"); if (arguments.prefix) @@ -280,7 +280,7 @@ int main(int argc, char **argv) ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " __code char * __code mime_strings[] = {\n \"text/html\",\n \"image/svg+xml\",\n" " \"image/svg+xml\",\n \"image/png\",\n \"text/javascript\",\n \"text/css\",\n \"text/plain\"};\n\n"); ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, "__code struct f_data f_data[] = {\n"); - fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n"); + // fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "\n__code fcall_ptr f_calls[] = {\n"); // Now that the beginning of the buffer is filled with out image, optionally resize the image if (filesize) @@ -335,7 +335,7 @@ int main(int argc, char **argv) } ibuf_p += snprintf(&ibuf[ibuf_p], INDEX_SIZE - ibuf_p, " {0, 0, 0}\n};\n"); - fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n"); + // fbuf_p += snprintf(&fbuf[fbuf_p], DEF_SIZE - fbuf_p, "};\n"); defbuf_p += snprintf(&dbuf[defbuf_p], DEF_SIZE - defbuf_p, "#endif\n"); if (filesize) { diff --git a/tools/httpd_sim.c b/tools/httpd_sim.c index 2a4f8d1..9c54444 100644 --- a/tools/httpd_sim.c +++ b/tools/httpd_sim.c @@ -67,6 +67,13 @@ char *getMime(const char *name) return "text/plain"; } +void send_basic_info(int socket) +{ + char *response = "HTTP/1.1 200 OK\r\n" + "Content-Type: application/json; charset=UTF-8\r\n\r\n" + "{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"v0.1-ge4c48586\",\"hw_ver\":\"SWGT024-V2.0\"}"; + write(socket, response, strlen(response)); +} void send_vlan(int s, int vlan) { @@ -249,6 +256,11 @@ void launch(struct Server *server) send_status(new_socket); goto done; } + if (!strncmp(&buffer[4], "/information.json", 12)) { + printf("Status request\n"); + send_basic_info(new_socket); + goto done; + } if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) { int vlan = atoi(&buffer[19]); printf("VLAN request for %d\n", vlan); From 1bec5cdf8a0115ca0a8a97c1b7316845dceb9bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 5 Oct 2025 16:18:39 +0200 Subject: [PATCH 09/12] Add basic config.txt --- config.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 config.txt diff --git a/config.txt b/config.txt new file mode 100644 index 0000000..3200af0 --- /dev/null +++ b/config.txt @@ -0,0 +1,3 @@ +ip 192.168.10.247 +gw 192.168.10.1 +netmask 255.255.255.0 \ No newline at end of file From 52fa41760cd0a061128bef050232abf992fb4148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 5 Oct 2025 16:22:23 +0200 Subject: [PATCH 10/12] Don't pass the first 16-bit argument via xdata. Calling confention already uses the DPTR registers as the first two byte arguments. So adds a lot of code to put the 16-bit value on xdata, still passes the 16-bit xdata ptr in DPTR registers, then read the xdata value. So it doesn't save any sram bytes. --- httpd/httpd.c | 20 ++++++++++---------- httpd/page_impl.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/httpd/httpd.c b/httpd/httpd.c index cf396a3..704a3dd 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -61,9 +61,9 @@ void httpd_init(void) __banked } -uint8_t find_entry(__xdata uint8_t * __xdata e) +uint8_t find_entry(__xdata uint8_t *e) { - __xdata uint8_t i, j; + uint8_t i, j; for (i = 0; f_data[i].len; i++) { j = 0; @@ -78,9 +78,9 @@ uint8_t find_entry(__xdata uint8_t * __xdata e) } -char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) +char strcmp(__xdata uint8_t *c, __code uint8_t * __xdata d) { - register uint8_t i = 0; + uint8_t i = 0; while (d[i] && (d[i] == c[i])) i++; @@ -93,9 +93,9 @@ char strcmp(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) } -char is_word(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) +char is_word(__xdata uint8_t *c, __code uint8_t * __xdata d) { - register uint8_t i = 0; + uint8_t i = 0; while (d[i] && (d[i] == c[i])) i++; @@ -108,7 +108,7 @@ char is_word(__xdata uint8_t * __xdata c, __code uint8_t * __xdata d) } -char is_word_x(__xdata uint8_t * __xdata c, __xdata uint8_t *d) +char is_word_x(__xdata uint8_t *c, __xdata uint8_t *d) { register uint8_t i = 0; @@ -197,7 +197,7 @@ __xdata uint8_t *scan_header(__xdata uint8_t *p) * Input: the current position in the TCP buffer (uip_appdata) * Returns 1: More data to read, 0: Upload complete, all parts reads */ -uint8_t stream_upload(__xdata uint16_t bptr) +uint8_t stream_upload(uint16_t bptr) { __xdata uint8_t *p = uip_appdata; __xdata struct httpd_state * __xdata s = &(uip_conn->appstate); @@ -261,11 +261,11 @@ void handle_post(void) // Find end of request path while (*p && !is_separator(*p)) p++; - *p = '\0'; + *p++ = '\0'; // Find end of request header boundary[0] ='\0'; - p = scan_header(p + 1); + p = scan_header(p); print_string("Boundary: >"); print_string_x(boundary); print_string("<\n"); if (!*p || !content_type) { print_string("Bad Request!\n"); diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 3a66242..dce8843 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -165,7 +165,7 @@ void send_basic_info(void) } -void send_vlan(__xdata uint16_t vlan) +void send_vlan(uint16_t vlan) { slen = strtox(outbuf, HTTP_RESPONCE_JSON); print_string("sending VLAN\n"); From a59f92a6480ff6a53a913d6e8beb6c257526ee12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Sun, 5 Oct 2025 16:49:44 +0200 Subject: [PATCH 11/12] Also use struct flash_region in flash_read_security(), flash_sector_erase(). --- cmd_parser.c | 15 +++++++++++---- rtl837x_flash.c | 36 ++++++++++++++++++------------------ rtl837x_flash.h | 4 ++-- rtlplayground.c | 9 ++++++--- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 1f9ad4c..4538c3d 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -491,9 +491,15 @@ void cmd_parser(void) __banked if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'r') { print_string("\nPRINT SECURITY REGISTERS\n"); // The following will only show something else than 0xff if it was programmed for a managed switch - flash_read_security(0x0001000, 40); - flash_read_security(0x0002000, 40); - flash_read_security(0x0003000, 40); + flash_region.addr = 0x0001000; + flash_region.len = 40; + flash_read_security(); + flash_region.addr = 0x0002000; + flash_region.len = 40; + flash_read_security(); + flash_region.addr = 0x0003000; + flash_region.len = 40; + flash_read_security(); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'd') { print_string("\nDUMPING FLASH\n"); @@ -520,7 +526,8 @@ void cmd_parser(void) __banked } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'e') { print_string("\nFLASH erase\n"); - flash_sector_erase(0x20000); + flash_region.addr = 0x20000; + flash_sector_erase(); } if (cmd_compare(0, "flash") && cmd_words_b[1] > 0 && cmd_buffer[cmd_words_b[1]] == 'w') { print_string("\nFLASH write\n"); diff --git a/rtl837x_flash.c b/rtl837x_flash.c index c4bf5af..4df0604 100644 --- a/rtl837x_flash.c +++ b/rtl837x_flash.c @@ -283,7 +283,7 @@ void flash_read_bulk(__xdata uint8_t *dst) } -void flash_read_security(uint32_t addr, uint8_t len) +void flash_read_security() { while (flash_read_status() & 0x1); @@ -294,40 +294,40 @@ void flash_read_security(uint32_t addr, uint8_t len) // Transfer 4 bytes (command + 3byte address) SFR_FLASH_TCONF = 4; - while (len) { - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; - addr += 4; + do { + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; + flash_region.addr += 4; SFR_FLASH_EXEC_GO = 1; while(SFR_FLASH_EXEC_BUSY); print_byte(SFR_FLASH_DATA0); - if (len == 1) - return; + if (flash_region.len == 1) + break; print_byte(SFR_FLASH_DATA8); - if (len == 2) - return; + if (flash_region.len == 2) + break; print_byte(SFR_FLASH_DATA16); - if (len == 3) - return; + if (flash_region.len == 3) + break; print_byte(SFR_FLASH_DATA24); - len -= 4; - } + flash_region.len -= 4; + } while(flash_region.len); } -void flash_sector_erase(uint32_t addr) +void flash_sector_erase(void) { flash_write_enable(); SFR_FLASH_TCONF = 8; SFR_FLASH_CMD = CMD_SECTOR_ERASE; - SFR_FLASH_ADDR16 = addr >> 16; - SFR_FLASH_ADDR8 = addr >> 8; - SFR_FLASH_ADDR0 = addr; + SFR_FLASH_ADDR16 = flash_region.addr >> 16; + SFR_FLASH_ADDR8 = flash_region.addr >> 8; + SFR_FLASH_ADDR0 = flash_region.addr; SFR_FLASH_EXEC_GO = 1; while (flash_read_status() & 0x1); diff --git a/rtl837x_flash.h b/rtl837x_flash.h index fb0ada6..cad66b0 100644 --- a/rtl837x_flash.h +++ b/rtl837x_flash.h @@ -6,8 +6,8 @@ void flash_read_uid(void); void flash_write_enable(void); void flash_dump(uint8_t len); void flash_read_jedecid(void); -void flash_read_security(uint32_t addr, uint8_t len); -void flash_sector_erase(uint32_t addr); +void flash_read_security(void); +void flash_sector_erase(void); void flash_read_bulk(__xdata uint8_t *dst); void flash_write_bytes(__xdata uint8_t *ptr); #endif diff --git a/rtlplayground.c b/rtlplayground.c index b4aeb73..5ce107c 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1717,8 +1717,10 @@ void bootloader(void) flash_region.len = 0x200; flash_read_bulk(flash_buf); write_char('\n'); - if (!(i & 0x7)) - flash_sector_erase(dest); + if (!(i & 0x7)) { + flash_region.addr = dest; + flash_sector_erase(); + } flash_region.addr = dest; flash_region.len = 0x200; flash_write_bytes(flash_buf); @@ -1728,7 +1730,8 @@ void bootloader(void) print_string("Deleting uploaded flash image\n"); dest = FIRMWARE_UPLOAD_START; for (register uint8_t i=0; i < 120; i++) { - flash_sector_erase(dest); + flash_region.addr = dest; + flash_sector_erase(); dest += 0x1000; } print_string("Resetting now"); From 928cf1cf58b7cc11a388be539c448191d507425f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Tue, 7 Oct 2025 21:12:08 +0200 Subject: [PATCH 12/12] http: upload: make sure we don't cross flash page boundaries. This causes the address pointer to wrap back to the front of the page. Which results in that the beginnen of the page can have data for the next page. --- httpd/httpd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/httpd/httpd.c b/httpd/httpd.c index 704a3dd..b376399 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -10,6 +10,9 @@ // Upload Firmware to 1M #define FIRMWARE_UPLOAD_START 0x100000 +// SPI FLASH MEMORY PAGE SIZE. +#define FLASHMEM_PAGE_SIZE 0x100 + #define CMARK_S 6 #pragma codeseg BANK1 @@ -236,13 +239,18 @@ uint8_t stream_upload(uint16_t bptr) bindex = 0; } flash_buf[write_len++] = p[bptr++]; - if (write_len >= 256) { + if (write_len >= FLASHMEM_PAGE_SIZE) { print_string("len: "); print_short(write_len); write_char(' '); flash_region.addr = uptr; - flash_region.len = write_len; + flash_region.len = FLASHMEM_PAGE_SIZE; flash_write_bytes(flash_buf); - uptr += write_len; - write_len = 0; + uptr += FLASHMEM_PAGE_SIZE; + write_len -= FLASHMEM_PAGE_SIZE; + + // Copy the remaining byte for the next page to the beginning of the buffer. + if (write_len > 0) { + memcpy(flash_buf, flash_buf + FLASHMEM_PAGE_SIZE, write_len); + } } bindex = 0; }