From 4bfb7bcce6263c82adee3d44c6ba01bd05517646 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Sat, 14 Feb 2026 16:01:35 +0000 Subject: [PATCH 1/2] Various tweaks to pio_blink example * Add extra comments and defines to make the code easier to understand * Use pio_claim_unused_sm instead of hardcoding "last SM + 1" * Should now work with LED3 on GPIO 31 and LED4 on GPIO 32 --- pio/pio_blink/blink.c | 78 ++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/pio/pio_blink/blink.c b/pio/pio_blink/blink.c index 6187186b2..e317c88dd 100644 --- a/pio/pio_blink/blink.c +++ b/pio/pio_blink/blink.c @@ -13,76 +13,92 @@ void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq); -// by default flash leds on gpios 3-4 +// By default flash LEDs on GPIOs 3 and 4 #ifndef PIO_BLINK_LED1_GPIO #define PIO_BLINK_LED1_GPIO 3 +#define PIO_BLINK_LED2_GPIO (PIO_BLINK_LED1_GPIO + 1) #endif -// and flash leds on gpios 5-6 -// or if the device supports more than 32 gpios, flash leds on 32-33 +// and also flash LEDs on GPIOs 5 and 6 +// Or if the device has more than 32 gpios, also flash LEDs on GPIOs 32 and 33 #ifndef PIO_BLINK_LED3_GPIO #if NUM_BANK0_GPIOS <= 32 #define PIO_BLINK_LED3_GPIO 5 #else #define PIO_BLINK_LED3_GPIO 32 #endif +#define PIO_BLINK_LED4_GPIO (PIO_BLINK_LED3_GPIO + 1) #endif +#define PIO_BLINK_LED1_FREQUENCY 4 +#define PIO_BLINK_LED2_FREQUENCY 3 +#define PIO_BLINK_LED3_FREQUENCY 2 +#define PIO_BLINK_LED4_FREQUENCY 1 + int main() { setup_default_uart(); - assert(PIO_BLINK_LED1_GPIO < 31); - assert(PIO_BLINK_LED3_GPIO < 31 || PIO_BLINK_LED3_GPIO >= 32); - + // LED1 and LED2 are both expected to be in the "lower" range of PIO-addressable GPIOs + assert((PIO_BLINK_LED1_GPIO < 32) && (PIO_BLINK_LED2_GPIO < 32)); + // check LED3 and LED4 are both in the same range of PIO-addressable GPIOs + assert(((PIO_BLINK_LED3_GPIO < 32) && (PIO_BLINK_LED4_GPIO < 32)) || ((PIO_BLINK_LED3_GPIO >= 16) && (PIO_BLINK_LED3_GPIO < 48) && (PIO_BLINK_LED4_GPIO >= 16) && (PIO_BLINK_LED4_GPIO < 48))); + + // LED1 and LED2 are both controlled by the program loaded into pio[0] at offset[0] + // LED3 and LED4 are both controlled by the program loaded into pio[1] at offset[1] (which might be the same as pio[0] and offset[0] if LED3 and LED4 are both on GPIOs < 32) + // LED1 is controlled by sm[0] + // LED2 is controlled by sm[1] + // LED3 is controlled by sm[2] + // LED4 is controlled by sm[3] PIO pio[2]; - uint sm[2]; + uint sm[4]; uint offset[2]; - // Find a free pio and state machine and add the program + // Find a free PIO and state machine and add the program bool rc = pio_claim_free_sm_and_add_program_for_gpio_range(&blink_program, &pio[0], &sm[0], &offset[0], PIO_BLINK_LED1_GPIO, 2, true); hard_assert(rc); printf("Loaded program at %u on pio %u\n", offset[0], PIO_NUM(pio[0])); - // Start led1 flashing - blink_pin_forever(pio[0], sm[0], offset[0], PIO_BLINK_LED1_GPIO, 4); + // Start LED1 flashing + blink_pin_forever(pio[0], sm[0], offset[0], PIO_BLINK_LED1_GPIO, PIO_BLINK_LED1_FREQUENCY); - // Claim the next state machine and start led2 flashing - pio_sm_claim(pio[0], sm[0] + 1); - blink_pin_forever(pio[0], sm[0] + 1, offset[0], PIO_BLINK_LED1_GPIO + 1, 3); + // Claim the next unused state machine and start LED2 flashing + sm[1] = pio_claim_unused_sm(pio[0], true); + blink_pin_forever(pio[0], sm[1], offset[0], PIO_BLINK_LED2_GPIO, PIO_BLINK_LED2_FREQUENCY); - if (PIO_BLINK_LED3_GPIO >= 32) { - // Find a free pio and state machine and add the program - rc = pio_claim_free_sm_and_add_program_for_gpio_range(&blink_program, &pio[1], &sm[1], &offset[1], PIO_BLINK_LED3_GPIO, 2, true); + if ((PIO_BLINK_LED3_GPIO >= 32) || (PIO_BLINK_LED4_GPIO >= 32)) { + // Find a free PIO and state machine and add the program + rc = pio_claim_free_sm_and_add_program_for_gpio_range(&blink_program, &pio[1], &sm[2], &offset[1], PIO_BLINK_LED3_GPIO, 2, true); printf("Loaded program at %u on pio %u\n", offset[1], PIO_NUM(pio[1])); } else { // no need to load the program again rc = true; pio[1] = pio[0]; - sm[1] = sm[0] + 2; offset[1] = offset[0]; - pio_sm_claim(pio[1], sm[1]); + sm[2] = pio_claim_unused_sm(pio[1], true); } hard_assert(rc); - // Start led3 flashing - blink_pin_forever(pio[1], sm[1], offset[1], PIO_BLINK_LED3_GPIO, 2); + // Start LED3 flashing + blink_pin_forever(pio[1], sm[2], offset[1], PIO_BLINK_LED3_GPIO, PIO_BLINK_LED3_FREQUENCY); + + // Claim the next unused state machine and start LED4 flashing + sm[3] = pio_claim_unused_sm(pio[1], true); + blink_pin_forever(pio[1], sm[3], offset[1], PIO_BLINK_LED4_GPIO, PIO_BLINK_LED4_FREQUENCY); - // Claim the next state machine and start led4 flashing - pio_sm_claim(pio[1], sm[1] + 1); - blink_pin_forever(pio[1], sm[1] + 1, offset[1], PIO_BLINK_LED3_GPIO + 1, 1); + printf("All LEDs should be flashing\n"); - // free up pio resources - pio_sm_unclaim(pio[1], sm[1] + 1); - if (PIO_BLINK_LED3_GPIO >= 32) { - pio_remove_program_and_unclaim_sm(&blink_program, pio[1], sm[1], offset[1]); + // free up PIO resources + pio_sm_unclaim(pio[1], sm[3]); + if ((PIO_BLINK_LED3_GPIO >= 32) || (PIO_BLINK_LED4_GPIO >= 32)) { + pio_remove_program_and_unclaim_sm(&blink_program, pio[1], sm[2], offset[1]); } else { - pio_sm_unclaim(pio[1], sm[1]); + pio_sm_unclaim(pio[1], sm[2]); } - pio_sm_unclaim(pio[0], sm[0] + 1); + pio_sm_unclaim(pio[0], sm[1]); pio_remove_program_and_unclaim_sm(&blink_program, pio[0], sm[0], offset[0]); - // the program exits but the pio keeps running! - printf("All leds should be flashing\n"); + // the program exits but the PIO keeps running! + printf("All LEDs should continue to flash\n"); } void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq) { From d2b7a42d6dbcc66243ef4aa34192c6ed4dc40db3 Mon Sep 17 00:00:00 2001 From: Andrew Scheller Date: Mon, 16 Feb 2026 10:55:46 +0000 Subject: [PATCH 2/2] Add additional explanatory comment --- pio/pio_blink/blink.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pio/pio_blink/blink.c b/pio/pio_blink/blink.c index e317c88dd..f5eecf9ca 100644 --- a/pio/pio_blink/blink.c +++ b/pio/pio_blink/blink.c @@ -11,6 +11,13 @@ #include "hardware/clocks.h" #include "blink.pio.h" +/** + * This example demonstrates using PIO to flash four LEDs at different frequencies. + * On RP2040 and RP2350A those GPIOs are all in the same "PIO range" of 0 - 31 (so a single PIO is used). + * On RP2350B the first two GPIOs are in the "lower PIO range" of 0 - 31 and the + * next two LEDs are in the "higher PIO range" of 16 - 47 (so two PIOs are used). + */ + void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq); // By default flash LEDs on GPIOs 3 and 4 @@ -39,8 +46,10 @@ int main() { setup_default_uart(); // LED1 and LED2 are both expected to be in the "lower" range of PIO-addressable GPIOs + assert(PIO_BLINK_LED2_GPIO == PIO_BLINK_LED1_GPIO + 1); assert((PIO_BLINK_LED1_GPIO < 32) && (PIO_BLINK_LED2_GPIO < 32)); // check LED3 and LED4 are both in the same range of PIO-addressable GPIOs + assert(PIO_BLINK_LED4_GPIO == PIO_BLINK_LED3_GPIO + 1); assert(((PIO_BLINK_LED3_GPIO < 32) && (PIO_BLINK_LED4_GPIO < 32)) || ((PIO_BLINK_LED3_GPIO >= 16) && (PIO_BLINK_LED3_GPIO < 48) && (PIO_BLINK_LED4_GPIO >= 16) && (PIO_BLINK_LED4_GPIO < 48))); // LED1 and LED2 are both controlled by the program loaded into pio[0] at offset[0]