7
31
Fork
You've already forked blackmagic
23

Feature: Accelerate BMPremote SPI data phase by removing inter-byte gaps #1946

Open
ALTracer wants to merge 4 commits from ALTracer/feature/spi-perf into main
pull from: ALTracer/feature/spi-perf
merge into: blackmagic-debug:main
blackmagic-debug:main
blackmagic-debug:feature/bmda-remote-comms
blackmagic-debug:ALTracer/feature/aarch64-ident
blackmagic-debug:feature/better-meson-optimisation-handling
blackmagic-debug:feature/am335x-support
blackmagic-debug:feature/esp32-c3-support
blackmagic-debug:feature/cortex-ar-software-breakpoints
blackmagic-debug:feature/unit-testing
blackmagic-debug:feature/windows-usb-serial-interface-naming
blackmagic-debug:fix/bmp-external-spi
blackmagic-debug:ALTracer/feature/bluepillplus-platform
blackmagic-debug:ALTracer/feature/at32f43x-unrdp
blackmagic-debug:feature/const-correctness
blackmagic-debug:ALTracer/feature/fault_handlers
blackmagic-debug:ALTracer/feature/hazard3-ice40-support
blackmagic-debug:fix/ci-cleanup
blackmagic-debug:ALTracer/fix/gdb-10-12-thread
blackmagic-debug:ALTracer/feature/blackpill-f4-adc
blackmagic-debug:ALTracer/fix/cortex-desc-allocfail-report
blackmagic-debug:ALTracer/feature/calibrate_swd
blackmagic-debug:ALTracer/feature/blank-check
blackmagic-debug:feature/avr
blackmagic-debug:v2.0
blackmagic-debug:v1.9
blackmagic-debug:v1.10
blackmagic-debug:v1.8
ALTracer commented 2024年10月01日 18:58:06 +02:00 (Migrated from github.com)
Copy link

Detailed description

  • This is a perf fix to an existing feature.
  • The existing problem is significant gaps between SPI bytes in both read and write xfers as driven by bmpflash + blackpill-f411ce (and likely others).
  • This PR solves it by providing a continuous block xfer primitive (no IRQ and no DMA involved)

Tested to increase bmpflash read -b int dump times from 35 to 31 seconds for a 8192 KiB w25q64 chip (using 12 MHz). The atomic section is used to block interrupts for 170 microseconds (256 byte read), otherwise my patch made the board hang reliably (no read timeouts). I may likely rewrite this once more using direct register manipulation as opposed to libopencm3 spi API usage. Short reads, like SFDP, indicate normal gaps between command bytes (I didn't change them) but no gaps in data page phase.
The acceleration is achieved by keeping a byte (actually 8/16-bit SPI word) in flight behind the DR shadow register, which is how it is intended to be used. DMA bindings are harder and may result in channel/stream conflicts.

Your checklist for this pull request

Closing issues

## Detailed description * This is a perf fix to an existing feature. * The existing problem is significant gaps between SPI bytes in both read and write xfers as driven by bmpflash + blackpill-f411ce (and likely others). * This PR solves it by providing a continuous block xfer primitive (no IRQ and no DMA involved) Tested to increase `bmpflash read -b int` dump times from 35 to 31 seconds for a 8192 KiB w25q64 chip (using 12 MHz). The atomic section is used to block interrupts for 170 microseconds (256 byte read), otherwise my patch made the board hang reliably (no read timeouts). I may likely rewrite this once more using direct register manipulation as opposed to libopencm3 spi API usage. Short reads, like SFDP, indicate normal gaps between command bytes (I didn't change them) but no gaps in data page phase. The acceleration is achieved by keeping a byte (actually 8/16-bit SPI word) in flight behind the DR shadow register, which is how it is intended to be used. DMA bindings are harder and may result in channel/stream conflicts. ## Your checklist for this pull request * [x] I've read the [Code of Conduct](https://github.com/blackmagic-debug/blackmagic/blob/main/CODE_OF_CONDUCT.md) * [x] I've read the [guidelines for contributing](https://github.com/blackmagic-debug/blackmagic/blob/main/CONTRIBUTING.md) to this repository * [x] It builds for hardware native (see [Building the firmware](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-firmware)) * [x] It builds as BMDA (see [Building the BMDA](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-app)) * [x] I've tested it to the best of my ability * [x] My commit messages provide a useful short description of what the commits do ## Closing issues
ALTracer commented 2024年10月26日 18:20:33 +02:00 (Migrated from github.com)
Copy link

Rebased to main.
A one-line change in PR1968 triggers a warning from reusing tx buffer as a rx buffer now.
I can split them into distinct TX and RX buffers.
The IRQ-masking DR-polling version can deal with one of them possibly being NULL. I'd like to rely on TX buffer being non-null for simplicity, and containing zero-bytes which can be submitted to SPI DR.
Another venue is actually leveraging a DMA stream on F4 (or channel on F1) where platforms allow, and where it does not conflict with aux USART and SWO USART.
What is the API here -- submitting two unidirectional transfers, or submitting one transfer but specifying the Tx header length (and the rest is Rx)? I'm assuming full-duplex is time-divided into Tx then Rx. Block reads (and block writes) to 25-series flash are already implemented as a byte-wise Tx command then block-wise Rx.

Rebased to main. A one-line change in PR1968 triggers a warning from reusing tx buffer as a rx buffer now. I can split them into distinct TX and RX buffers. The IRQ-masking DR-polling version can deal with one of them possibly being NULL. I'd like to rely on TX buffer being non-null for simplicity, and containing zero-bytes which can be submitted to SPI DR. Another venue is actually leveraging a DMA stream on F4 (or channel on F1) where platforms allow, and where it does not conflict with aux USART and SWO USART. What is the API here -- submitting two unidirectional transfers, or submitting one transfer but specifying the Tx header length (and the rest is Rx)? I'm assuming full-duplex is time-divided into Tx then Rx. Block reads (and block writes) to 25-series flash are already implemented as a byte-wise Tx command then block-wise Rx.
dragonmux left a comment
Copy link

Apologies this landed by the way side, done an initial review as with the revised platform configurations and such this is worth getting in for v2.0.

Apologies this landed by the way side, done an initial review as with the revised platform configurations and such this is worth getting in for v2.0.
@ -77,6 +77,7 @@ bool platform_spi_deinit(spi_bus_e bus);

The const here is correct on the buffer in the function definition itself, but should be dropped from this declaration per the clang-tidy lint about useless const.

The `const` here is correct on the buffer in the function definition itself, but should be dropped from this declaration per the `clang-tidy` lint about useless `const`.
@ -291,6 +291,52 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
}

