Kaben123 commented on PR #19950:
URL: https://github.com/apache/nuttx/pull/19950#issuecomment-5420174725

   ## CI analysis: `xtensa-03` (`esp32s3-devkit:usbmsc`) — root cause 
reproduced locally
   
   I reproduced the `xtensa-03` failure locally inside the official NuttX CI 
Docker image (`ghcr.io/apache/nuttx/apache-nuttx-ci-linux`, esptool v5.2.0) and 
traced it to a deterministic, PR-independent-looking, but size-triggered issue 
in `esptool`'s `--ram-only-header` image layout. **It is not a flash-size 
overflow, and it is not in the fs/inode code.**
   
   ### What actually fails
   
   NuttX itself compiles and links fine — the `nuttx` ELF is produced 
successfully. The failure happens afterwards, when `esptool elf2image 
--ram-only-header` converts the ELF into the flash image:
   
   ```
   File ".../esptool/bin_image.py", line 887, in save
       assert (f.tell() + 8 + self.ROM_LOADER.BOOTLOADER_FLASH_OFFSET) % (
   AssertionError
   ```
   
   This is `esptool`'s MMU-page (IROM_ALIGN = 64 KB) alignment assertion in the 
`ram_only_header` path, not a capacity check.
   
   ### Controlled comparison (same image, same esptool v5.2.0)
   
   | ELF | `elf2image --ram-only-header` | `elf2image` (no `--ram-only-header`) 
|
   |-----|:---:|:---:|
   | **master** | ✅ success | ✅ success |
   | **this PR** | ❌ AssertionError | ✅ success |
   
   So the same esptool that fails on this PR's ELF succeeds on master's ELF, 
and the same PR ELF succeeds once `--ram-only-header` is dropped. The trigger 
is the combination of `--ram-only-header` (enabled by 
`CONFIG_ESPRESSIF_SIMPLE_BOOT`, via `tools/esp32s3/Config.mk`) and the exact 
size of the flash-mapped segment.
   
   ### Why the size matters
   
   ```
   .flash.text size:
     master : 0x1ff13 (130835 B)
     this PR : 0x1fff7 (131063 B)   (+228 B)
   ```
   
   This PR's fs/inode path-resolution code adds ~228 bytes of `.text`, pushing 
`.flash.text` right up against the `0x20000` (2 × 64 KB IROM_ALIGN) boundary. 
In esptool's `--ram-only-header` padding logic this makes the per-segment 
alignment congruence `(f.tell() + 8 + BOOTLOADER_FLASH_OFFSET) % IROM_ALIGN == 
segment.addr % IROM_ALIGN` unsatisfiable, so the assertion fires. master's 
slightly smaller `.flash.text` still lands in a satisfiable range, which is why 
master passes and re-runs of this PR keep failing (the ELF is deterministic).
   
   ### Conclusion
   
   - Not flash overflow; the ELF builds and links cleanly.
   - Not caused by the fs/inode logic — that code is correct; it only changes 
code size.
   - The defect is in esptool v5.2.0's `--ram-only-header` layout, exposed here 
because this PR's size increase lands `.flash.text` on an IROM_ALIGN boundary 
for the `esp32s3-devkit:usbmsc` (SIMPLE_BOOT) config.
   
   Could an esp32s3 maintainer advise on the preferred path — e.g. an esptool 
version bump on CI, or an upstream fix for the `--ram-only-header` alignment 
padding? Happy to file an esptool issue with this reproduction if that helps.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to