Skip to content

Correct GPIOBase mask width for 32- and 64-pin modules - #538

Open
BanjoR wants to merge 3 commits into
DCC-EX:masterfrom
BanjoR:codex/commandstation-gpio-width
Open

BanjoR wants to merge 3 commits into
DCC-EX:masterfrom
BanjoR:codex/commandstation-gpio-width

Conversation

@BanjoR

@BanjoR BanjoR commented Aug 16, 2026

Copy link
Copy Markdown

Automatic issue closing

Fixes #492

Summary

Correct GPIOBase<T>::_configure() so the temporary input mask uses the GPIOBase template type T, preventing truncation when a GPIO module uses more than 16 bits. Add a host-side regression test covering the production source contract and the 16-, 32-, and 64-pin boundary masks.

Root cause

IO_GPIOBase.h previously declared the _configure() mask as uint16_t mask = 1 << pin;. The fixed-width local could discard bits above bit 15 even though GPIOBase stores port state in T. It is now T mask = T(1) << pin;.

Bounded scope

In scope:

  • One production change in IO_GPIOBase.h: derive the _configure() mask from T.
  • One host-side test in test/gpio_base_mask_test.py: verify the production source contract and the 16-, 32-, and 64-bit boundary masks.

Explicit exclusions:

  • No new GPIO drivers, protocol changes, vendor or integration changes, or application-level changes.
  • Personal integration code and unrelated protocol behavior are explicitly out of scope.
  • No claim of support beyond the existing template-width model, including no new widths beyond 64 bits.
  • No physical hardware validation was performed.

Validation

Local host checks:

  • C:\Users\banjo\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe test\gpio_base_mask_test.py: 4 tests passed.
  • C:\Users\banjo\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe -m unittest discover -s test -p "*_test.py": 4 tests passed.
  • Read-only Python built-in compile() syntax check for test/gpio_base_mask_test.py: passed.
  • git diff --check upstream/master...HEAD: passed.
  • python -m py_compile test\gpio_base_mask_test.py: not completed because this host denied creating test\__pycache__ ([WinError 5] Access is denied); the no-write syntax check above passed.
  • PASS - Exact default python -m platformio run in a clean task checkout with an isolated PlatformIO core completed for all five configured environments: mega2560, ESP32, Nucleo-F411RE, Nucleo-F446RE, and Nucleo-F429ZI.

CI:

  • GitHub Actions run 31946743946 at commit 4cb8e4316dc29573b778301326a739d38135ced7 passed for mega2560, ESP32, Nucleo-F411RE, Nucleo-F446RE, and Nucleo-F429ZI.
  • Historical run 31945295119 failed because the initial C++ host test was compiled into firmware and <cassert> was unavailable; commit 4cb8e43 replaced it with the host Python test. The current run is the corrected result.
  • No required-status-check configuration is exposed for upstream master; the PR check rollup is empty because the workflow is push-triggered. The linked green run is the available CI result.

Hardware validation

Not run—no hardware available.

Maintainer bench criteria (not performed in this contribution):

  1. Build a test double or supported device implementation that instantiates GPIOBase<uint16_t>, GPIOBase<uint32_t>, and GPIOBase<uint64_t>.
  2. Configure the highest valid input pin for each width (15, 31, and 63), with pull-up enabled and disabled.
  3. Verify _portInUse retains the highest-bit mask, _portMode clears that bit, and the device receives the corresponding pull-up and mode writes without truncation.
  4. On physical hardware, toggle and read each highest pin and confirm the expected callback/readback path after a write-to-input transition.

References

The issue reference is intentionally non-closing.

@BanjoR
BanjoR marked this pull request as ready for review August 17, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The GPIOBase template only supports modules with a maximum of 16 pins.

1 participant