drivers/spi/ice40: fix operator precedence in final clock cycle count#19415
Open
94xhn wants to merge 1 commit into
Open
drivers/spi/ice40: fix operator precedence in final clock cycle count#1941594xhn wants to merge 1 commit into
94xhn wants to merge 1 commit into
Conversation
ice40_endwrite() computes how many dummy SPI bytes to clock out after
the bitstream to finish FPGA configuration with:
for (size_t i = 0; i < ICE40_SPI_FINAL_CLK_CYCLES + 7 / 8; i++)
`/` binds tighter than `+` in C, so this parses as
ICE40_SPI_FINAL_CLK_CYCLES + (7 / 8) = 160 + 0 = 160, i.e. the "+ 7 / 8"
is a silent no-op. The macro name and the classic `(n + 7) / 8`
ceiling-division idiom (used elsewhere in embedded code to convert a
bit/cycle count into a byte count) make clear the intent was to send
ceil(ICE40_SPI_FINAL_CLK_CYCLES / 8) = 20 bytes (160 SPI clock cycles,
matching the macro name). Instead the unmodified code sends 160 bytes,
i.e. 1280 clock cycles - 8x more than intended.
Fix by parenthesizing the ceiling-division: (ICE40_SPI_FINAL_CLK_CYCLES
+ 7) / 8, which evaluates to 20, restoring the intended 160-clock-cycle
finalization sequence.
Fixes apache#19367
Assisted-by: Claude Code:claude-sonnet-5
Signed-off-by: yi chen <94xhn1@gmail.com>
xiaoxiang781216
approved these changes
Jul 12, 2026
Contributor
|
Hi @janouja since it is your baby, could you please test? to confirm everything is working as expected. |
Contributor
|
You should spend some time setting up the build environment so you can test your PRs/apply the style checks. There are some helpful docs here: https://nuttx.apache.org/docs/latest/contributing/index.html |
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.
drivers/spi/ice40: fix operator precedence in final clock cycle count
Summary
Why change is necessary (fix, update, new feature)? Bug fix: an operator-precedence error causes
ice40_endwrite()to clock out 8x more finalization SPI bytes than intended.What functional part of the code is being changed?
ice40_endwrite()indrivers/spi/ice40.c, the loop that clocks out dummy bytes after the FPGA bitstream to finish iCE40 configuration.How does the change exactly work (what will change and how)?
ICE40_SPI_FINAL_CLK_CYCLES + 7 / 8is parenthesized to(ICE40_SPI_FINAL_CLK_CYCLES + 7) / 8.In C,
/binds tighter than+, so the unmodified expression parses asICE40_SPI_FINAL_CLK_CYCLES + (7 / 8)=160 + 0=160; the+ 7 / 8part is a silent no-op.ICE40_SPI_FINAL_CLK_CYCLESis defined as160ininclude/nuttx/spi/ice40.h:54. EachSPI_SEND()call sends one byte = 8 SPI clock cycles (word size is configured to 8 bits viaSPI_SETBITS(spi, 8)inice40_configspi()), so the unmodified loop runs 160 times and clocks out 160 × 8 = 1280 SPI clock cycles.The macro name (
_CLK_CYCLES, not_BYTES) together with the classic(n + 7) / 8ceiling-division idiom used elsewhere in embedded code to convert a bit/cycle count into a byte count make it clear the intent wasbytes_to_send = ceil(ICE40_SPI_FINAL_CLK_CYCLES / 8) = (160 + 7) / 8 = 20bytes, i.e. exactly 160 clock cycles, matching the macro name. Adding the missing parentheses restores that intended value (20 bytes / 160 cycles).Related NuttX Issue reference if applicable. Fixes drivers/spi/ice40.c: operator precedence issue in final clock cycles calculation #19367, reported by @Zepp-Hanzj on 2026-07-08. I independently verified the analysis in the issue against the current
mastersource before implementing this fix.Impact
ice40_endwrite()'s configuration-finalization step changes: it now clocks out 160 SPI clock cycles instead of 1280.SPI_SCKclock cycles afterCDONEgoes high are required to complete configuration. Both the buggy (1280) and fixed (160) cycle counts are well above that minimum, so this is not expected to change observable behavior on hardware — it corrects a value that visibly contradicts both the macro's name and the intent documented by the code shape, without being a functional regression risk.drivers/spi/ice40.c(iCE40 FPGA bitstream-loading SPI driver, used e.g. byboards/risc-v/esp32c3-legacyiCE40 board support). Only the loop trip count in the finalization step changes; no other logic, no ABI/API/Kconfig change.Testing
I do not have access to real iCE40/iCE-V-Wireless hardware, so I could not produce a real-hardware build+runtime log for this change, which I understand is normally expected for driver changes. Given that, here is exactly what I did verify, so maintainers can judge whether it's sufficient or whether hardware confirmation from someone with the board is needed before merge:
gcc -std=c11 -Wall -Wextra -Werror.ice40_endwrite()(before and after the fix), the exact macro definition frominclude/nuttx/spi/ice40.h, and a mockSPI_SEND()that counts bytes/clock cycles the same way the real one would (1 byte = 8 clock cycles, perSPI_SETBITS(spi, 8)inice40_configspi()). This isolates and proves the arithmetic/loop-trip-count discrepancy without needing real SPI hardware, but it is not a substitute for an end-to-end hardware test ofice40_endwrite()itself.ICE40_SPI_FINAL_CLK_CYCLESis used in the tree (grep -r ICE40_SPI_FINAL_CLK_CYCLES), so the fix cannot affect any other code path.Reproduction steps (repository-independent, does not require NuttX build system):
Testing logs (this is the reproduction program's output, not a NuttX board build/run log):
(exit code 0, compiled with
-Werrorand no warnings.)Full source of the reproduction program (click to expand)
I was not able to cross-compile or run
tools/nxstylecleanly in my environment against this file (it reports a path-resolution error on Windows/Git-Bash that also occurs on unmodified files, e.g.drivers/spi/spi.c, so it is an environment/tooling limitation unrelated to this change, not a style issue introduced by it). The changed line is 67 columns, within the 80-column limit, and matches surrounding indentation/style.PR verification Self-Check
Disclosure
I used Claude (Anthropic, model
claude-sonnet-5, via Claude Code) to help investigate this issue, write the fix, write the reproduction program, and draft this PR description. I (the human author, credited in theSigned-off-bytrailer) reviewed the diff, the reasoning, and the reproduction output before submitting. Per this repository'sCONTRIBUTING.md§1.5, the commit carries anAssisted-by: Claude Code:claude-sonnet-5trailer. I do not have physical iCE40/iCE-V-Wireless hardware, so — as stated above in Testing — this fix has not been verified on real hardware, only via an isolated logic reproduction; I'm flagging this explicitly rather than implying hardware verification took place.