PicoMite / WebMite 7.00.00RC2 - fixes for the RP2350 PSRAM builds
=================================================================

Files
  7.00.00RC2-Retime.patch  PSRAM timing after a run-time clock change (CPU SPEED, RESOLUTION)
  7.00.00RC2-Heap.patch    ERASE etc. never freed a block on a heap's first page
  7.00.00RC2-16MB.patch    optional: 16 MB PSRAM for WEBRP2350 and HDMIWEB
  CLOCKTEST.bas            test for the retime fix (CPU SPEED through 126..320 MHz)
  HEAPLEAK.bas             test for the heap fix (WebMite, 304 KB SRAM heap)

Applying (in a clean 7.00.00RC2 checkout)
  git apply 7.00.00RC2-Retime.patch
  git apply 7.00.00RC2-Heap.patch
Retime and Heap each apply on their own. For all three, apply
7.00.00RC2-16MB.patch first, then Retime, then Heap.

Testing
  CLOCKTEST.bas: boot with OPTION CPUSPEED 126000 or 200000, RUN, every line
  must show OK. No user PIO program may be running. CONST WITH378 = 1 adds
  378 MHz (core voltage 1.6 V).
  HEAPLEAK.bas: RUN; "No leak found" with the fix, "LEAK: ..." without it.

Details
-------
1. PSRAM timing is not updated when clk_sys changes at run time

CPUSpeedRuntime() rewrites the flash timing (qmi_hw->m[0].timing) but not the PSRAM's (m[1]), which keeps what psram_init() computed for the boot clock, and every field of it counts clk_sys cycles. Booting at 200 MHz (CLKDIV 2) and then CPU SPEED 320000 runs the PSRAM at 160 MHz; on HDMIWEB, booting at 252 MHz and then RESOLUTION 640,378000 gives 126 MHz. An ISSI part is rated for 104 MHz. Going down stretches MAX_SELECT past tCEM instead (boot at 320 MHz, switch to 126 MHz: about 10 us of CS low against the 4 us allowed).

The patch adds psram_retime() to psram.c (in RAM, interrupts off) and shares the calculation with psram_init(). Before the switch, CPUSpeedRuntime() writes a timing that holds at every clock the switch passes through: the old one, the new one and the 48 MHz of PLL_USB that set_sys_clock_pll() parks clk_sys on while PLL_SYS relocks. CLKDIV comes from the fastest of them, MAX_SELECT from the slowest. After the switch it writes the exact timing for the new clock. For a single clock psram_init() gets bit-identical values to before.

Test: CLOCKTEST.bas, best after booting at 126 or 200 MHz. On my board: boot at 200 MHz, 10 switches between 126 and 320 MHz, all OK (run twice).

2. ERASE never frees an array that starts on the first page of a heap

erase(), ClearVars(), REDIM PRESERVE, FreeMemory(), MemSize() and FRAMEBUFFER LAYER test "addr > MMHeap" or "addr > PSRAMbase" instead of ">=". A block that starts exactly at a heap's base is therefore not freed (and in FreeMemory() a PSRAM block at PSRAMbase goes to the SRAM branch). It stays allocated until the next RUN. Temporaries are found bottom-up from MMHeap (GetSystemMemory), so afterwards every one of them has to walk past the leaked block: in my stress test string and function heavy code then ran about 4x slower (20000 string operations 2.87 s, 0.72 s with the fix; a SIN+SQR loop 14.5k/s, 60k/s with the fix). The patch changes the 13 comparisons to >=.

Test: HEAPLEAK.bas (sizes are for the WebMite's 304 KB SRAM heap). Without the fix it reports "LEAK: an array of 362 pages (92672 bytes) was not freed by ERASE", with it "No leak found".

3. Optional: 16 MB PSRAM for WEBRP2350 and HDMIWEB

PSRAM_PART_MAX 16 MB and PSRAMHEAPMAX 14 MB for those two builds. The page map grows by 8 KB, paid for with 8 KB less HEAP_MEMORY_SIZE so the stack margins stay as they were. Tested on the WebMite with an ISSI IS66WVS16M8FBLL-104 (14 MB PSRAM heap, a 13 MB array written and checked). HDMIWEB builds but is untested: I have no HDMI.