What is the benefit and drawback of these two approaches? Can the simpler more expressive loop get similar performance if interrupts are suspended with an atomic context?

What is the benefit and drawback of these two approaches? Can the simpler more expressive loop get similar performance if interrupts are suspended with an atomic context?
src/target/spi.c Outdated
@ -67,9 +67,13 @@ void bmp_spi_read(const spi_bus_e bus, const uint8_t device, const uint16_t comm
bmp_spi_setup_xfer(bus, device, command, address);
/* Now read back the data that elicited */
uint8_t *const data = (uint8_t *const)buffer;
#if 0

If you're adding this new functionality, please just add it - if you want to preserve working with the old API then introduce a #define in the platform header that can be tested for here to switch to the new implementation. This will then also fix the builds.

If you're adding this new functionality, please just add it - if you want to preserve working with the old API then introduce a `#define` in the platform header that can be tested for here to switch to the new implementation. This will then also fix the builds.
ALTracer (Migrated from github.com) reviewed 2024年11月21日 16:58:34 +01:00
@ -291,6 +291,52 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
}
ALTracer (Migrated from github.com) commented 2024年11月21日 16:58:34 +01:00
Copy link

No, it can't, because it blocking-waits for the entire duration of 8/16-bit SPI word in github.com/libopencm3/libopencm3@201f5bcfb3/lib/stm32/common/spi_common_all.c (L189-L190)
But thanks to that it does not submit an extra word in flight to keep data pumping, and hence cannot miss an Rx byte.

No, it can't, because it blocking-waits for the entire duration of 8/16-bit SPI word in https://github.com/libopencm3/libopencm3/blob/201f5bcfb3fa70ee34818152463e7139f24db377/lib/stm32/common/spi_common_all.c#L189-L190 But thanks to that it does not submit an extra word in flight to keep data pumping, and hence cannot miss an Rx byte.
@ -291,6 +291,52 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
}

ok, fair enough - then drop the simpler loop please as there's no point keeping it in this new code.

