Skip to content

Check for parameter underflow when PIO_USE_GPIO_BASE is in use #2618

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: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/rp2_common/hardware_pio/include/hardware/pio.h
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,15 @@ static inline uint pio_get_gpio_base(PIO pio) {
#endif
}

static inline void check_pio_pin_mask(__unused PIO pio, __unused uint sm, __unused uint32_t pinmask) {
// check no pins are set in the mask which are incompatible with the pio
#if PICO_PIO_USE_GPIO_BASE
valid_params_if(HARDWARE_PIO, (pinmask & ~(0xfffffffful << pio_get_gpio_base(pio))) == 0);
#else
valid_params_if(HARDWARE_PIO, (pinmask & ~0xfffffffful) == 0);
#endif
}

static inline void check_pio_pin_mask64(__unused PIO pio, __unused uint sm, __unused uint64_t pinmask) {
// check no pins are set in the mask which are incompatible with the pio
#if PICO_PIO_USE_GPIO_BASE
Expand Down Expand Up @@ -1514,6 +1523,7 @@ static inline void pio_sm_set_out_pins(PIO pio, uint sm, uint out_base, uint out
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if(HARDWARE_PIO, out_base < pio_get_gpio_base(pio));
out_base -= pio_get_gpio_base(pio);
#endif
valid_params_if(HARDWARE_PIO, out_base < 32);
Expand All @@ -1538,6 +1548,7 @@ static inline void pio_sm_set_set_pins(PIO pio, uint sm, uint set_base, uint set
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if(HARDWARE_PIO, set_base < pio_get_gpio_base(pio));
set_base -= pio_get_gpio_base(pio);
#endif
valid_params_if(HARDWARE_PIO, set_base < 32);
Expand All @@ -1560,6 +1571,7 @@ static inline void pio_sm_set_in_pins(PIO pio, uint sm, uint in_base) {
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if(HARDWARE_PIO, in_base < pio_get_gpio_base(pio));
in_base -= pio_get_gpio_base(pio);
#endif
valid_params_if(HARDWARE_PIO, in_base < 32);
Expand All @@ -1580,6 +1592,7 @@ static inline void pio_sm_set_sideset_pins(PIO pio, uint sm, uint sideset_base)
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if(HARDWARE_PIO, sideset_base < pio_get_gpio_base(pio));
sideset_base -= pio_get_gpio_base(pio);
#endif
valid_params_if(HARDWARE_PIO, sideset_base < 32);
Expand All @@ -1599,6 +1612,7 @@ static inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint pin) {
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if(HARDWARE_PIO, pin < pio_get_gpio_base(pio));
pin -= pio_get_gpio_base(pio);
#endif
valid_params_if(HARDWARE_PIO, pin < 32);
Expand Down
17 changes: 12 additions & 5 deletions src/rp2_common/hardware_pio/pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ static int find_offset_for_program(PIO pio, const pio_program_t *program) {
}

static int pio_set_gpio_base_unsafe(PIO pio, uint gpio_base) {
invalid_params_if_and_return(PIO, gpio_base != 0 && (!PICO_PIO_VERSION || gpio_base != 16), PICO_ERROR_BAD_ALIGNMENT);
invalid_params_if_and_return(HARDWARE_PIO, gpio_base != 0 && (!PICO_PIO_VERSION || gpio_base != 16), PICO_ERROR_BAD_ALIGNMENT);
#if PICO_PIO_VERSION > 0
uint32_t used_mask = _used_instruction_space[pio_get_index(pio)];
invalid_params_if_and_return(PIO, used_mask, PICO_ERROR_INVALID_STATE);
invalid_params_if_and_return(HARDWARE_PIO, used_mask, PICO_ERROR_INVALID_STATE);
pio->gpiobase = gpio_base;
#else
((void)pio);
Expand Down Expand Up @@ -251,6 +251,7 @@ void pio_sm_set_pins_internal(PIO pio, uint sm, uint32_t pins) {

#ifndef pio_sm_set_pins_internal
void pio_sm_set_pins(PIO pio, uint sm, uint32_t pins) {
check_pio_pin_mask(pio, sm, pins);
#if PICO_PIO_USE_GPIO_BASE
pins >>= pio_get_gpio_base(pio);
#endif
Expand Down Expand Up @@ -287,6 +288,7 @@ void pio_sm_set_pins_with_mask_internal(PIO pio, uint sm, uint32_t pin_values, u

#ifndef pio_sm_set_pins_with_mask_internal
void pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask) {
check_pio_pin_mask(pio, sm, pin_mask);
#if PICO_PIO_USE_GPIO_BASE
pin_values >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
Expand Down Expand Up @@ -324,6 +326,7 @@ void pio_sm_set_pindirs_with_mask_internal(PIO pio, uint sm, uint32_t pindirs, u

#ifndef pio_sm_set_pindirs_with_mask_internal
void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t pin_mask) {
check_pio_pin_mask(pio, sm, pin_mask);
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
Expand All @@ -333,6 +336,7 @@ void pio_sm_set_pindirs_with_mask(PIO pio, uint sm, uint32_t pindirs, uint32_t p
#endif

void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t pin_mask) {
check_pio_pin_mask64(pio, sm, pin_mask);
#if PICO_PIO_USE_GPIO_BASE
pindirs >>= pio_get_gpio_base(pio);
pin_mask >>= pio_get_gpio_base(pio);
Expand All @@ -343,8 +347,11 @@ void pio_sm_set_pindirs_with_mask64(PIO pio, uint sm, uint64_t pindirs, uint64_t
int pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin, uint count, bool is_out) {
check_pio_param(pio);
check_sm_param(sm);
#if PICO_PIO_USE_GPIO_BASE
invalid_params_if_and_return(HARDWARE_PIO, pin < pio_get_gpio_base(pio), PICO_ERROR_INVALID_ARG);
pin -= pio_get_gpio_base(pio);
invalid_params_if_and_return(PIO, pin >= 32u, PICO_ERROR_INVALID_ARG);
#endif
invalid_params_if_and_return(HARDWARE_PIO, pin >= 32u, PICO_ERROR_INVALID_ARG);
uint32_t pinctrl_saved = pio->sm[sm].pinctrl;
uint32_t execctrl_saved = pio->sm[sm].execctrl;
hw_clear_bits(&pio->sm[sm].execctrl, 1u << PIO_SM0_EXECCTRL_OUT_STICKY_LSB);
Expand Down Expand Up @@ -409,12 +416,12 @@ bool pio_claim_free_sm_and_add_program_for_gpio_range(const pio_program_t *progr
invalid_params_if(HARDWARE_PIO, (gpio_base + gpio_count) > NUM_BANK0_GPIOS);

#if !PICO_PIO_USE_GPIO_BASE
// short-circuit some logic when not using GIO_BASE
// short-circuit some logic when not using GPIO_BASE
set_gpio_base = 0;
gpio_count = 0;
#endif

// note if we gpio_count == 0, we don't care about GPIOs so use a zero mask for what we require
// note if gpio_count == 0, we don't care about GPIOs so use a zero mask for what we require
// if gpio_count > 0, then we just set used mask for the ends, since that is all that is checked at the moment
uint32_t required_gpio_ranges;
if (gpio_count) required_gpio_ranges = (1u << (gpio_base >> 4)) | (1u << ((gpio_base + gpio_count - 1) >> 4));
Expand Down
Loading