From bccd2f9d8713a2648b2d0fb1230d6078f3329849 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 10 Sep 2026 15:32:24 +0100 Subject: [PATCH 1/2] piolib: Add pio_sm_config_xfer_flags pio_sm_config_xfer_flags adds option to control the selection of DMA channel and to enable cyclic DMA support. Signed-off-by: Phil Elwell --- piolib/include/piolib.h | 15 +++++++++++++++ piolib/include/rp1_pio_if.h | 15 +++++++++++++++ piolib/pio_rp1.c | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/piolib/include/piolib.h b/piolib/include/piolib.h index 93afb8d..fc87547 100644 --- a/piolib/include/piolib.h +++ b/piolib/include/piolib.h @@ -65,6 +65,14 @@ enum pio_xfer_dir { PIO_DIR_COUNT }; +enum pio_dma_flags { + PIO_DMA_PREFER_HEAVY = (0 << 0), + PIO_DMA_PREFER_LIGHT = (1 << 0), + PIO_DMA_FORCE_HEAVY = (2 << 0), + PIO_DMA_FORCE_LIGHT = (3 << 0), + PIO_DMA_CYCLIC = (1 << 2), +}; + enum pio_sm_flags { PIO_SM_FLAG_TXSTALL = 0x0001, PIO_SM_FLAG_RXSTALL = 0x0002, @@ -134,6 +142,7 @@ struct pio_chip { void (*close_instance)(PIO pio); int (*pio_sm_config_xfer)(PIO pio, uint sm, uint dir, uint buf_size, uint buf_count); + int (*pio_sm_config_xfer_flags)(PIO pio, uint sm, uint dir, uint buf_size, uint buf_count, uint flags); int (*pio_sm_xfer_data)(PIO pio, uint sm, uint dir, uint data_bytes, void *data); bool (*pio_can_add_program_at_offset)(PIO pio, const pio_program_t *program, uint offset); @@ -313,6 +322,12 @@ static inline int pio_sm_config_xfer(PIO pio, uint sm, uint dir, uint buf_size, return pio->chip->pio_sm_config_xfer(pio, sm, dir, buf_size, buf_count); } +static inline int pio_sm_config_xfer_flags(PIO pio, uint sm, uint dir, uint buf_size, uint buf_count, uint flags) +{ + check_pio_param(pio); + return pio->chip->pio_sm_config_xfer_flags(pio, sm, dir, buf_size, buf_count, flags); +} + static inline int pio_sm_xfer_data(PIO pio, uint sm, uint dir, uint data_bytes, void *data) { check_pio_param(pio); diff --git a/piolib/include/rp1_pio_if.h b/piolib/include/rp1_pio_if.h index b0dd91c..1b4b46f 100644 --- a/piolib/include/rp1_pio_if.h +++ b/piolib/include/rp1_pio_if.h @@ -20,6 +20,12 @@ #define RP1_PIO_DIR_FROM_SM 1 #define RP1_PIO_DIR_COUNT 2 +#define RP1_PIO_SM_CONFIG_XFER_FL_DMA_PREFER_HEAVY (0 << 0) +#define RP1_PIO_SM_CONFIG_XFER_FL_DMA_PREFER_LIGHT (1 << 0) +#define RP1_PIO_SM_CONFIG_XFER_FL_DMA_FORCE_HEAVY (2 << 0) +#define RP1_PIO_SM_CONFIG_XFER_FL_DMA_FORCE_LIGHT (3 << 0) +#define RP1_PIO_SM_CONFIG_XFER_FL_DMA_CYCLIC (1 << 2) + typedef struct { uint32_t clkdiv; uint32_t execctrl; @@ -183,6 +189,14 @@ struct rp1_pio_sm_config_xfer32_args { uint32_t buf_count; }; +struct rp1_pio_sm_config_xfer_v2_args { + uint16_t sm; + uint16_t dir; + uint32_t flags; + uint32_t buf_size; + uint32_t buf_count; +}; + struct rp1_pio_sm_xfer_data_args { uint16_t sm; uint16_t dir; @@ -242,6 +256,7 @@ struct rp1_pio_interrupt_clear_args { #define PIO_IOC_SM_XFER_DATA _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args) #define PIO_IOC_SM_XFER_DATA32 _IOW(PIO_IOC_MAGIC, 2, struct rp1_pio_sm_xfer_data32_args) #define PIO_IOC_SM_CONFIG_XFER32 _IOW(PIO_IOC_MAGIC, 3, struct rp1_pio_sm_config_xfer32_args) +#define PIO_IOC_SM_CONFIG_XFER_V2 _IOW(PIO_IOC_MAGIC, 4, struct rp1_pio_sm_config_xfer_v2_args) #define PIO_IOC_READ_HW _IOW(PIO_IOC_MAGIC, 8, struct rp1_access_hw_args) #define PIO_IOC_WRITE_HW _IOW(PIO_IOC_MAGIC, 9, struct rp1_access_hw_args) diff --git a/piolib/pio_rp1.c b/piolib/pio_rp1.c index 7f15ecf..b74241b 100644 --- a/piolib/pio_rp1.c +++ b/piolib/pio_rp1.c @@ -272,6 +272,13 @@ static int rp1_pio_sm_config_xfer(PIO pio, uint sm, uint dir, uint buf_size, uin return err; } +static int rp1_pio_sm_config_xfer_flags(PIO pio, uint sm, uint dir, uint buf_size, uint buf_count, uint flags) +{ + struct rp1_pio_sm_config_xfer_v2_args args = { .sm = sm, .dir = dir, .buf_size = buf_size, .buf_count = buf_count, .flags = flags }; + check_sm_param(sm); + return rp1_ioctl(pio, PIO_IOC_SM_CONFIG_XFER_V2, &args); +} + static int rp1_pio_sm_xfer_data(PIO pio, uint sm, uint dir, uint data_bytes, void *data) { struct rp1_pio_sm_xfer_data_args args = { .sm = sm, .dir = dir, .data_bytes = data_bytes, .rsvd = 0, .data = data }; @@ -990,6 +997,7 @@ DECLARE_PIO_CHIP(rp1) { .close_instance = rp1_close_instance, .pio_sm_config_xfer = rp1_pio_sm_config_xfer, + .pio_sm_config_xfer_flags = rp1_pio_sm_config_xfer_flags, .pio_sm_xfer_data = rp1_pio_sm_xfer_data, .pio_can_add_program_at_offset = rp1_pio_can_add_program_at_offset, From 36d8b83a95de472588cb531291fb54f8fbba989f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 2 Nov 2026 20:44:56 +0000 Subject: [PATCH 2/2] piolib: Add functions from the V2 SDK The new pioasm makes use of some new functions that were previously absent from piolib. Signed-off-by: Phil Elwell --- piolib/examples/apitest.c | 22 ++++++++++ piolib/include/piolib.h | 85 ++++++++++++++++++++++++++++++++++++++- piolib/pio_rp1.c | 72 +++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/piolib/examples/apitest.c b/piolib/examples/apitest.c index a39f23c..e5ed810 100644 --- a/piolib/examples/apitest.c +++ b/piolib/examples/apitest.c @@ -6,6 +6,7 @@ #include #include +#include #include "piolib.h" @@ -107,6 +108,27 @@ int main(int argc, const char **argv) { pio_remove_program(pio, &dummy_program, offset); } + // V2 additions + { + pio_sm_config c1 = pio_get_default_sm_config(); + pio_sm_config c2 = pio_get_default_sm_config(); + sm_config_set_out_pins(&c1, 1, 2); + sm_config_set_out_pin_base(&c2, 1); + sm_config_set_out_pin_count(&c2, 2); + check("sm_config_set_out_pins", !memcmp(&c1, &c2, sizeof(c1))); + sm_config_set_in_pins(&c1, 3); + sm_config_set_in_pin_base(&c2, 3); + sm_config_set_in_pin_count(&c2, 32); + check("sm_config_set_in_pins", !memcmp(&c1, &c2, sizeof(c1))); + sm_config_set_set_pins(&c1, 4, 5); + sm_config_set_set_pin_base(&c2, 4); + sm_config_set_set_pin_count(&c2, 5); + check("sm_config_set_set_pins", !memcmp(&c1, &c2, sizeof(c1))); + sm_config_set_sideset_pins(&c1, 6); + sm_config_set_sideset_pin_base(&c2, 6); + check("sm_config_set_sideset_pins", !memcmp(&c1, &c2, sizeof(c1))); + } + offset = pio_add_program(pio, &echo_program); c = pio_get_default_sm_config(); sm_config_set_wrap(&c, offset + echo_wrap_target, offset + echo_wrap); diff --git a/piolib/include/piolib.h b/piolib/include/piolib.h index fc87547..8f55a3e 100644 --- a/piolib/include/piolib.h +++ b/piolib/include/piolib.h @@ -246,6 +246,16 @@ struct pio_chip { void (*pio_interrupt_clear)(PIO pio, uint pio_interrupt_num); int (*pio_irq_claim)(PIO pio); uint32_t (*pio_irq_wait)(PIO pio, uint timeout_ms); + + /* Additions for V2 SDK */ + void (*smc_set_out_pin_base)(PIO pio, pio_sm_config *c, uint out_base); + void (*smc_set_out_pin_count)(PIO pio, pio_sm_config *c, uint out_count); + void (*smc_set_set_pin_base)(PIO pio, pio_sm_config *c, uint set_base); + void (*smc_set_set_pin_count)(PIO pio, pio_sm_config *c, uint set_count); + void (*smc_set_in_pin_base)(PIO pio, pio_sm_config *c, uint in_base); + void (*smc_set_in_pin_count)(PIO pio, pio_sm_config *c, uint in_count); + void (*smc_set_sideset_pin_base)(PIO pio, pio_sm_config *c, uint sideset_base); + void (*smc_set_sideset_pin_count)(PIO pio, pio_sm_config *c, uint sideset_count); }; struct pio_instance { @@ -274,8 +284,24 @@ irq_handler_t irq_get_handler(uint num); void irq_set_enabled(uint num, bool enabled); bool irq_is_enabled(uint num); +static inline void check_pio_param(__unused PIO pio) +{ + valid_params_if(PIO, pio_get_index(pio) >= 0); +} + +static inline PIO pio_get_instance(uint instance) +{ + return pio_open_helper(instance); +} + +static inline uint pio_get_funcsel(PIO pio) { + check_pio_param(pio); + return GPIO_FUNC_PIO0; +} + static inline void pio_error(PIO pio, const char *msg) { + check_pio_param(pio); pio->error = true; if (pio->errors_are_fatal) pio_panic(msg); @@ -283,37 +309,44 @@ static inline void pio_error(PIO pio, const char *msg) static inline bool pio_get_error(PIO pio) { + check_pio_param(pio); return pio->error; } static inline void pio_clear_error(PIO pio) { + check_pio_param(pio); pio->error = false; } static inline void pio_enable_fatal_errors(PIO pio, bool enable) { + check_pio_param(pio); pio->errors_are_fatal = enable; } static inline uint pio_get_sm_count(PIO pio) { + check_pio_param(pio); return pio->chip->sm_count; } static inline uint pio_get_instruction_count(PIO pio) { + check_pio_param(pio); return pio->chip->instr_count; } static inline uint pio_get_fifo_depth(PIO pio) { + check_pio_param(pio); return pio->chip->fifo_depth; } -static inline void check_pio_param(__unused PIO pio) +static inline uint pio_get_gpio_base(PIO pio) { - valid_params_if(PIO, pio_get_index(pio) >= 0); + check_pio_param(pio); + return 0; } static inline int pio_sm_config_xfer(PIO pio, uint sm, uint dir, uint buf_size, uint buf_count) @@ -811,6 +844,54 @@ static inline void sm_config_set_sideset(pio_sm_config *c, uint bit_count, bool pio->chip->smc_set_sideset(pio, c, bit_count, optional, pindirs); } +static inline void sm_config_set_out_pin_base(pio_sm_config *c, uint out_base) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_out_pin_base(pio, c, out_base); +} + +static inline void sm_config_set_out_pin_count(pio_sm_config *c, uint out_count) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_out_pin_count(pio, c, out_count); +} + +static inline void sm_config_set_set_pin_base(pio_sm_config *c, uint set_base) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_set_pin_base(pio, c, set_base); +} + +static inline void sm_config_set_set_pin_count(pio_sm_config *c, uint set_count) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_set_pin_count(pio, c, set_count); +} + +static inline void sm_config_set_in_pin_base(pio_sm_config *c, uint in_base) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_in_pin_base(pio, c, in_base); +} + +static inline void sm_config_set_in_pin_count(pio_sm_config *c, uint in_count) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_in_pin_count(pio, c, in_count); +} + +static inline void sm_config_set_sideset_pin_base(pio_sm_config *c, uint sideset_base) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_sideset_pin_base(pio, c, sideset_base); +} + +static inline void sm_config_set_sideset_pin_count(pio_sm_config *c, uint sideset_count) +{ + PIO pio = pio_get_current(); + pio->chip->smc_set_sideset_pin_count(pio, c, sideset_count); +} + static inline void sm_config_set_clkdiv_int_frac(pio_sm_config *c, uint16_t div_int, uint8_t div_frac) { PIO pio = pio_get_current(); diff --git a/piolib/pio_rp1.c b/piolib/pio_rp1.c index b74241b..1b82e67 100644 --- a/piolib/pio_rp1.c +++ b/piolib/pio_rp1.c @@ -676,6 +676,68 @@ static void rp1_smc_set_sideset_pins(PIO, pio_sm_config *config, uint sideset_ba (sideset_base << PROC_PIO_SM0_PINCTRL_SIDESET_BASE_LSB); } +static void rp1_smc_set_out_pin_base(PIO, pio_sm_config *config, uint out_base) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, out_base < RP1_PIO_GPIO_COUNT); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_OUT_BASE_BITS) | + (out_base << PROC_PIO_SM0_PINCTRL_OUT_BASE_LSB); +} + +static void rp1_smc_set_out_pin_count(PIO, pio_sm_config *config, uint out_count) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, out_count <= RP1_PIO_GPIO_COUNT); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_OUT_COUNT_BITS) | + (out_count << PROC_PIO_SM0_PINCTRL_OUT_COUNT_LSB); +} + +static void rp1_smc_set_set_pin_base(PIO, pio_sm_config *config, uint set_base) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, set_base < RP1_PIO_GPIO_COUNT); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SET_BASE_BITS) | + (set_base << PROC_PIO_SM0_PINCTRL_SET_BASE_LSB); +} + +static void rp1_smc_set_set_pin_count(PIO, pio_sm_config *config, uint set_count) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, set_count <= 5); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SET_COUNT_BITS) | + (set_count << PROC_PIO_SM0_PINCTRL_SET_COUNT_LSB); +} + +static void rp1_smc_set_in_pin_base(PIO, pio_sm_config *config, uint in_base) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, in_base < RP1_PIO_GPIO_COUNT); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_IN_BASE_BITS) | + (in_base << PROC_PIO_SM0_PINCTRL_IN_BASE_LSB); +} + +static void rp1_smc_set_in_pin_count(PIO, __unused pio_sm_config *config, __unused uint in_count) +{ + /* RP1 PIO has no IN_COUNT field - the count is fixed at 32 */ + valid_params_if(PIO, in_count == 32); +} + +static void rp1_smc_set_sideset_pin_base(PIO, pio_sm_config *config, uint sideset_base) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, sideset_base < RP1_PIO_GPIO_COUNT); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_BASE_BITS) | + (sideset_base << PROC_PIO_SM0_PINCTRL_SIDESET_BASE_LSB); +} + +static void rp1_smc_set_sideset_pin_count(PIO, pio_sm_config *config, uint sideset_count) +{ + smc_to_rp1(config, c); + valid_params_if(PIO, sideset_count <= 5); + c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_BITS) | + (sideset_count << PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_LSB); +} + static void rp1_smc_set_sideset(PIO, pio_sm_config *config, uint bit_count, bool optional, bool pindirs) { smc_to_rp1(config, c); @@ -1083,6 +1145,16 @@ DECLARE_PIO_CHIP(rp1) { .smc_set_out_special = rp1_smc_set_out_special, .smc_set_mov_status = rp1_smc_set_mov_status, + /* Additions for V2 SDK */ + .smc_set_out_pin_base = rp1_smc_set_out_pin_base, + .smc_set_out_pin_count = rp1_smc_set_out_pin_count, + .smc_set_set_pin_base = rp1_smc_set_set_pin_base, + .smc_set_set_pin_count = rp1_smc_set_set_pin_count, + .smc_set_in_pin_base = rp1_smc_set_in_pin_base, + .smc_set_in_pin_count = rp1_smc_set_in_pin_count, + .smc_set_sideset_pin_base = rp1_smc_set_sideset_pin_base, + .smc_set_sideset_pin_count = rp1_smc_set_sideset_pin_count, + .clock_get_hz = rp1_clock_get_hz, .pio_gpio_init = rp1_pio_gpio_init,