diff --git a/examples/pio_blink/Makefile b/examples/pio_blink/Makefile new file mode 100644 index 0000000000..7e41658c1d --- /dev/null +++ b/examples/pio_blink/Makefile @@ -0,0 +1,18 @@ +APPLICATION = pio_blink +BOARD ?= rpi-pico +RIOTBASE ?= $(CURDIR)/../.. +# The board rpi-pico-w has no LED pin so you have to select the pin by hand with: +# PIO_BLINK_PIN=GPIO_PIN\(x,y\) make ... +PIO_BLINK_PIN ?= GPIO_UNDEF + +CFLAGS += -DPIO_BLINK_PIN=$(PIO_BLINK_PIN) + +FEATURES_REQUIRED += periph_pio + +DEVELHELP ?= 1 +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include + +DIRS += $(CPU)_pio_blink +USEMODULE += $(CPU)_pio_blink diff --git a/examples/pio_blink/main.c b/examples/pio_blink/main.c new file mode 100644 index 0000000000..1a47eb05f3 --- /dev/null +++ b/examples/pio_blink/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include "board.h" +#include "periph/pio.h" + +/* see blink.c */ +pio_program_t pio_blink_export_program(void); + +/* see blink.c */ +int pio_blink_write_program(pio_t pio, pio_program_t *pro); + +/* see blink.c */ +int pio_blink_init(pio_t pio, pio_sm_t sm, const pio_program_t *pro, + gpio_t pin); + +int main(void) +{ + pio_program_t blink = pio_blink_export_program(); + pio_t pio; + pio_sm_t sm; + if (pio_alloc_program_sm_lock_any(&pio, &sm, &blink)) { + puts("No PIO resources available."); + return 1; + } + if (pio_blink_write_program(pio, &blink)) { + puts("Program could not be written."); + return -1; + } + gpio_t blink_gpio = PIO_BLINK_PIN; /* see Makefile */ + if (blink_gpio == GPIO_UNDEF) { +#ifdef LED0_PIN + blink_gpio = LED0_PIN; +#endif + } + if (pio_blink_init(pio, sm, &blink, blink_gpio)) { + puts("PIO blink initialization failed"); + return 1; + } + pio_sm_start(pio, sm); + return 0; +} diff --git a/examples/pio_blink/rpx0xx_pio_blink/Makefile b/examples/pio_blink/rpx0xx_pio_blink/Makefile new file mode 100644 index 0000000000..abf33e019d --- /dev/null +++ b/examples/pio_blink/rpx0xx_pio_blink/Makefile @@ -0,0 +1,5 @@ +include $(RIOTBASE)/Makefile.base +include $(RIOTMAKE)/pio.inc.mk + +# Force generation of not existing pio header file +blink.c: blink.pio.h diff --git a/examples/pio_blink/rpx0xx_pio_blink/blink.c b/examples/pio_blink/rpx0xx_pio_blink/blink.c new file mode 100644 index 0000000000..8101e6a1ce --- /dev/null +++ b/examples/pio_blink/rpx0xx_pio_blink/blink.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 Fabian Hüßler + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include "pio/pio.h" /* this is the internal PIO header of the rpx0xx */ +#include "blink.pio.h" /* this is the auto generated header from blink.pio */ + +/** + * @brief Initialize the GPIO, which will be controlled by PIO + * + * Every PIO program should have a custom function to initialize GPIOs + * as required for the use case. The first (0) mapped set-pin (GPIO @p pin) + * is initially configured as low output pin. + * + * @param[in] pio PIO index of the PIO to use + * @param[in] sm PIO state machine index of the SM to use + * @param[in] pin GPIO pin to be mapped as first set-pin (base) + */ +static void pio_blink_init_pins(pio_t pio, pio_sm_t sm, gpio_t pin) +{ + pio_gpio_init_t init = { + .gpio_direction = PIO_GPIO_INIT_OUT(0), + .gpio_state = PIO_GPIO_INIT_LOW(0), + .gpio_base = pin, + .gpio_count = 1 + }; + pio_sm_set_set_pins_init(pio, sm, &init); +} + +/** + * @brief Create an unmapped blinky PIO program + * + * A PIO program needs a kind of constructor (in OOP). + * + * @return Blinky program + */ +pio_program_t pio_blink_export_program(void) +{ + /* Call auto-generated function to retrieve a PIO program handle. + The program is not loaded yet. */ + return pio_blink_create_program(); +} + +/** + * @brief Write blink program to instruction memory + * + * A PIO program needs a function to write the instructions + * to the allocated program memory. + * + * @param[in] pio PIO index + * @param[in] pro Allocated program + * + * @return 0 on success or negative number on error + */ +int pio_blink_write_program(pio_t pio, pio_program_t *pro) +{ + pio_instr_t instr[] = PIO_BLINK_PROGRAM; + int ret; + if ((ret = pio_write_program(pio, pro, instr))) { + return ret; + } + return 0; +} + +/** + * @brief Initialize and start running a blinky PIO program from an + * allocated program @p pro and PIO @p pio and locked state machine @p sm + * + * A PIO program needs a function to initialize a PIO state machine to run a program. + * + * @param[in] pio PIO index + * @param[in] sm PIO state machine index + * @param[in] pro Allocated program + * @param[in] pin GPIO pin to use for blinking + * + * @return 0 on successful program start or negative number on error + */ +int pio_blink_init(pio_t pio, pio_sm_t sm, const pio_program_t *pro, + gpio_t pin) +{ + pio_program_conf_t conf = PIO_BLINK_PROGRAM_CONF; + int ret; + if (pin >= 32) { + return -ENOTSUP; + } + if ((ret = pio_sm_init_common(pio, sm, pro, &conf))) { + return ret; + } + pio_sm_set_clkdiv(pio, sm, pio_sm_clkdiv(2000)); + pio_blink_init_pins(pio, sm, pin); + pio_sm_restart(pio, sm); + return 0; +} diff --git a/examples/pio_blink/rpx0xx_pio_blink/blink.pio b/examples/pio_blink/rpx0xx_pio_blink/blink.pio new file mode 100644 index 0000000000..4d873a4561 --- /dev/null +++ b/examples/pio_blink/rpx0xx_pio_blink/blink.pio @@ -0,0 +1,22 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; + +.program blink + +.wrap_target +begin: + set pins, 0 [31] + nop [31] + nop [31] + nop [31] + nop [31] + set pins, 1 [31] + nop [31] + nop [31] + nop [31] + nop [31] + jmp begin +.wrap