Repository navigation
firmware: GEOS boot code copies read flash, not a DTCM copy - #97
Merged
SensoriumEmbedded merged 1 commit intoNov 10, 2026
Merged
Conversation
GCC turns a memcpy of a whole const array it can see into a copy of the array in .rodata, which the Teensy linker script places in DTCM. So the GEOS 128 boot ROML (245 bytes), its vectors (7) and the TR probe (12) cost RAM1 in every main image even though they are PROGMEM. Copying through a pointer GCC cannot see through keeps them in flash only.
kfox
marked this pull request as ready for review
November 10, 2026 16:16
SensoriumEmbedded
left a comment
Owner
There was a problem hiding this comment.
Thank you for chasing these bytes back into flash, nice find!
I reviewed this merged onto main (ac24701) and built both targets.
Memory: it matches your numbers. .data content drops 272 bytes on TR+ and 264 on TR, ITCM is unchanged, and flash grows by 256 bytes of progmem plus 40 (TR+) / 128 (TR) bytes of code.
Nothing to change from my side.
Hardware testing: Just to document. I'll hit these at some point, not a request or requirement! :)
Your GEOS 128 launches on the TR+ cover the boot ROM copies.
- A first launch from a fresh stock disk image, so the CONFIGURE probe gets patched
- One GEOS 128 launch on a plain TR
Thank you!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GeosBoot.hcopies threePROGMEMarrays with a plainmemcpy: the GEOS 128 boot ROML (245 bytes), its vectors (7) and the TR probe (12). GCC turns amemcpyof a whole const array it can see into a copy of that array in.rodata, which the Teensy linker script places in DTCM, so all 264 bytes sat in RAM1 in every main image whether or not GEOS was used. The three copies now go throughGeosCopyFromFlash(), which hides the source pointer from the optimizer with an empty__asm__, so the bytes stay in flash only. (__asm__rather thanasmbecause the GEOS host harnesses compile this header as-std=c99.)Verification
Main image, Docker linux/amd64, Teensyduino 1.61.0,
main(ac24701) vs this branch:The reported RAM1 figures don't move:
.datakeeps its size on both targets, because the freed bytes fall inside the padding before its next alignment step. That padding grows by 272 bytes on TR+ and 264 on TR, which is headroom before the next change costs a 4 KiB step of free-for-locals..dataon both targets and none is in.text.progmem. After, none is in.data, andnmshowsGeos128BootRomlandGeos128BootVectorsin flash.npm test: pass. Shortening the copy by one byte fails 5 GEOS boot tests, so the tests reach all three copies.Reviewed at
low(13 changed code lines), no findings.