fix: use offsetof for config checksum CRC range#329
Open
zekaizer wants to merge 1 commit into
Open
Conversation
sizeof(config_t) - sizeof(uint32_t) does not reliably point to the checksum field when the compiler adds tail padding (e.g., due to uint64_t alignment in output_t). This causes CRC mismatch on load, silently resetting config to defaults. Use offsetof(config_t, checksum) to compute the exact CRC range regardless of struct padding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
offsetof(config_t, checksum)instead ofsizeof(config_t) - sizeof(uint32_t)to compute the CRC range inload_config()andsave_config()Problem
sizeof(config_t) - sizeof(uint32_t)assumeschecksumoccupies the last 4 bytes of the struct with no trailing padding. This holds today on ARM Cortex-M0+ because the currentconfig_tlayout happens to have 4-byte alignment.However,
screensaver_tcontainsuint64_tfields (idle_time_us,max_time_us), which giveoutput_tan 8-byte alignment requirement on some ABIs. Ifconfig_tis extended with fields that break the current alignment (e.g., addinguint8_tfields beforechecksum), the compiler inserts tail padding afterchecksum, makingsizeof(config_t) - 4 > offsetof(config_t, checksum).When this happens, the CRC range includes the
checksumfield itself (and padding bytes), causingload_config()to always fail validation and silently reset config to defaults on every boot — even after a successfulsave_config().Fix
Replace
sizeof(config_t) - sizeof(uint32_t)withoffsetof(config_t, checksum), which always computes the exact byte range before the checksum field regardless of struct padding.Testing
Verified on RP2040 hardware (DeskHop PCB v1.1):
save_config()→ flash verify OK → simulatedload_config()CRC matchesTest plan
arm-none-eabi-gccconfig_tlayout (offsetof == sizeof - 4)🤖 Generated with Claude Code