Skip to content

drivers: spi: Fix PIO program memory leak in RP2040 SPI driver #91343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Karthik-Sarvan
Copy link

Hi everyone!

I noticed issue #91323 about the Pico RP2040 SPI PIO driver failing after 16 configuration changes, so I decided to take a look and fix it.

What was happening

The SPI PIO driver was leaking memory every time you switched between different SPI configurations. Each time you called the driver with a different config, it would allocate new PIO program space but never clean up the old programs. After 16 switches, the PIO runs out of memory and the driver permanently fails with error -16.

The fix

I tracked down the issue to the spi_pico_pio_configure() function. The problem was:

  1. When configs are the same → everything works fine (early return)
  2. When configs are different → new PIO programs get loaded but old ones never get removed

My solution adds proper cleanup:

  • Track which PIO programs are currently loaded
  • Remove old programs before loading new ones
  • Clean up everything when the device is released
  • Initialize pointers properly

Changes made

  • Added loaded_tx_program and loaded_rx_program fields to track active programs
  • Call pio_remove_program() to clean up before loading new programs
  • Enhanced the release function to properly clean up resources
  • Made sure everything gets initialized to NULL

Testing

With this fix, you should be able to run the patched SPI shell test from the issue indefinitely without hitting the 16-change limit. The driver will properly manage PIO memory and won't enter that permanent error state anymore.

Let me know if you'd like me to test anything specific or if there are any concerns with the approach!

Fixes #91323

The Raspberry Pi Pico SPI PIO driver was leaking PIO program memory
when switching between different SPI configurations. Each configuration
change would allocate new PIO program space without releasing the
previously loaded programs, leading to resource exhaustion after 16
configuration changes.

This fix:

1. Adds tracking of loaded PIO programs in the driver data structure
2. Properly removes old PIO programs before loading new ones during
   configuration changes
3. Cleans up PIO programs when the device is released
4. Initializes program pointers to NULL

Fixes the permanent failure that occurred after multiple SPI
configuration changes, allowing arbitrary sequences of SPI transfers
with different configurations to succeed.

Fixes: #xxx
Copy link

Copy link
Contributor

@nzmichaelh nzmichaelh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -779,7 +806,10 @@ int spi_pico_pio_init(const struct device *dev)
static struct spi_pico_pio_data spi_pico_pio_data_##inst = { \
SPI_CONTEXT_INIT_LOCK(spi_pico_pio_data_##inst, spi_ctx), \
SPI_CONTEXT_INIT_SYNC(spi_pico_pio_data_##inst, spi_ctx), \
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), spi_ctx)}; \
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), spi_ctx), \
.loaded_tx_program = NULL, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a static struct, so you can skip initializing to NULL.

@@ -694,6 +711,16 @@ int spi_pico_pio_release(const struct device *dev, const struct spi_config *spi_
{
struct spi_pico_pio_data *data = dev->data;

/* Clean up PIO programs when releasing the device */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional, as it doesn't significantly improve readability: this code is repeated so consider refactoring it out into a 'spi_pico_pio_remove_existing_programs`.

@nzmichaelh
Copy link
Contributor

You'll want to remove the merge commits from this PR.

@nzmichaelh
Copy link
Contributor

Looks like this PR doesn't have any reviewers. You may want to look at the maintainers and previous authors and add them .

@soburi soburi added the platform: Raspberry Pi Pico Raspberry Pi Pico (RPi Pico) label Jun 24, 2025
@soburi soburi requested a review from ThreeEights June 26, 2025 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: Raspberry Pi Pico Raspberry Pi Pico (RPi Pico)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Driver: SPI: Unreleased resources cause a malfunction in spi_rpi_pico_pio.c
3 participants