diff --git a/pio/pio_blink/blink.c b/pio/pio_blink/blink.c index 6187186b2..f5eecf9ca 100644 --- a/pio/pio_blink/blink.c +++ b/pio/pio_blink/blink.c @@ -11,78 +11,103 @@ #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-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_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] + // 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) {