From 98763e3bff1fe9a36337935bb7fa113c7175a6b9 Mon Sep 17 00:00:00 2001 From: Andre Brait Date: Wed, 21 Oct 2026 11:04:44 +0200 Subject: [PATCH] startup: clear MAP_FLASH_PAGE_TO_XDATA before the C runtime initialises xdata Hardware reset starts the firmware with SFR 0x97 = 1, which maps xdata 0x4000-0xbfff to the flash image: reads return flash bytes, writes are lost. main() cleared it only after __mcs51_genXINIT and the XSEG clear had run, so XISEG (initialised globals) and the part of XSEG above 0x4000 kept stale RAM contents, e.g. session_timeout = 4484 and LLDP blocked on logical ports 0, 3 and 5. Clear it in __sdcc_external_startup(), which SDCC calls before both. Rename SFR_97 to MAP_FLASH_PAGE_TO_XDATA. --- CHANGELOG.md | 6 ++++++ installer/installer.c | 2 +- rtl837x_sfr.h | 2 +- rtlplayground.c | 10 +++++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb7d22bb..82559d0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,12 @@ - The web UI and the configuration upload now refuse a line the replay cannot take, instead of writing it to flash. +- Startup + - Initialised and zero-initialised globals above xdata 0x4000 now get their values at boot. + Hardware reset leaves SFR 0x97 at 1, which maps xdata 0x4000-0xbfff to the flash image, + and it was cleared only in `main()`, after the C startup code had copied and cleared them. + This showed as a random web session timeout and LLDP blocked on some ports without config. + ## Breaking changes - Config diff --git a/installer/installer.c b/installer/installer.c index 18dbdfdd..9d21dae4 100644 --- a/installer/installer.c +++ b/installer/installer.c @@ -348,7 +348,7 @@ void installer(void) { CKCON = 0; // Initial Clock configuration - SFR_97 = 0; // HADDR? + MAP_FLASH_PAGE_TO_XDATA = 0; // HADDR? // Set in managed mode: SFR_b9 = 0x00; diff --git a/rtl837x_sfr.h b/rtl837x_sfr.h index 45c117a6..4bde35d1 100644 --- a/rtl837x_sfr.h +++ b/rtl837x_sfr.h @@ -55,7 +55,7 @@ __sfr __at(0xbb) SFR_BANK_RET; __sfr __at(0x8e) CKCON; -__sfr __at(0x97) SFR_97; // HADDR? +__sfr __at(0x97) MAP_FLASH_PAGE_TO_XDATA; // 1 (hardware reset default): xdata 0x4000-0xbfff reads the flash image; 0: RAM __sfr __at(0xb9) SFR_b9; __sfr __at(0xba) SFR_ba; diff --git a/rtlplayground.c b/rtlplayground.c index 95681c49..a3213e4e 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1567,6 +1567,15 @@ void check_and_flash_update_image(void) } +/* Called by the SDCC startup code before it copies XINIT to XISEG and clears XSEG. + * Hardware reset starts us with MAP_FLASH_PAGE_TO_XDATA = 1, which maps xdata + * 0x4000-0xbfff to the flash image (reads return flash, writes are lost), so it + * must be 0 by then. */ +unsigned char __sdcc_external_startup(void) +{ + MAP_FLASH_PAGE_TO_XDATA = 0; + return 0; +} void main(void) { @@ -1577,7 +1586,6 @@ void main(void) sbuf_ptr = 0; CKCON = 0; // Initial Clock configuration - SFR_97 = 0; // HADDR? // Set in managed mode: SFR_b9 = 0x00;