Skip to content

RP2040 Can't use both PIO channels at the same time #854

@JeronimusII

Description

@JeronimusII

Describe the bug
When creating NeoPixelBus instances for both PIO 0 and PIO 1 (for example to have up to 8 instances instead of 4) and the first Begin() call is made on an instance using PIO 0, all instances using PIO 0 will work fine but the other ones (using PIO 1) will never be able to send data to the LED and get stuck blocking forever on the second Show() call.

To Reproduce

  1. Create instances of NeoPixelBus for PIO 0 and PIO 1.
  2. Call Begin() on the instances using PIO 0 first.
  3. Change colors using for example ClearTo(RgbwColor(random(256)).
  4. Call Show() methods on all instances.
  5. Repeat once from step 3 and it will get stuck at step 4 when making a call to Show() of any instance using PIO 1.

Expected behavior
Show() calls to all instances (using both PIO 0 and 1) should update the LEDs and not get stuck blocking forever.

Development environment (please complete the following information):

  • OS: Windows 10
  • Build Environment: PlatformIO (VSCode; Arduino)
  • Board target: Raspberry Pi Pico W (RP2040)
  • Library version: v2.8.3

Minimal Sketch that reproduced the problem:

#include <Arduino.h>
#include <NeoPixelBus.h>

using LEDStrip = NeoPixelBus<NeoGrbwFeature, Rp2040x4NSk6812Method>;

LEDStrip strip0(100, 0, NeoBusChannel_0);
LEDStrip strip1(100, 1, NeoBusChannel_1);

void setup()
{
    strip0.Begin();
    strip1.Begin();
}

void loop()
{
    strip0.ClearTo(RgbwColor(random(256)));
    strip0.Show();
    strip1.ClearTo(RgbwColor(random(256)));
    strip1.Show();  // Gets stuck second time here.
    delay(500);
}

Root cause
In src/internal/methods/Rp2040/NeoRp2040PioMonoProgram.h class NeoRp2040PioMonoProgram it loads the program into the instruction memory of the first PIO (PIO 0) when making the first call to add() and stores the offset. But when you want to use the other PIO (PIO 1) it won't load the program into the memory of PIO 1 since the s_loadedOffset it already set. Instead it will try using the offset of the program stored in PIO 0 instruction memory which will obviously cause the state machine in PIO 1 to not run how it should and the data to never finish sending.

(very inconvenient) workaround
It is still possible to get it to work like this if you try running it with PIO 0 initializing first then flashing it (dont turn off power; using a debug probe) with a new program that initializes PIO 1 first. Since the program stays on the memory of PIO 0 everything will work... until you try turning the power off and on again.

Metadata

Metadata

Assignees

Labels

bugpendingPending new release; already merged but not released in a version

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions