arm/rp2040: Add RP2040 PIO APIs
This commit is contained in:
parent
2c628cf858
commit
41b193e07f
@ -55,6 +55,7 @@ CHIP_CSRCS += rp2040_serial.c
|
||||
CHIP_CSRCS += rp2040_start.c
|
||||
CHIP_CSRCS += rp2040_timerisr.c
|
||||
CHIP_CSRCS += rp2040_gpio.c
|
||||
CHIP_CSRCS += rp2040_pio.c
|
||||
CHIP_CSRCS += rp2040_clock.c
|
||||
CHIP_CSRCS += rp2040_xosc.c
|
||||
CHIP_CSRCS += rp2040_pll.c
|
||||
|
286
arch/arm/src/rp2040/hardware/rp2040_pio.h
Normal file
286
arch/arm/src/rp2040/hardware/rp2040_pio.h
Normal file
@ -0,0 +1,286 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/rp2040/hardware/rp2040_pio.h
|
||||
*
|
||||
* Generated from rp2040.svd originally provided by
|
||||
* Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_RP2040_HARDWARE_RP2040_PIO_H
|
||||
#define __ARCH_ARM_SRC_RP2040_HARDWARE_RP2040_PIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "hardware/rp2040_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Register offsets *********************************************************/
|
||||
|
||||
#define RP2040_PIO_CTRL_OFFSET 0x000000 /* PIO control register */
|
||||
#define RP2040_PIO_FSTAT_OFFSET 0x000004 /* FIFO status register */
|
||||
#define RP2040_PIO_FDEBUG_OFFSET 0x000008 /* FIFO debug register */
|
||||
#define RP2040_PIO_FLEVEL_OFFSET 0x00000c /* FIFO levels */
|
||||
#define RP2040_PIO_TXF_OFFSET(m) (0x000010 + (m) * 4) /* Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. */
|
||||
#define RP2040_PIO_RXF_OFFSET(m) (0x000020 + (m) * 4) /* Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. */
|
||||
#define RP2040_PIO_IRQ_OFFSET 0x000030 /* Interrupt request register. Write 1 to clear */
|
||||
#define RP2040_PIO_IRQ_FORCE_OFFSET 0x000034 /* Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. */
|
||||
#define RP2040_PIO_INPUT_SYNC_BYPASS_OFFSET 0x000038 /* There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. */
|
||||
#define RP2040_PIO_DBG_PADOUT_OFFSET 0x00003c /* Read to sample the pad output values PIO is currently driving to the GPIOs. */
|
||||
#define RP2040_PIO_DBG_PADOE_OFFSET 0x000040 /* Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. */
|
||||
#define RP2040_PIO_DBG_CFGINFO_OFFSET 0x000044 /* The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. */
|
||||
#define RP2040_PIO_INSTR_MEM_OFFSET(m) (0x000048 + (m) * 4) /* Write-only access to instruction memory location m */
|
||||
#define RP2040_PIO_SM_CLKDIV_OFFSET(m) (0x0000c8 + (m) * 0x18) /* Clock divider register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) */
|
||||
#define RP2040_PIO_SM_EXECCTRL_OFFSET(m) (0x0000cc + (m) * 0x18) /* Execution/behavioural settings for state machine 0 */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_OFFSET(m) (0x0000d0 + (m) * 0x18) /* Control behaviour of the input/output shift registers for state machine 0 */
|
||||
#define RP2040_PIO_SM_ADDR_OFFSET(m) (0x0000d4 + (m) * 0x18) /* Current instruction address of state machine 0 */
|
||||
#define RP2040_PIO_SM_INSTR_OFFSET(m) (0x0000d8 + (m) * 0x18) /* Instruction currently being executed by state machine 0 Write to execute an instruction immediately (including jumps) and then resume execution. */
|
||||
#define RP2040_PIO_SM_PINCTRL_OFFSET(m) (0x0000dc + (m) * 0x18) /* State machine pin control */
|
||||
#define RP2040_PIO_SM0_CLKDIV_OFFSET 0x0000c8 /* Clock divider register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) */
|
||||
#define RP2040_PIO_SM0_EXECCTRL_OFFSET 0x0000cc /* Execution/behavioural settings for state machine 0 */
|
||||
#define RP2040_PIO_SM0_SHIFTCTRL_OFFSET 0x0000d0 /* Control behaviour of the input/output shift registers for state machine 0 */
|
||||
#define RP2040_PIO_SM0_ADDR_OFFSET 0x0000d4 /* Current instruction address of state machine 0 */
|
||||
#define RP2040_PIO_SM0_INSTR_OFFSET 0x0000d8 /* Instruction currently being executed by state machine 0 Write to execute an instruction immediately (including jumps) and then resume execution. */
|
||||
#define RP2040_PIO_SM0_PINCTRL_OFFSET 0x0000dc /* State machine pin control */
|
||||
#define RP2040_PIO_SM1_CLKDIV_OFFSET 0x0000e0 /* Clock divider register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) */
|
||||
#define RP2040_PIO_SM1_EXECCTRL_OFFSET 0x0000e4 /* Execution/behavioural settings for state machine 1 */
|
||||
#define RP2040_PIO_SM1_SHIFTCTRL_OFFSET 0x0000e8 /* Control behaviour of the input/output shift registers for state machine 1 */
|
||||
#define RP2040_PIO_SM1_ADDR_OFFSET 0x0000ec /* Current instruction address of state machine 1 */
|
||||
#define RP2040_PIO_SM1_INSTR_OFFSET 0x0000f0 /* Instruction currently being executed by state machine 1 Write to execute an instruction immediately (including jumps) and then resume execution. */
|
||||
#define RP2040_PIO_SM1_PINCTRL_OFFSET 0x0000f4 /* State machine pin control */
|
||||
#define RP2040_PIO_SM2_CLKDIV_OFFSET 0x0000f8 /* Clock divider register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) */
|
||||
#define RP2040_PIO_SM2_EXECCTRL_OFFSET 0x0000fc /* Execution/behavioural settings for state machine 2 */
|
||||
#define RP2040_PIO_SM2_SHIFTCTRL_OFFSET 0x000100 /* Control behaviour of the input/output shift registers for state machine 2 */
|
||||
#define RP2040_PIO_SM2_ADDR_OFFSET 0x000104 /* Current instruction address of state machine 2 */
|
||||
#define RP2040_PIO_SM2_INSTR_OFFSET 0x000108 /* Instruction currently being executed by state machine 2 Write to execute an instruction immediately (including jumps) and then resume execution. */
|
||||
#define RP2040_PIO_SM2_PINCTRL_OFFSET 0x00010c /* State machine pin control */
|
||||
#define RP2040_PIO_SM3_CLKDIV_OFFSET 0x000110 /* Clock divider register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) */
|
||||
#define RP2040_PIO_SM3_EXECCTRL_OFFSET 0x000114 /* Execution/behavioural settings for state machine 3 */
|
||||
#define RP2040_PIO_SM3_SHIFTCTRL_OFFSET 0x000118 /* Control behaviour of the input/output shift registers for state machine 3 */
|
||||
#define RP2040_PIO_SM3_ADDR_OFFSET 0x00011c /* Current instruction address of state machine 3 */
|
||||
#define RP2040_PIO_SM3_INSTR_OFFSET 0x000120 /* Instruction currently being executed by state machine 3 Write to execute an instruction immediately (including jumps) and then resume execution. */
|
||||
#define RP2040_PIO_SM3_PINCTRL_OFFSET 0x000124 /* State machine pin control */
|
||||
#define RP2040_PIO_INTR_OFFSET 0x000128 /* Raw Interrupts */
|
||||
#define RP2040_PIO_IRQ0_INTE_OFFSET 0x00012c /* Interrupt Enable for irq0 */
|
||||
#define RP2040_PIO_IRQ0_INTF_OFFSET 0x000130 /* Interrupt Force for irq0 */
|
||||
#define RP2040_PIO_IRQ0_INTS_OFFSET 0x000134 /* Interrupt status after masking & forcing for irq0 */
|
||||
#define RP2040_PIO_IRQ1_INTE_OFFSET 0x000138 /* Interrupt Enable for irq1 */
|
||||
#define RP2040_PIO_IRQ1_INTF_OFFSET 0x00013c /* Interrupt Force for irq1 */
|
||||
#define RP2040_PIO_IRQ1_INTS_OFFSET 0x000140 /* Interrupt status after masking & forcing for irq1 */
|
||||
|
||||
/* Register definitions *****************************************************/
|
||||
|
||||
#define RP2040_PIO_CTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_CTRL_OFFSET)
|
||||
#define RP2040_PIO_FSTAT(n) (RP2040_PIO_BASE(n) + RP2040_PIO_FSTAT_OFFSET)
|
||||
#define RP2040_PIO_FDEBUG(n) (RP2040_PIO_BASE(n) + RP2040_PIO_FDEBUG_OFFSET)
|
||||
#define RP2040_PIO_FLEVEL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_FLEVEL_OFFSET)
|
||||
#define RP2040_PIO_TXF(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_TXF_OFFSET(m))
|
||||
#define RP2040_PIO_TXF0(n) (RP2040_PIO_BASE(n) + RP2040_PIO_TXF0_OFFSET)
|
||||
#define RP2040_PIO_TXF1(n) (RP2040_PIO_BASE(n) + RP2040_PIO_TXF1_OFFSET)
|
||||
#define RP2040_PIO_TXF2(n) (RP2040_PIO_BASE(n) + RP2040_PIO_TXF2_OFFSET)
|
||||
#define RP2040_PIO_TXF3(n) (RP2040_PIO_BASE(n) + RP2040_PIO_TXF3_OFFSET)
|
||||
#define RP2040_PIO_RXF(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_RXF_OFFSET(m))
|
||||
#define RP2040_PIO_RXF0(n) (RP2040_PIO_BASE(n) + RP2040_PIO_RXF0_OFFSET)
|
||||
#define RP2040_PIO_RXF1(n) (RP2040_PIO_BASE(n) + RP2040_PIO_RXF1_OFFSET)
|
||||
#define RP2040_PIO_RXF2(n) (RP2040_PIO_BASE(n) + RP2040_PIO_RXF2_OFFSET)
|
||||
#define RP2040_PIO_RXF3(n) (RP2040_PIO_BASE(n) + RP2040_PIO_RXF3_OFFSET)
|
||||
#define RP2040_PIO_IRQ(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ_OFFSET)
|
||||
#define RP2040_PIO_IRQ_FORCE(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ_FORCE_OFFSET)
|
||||
#define RP2040_PIO_INPUT_SYNC_BYPASS(n) (RP2040_PIO_BASE(n) + RP2040_PIO_INPUT_SYNC_BYPASS_OFFSET)
|
||||
#define RP2040_PIO_DBG_PADOUT(n) (RP2040_PIO_BASE(n) + RP2040_PIO_DBG_PADOUT_OFFSET)
|
||||
#define RP2040_PIO_DBG_PADOE(n) (RP2040_PIO_BASE(n) + RP2040_PIO_DBG_PADOE_OFFSET)
|
||||
#define RP2040_PIO_DBG_CFGINFO(n) (RP2040_PIO_BASE(n) + RP2040_PIO_DBG_CFGINFO_OFFSET)
|
||||
#define RP2040_PIO_INSTR_MEM(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_INSTR_MEM_OFFSET(m))
|
||||
|
||||
#define RP2040_PIO_SM_CLKDIV(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_CLKDIV_OFFSET(m))
|
||||
#define RP2040_PIO_SM_EXECCTRL(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_EXECCTRL_OFFSET(m))
|
||||
#define RP2040_PIO_SM_SHIFTCTRL(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_SHIFTCTRL_OFFSET(m))
|
||||
#define RP2040_PIO_SM_ADDR(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_ADDR_OFFSET(m))
|
||||
#define RP2040_PIO_SM_INSTR(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_INSTR_OFFSET(m))
|
||||
#define RP2040_PIO_SM_PINCTRL(n, m) (RP2040_PIO_BASE(n) + RP2040_PIO_SM_PINCTRL_OFFSET(m))
|
||||
|
||||
#define RP2040_PIO_SM0_CLKDIV(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_CLKDIV_OFFSET)
|
||||
#define RP2040_PIO_SM0_EXECCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_EXECCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM0_SHIFTCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_SHIFTCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM0_ADDR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_ADDR_OFFSET)
|
||||
#define RP2040_PIO_SM0_INSTR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_INSTR_OFFSET)
|
||||
#define RP2040_PIO_SM0_PINCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM0_PINCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM1_CLKDIV(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_CLKDIV_OFFSET)
|
||||
#define RP2040_PIO_SM1_EXECCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_EXECCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM1_SHIFTCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_SHIFTCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM1_ADDR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_ADDR_OFFSET)
|
||||
#define RP2040_PIO_SM1_INSTR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_INSTR_OFFSET)
|
||||
#define RP2040_PIO_SM1_PINCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM1_PINCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM2_CLKDIV(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_CLKDIV_OFFSET)
|
||||
#define RP2040_PIO_SM2_EXECCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_EXECCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM2_SHIFTCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_SHIFTCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM2_ADDR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_ADDR_OFFSET)
|
||||
#define RP2040_PIO_SM2_INSTR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_INSTR_OFFSET)
|
||||
#define RP2040_PIO_SM2_PINCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM2_PINCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM3_CLKDIV(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_CLKDIV_OFFSET)
|
||||
#define RP2040_PIO_SM3_EXECCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_EXECCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM3_SHIFTCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_SHIFTCTRL_OFFSET)
|
||||
#define RP2040_PIO_SM3_ADDR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_ADDR_OFFSET)
|
||||
#define RP2040_PIO_SM3_INSTR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_INSTR_OFFSET)
|
||||
#define RP2040_PIO_SM3_PINCTRL(n) (RP2040_PIO_BASE(n) + RP2040_PIO_SM3_PINCTRL_OFFSET)
|
||||
#define RP2040_PIO_INTR(n) (RP2040_PIO_BASE(n) + RP2040_PIO_INTR_OFFSET)
|
||||
#define RP2040_PIO_IRQ0_INTE(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ0_INTE_OFFSET)
|
||||
#define RP2040_PIO_IRQ0_INTF(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ0_INTF_OFFSET)
|
||||
#define RP2040_PIO_IRQ0_INTS(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ0_INTS_OFFSET)
|
||||
#define RP2040_PIO_IRQ1_INTE(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ1_INTE_OFFSET)
|
||||
#define RP2040_PIO_IRQ1_INTF(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ1_INTF_OFFSET)
|
||||
#define RP2040_PIO_IRQ1_INTS(n) (RP2040_PIO_BASE(n) + RP2040_PIO_IRQ1_INTS_OFFSET)
|
||||
|
||||
/* Register bit definitions *************************************************/
|
||||
|
||||
#define RP2040_PIO_CTRL_CLKDIV_RESTART_SHIFT (8) /* Force clock dividers to restart their count and clear fractional accumulators. Restart multiple dividers to synchronise them. */
|
||||
#define RP2040_PIO_CTRL_CLKDIV_RESTART_MASK (0x0f << RP2040_PIO_CTRL_CLKDIV_RESTART_SHIFT)
|
||||
#define RP2040_PIO_CTRL_SM_RESTART_SHIFT (4) /* Clear internal SM state which is otherwise difficult to access (e.g. shift counters). Self-clearing. */
|
||||
#define RP2040_PIO_CTRL_SM_RESTART_MASK (0x0f << RP2040_PIO_CTRL_SM_RESTART_SHIFT)
|
||||
#define RP2040_PIO_CTRL_SM_ENABLE_MASK (0x0f) /* Enable state machine */
|
||||
|
||||
#define RP2040_PIO_FSTAT_TXEMPTY_SHIFT (24) /* State machine TX FIFO is empty */
|
||||
#define RP2040_PIO_FSTAT_TXEMPTY_MASK (0x0f << RP2040_PIO_FSTAT_TXEMPTY_SHIFT)
|
||||
#define RP2040_PIO_FSTAT_TXFULL_SHIFT (16) /* State machine TX FIFO is full */
|
||||
#define RP2040_PIO_FSTAT_TXFULL_MASK (0x0f << RP2040_PIO_FSTAT_TXFULL_SHIFT)
|
||||
#define RP2040_PIO_FSTAT_RXEMPTY_SHIFT (8) /* State machine RX FIFO is empty */
|
||||
#define RP2040_PIO_FSTAT_RXEMPTY_MASK (0x0f << RP2040_PIO_FSTAT_RXEMPTY_SHIFT)
|
||||
#define RP2040_PIO_FSTAT_RXFULL_SHIFT (0) /* State machine RX FIFO is full */
|
||||
#define RP2040_PIO_FSTAT_RXFULL_MASK (0x0f) /* State machine RX FIFO is full */
|
||||
|
||||
#define RP2040_PIO_FDEBUG_TXSTALL_SHIFT (24) /* State machine has stalled on empty TX FIFO. Write 1 to clear. */
|
||||
#define RP2040_PIO_FDEBUG_TXSTALL_MASK (0x0f << RP2040_PIO_FDEBUG_TXSTALL_SHIFT)
|
||||
#define RP2040_PIO_FDEBUG_TXOVER_SHIFT (16) /* TX FIFO overflow has occurred. Write 1 to clear. */
|
||||
#define RP2040_PIO_FDEBUG_TXOVER_MASK (0x0f << RP2040_PIO_FDEBUG_TXOVER_SHIFT)
|
||||
#define RP2040_PIO_FDEBUG_RXUNDER_SHIFT (8) /* RX FIFO underflow has occurred. Write 1 to clear. */
|
||||
#define RP2040_PIO_FDEBUG_RXUNDER_MASK (0x0f << RP2040_PIO_FDEBUG_RXUNDER_SHIFT)
|
||||
#define RP2040_PIO_FDEBUG_RXSTALL_SHIFT (0) /* State machine has stalled on full RX FIFO. Write 1 to clear. */
|
||||
#define RP2040_PIO_FDEBUG_RXSTALL_MASK (0x0f) /* State machine has stalled on full RX FIFO. Write 1 to clear. */
|
||||
|
||||
#define RP2040_PIO_FLEVEL_RX3_SHIFT (28)
|
||||
#define RP2040_PIO_FLEVEL_RX3_MASK (0x0f << RP2040_PIO_FLEVEL_RX3_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_TX3_SHIFT (24)
|
||||
#define RP2040_PIO_FLEVEL_TX3_MASK (0x0f << RP2040_PIO_FLEVEL_TX3_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_RX2_SHIFT (20)
|
||||
#define RP2040_PIO_FLEVEL_RX2_MASK (0x0f << RP2040_PIO_FLEVEL_RX2_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_TX2_SHIFT (16)
|
||||
#define RP2040_PIO_FLEVEL_TX2_MASK (0x0f << RP2040_PIO_FLEVEL_TX2_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_RX1_SHIFT (12)
|
||||
#define RP2040_PIO_FLEVEL_RX1_MASK (0x0f << RP2040_PIO_FLEVEL_RX1_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_TX1_SHIFT (8)
|
||||
#define RP2040_PIO_FLEVEL_TX1_MASK (0x0f << RP2040_PIO_FLEVEL_TX1_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_RX0_SHIFT (4)
|
||||
#define RP2040_PIO_FLEVEL_RX0_MASK (0x0f << RP2040_PIO_FLEVEL_RX0_SHIFT)
|
||||
#define RP2040_PIO_FLEVEL_TX0_SHIFT (0)
|
||||
#define RP2040_PIO_FLEVEL_TX0_MASK (0x0f)
|
||||
|
||||
#define RP2040_PIO_IRQ_MASK (0xff)
|
||||
|
||||
#define RP2040_PIO_IRQ_FORCE_MASK (0xff)
|
||||
|
||||
#define RP2040_PIO_DBG_CFGINFO_IMEM_SIZE_SHIFT (16) /* The size of the instruction memory, measured in units of one instruction */
|
||||
#define RP2040_PIO_DBG_CFGINFO_IMEM_SIZE_MASK (0x3f << RP2040_PIO_DBG_CFGINFO_IMEM_SIZE_SHIFT)
|
||||
#define RP2040_PIO_DBG_CFGINFO_SM_COUNT_SHIFT (8) /* The number of state machines this PIO instance is equipped with. */
|
||||
#define RP2040_PIO_DBG_CFGINFO_SM_COUNT_MASK (0x0f << RP2040_PIO_DBG_CFGINFO_SM_COUNT_SHIFT)
|
||||
#define RP2040_PIO_DBG_CFGINFO_FIFO_DEPTH_MASK (0x3f) /* The depth of the state machine TX/RX FIFOs, measured in words. Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double this depth. */
|
||||
|
||||
#define RP2040_PIO_INSTR_MEM_MASK (0xffff)
|
||||
|
||||
#define RP2040_PIO_SM_CLKDIV_INT_SHIFT (16) /* Effective frequency is sysclk/int. Value of 0 is interpreted as max possible value */
|
||||
#define RP2040_PIO_SM_CLKDIV_INT_MASK (0xffff << RP2040_PIO_SM_CLKDIV_INT_SHIFT)
|
||||
#define RP2040_PIO_SM_CLKDIV_FRAC_SHIFT (8) /* Fractional part of clock divider */
|
||||
#define RP2040_PIO_SM_CLKDIV_FRAC_MASK (0xff << RP2040_PIO_SM_CLKDIV_FRAC_SHIFT)
|
||||
|
||||
#define RP2040_PIO_SM_EXECCTRL_EXEC_STALLED (1 << 31) /* An instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear once the instruction completes. */
|
||||
#define RP2040_PIO_SM_EXECCTRL_SIDE_EN (1 << 30) /* If 1, the delay MSB is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction. */
|
||||
#define RP2040_PIO_SM_EXECCTRL_SIDE_PINDIR (1 << 29) /* Side-set data is asserted to pin OEs instead of pin values */
|
||||
#define RP2040_PIO_SM_EXECCTRL_JMP_PIN_SHIFT (24) /* The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. */
|
||||
#define RP2040_PIO_SM_EXECCTRL_JMP_PIN_MASK (0x1f << RP2040_PIO_SM_EXECCTRL_JMP_PIN_SHIFT)
|
||||
#define RP2040_PIO_SM_EXECCTRL_OUT_EN_SEL_SHIFT (19) /* Which data bit to use for inline OUT enable */
|
||||
#define RP2040_PIO_SM_EXECCTRL_OUT_EN_SEL_MASK (0x1f << RP2040_PIO_SM_EXECCTRL_OUT_EN_SEL_SHIFT)
|
||||
#define RP2040_PIO_SM_EXECCTRL_INLINE_OUT_EN (1 << 18) /* If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) */
|
||||
#define RP2040_PIO_SM_EXECCTRL_OUT_STICKY (1 << 17) /* Continuously assert the most recent OUT/SET to the pins */
|
||||
#define RP2040_PIO_SM_EXECCTRL_WRAP_TOP_SHIFT (12) /* After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. */
|
||||
#define RP2040_PIO_SM_EXECCTRL_WRAP_TOP_MASK (0x1f << RP2040_PIO_SM_EXECCTRL_WRAP_TOP_SHIFT)
|
||||
#define RP2040_PIO_SM_EXECCTRL_WRAP_BOTTOM_SHIFT (7) /* After reaching wrap_top, execution is wrapped to this address. */
|
||||
#define RP2040_PIO_SM_EXECCTRL_WRAP_BOTTOM_MASK (0x1f << RP2040_PIO_SM_EXECCTRL_WRAP_BOTTOM_SHIFT)
|
||||
#define RP2040_PIO_SM_EXECCTRL_STATUS_SEL (1 << 4) /* All-ones if RX FIFO level < N, otherwise all-zeroes */
|
||||
#define RP2040_PIO_SM_EXECCTRL_STATUS_N_MASK (0x0f) /* Comparison level for the MOV x, STATUS instruction */
|
||||
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_FJOIN_RX (1 << 31) /* When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_FJOIN_TX (1 << 30) /* When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_PULL_THRESH_SHIFT (25) /* Number of bits shifted out of TXSR before autopull or conditional pull. Write 0 for value of 32. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_PULL_THRESH_MASK (0x1f << RP2040_PIO_SM_SHIFTCTRL_PULL_THRESH_SHIFT)
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_PUSH_THRESH_SHIFT (20) /* Number of bits shifted into RXSR before autopush or conditional push. Write 0 for value of 32. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_PUSH_THRESH_MASK (0x1f << RP2040_PIO_SM_SHIFTCTRL_PUSH_THRESH_SHIFT)
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_OUT_SHIFTDIR (1 << 19) /* 1 = shift out of output shift register to right. 0 = to left. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_IN_SHIFTDIR (1 << 18) /* 1 = shift input shift register to right (data enters from left). 0 = to left. */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_AUTOPULL (1 << 17) /* Pull automatically when the output shift register is emptied */
|
||||
#define RP2040_PIO_SM_SHIFTCTRL_AUTOPUSH (1 << 16) /* Push automatically when the input shift register is filled */
|
||||
|
||||
#define RP2040_PIO_SM_ADDR_MASK (0x1f)
|
||||
|
||||
#define RP2040_PIO_SM_INSTR_MASK (0xffff)
|
||||
|
||||
#define RP2040_PIO_SM_PINCTRL_SIDESET_COUNT_SHIFT (29) /* The number of delay bits co-opted for side-set. Inclusive of the enable bit, if present. */
|
||||
#define RP2040_PIO_SM_PINCTRL_SIDESET_COUNT_MASK (0x07 << RP2040_PIO_SM_PINCTRL_SIDESET_COUNT_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT (26) /* The number of pins asserted by a SET. Max of 5 */
|
||||
#define RP2040_PIO_SM_PINCTRL_SET_COUNT_MASK (0x07 << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_OUT_COUNT_SHIFT (20) /* The number of pins asserted by an OUT. Value of 0 -> 32 pins */
|
||||
#define RP2040_PIO_SM_PINCTRL_OUT_COUNT_MASK (0x3f << RP2040_PIO_SM_PINCTRL_OUT_COUNT_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_IN_BASE_SHIFT (15) /* The virtual pin corresponding to IN bit 0 */
|
||||
#define RP2040_PIO_SM_PINCTRL_IN_BASE_MASK (0x1f << RP2040_PIO_SM_PINCTRL_IN_BASE_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_SIDESET_BASE_SHIFT (10) /* The virtual pin corresponding to delay field bit 0 */
|
||||
#define RP2040_PIO_SM_PINCTRL_SIDESET_BASE_MASK (0x1f << RP2040_PIO_SM_PINCTRL_SIDESET_BASE_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT (5) /* The virtual pin corresponding to SET bit 0 */
|
||||
#define RP2040_PIO_SM_PINCTRL_SET_BASE_MASK (0x1f << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT)
|
||||
#define RP2040_PIO_SM_PINCTRL_OUT_BASE_SHIFT (0) /* The virtual pin corresponding to OUT bit 0 */
|
||||
#define RP2040_PIO_SM_PINCTRL_OUT_BASE_MASK (0x1f) /* The virtual pin corresponding to OUT bit 0 */
|
||||
|
||||
#define RP2040_PIO_INTR_SM3 (1 << 11)
|
||||
#define RP2040_PIO_INTR_SM2 (1 << 10)
|
||||
#define RP2040_PIO_INTR_SM1 (1 << 9)
|
||||
#define RP2040_PIO_INTR_SM0 (1 << 8)
|
||||
#define RP2040_PIO_INTR_SM3_TXNFULL (1 << 7)
|
||||
#define RP2040_PIO_INTR_SM2_TXNFULL (1 << 6)
|
||||
#define RP2040_PIO_INTR_SM1_TXNFULL (1 << 5)
|
||||
#define RP2040_PIO_INTR_SM0_TXNFULL (1 << 4)
|
||||
#define RP2040_PIO_INTR_SM3_RXNEMPTY (1 << 3)
|
||||
#define RP2040_PIO_INTR_SM2_RXNEMPTY (1 << 2)
|
||||
#define RP2040_PIO_INTR_SM1_RXNEMPTY (1 << 1)
|
||||
#define RP2040_PIO_INTR_SM0_RXNEMPTY (1 << 0)
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_RP2040_HARDWARE_RP2040_PIO_H */
|
480
arch/arm/src/rp2040/rp2040_pio.c
Normal file
480
arch/arm/src/rp2040/rp2040_pio.c
Normal file
@ -0,0 +1,480 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/rp2040/rp2040_pio.c
|
||||
*
|
||||
* Based upon the software originally developed by
|
||||
* Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "hardware/rp2040_pio.h"
|
||||
#include "rp2040_pio.h"
|
||||
#include "rp2040_pio_instructions.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define hw_claim_lock() spin_lock_irqsave(&pio_lock)
|
||||
#define hw_claim_unlock(save) spin_unlock_irqrestore(&pio_lock, save)
|
||||
#else
|
||||
#define hw_claim_lock() spin_lock_irqsave(NULL)
|
||||
#define hw_claim_unlock(save) spin_unlock_irqrestore(NULL, save)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static spinlock_t pio_lock;
|
||||
#endif
|
||||
|
||||
static uint8_t claimed;
|
||||
|
||||
static uint32_t _used_instruction_space[2];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void hw_claim_or_assert(uint8_t *bits, uint32_t bit_index,
|
||||
const char *message)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
if (bits[bit_index >> 3u] & (1u << (bit_index & 7u)))
|
||||
{
|
||||
DEBUGPANIC();
|
||||
}
|
||||
else
|
||||
{
|
||||
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
||||
}
|
||||
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
||||
static int hw_claim_unused_from_range(uint8_t *bits, bool required,
|
||||
uint32_t bit_lsb, uint32_t bit_msb,
|
||||
const char *message)
|
||||
{
|
||||
/* don't bother check lsb / msb order as if wrong, then it'll fail anyway */
|
||||
|
||||
uint32_t save = hw_claim_lock();
|
||||
int found_bit = -1;
|
||||
for (uint32_t bit = bit_lsb; bit <= bit_msb; bit++)
|
||||
{
|
||||
if (!(bits[bit >> 3u] & (1u << (bit & 7u))))
|
||||
{
|
||||
bits[bit >> 3u] |= (uint8_t)(1u << (bit & 7u));
|
||||
found_bit = (int)bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hw_claim_unlock(save);
|
||||
if (found_bit < 0 && required)
|
||||
{
|
||||
DEBUGPANIC();
|
||||
}
|
||||
|
||||
return found_bit;
|
||||
}
|
||||
|
||||
static void hw_claim_clear(uint8_t *bits, uint32_t bit_index)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
assert(bits[bit_index >> 3u] & (1u << (bit_index & 7u)));
|
||||
bits[bit_index >> 3u] &= (uint8_t) ~(1u << (bit_index & 7u));
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
||||
static int _pio_find_offset_for_program(uint32_t pio,
|
||||
const rp2040_pio_program_t *program)
|
||||
{
|
||||
assert(program->length < PIO_INSTRUCTION_COUNT);
|
||||
uint32_t used_mask = _used_instruction_space[rp2040_pio_get_index(pio)];
|
||||
uint32_t program_mask = (1u << program->length) - 1;
|
||||
|
||||
if (program->origin >= 0)
|
||||
{
|
||||
if (program->origin > 32 - program->length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return used_mask & (program_mask << program->origin) ?
|
||||
-1 : program->origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* work down from the top always */
|
||||
|
||||
for (int i = 32 - program->length; i >= 0; i--)
|
||||
{
|
||||
if (!(used_mask & (program_mask << (uint32_t) i)))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool _pio_can_add_program_at_offset(uint32_t pio,
|
||||
const rp2040_pio_program_t *program,
|
||||
uint32_t offset)
|
||||
{
|
||||
valid_params_if(PIO, offset < PIO_INSTRUCTION_COUNT);
|
||||
valid_params_if(PIO, offset + program->length <= PIO_INSTRUCTION_COUNT);
|
||||
if (program->origin >= 0 && (uint32_t)program->origin != offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t used_mask = _used_instruction_space[rp2040_pio_get_index(pio)];
|
||||
uint32_t program_mask = (1u << program->length) - 1;
|
||||
return !(used_mask & (program_mask << offset));
|
||||
}
|
||||
|
||||
static void _pio_add_program_at_offset(uint32_t pio,
|
||||
const rp2040_pio_program_t *program,
|
||||
uint32_t offset)
|
||||
{
|
||||
if (!_pio_can_add_program_at_offset(pio, program, offset))
|
||||
{
|
||||
DEBUGPANIC(); /* "No program space" */
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < program->length; ++i)
|
||||
{
|
||||
uint16_t instr = program->instructions[i];
|
||||
putreg32(pio_instr_bits_jmp != _pio_major_instr_bits(instr) ?
|
||||
instr : instr + offset,
|
||||
RP2040_PIO_INSTR_MEM(pio, offset + i));
|
||||
}
|
||||
|
||||
uint32_t program_mask = (1u << program->length) - 1;
|
||||
_used_instruction_space[rp2040_pio_get_index(pio)] |=
|
||||
program_mask << offset;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_pio_sm_claim(uint32_t pio, uint32_t sm)
|
||||
{
|
||||
check_sm_param(sm);
|
||||
uint32_t which = rp2040_pio_get_index(pio);
|
||||
|
||||
if (which)
|
||||
{
|
||||
hw_claim_or_assert(&claimed, RP2040_PIO_SM_NUM + sm,
|
||||
"PIO 1 SM (%d - 4) already claimed");
|
||||
}
|
||||
else
|
||||
{
|
||||
hw_claim_or_assert(&claimed, sm,
|
||||
"PIO 0 SM %d already claimed");
|
||||
}
|
||||
}
|
||||
|
||||
void rp2040_pio_claim_sm_mask(uint32_t pio, uint32_t sm_mask)
|
||||
{
|
||||
for (uint32_t i = 0; sm_mask; i++, sm_mask >>= 1u)
|
||||
{
|
||||
if (sm_mask & 1u)
|
||||
{
|
||||
rp2040_pio_sm_claim(pio, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_unclaim(uint32_t pio, uint32_t sm)
|
||||
{
|
||||
check_sm_param(sm);
|
||||
uint32_t which = rp2040_pio_get_index(pio);
|
||||
hw_claim_clear(&claimed, which * RP2040_PIO_SM_NUM + sm);
|
||||
}
|
||||
|
||||
int rp2040_pio_claim_unused_sm(uint32_t pio, bool required)
|
||||
{
|
||||
/* PIO index is 0 or 1. */
|
||||
|
||||
uint32_t which = rp2040_pio_get_index(pio);
|
||||
uint32_t base = which * RP2040_PIO_SM_NUM;
|
||||
int index = hw_claim_unused_from_range((uint8_t *)&claimed, required, base,
|
||||
base + RP2040_PIO_SM_NUM - 1,
|
||||
"No PIO state machines are available");
|
||||
return index >= (int)base ? index - (int)base : -1;
|
||||
}
|
||||
|
||||
bool rp2040_pio_can_add_program(uint32_t pio,
|
||||
const rp2040_pio_program_t *program)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
bool rc = -1 != _pio_find_offset_for_program(pio, program);
|
||||
hw_claim_unlock(save);
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool rp2040_pio_can_add_program_at_offset(uint32_t pio,
|
||||
const rp2040_pio_program_t *program,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
bool rc = _pio_can_add_program_at_offset(pio, program, offset);
|
||||
hw_claim_unlock(save);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* these assert if unable */
|
||||
|
||||
uint32_t rp2040_pio_add_program(uint32_t pio,
|
||||
const rp2040_pio_program_t *program)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
int offset = _pio_find_offset_for_program(pio, program);
|
||||
if (offset < 0)
|
||||
{
|
||||
DEBUGPANIC(); /* "No program space" */
|
||||
}
|
||||
|
||||
_pio_add_program_at_offset(pio, program, (uint32_t)offset);
|
||||
hw_claim_unlock(save);
|
||||
return (uint32_t)offset;
|
||||
}
|
||||
|
||||
void rp2040_pio_add_program_at_offset(uint32_t pio,
|
||||
const rp2040_pio_program_t *program,
|
||||
uint32_t offset)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
_pio_add_program_at_offset(pio, program, offset);
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
||||
void rp2040_pio_remove_program(uint32_t pio,
|
||||
const rp2040_pio_program_t *program,
|
||||
uint32_t loaded_offset)
|
||||
{
|
||||
uint32_t program_mask = (1u << program->length) - 1;
|
||||
program_mask <<= loaded_offset;
|
||||
uint32_t save = hw_claim_lock();
|
||||
assert(program_mask ==
|
||||
(_used_instruction_space[rp2040_pio_get_index(pio)] &
|
||||
program_mask));
|
||||
_used_instruction_space[rp2040_pio_get_index(pio)] &= ~program_mask;
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
||||
void rp2040_pio_clear_instruction_memory(uint32_t pio)
|
||||
{
|
||||
uint32_t save = hw_claim_lock();
|
||||
_used_instruction_space[rp2040_pio_get_index(pio)] = 0;
|
||||
for (uint32_t i = 0; i < PIO_INSTRUCTION_COUNT; i++)
|
||||
{
|
||||
putreg32(pio_encode_jmp(i), RP2040_PIO_INSTR_MEM(pio, i));
|
||||
}
|
||||
|
||||
hw_claim_unlock(save);
|
||||
}
|
||||
|
||||
/* Set the value of all PIO pins. This is done by forcibly executing
|
||||
* instructions on a "victim" state machine, sm. Ideally you should choose
|
||||
* one which is not currently running a program. This is intended for
|
||||
* one-time setup of initial pin states.
|
||||
*/
|
||||
|
||||
void rp2040_pio_sm_set_pins(uint32_t pio, uint32_t sm, uint32_t pins)
|
||||
{
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
uint32_t pinctrl_saved = getreg32(RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
uint32_t remaining = 32;
|
||||
uint32_t base = 0;
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
uint32_t decrement = remaining > 5 ? 5 : remaining;
|
||||
putreg32((decrement << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT) |
|
||||
(base << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT),
|
||||
RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
rp2040_pio_sm_exec(pio, sm,
|
||||
pio_encode_set(pio_pins, pins & 0x1fu));
|
||||
remaining -= decrement;
|
||||
base += decrement;
|
||||
pins >>= 5;
|
||||
}
|
||||
|
||||
putreg32(pinctrl_saved, RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_set_pins_with_mask(uint32_t pio, uint32_t sm,
|
||||
uint32_t pinvals, uint32_t pin_mask)
|
||||
{
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
uint32_t pinctrl_saved = getreg32(RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
|
||||
while (pin_mask)
|
||||
{
|
||||
uint32_t base = (uint32_t)__builtin_ctz(pin_mask);
|
||||
putreg32((1u << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT) |
|
||||
(base << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT),
|
||||
RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
rp2040_pio_sm_exec(pio, sm,
|
||||
pio_encode_set(pio_pins,
|
||||
(pinvals >> base) & 0x1u));
|
||||
pin_mask &= pin_mask - 1;
|
||||
}
|
||||
|
||||
putreg32(pinctrl_saved, RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_set_pindirs_with_mask(uint32_t pio, uint32_t sm,
|
||||
uint32_t pindirs,
|
||||
uint32_t pin_mask)
|
||||
{
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
uint32_t pinctrl_saved = getreg32(RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
|
||||
while (pin_mask)
|
||||
{
|
||||
uint32_t base = (uint32_t)__builtin_ctz(pin_mask);
|
||||
putreg32((1u << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT) |
|
||||
(base << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT),
|
||||
RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
rp2040_pio_sm_exec(pio, sm,
|
||||
pio_encode_set(pio_pindirs,
|
||||
(pindirs >> base) & 0x1u));
|
||||
pin_mask &= pin_mask - 1;
|
||||
}
|
||||
|
||||
putreg32(pinctrl_saved, RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_set_consecutive_pindirs(uint32_t pio, uint32_t sm,
|
||||
uint32_t pin,
|
||||
uint32_t count, bool is_out)
|
||||
{
|
||||
check_pio_param(pio);
|
||||
check_sm_param(sm);
|
||||
valid_params_if(PIO, pin < 32u);
|
||||
|
||||
uint32_t pinctrl_saved = getreg32(RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
uint32_t pindir_val = is_out ? 0x1f : 0;
|
||||
|
||||
while (count > 5)
|
||||
{
|
||||
putreg32((5u << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT) |
|
||||
(pin << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT),
|
||||
RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
rp2040_pio_sm_exec(pio, sm,
|
||||
pio_encode_set(pio_pindirs, pindir_val));
|
||||
count -= 5;
|
||||
pin = (pin + 5) & 0x1f;
|
||||
}
|
||||
|
||||
putreg32((count << RP2040_PIO_SM_PINCTRL_SET_COUNT_SHIFT) |
|
||||
(pin << RP2040_PIO_SM_PINCTRL_SET_BASE_SHIFT),
|
||||
RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
rp2040_pio_sm_exec(pio, sm,
|
||||
pio_encode_set(pio_pindirs, pindir_val));
|
||||
putreg32(pinctrl_saved, RP2040_PIO_SM_PINCTRL(pio, sm));
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_init(uint32_t pio, uint32_t sm, uint32_t initial_pc,
|
||||
const rp2040_pio_sm_config *config)
|
||||
{
|
||||
valid_params_if(PIO, initial_pc < PIO_INSTRUCTION_COUNT);
|
||||
|
||||
/* Halt the machine, set some sensible defaults */
|
||||
|
||||
rp2040_pio_sm_set_enabled(pio, sm, false);
|
||||
|
||||
if (config)
|
||||
{
|
||||
rp2040_pio_sm_set_config(pio, sm, config);
|
||||
}
|
||||
else
|
||||
{
|
||||
rp2040_pio_sm_config c = rp2040_pio_get_default_sm_config();
|
||||
rp2040_pio_sm_set_config(pio, sm, &c);
|
||||
}
|
||||
|
||||
rp2040_pio_sm_clear_fifos(pio, sm);
|
||||
|
||||
/* Clear FIFO debug flags */
|
||||
|
||||
const uint32_t fdebug_sm_mask = (1u << RP2040_PIO_FDEBUG_TXOVER_SHIFT) |
|
||||
(1u << RP2040_PIO_FDEBUG_RXUNDER_SHIFT) |
|
||||
(1u << RP2040_PIO_FDEBUG_TXSTALL_SHIFT) |
|
||||
(1u << RP2040_PIO_FDEBUG_RXSTALL_SHIFT);
|
||||
putreg32(fdebug_sm_mask << sm, RP2040_PIO_FDEBUG(pio));
|
||||
|
||||
/* Finally, clear some internal SM state */
|
||||
|
||||
rp2040_pio_sm_restart(pio, sm);
|
||||
rp2040_pio_sm_clkdiv_restart(pio, sm);
|
||||
rp2040_pio_sm_exec(pio, sm, pio_encode_jmp(initial_pc));
|
||||
}
|
||||
|
||||
void rp2040_pio_sm_drain_tx_fifo(uint32_t pio, uint32_t sm)
|
||||
{
|
||||
uint32_t instr = (getreg32(RP2040_PIO_SM_SHIFTCTRL(pio, sm)) &
|
||||
RP2040_PIO_SM_SHIFTCTRL_AUTOPULL) ?
|
||||
pio_encode_out(pio_null, 32) :
|
||||
pio_encode_pull(false, false);
|
||||
|
||||
while (!rp2040_pio_sm_is_tx_fifo_empty(pio, sm))
|
||||
{
|
||||
rp2040_pio_sm_exec(pio, sm, instr);
|
||||
}
|
||||
}
|
1968
arch/arm/src/rp2040/rp2040_pio.h
Normal file
1968
arch/arm/src/rp2040/rp2040_pio.h
Normal file
File diff suppressed because it is too large
Load Diff
301
arch/arm/src/rp2040/rp2040_pio_instructions.h
Normal file
301
arch/arm/src/rp2040/rp2040_pio_instructions.h
Normal file
@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/rp2040/rp2040_pio_instructions.h
|
||||
*
|
||||
* Based upon the software originally developed by
|
||||
* Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_RP2040_RP2040_PIO_INSTRUCTIONS_H
|
||||
#define __ARCH_ARM_SRC_RP2040_RP2040_PIO_INSTRUCTIONS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "rp2040_pio.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS,
|
||||
* Enable/disable assertions in the PIO instructions, type=bool, default=0,
|
||||
* group=hardware_pio
|
||||
*/
|
||||
|
||||
#ifndef PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
|
||||
#define PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS 0
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
enum pio_instr_bits
|
||||
{
|
||||
pio_instr_bits_jmp = 0x0000,
|
||||
pio_instr_bits_wait = 0x2000,
|
||||
pio_instr_bits_in = 0x4000,
|
||||
pio_instr_bits_out = 0x6000,
|
||||
pio_instr_bits_push = 0x8000,
|
||||
pio_instr_bits_pull = 0x8080,
|
||||
pio_instr_bits_mov = 0xa000,
|
||||
pio_instr_bits_irq = 0xc000,
|
||||
pio_instr_bits_set = 0xe000,
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define _PIO_INVALID_IN_SRC 0x08u
|
||||
#define _PIO_INVALID_OUT_DEST 0x10u
|
||||
#define _PIO_INVALID_SET_DEST 0x20u
|
||||
#define _PIO_INVALID_MOV_SRC 0x40u
|
||||
#define _PIO_INVALID_MOV_DEST 0x80u
|
||||
#else
|
||||
#define _PIO_INVALID_IN_SRC 0u
|
||||
#define _PIO_INVALID_OUT_DEST 0u
|
||||
#define _PIO_INVALID_SET_DEST 0u
|
||||
#define _PIO_INVALID_MOV_SRC 0u
|
||||
#define _PIO_INVALID_MOV_DEST 0u
|
||||
#endif
|
||||
|
||||
enum pio_src_dest
|
||||
{
|
||||
pio_pins = 0u,
|
||||
pio_x = 1u,
|
||||
pio_y = 2u,
|
||||
pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
||||
pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC |
|
||||
_PIO_INVALID_MOV_DEST,
|
||||
pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST |
|
||||
_PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
|
||||
pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST |
|
||||
_PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
||||
pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST |
|
||||
_PIO_INVALID_MOV_SRC,
|
||||
pio_isr = 6u | _PIO_INVALID_SET_DEST,
|
||||
pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
|
||||
pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST |
|
||||
_PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
inline static uint32_t _pio_major_instr_bits(uint32_t instr)
|
||||
{
|
||||
return instr & 0xe000u;
|
||||
}
|
||||
|
||||
inline static uint32_t _pio_encode_instr_and_args(
|
||||
enum pio_instr_bits instr_bits,
|
||||
uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
|
||||
#if PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
|
||||
uint32_t major = _pio_major_instr_bits(instr_bits);
|
||||
if (major == pio_instr_bits_in || major == pio_instr_bits_out)
|
||||
{
|
||||
assert(arg2 && arg2 <= 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(arg2 <= 31);
|
||||
}
|
||||
#endif
|
||||
return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
|
||||
}
|
||||
|
||||
inline static uint32_t _pio_encode_instr_and_src_dest(
|
||||
enum pio_instr_bits instr_bits,
|
||||
enum pio_src_dest dest,
|
||||
uint32_t value)
|
||||
{
|
||||
return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_delay(uint32_t cycles)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
|
||||
return cycles << 8u;
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_sideset(uint32_t sideset_bit_count,
|
||||
uint32_t value)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS,
|
||||
sideset_bit_count >= 1 && sideset_bit_count <= 5);
|
||||
valid_params_if(PIO_INSTRUCTIONS, value <= (0x1fu >> sideset_bit_count));
|
||||
return value << (13u - sideset_bit_count);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_sideset_opt(uint32_t sideset_bit_count,
|
||||
uint32_t value)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS,
|
||||
sideset_bit_count >= 2 && sideset_bit_count <= 5);
|
||||
valid_params_if(PIO_INSTRUCTIONS, value <= (0x1fu >> sideset_bit_count));
|
||||
return 0x1000u | value << (12u - sideset_bit_count);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_jmp(uint32_t addr)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
|
||||
}
|
||||
|
||||
inline static uint32_t _pio_encode_irq(bool relative, uint32_t irq)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
||||
return (relative ? 0x10u : 0x0u) | irq;
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_wait_gpio(bool polarity, uint32_t pin)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_wait,
|
||||
0u | (polarity ? 4u : 0u), pin);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_wait_pin(bool polarity, uint32_t pin)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_wait,
|
||||
1u | (polarity ? 4u : 0u), pin);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_wait_irq(bool polarity, bool relative,
|
||||
uint32_t irq)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_wait,
|
||||
2u | (polarity ? 4u : 0u),
|
||||
_pio_encode_irq(relative, irq));
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_in(enum pio_src_dest src, uint32_t value)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, value);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_out(enum pio_src_dest dest, uint32_t value)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, value);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_push(bool if_full, bool block)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_push,
|
||||
(if_full ? 2u : 0u) | (block ? 1u : 0u),
|
||||
0);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_pull(bool if_empty, bool block)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_pull,
|
||||
(if_empty ? 2u : 0u) | (block ? 1u : 0u),
|
||||
0);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_mov(enum pio_src_dest dest,
|
||||
enum pio_src_dest src)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest,
|
||||
src & 7u);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_mov_not(enum pio_src_dest dest,
|
||||
enum pio_src_dest src)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest,
|
||||
(1u << 3u) | (src & 7u));
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_mov_reverse(enum pio_src_dest dest,
|
||||
enum pio_src_dest src)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest,
|
||||
(2u << 3u) | (src & 7u));
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_irq_set(bool relative, uint32_t irq)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_irq, 0,
|
||||
_pio_encode_irq(relative, irq));
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_irq_clear(bool relative, uint32_t irq)
|
||||
{
|
||||
return _pio_encode_instr_and_args(pio_instr_bits_irq, 2,
|
||||
_pio_encode_irq(relative, irq));
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_set(enum pio_src_dest dest, uint32_t value)
|
||||
{
|
||||
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
|
||||
return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
|
||||
}
|
||||
|
||||
inline static uint32_t pio_encode_nop(void)
|
||||
{
|
||||
return pio_encode_mov(pio_y, pio_y);
|
||||
}
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_ARM_SRC_RP2040_RP2040_PIO_INSTRUNCTIONS_H */
|
Loading…
x
Reference in New Issue
Block a user