ok, fair enough - then drop the simpler loop please as there's no point keeping it in this new code.
ALTracer (Migrated from github.com) reviewed 2024年11月22日 18:52:26 +01:00
src/target/spi.c Outdated
@ -67,9 +67,13 @@ void bmp_spi_read(const spi_bus_e bus, const uint8_t device, const uint16_t comm
bmp_spi_setup_xfer(bus, device, command, address);
/* Now read back the data that elicited */
uint8_t *const data = (uint8_t *const)buffer;
#if 0
ALTracer (Migrated from github.com) commented 2024年11月22日 18:52:25 +01:00
Copy link

Yes, I felt like PLATFORM_HAS_SPI and PLATFORM_HAS_SPI_BLOCKWISE or so would be nice to add. The first macro would guard dummy impls in all but two platforms, the second macro would dispatch to calling a block xfer function instead of slow byte wise callchains.
But first I wanted to evaluate flash size increase from this feature.

Yes, I felt like `PLATFORM_HAS_SPI` and `PLATFORM_HAS_SPI_BLOCKWISE` or so would be nice to add. The first macro would guard dummy impls in all but two platforms, the second macro would dispatch to calling a block xfer function instead of slow byte wise callchains. But first I wanted to evaluate flash size increase from this feature.
dragonmux force-pushed ALTracer/feature/spi-perf from 8fb69b8c5b to 4634d88f11
Some checks failed
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/6 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/18 Pipeline was successful
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-windows Pipeline was successful
2026年03月25日 16:19:24 +01:00
Compare
dragonmux force-pushed ALTracer/feature/spi-perf from 4634d88f11
Some checks failed
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/6 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/18 Pipeline was successful
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-windows Pipeline was successful
to e26758d683
Some checks failed
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/6 Pipeline failed
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline was successful
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-firmware/18 Pipeline was successful
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-windows Pipeline was successful
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
2026年03月30日 00:12:11 +02:00
Compare
dragonmux force-pushed ALTracer/feature/spi-perf from e26758d683
Some checks failed
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/6 Pipeline failed
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline was successful
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-firmware/18 Pipeline was successful
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-windows Pipeline was successful
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
to 590306465d
Some checks failed
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/6 Pipeline failed
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline was successful
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-linux/1 Pipeline was successful
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-firmware/18 Pipeline failed
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-windows Pipeline was successful
2026年04月06日 17:57:58 +02:00
Compare
Some checks are pending
ci/woodpecker/pr/build-firmware/1 Pipeline failed
ci/woodpecker/pr/build-firmware/6 Pipeline failed
Required
Details
ci/woodpecker/pr/build-firmware/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/5 Pipeline was successful
ci/woodpecker/pr/build-firmware/4 Pipeline was successful
ci/woodpecker/pr/build-firmware/3 Pipeline was successful
ci/woodpecker/pr/build-firmware/8 Pipeline failed
ci/woodpecker/pr/build-firmware/7 Pipeline failed
ci/woodpecker/pr/build-firmware/14 Pipeline was successful
ci/woodpecker/pr/build-firmware/9 Pipeline failed
ci/woodpecker/pr/build-firmware/10 Pipeline failed
ci/woodpecker/pr/build-firmware/12 Pipeline failed
ci/woodpecker/pr/build-firmware/13 Pipeline was successful
ci/woodpecker/pr/build-firmware/11 Pipeline failed
ci/woodpecker/pr/build-linux/1 Pipeline was successful
Required
Details
ci/woodpecker/pr/build-firmware/19 Pipeline failed
ci/woodpecker/pr/build-firmware/18 Pipeline failed
ci/woodpecker/pr/build-firmware/20 Pipeline was successful
ci/woodpecker/pr/build-firmware/16 Pipeline was successful
ci/woodpecker/pr/build-linux/2 Pipeline was successful
ci/woodpecker/pr/build-firmware/15 Pipeline was successful
ci/woodpecker/pr/build-firmware/17 Pipeline was successful
ci/woodpecker/pr/build-windows Pipeline was successful
Required
Details
ci/woodpecker/pr/lint
Required
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin ALTracer/feature/spi-perf:ALTracer/feature/spi-perf
git switch ALTracer/feature/spi-perf
Sign in to join this conversation.
No reviewers
Labels
Clear labels
BMD App
Black Magic Debug App (aka. PC hosted) (not firmware)
BMP Firmware
Black Magic Probe Firmware (not PC hosted software)
Bug
Confirmed bug
Build system
Build system
Can't reproduce
Maintainers can't reproduce this problem
CI
Continuous Integration System
Contribution wanted
User contributions welcome
Documentation
Project documentation
Draft
Work in progress draft
Duplicate
This issue or pull request already exists
Enhancement
General project improvement
Feedback wanted
Requires additional submitter feedback
Foreign Host Board
Non Native hardware to runing Black Magic firmware on
GDB
Issue/PR related to GDB
Good first issue
Good for newcommers
HwIssue Mitigation
Solving or mitigating a Hardware issue in Software
Information Needed
Maintainers need more information
NativeHardware
Official Black Magic Debug Hardware
New Host Board
New hardware to run Black Magic firmware on
New Target
New debug target
Off Topic
Something that does not involve the project in any way
Potential Bug
A potential, unconfirmed or very special circumstance bug
Regression
Bug caused by a regression
User Interest Needed
More user interest required before consideration
User Testing Needed
Looking for user testing reports
Won't fix
Outside of the project scope or works as intended
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
blackmagic-debug/blackmagic!1946
Reference in a new issue
blackmagic-debug/blackmagic
No description provided.
Delete branch "ALTracer/feature/spi-perf"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?