[feat] add timer and pio driver
This commit is contained in:
parent
b1cf958fd2
commit
60ce3bbf6d
@ -5,6 +5,8 @@ src/reset.c
|
||||
src/clock.c
|
||||
src/sio.c
|
||||
src/gpio.c
|
||||
src/pio.c
|
||||
src/timer.c
|
||||
)
|
||||
|
||||
set(TARGET driver)
|
||||
|
||||
132
driver/inc/pio.h
Normal file
132
driver/inc/pio.h
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef __HARDWARE_PIO_H__
|
||||
#define __HARDWARE_PIO_H__
|
||||
|
||||
#include "reg.h"
|
||||
#include "pio_reg.h"
|
||||
#include "pio_instr.h"
|
||||
|
||||
#define PIO0 (0)
|
||||
#define PIO1 (1)
|
||||
#define PIO_MAX (2)
|
||||
|
||||
#define PIO_SM0 (0)
|
||||
#define PIO_SM1 (1)
|
||||
#define PIO_SM2 (2)
|
||||
#define PIO_SM3 (3)
|
||||
#define PIO_SM_MAX (4)
|
||||
|
||||
#define PIO_FIFO_DEEPTH (4)
|
||||
#define PIO_SM_COUNT (4)
|
||||
#define PIO_IMEM_SIZE (32)
|
||||
|
||||
#define PIO_FIFO_JOIN_NONE (0)
|
||||
#define PIO_FIFO_RX_JOIN_TX (1)
|
||||
#define PIO_FIFO_TX_JOIN_RX (2)
|
||||
|
||||
#define PIO_FIFO_STATUS_SM0_RX_FULL (1 << 0U)
|
||||
#define PIO_FIFO_STATUS_SM1_RX_FULL (1 << 1U)
|
||||
#define PIO_FIFO_STATUS_SM2_RX_FULL (1 << 2U)
|
||||
#define PIO_FIFO_STATUS_SM3_RX_FULL (1 << 3U)
|
||||
#define PIO_FIFO_STATUS_SM0_RX_EMPTY (1 << 8U)
|
||||
#define PIO_FIFO_STATUS_SM1_RX_EMPTY (1 << 9U)
|
||||
#define PIO_FIFO_STATUS_SM2_RX_EMPTY (1 << 10U)
|
||||
#define PIO_FIFO_STATUS_SM3_RX_EMPTY (1 << 11U)
|
||||
#define PIO_FIFO_STATUS_SM0_TX_FULL (1 << 16U)
|
||||
#define PIO_FIFO_STATUS_SM1_TX_FULL (1 << 17U)
|
||||
#define PIO_FIFO_STATUS_SM2_TX_FULL (1 << 18U)
|
||||
#define PIO_FIFO_STATUS_SM3_TX_FULL (1 << 19U)
|
||||
#define PIO_FIFO_STATUS_SM0_TX_EMPTY (1 << 24U)
|
||||
#define PIO_FIFO_STATUS_SM1_TX_EMPTY (1 << 25U)
|
||||
#define PIO_FIFO_STATUS_SM2_TX_EMPTY (1 << 26U)
|
||||
#define PIO_FIFO_STATUS_SM3_TX_EMPTY (1 << 27U)
|
||||
|
||||
#define PIO_INT_SM0_RX_N_EMPTY (1 << 0)
|
||||
#define PIO_INT_SM1_RX_N_EMPTY (1 << 1)
|
||||
#define PIO_INT_SM2_RX_N_EMPTY (1 << 2)
|
||||
#define PIO_INT_SM3_RX_N_EMPTY (1 << 3)
|
||||
#define PIO_INT_SM0_TX_N_FULL (1 << 4)
|
||||
#define PIO_INT_SM1_TX_N_FULL (1 << 5)
|
||||
#define PIO_INT_SM2_TX_N_FULL (1 << 6)
|
||||
#define PIO_INT_SM3_TX_N_FULL (1 << 7)
|
||||
#define PIO_INT_FLAG_0 (1 << 8)
|
||||
#define PIO_INT_FLAG_1 (1 << 9)
|
||||
#define PIO_INT_FLAG_2 (1 << 10)
|
||||
#define PIO_INT_FLAG_3 (1 << 11)
|
||||
|
||||
#define PIO_DIR_TX (0)
|
||||
#define PIO_DIR_RX (1)
|
||||
|
||||
struct pio_cfg_s {
|
||||
uint32_t pio_base; /* pio register address base */
|
||||
uint16_t clkdiv_int; /* clock divisor of integer part, 1~65535 is available, 0 present 65536 divisor */
|
||||
uint8_t clkdiv_frac; /* clock divisor of fractional part, (div_frac/256) is actual value */
|
||||
uint8_t sm; /* state machine identification, 0~3 is available */
|
||||
uint8_t fifo_join; /* tx/ tx fifo join type */
|
||||
uint8_t wrap_bottom; /* ater reaching wrap_top, execution is wrapped to this address */
|
||||
uint8_t wrap_top; /* after reaching this address, execution is wrapped to wrap_bottom */
|
||||
uint8_t mov_status_sel_rx; /* comparison used for the 'MOV x, STATUS' instruction */
|
||||
uint8_t mov_status_level; /* comparison level for the 'MOV x, STATUS' instruction */
|
||||
uint8_t thresh_bits_pull; /* number of bits shifted out of TXSR before autopull or conditional pull, 1~31, 0 present 32 */
|
||||
uint8_t thresh_bits_push; /* number of bits shifted into RXSR before autopush or conditional push, 1~31, 0 present 32 */
|
||||
uint8_t out_dir_to_right; /* shift OSR direction */
|
||||
uint8_t in_dir_to_right; /* shift ISR direction */
|
||||
uint8_t auto_pull; /* pull automatically when the output shift register is emptied */
|
||||
uint8_t auto_push; /* push automatically when the input shift register is filled */
|
||||
uint8_t out_sticky; /* continuously assert the most recent OUT/SET to the pins */
|
||||
uint8_t inline_outen; /* whether use a bit of OUT data as an auxiliary write enable */
|
||||
uint8_t outen_sel; /* which data bit to use for inline OUT enable */
|
||||
uint8_t side_optional; /* allow instructions to perform sideset optionally, rather than on every instruction */
|
||||
uint8_t side_dest_pindir; /* side data is asserted to pin OEs or pin values */
|
||||
uint8_t pin_side_count; /* the number of delay bits co-opted for side-set, inclusive of the enable bit, if present */
|
||||
uint8_t pin_side_base; /* the virtual pin corresponding to SIDESET bit 0, not PEC_PIN_XXX, is absolute pin index */
|
||||
uint8_t pin_set_count; /* the number of pins asserted by a SET, max of 5 */
|
||||
uint8_t pin_set_base; /* the virtual pin corresponding to SET bit 0, not PEC_PIN_XXX, is absolute pin index */
|
||||
uint8_t pin_out_count; /* the number of pins asserted by an OUT, value of 1 to 31 pins, 0 present 32 */
|
||||
uint8_t pin_out_base; /* the virtual pin corresponding to OUT bit 0 , not PEC_PIN_XXX, is absolute pin index*/
|
||||
uint8_t pin_in_base; /* the virtual pin corresponding to IN bit 0, not PEC_PIN_XXX, is absolute pin index */
|
||||
uint8_t pin_jmp; /* the pin index to use as condition for 'JMP PIN' instruction */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void pio_init(struct pio_cfg_s *cfg);
|
||||
void pio_enable(uint32_t pio_base, uint8_t sm);
|
||||
void pio_disable(uint32_t pio_base, uint8_t sm);
|
||||
void pio_enable_multi(uint32_t pio_base, uint8_t sms);
|
||||
void pio_disable_multi(uint32_t pio_base, uint8_t sms);
|
||||
void pio_restart(uint32_t pio_base, uint8_t sm);
|
||||
void pio_restart_multi(uint32_t pio_base, uint8_t sms);
|
||||
void pio_clkdiv_restart(uint32_t pio_base, uint8_t sm);
|
||||
void pio_clkdiv_restart_multi(uint32_t pio_base, uint8_t sms);
|
||||
|
||||
uint32_t pio_fifo_get_status(uint32_t pio_base, uint8_t sm);
|
||||
uint8_t pio_fifo_get_tx_level(uint32_t pio_base, uint8_t sm);
|
||||
uint8_t pio_fifo_get_rx_level(uint32_t pio_base, uint8_t sm);
|
||||
void pio_fifo_write(uint32_t pio_base, uint8_t sm, uint32_t value);
|
||||
uint32_t pio_fifo_read(uint32_t pio_base, uint8_t sm);
|
||||
|
||||
void pio_flag_clear(uint32_t pio_base, uint8_t flag);
|
||||
void pio_flag_set(uint32_t pio_base, uint8_t flag);
|
||||
void pio_flag_clear_multi(uint32_t pio_base, uint8_t flags);
|
||||
void pio_flag_set_multi(uint32_t pio_base, uint8_t flags);
|
||||
|
||||
uint8_t pio_addr_get(uint32_t pio_base, uint8_t sm);
|
||||
uint16_t pio_instr_get(uint32_t pio_base, uint8_t sm);
|
||||
void pio_instr_insert(uint32_t pio_base, uint8_t sm, uint16_t instr);
|
||||
int pio_instr_is_complete(uint32_t pio_base, uint8_t sm);
|
||||
void pio_instr_place(uint32_t pio_base, uint8_t addr, uint16_t instr);
|
||||
|
||||
uint32_t pio_int_get_raw_status(uint32_t pio_base);
|
||||
uint32_t pio_int_get_status(uint32_t pio_base, uint8_t int_group);
|
||||
void pio_int_enable(uint32_t pio_base, uint8_t int_group, uint32_t int_type);
|
||||
void pio_int_disable(uint32_t pio_base, uint8_t int_group, uint32_t int_type);
|
||||
void pio_int_force(uint32_t pio_base, uint8_t int_group, uint32_t int_type);
|
||||
void pio_int_deforce(uint32_t pio_base, uint8_t int_group, uint32_t int_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HARDWARE_PIO_H__ */
|
||||
119
driver/inc/pio_instr.h
Normal file
119
driver/inc/pio_instr.h
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef __HARDWARE_PIO_INSTR_H__
|
||||
#define __HARDWARE_PIO_INSTR_H__
|
||||
|
||||
#define PIO_INSTR_OP_CODE_POS (13U)
|
||||
#define PIO_INSTR_JMP_COND_POS (5U)
|
||||
#define PIO_INSTR_WAIT_SRC_POS (5U)
|
||||
#define PIO_INSTR_WAIT_POL_POS (7U)
|
||||
#define PIO_INSTR_IN_SRC_POS (5U)
|
||||
#define PIO_INSTR_OUT_DEST_POS (5U)
|
||||
#define PIO_INSTR_PUSH_IFF_POS (6U)
|
||||
#define PIO_INSTR_PUSH_BLK_POS (5U)
|
||||
#define PIO_INSTR_PULL_IFE_POS (6U)
|
||||
#define PIO_INSTR_PULL_BLK_POS (5U)
|
||||
#define PIO_INSTR_MOV_SRC_POS (0U)
|
||||
#define PIO_INSTR_MOV_DEST_POS (5U)
|
||||
#define PIO_INSTR_MOV_OP_POS (3U)
|
||||
#define PIO_INSTR_IRQ_OP_POS (6U)
|
||||
#define PIO_INSTR_IRQ_WAIT_POS (5U)
|
||||
#define PIO_INSTR_SET_DEST_POS (5U)
|
||||
#define PIO_INSTR_SIDE_POS (8U)
|
||||
|
||||
#define PIO_INSTR_OP_CODE_JMP (0 << PIO_INSTR_OP_CODE_POS) /* Set program counter to Address if Condition is true, otherwise no operation */
|
||||
#define PIO_INSTR_OP_CODE_WAIT (1 << PIO_INSTR_OP_CODE_POS) /* Stall until some condition is met */
|
||||
#define PIO_INSTR_OP_CODE_IN (2 << PIO_INSTR_OP_CODE_POS) /* Shift Bit count bits from Source into the Input Shift Register (ISR) */
|
||||
#define PIO_INSTR_OP_CODE_OUT (3 << PIO_INSTR_OP_CODE_POS) /* Shift Bit count bits out of the Output Shift Register (OSR), and write those bits to Destination */
|
||||
#define PIO_INSTR_OP_CODE_PUSH ((4 << PIO_INSTR_OP_CODE_POS) | (0 << 7U)) /* Push the contents of the ISR into the RX FIFO, as a single 32-bit word. Clear ISR to all-zeroes */
|
||||
#define PIO_INSTR_OP_CODE_PULL ((4 << PIO_INSTR_OP_CODE_POS) | (1 << 7U)) /* Load a 32-bit word from the TX FIFO into the OSR */
|
||||
#define PIO_INSTR_OP_CODE_MOV (5 << PIO_INSTR_OP_CODE_POS) /* Copy data from Source to Destination */
|
||||
#define PIO_INSTR_OP_CODE_IRQ (6 << PIO_INSTR_OP_CODE_POS) /* Set or clear the IRQ flag selected by Index argument */
|
||||
#define PIO_INSTR_OP_CODE_SET (7 << PIO_INSTR_OP_CODE_POS) /* Write immediate value Data to Destination */
|
||||
|
||||
#define PIO_INSTR_JMP_COND_ALWAYS (0 << PIO_INSTR_JMP_COND_POS) /* Always, no condition */
|
||||
#define PIO_INSTR_JMP_COND_X_ZERO (1 << PIO_INSTR_JMP_COND_POS) /* scratch X zero */
|
||||
#define PIO_INSTR_JMP_COND_X_WITH_DEC (2 << PIO_INSTR_JMP_COND_POS) /* scratch X non-zero, post-decrement */
|
||||
#define PIO_INSTR_JMP_COND_Y_ZERO (3 << PIO_INSTR_JMP_COND_POS) /* scratch Y zero */
|
||||
#define PIO_INSTR_JMP_COND_Y_WITH_DEC (4 << PIO_INSTR_JMP_COND_POS) /* scratch Y non-zero, post-decrement */
|
||||
#define PIO_INSTR_JMP_COND_X_NEQ_Y (5 << PIO_INSTR_JMP_COND_POS) /* scratch X not equal scratch Y */
|
||||
#define PIO_INSTR_JMP_COND_PIN (6 << PIO_INSTR_JMP_COND_POS) /* branch on input pin */
|
||||
#define PIO_INSTR_JMP_COND_OSR_NEMPTY (7 << PIO_INSTR_JMP_COND_POS) /* output shift register not empty */
|
||||
|
||||
#define PIO_INSTR_WAIT_SRC_GPIO (0 << PIO_INSTR_WAIT_SRC_POS) /* GPIO: System GPIO input selected by Index */
|
||||
#define PIO_INSTR_WAIT_SRC_PIN (1 << PIO_INSTR_WAIT_SRC_POS) /* PIN: Input pin selected by Index */
|
||||
#define PIO_INSTR_WAIT_SRC_IRQ (2 << PIO_INSTR_WAIT_SRC_POS) /* IRQ: PIO IRQ flag selected by Index */
|
||||
|
||||
#define PIO_INSTR_WAIT_POL_0 (0 << PIO_INSTR_WAIT_POL_POS) /* wait for a 0 */
|
||||
#define PIO_INSTR_WAIT_POL_1 (1 << PIO_INSTR_WAIT_POL_POS) /* wait for a 1 */
|
||||
|
||||
#define PIO_INSTR_IN_SRC_PINS (0 << PIO_INSTR_IN_SRC_POS) /* */
|
||||
#define PIO_INSTR_IN_SRC_X (1 << PIO_INSTR_IN_SRC_POS) /* scratch register X */
|
||||
#define PIO_INSTR_IN_SRC_Y (2 << PIO_INSTR_IN_SRC_POS) /* scratch register Y */
|
||||
#define PIO_INSTR_IN_SRC_NULL (3 << PIO_INSTR_IN_SRC_POS) /* all zeroes */
|
||||
#define PIO_INSTR_IN_SRC_ISR (6 << PIO_INSTR_IN_SRC_POS) /* */
|
||||
#define PIO_INSTR_IN_SRC_OSR (7 << PIO_INSTR_IN_SRC_POS) /* */
|
||||
|
||||
#define PIO_INSTR_OUT_DEST_PINS (0 << PIO_INSTR_OUT_DEST_POS) /* */
|
||||
#define PIO_INSTR_OUT_DEST_X (1 << PIO_INSTR_OUT_DEST_POS) /* scratch register X */
|
||||
#define PIO_INSTR_OUT_DEST_Y (2 << PIO_INSTR_OUT_DEST_POS) /* scratch register Y */
|
||||
#define PIO_INSTR_OUT_DEST_NULL (3 << PIO_INSTR_OUT_DEST_POS) /* discard data */
|
||||
#define PIO_INSTR_OUT_DEST_PINDIRS (4 << PIO_INSTR_OUT_DEST_POS) /* */
|
||||
#define PIO_INSTR_OUT_DEST_PC (5 << PIO_INSTR_OUT_DEST_POS) /* */
|
||||
#define PIO_INSTR_OUT_DEST_ISR (6 << PIO_INSTR_OUT_DEST_POS) /* also sets ISR shift counter to Bit count */
|
||||
#define PIO_INSTR_OUT_DEST_EXEC (7 << PIO_INSTR_OUT_DEST_POS) /* Execute OSR shift data as instruction */
|
||||
|
||||
#define PIO_INSTR_PUSH_IFF_DISABLE (0 << PIO_INSTR_PUSH_IFF_POS) /* */
|
||||
#define PIO_INSTR_PUSH_IFF_ENABLE (1 << PIO_INSTR_PUSH_IFF_POS) /* do nothing unless the total input shift count has reached its threshold */
|
||||
|
||||
#define PIO_INSTR_PUSH_BLK_DISABLE (0 << PIO_INSTR_PUSH_BLK_POS) /* */
|
||||
#define PIO_INSTR_PUSH_BLK_ENABLE (1 << PIO_INSTR_PUSH_BLK_POS) /* stall execution if RX FIFO is full */
|
||||
|
||||
#define PIO_INSTR_PULL_IFE_DISABLE (0 << PIO_INSTR_PULL_IFE_POS) /* */
|
||||
#define PIO_INSTR_PULL_IFE_ENABLE (1 << PIO_INSTR_PULL_IFE_POS) /* do nothing unless the total output shift count has reached its threshold */
|
||||
|
||||
#define PIO_INSTR_PULL_BLK_DISABLE (0 << PIO_INSTR_PULL_BLK_POS) /* pulling from an empty FIFO copies scratch X to OSR */
|
||||
#define PIO_INSTR_PULL_BLK_ENABLE (1 << PIO_INSTR_PULL_BLK_POS) /* stall if TX FIFO is empty */
|
||||
|
||||
#define PIO_INSTR_MOV_SRC_PINS (0 << PIO_INSTR_MOV_SRC_POS) /* Uses same pin mapping as IN */
|
||||
#define PIO_INSTR_MOV_SRC_X (1 << PIO_INSTR_MOV_SRC_POS) /* Scratch register X */
|
||||
#define PIO_INSTR_MOV_SRC_Y (2 << PIO_INSTR_MOV_SRC_POS) /* Scratch register Y */
|
||||
#define PIO_INSTR_MOV_SRC_NULL (3 << PIO_INSTR_MOV_SRC_POS) /* */
|
||||
#define PIO_INSTR_MOV_SRC_STATUS (5 << PIO_INSTR_MOV_SRC_POS) /* */
|
||||
#define PIO_INSTR_MOV_SRC_ISR (6 << PIO_INSTR_MOV_SRC_POS) /* */
|
||||
#define PIO_INSTR_MOV_SRC_OSR (7 << PIO_INSTR_MOV_SRC_POS) /* */
|
||||
|
||||
#define PIO_INSTR_MOV_DEST_PINS (0 << PIO_INSTR_MOV_DEST_POS) /* Uses same pin mapping as OUT */
|
||||
#define PIO_INSTR_MOV_DEST_X (1 << PIO_INSTR_MOV_DEST_POS) /* Scratch register X */
|
||||
#define PIO_INSTR_MOV_DEST_Y (2 << PIO_INSTR_MOV_DEST_POS) /* Scratch register Y */
|
||||
#define PIO_INSTR_MOV_DEST_EXEC (4 << PIO_INSTR_MOV_DEST_POS) /* Execute data as instruction */
|
||||
#define PIO_INSTR_MOV_DEST_PC (5 << PIO_INSTR_MOV_DEST_POS) /* */
|
||||
#define PIO_INSTR_MOV_DEST_ISR (6 << PIO_INSTR_MOV_DEST_POS) /* Input shift counter is reset to 0 by this operation, i.e. empty */
|
||||
#define PIO_INSTR_MOV_DEST_OSR (7 << PIO_INSTR_MOV_DEST_POS) /* Output shift counter is reset to 0 by this operation, i.e. full */
|
||||
|
||||
#define PIO_INSTR_MOV_OP_NONE (0 << PIO_INSTR_MOV_OP_POS) /* */
|
||||
#define PIO_INSTR_MOV_OP_INVERT (1 << PIO_INSTR_MOV_OP_POS) /* bitwise complement */
|
||||
#define PIO_INSTR_MOV_OP_BIT_REVERSE (2 << PIO_INSTR_MOV_OP_POS) /* */
|
||||
|
||||
#define PIO_INSTR_IRQ_OP_RAISE (0 << PIO_INSTR_IRQ_OP_POS) /* raise the flag selected by Index */
|
||||
#define PIO_INSTR_IRQ_OP_CLR (1 << PIO_INSTR_IRQ_OP_POS) /* clear the flag selected by Index */
|
||||
|
||||
#define PIO_INSTR_IRQ_WAIT_DISABLE (0 << PIO_INSTR_IRQ_WAIT_POS) /* */
|
||||
#define PIO_INSTR_IRQ_WAIT_ENABLE (1 << PIO_INSTR_IRQ_WAIT_POS) /* halt until the raised flag is lowered again */
|
||||
|
||||
#define PIO_INSTR_SET_DEST_PINS (0 << PIO_INSTR_SET_DEST_POS) /* */
|
||||
#define PIO_INSTR_SET_DEST_X (1 << PIO_INSTR_SET_DEST_POS) /* X (scratch register X) 5 LSBs are set to Data, all others cleared to 0 */
|
||||
#define PIO_INSTR_SET_DEST_Y (2 << PIO_INSTR_SET_DEST_POS) /* Y (scratch register Y) 5 LSBs are set to Data, all others cleared to 0 */
|
||||
#define PIO_INSTR_SET_DEST_PINDIRS (4 << PIO_INSTR_SET_DEST_POS) /* */
|
||||
|
||||
#define pio_instr_side(side, delay, side_width) ((side << (PIO_INSTR_SIDE_POS + 5 - side_width)) | ((delay) << PIO_INSTR_SIDE_POS))
|
||||
|
||||
#define pio_instr_JMP(cond, addr, side) ((PIO_INSTR_OP_CODE_JMP) | (cond) | (addr) | (side))
|
||||
#define pio_instr_WAIT(src, pol, index, side) ((PIO_INSTR_OP_CODE_WAIT) | (src) | (pol) | (index) | (side))
|
||||
#define pio_instr_IN(src, bit_count, side) ((PIO_INSTR_OP_CODE_IN) | (src) | ((bit_count) & 0x1F) | (side))
|
||||
#define pio_instr_OUT(dest, bit_count, side) ((PIO_INSTR_OP_CODE_OUT) | (dest) | ((bit_count) & 0x1F) | (side))
|
||||
#define pio_instr_PUSH(iff, blk, side) ((PIO_INSTR_OP_CODE_PUSH) | (iff) | (blk) | (side))
|
||||
#define pio_instr_PULL(ife, blk, side) ((PIO_INSTR_OP_CODE_PULL) | (ife) | (blk) | (side))
|
||||
#define pio_instr_MOV(dest, src, op, side) ((PIO_INSTR_OP_CODE_MOV) | (dest) | (src) | (op) | (side))
|
||||
#define pio_instr_IRQ(op, wait, index, side) ((PIO_INSTR_OP_CODE_IRQ) | (op) | (wait) | (index) | (side))
|
||||
#define pio_instr_SET(dest, data, side) ((PIO_INSTR_OP_CODE_SET) | (dest) | (data) | (side))
|
||||
|
||||
#endif /* __HARDWARE_PIO_INSTR_H__ */
|
||||
183
driver/inc/reg/pio_reg.h
Normal file
183
driver/inc/reg/pio_reg.h
Normal file
@ -0,0 +1,183 @@
|
||||
#ifndef __HARDWARE_PIO_REG_H__
|
||||
#define __HARDWARE_PIO_REG_H__
|
||||
|
||||
#define PIO_CTRL_OFFSET (0x000) /* PIO control register */
|
||||
#define PIO_FSTAT_OFFSET (0x004) /* FIFO status register */
|
||||
#define PIO_FDEBUG_OFFSET (0x008) /* FIFO debug register */
|
||||
#define PIO_FLEVEL_OFFSET (0x00C) /* FIFO levels */
|
||||
#define PIO_TXF0_OFFSET (0x010) /* Direct write access to the TX FIFO for state machine 0 */
|
||||
#define PIO_TXF1_OFFSET (0x014) /* Direct write access to the TX FIFO for state machine 1 */
|
||||
#define PIO_TXF2_OFFSET (0x018) /* Direct write access to the TX FIFO for state machine 2 */
|
||||
#define PIO_TXF3_OFFSET (0x01C) /* Direct write access to the TX FIFO for state machine 3 */
|
||||
#define PIO_RXF0_OFFSET (0x020) /* Direct read access to the RX FIFO for state machine 0 */
|
||||
#define PIO_RXF1_OFFSET (0x024) /* Direct read access to the RX FIFO for state machine 1 */
|
||||
#define PIO_RXF2_OFFSET (0x028) /* Direct read access to the RX FIFO for state machine 2 */
|
||||
#define PIO_RXF3_OFFSET (0x02C) /* Direct read access to the RX FIFO for state machine 3 */
|
||||
#define PIO_IRQ_OFFSET (0x030) /* State machine IRQ flags register */
|
||||
#define PIO_IRQ_FORCE_OFFSET (0x034) /* Writing a 1 to each of these bits will forcibly assert the corresponding IRQ */
|
||||
#define PIO_INPUT_SYNC_BYPASS_OFFSET (0x038) /* There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities */
|
||||
#define PIO_DBG_PADOUT_OFFSET (0x03C) /* Read to sample the pad output values PIO is currently driving to the GPIOs */
|
||||
#define PIO_DBG_PADOE_OFFSET (0x040) /* Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs */
|
||||
#define PIO_DBG_CFGINFO_OFFSET (0x044) /* The PIO hardware has some free parameters that may vary between chip products */
|
||||
|
||||
#define PIO_INSTR_MEM0_OFFSET (0x048) /* Write-only access to instruction memory location 0 */
|
||||
#define PIO_INSTR_MEM1_OFFSET (0x04C) /* Write-only access to instruction memory location 1 */
|
||||
#define PIO_INSTR_MEM2_OFFSET (0x050) /* Write-only access to instruction memory location 2 */
|
||||
#define PIO_INSTR_MEM3_OFFSET (0x054) /* Write-only access to instruction memory location 3 */
|
||||
#define PIO_INSTR_MEM4_OFFSET (0x058) /* Write-only access to instruction memory location 4 */
|
||||
#define PIO_INSTR_MEM5_OFFSET (0x05C) /* Write-only access to instruction memory location 5 */
|
||||
#define PIO_INSTR_MEM6_OFFSET (0x060) /* Write-only access to instruction memory location 6 */
|
||||
#define PIO_INSTR_MEM7_OFFSET (0x064) /* Write-only access to instruction memory location 7 */
|
||||
#define PIO_INSTR_MEM8_OFFSET (0x068) /* Write-only access to instruction memory location 8 */
|
||||
#define PIO_INSTR_MEM9_OFFSET (0x06C) /* Write-only access to instruction memory location 9 */
|
||||
#define PIO_INSTR_MEM10_OFFSET (0x070) /* Write-only access to instruction memory location 10 */
|
||||
#define PIO_INSTR_MEM11_OFFSET (0x074) /* Write-only access to instruction memory location 11 */
|
||||
#define PIO_INSTR_MEM12_OFFSET (0x078) /* Write-only access to instruction memory location 12 */
|
||||
#define PIO_INSTR_MEM13_OFFSET (0x07C) /* Write-only access to instruction memory location 13 */
|
||||
#define PIO_INSTR_MEM14_OFFSET (0x080) /* Write-only access to instruction memory location 14 */
|
||||
#define PIO_INSTR_MEM15_OFFSET (0x084) /* Write-only access to instruction memory location 15 */
|
||||
#define PIO_INSTR_MEM16_OFFSET (0x088) /* Write-only access to instruction memory location 16 */
|
||||
#define PIO_INSTR_MEM17_OFFSET (0x08C) /* Write-only access to instruction memory location 17 */
|
||||
#define PIO_INSTR_MEM18_OFFSET (0x090) /* Write-only access to instruction memory location 18 */
|
||||
#define PIO_INSTR_MEM19_OFFSET (0x094) /* Write-only access to instruction memory location 19 */
|
||||
#define PIO_INSTR_MEM20_OFFSET (0x098) /* Write-only access to instruction memory location 20 */
|
||||
#define PIO_INSTR_MEM21_OFFSET (0x09C) /* Write-only access to instruction memory location 21 */
|
||||
#define PIO_INSTR_MEM22_OFFSET (0x0A0) /* Write-only access to instruction memory location 22 */
|
||||
#define PIO_INSTR_MEM23_OFFSET (0x0A4) /* Write-only access to instruction memory location 23 */
|
||||
#define PIO_INSTR_MEM24_OFFSET (0x0A8) /* Write-only access to instruction memory location 24 */
|
||||
#define PIO_INSTR_MEM25_OFFSET (0x0AC) /* Write-only access to instruction memory location 25 */
|
||||
#define PIO_INSTR_MEM26_OFFSET (0x0B0) /* Write-only access to instruction memory location 26 */
|
||||
#define PIO_INSTR_MEM27_OFFSET (0x0B4) /* Write-only access to instruction memory location 27 */
|
||||
#define PIO_INSTR_MEM28_OFFSET (0x0B8) /* Write-only access to instruction memory location 28 */
|
||||
#define PIO_INSTR_MEM29_OFFSET (0x0BC) /* Write-only access to instruction memory location 29 */
|
||||
#define PIO_INSTR_MEM30_OFFSET (0x0C0) /* Write-only access to instruction memory location 30 */
|
||||
#define PIO_INSTR_MEM31_OFFSET (0x0C4) /* Write-only access to instruction memory location 31 */
|
||||
|
||||
#define PIO_SM0_CLKDIV_OFFSET (0x0C8) /* Clock divisor register for state machine 0 */
|
||||
#define PIO_SM0_EXECCTRL_OFFSET (0x0CC) /* Execution/behavioural settings for state machine 0 */
|
||||
#define PIO_SM0_SHIFTCTRL_OFFSET (0x0D0) /* Control behaviour of the input/output shift registers for state machine 0 */
|
||||
#define PIO_SM0_ADDR_OFFSET (0x0D4) /* Current instruction address of state machine 0 */
|
||||
#define PIO_SM0_INSTR_OFFSET (0x0D8) /* Instruction currently addressed by state machine or execute an instruction immediately */
|
||||
#define PIO_SM0_PINCTRL_OFFSET (0x0DC) /* State machine pin control */
|
||||
#define PIO_SM1_CLKDIV_OFFSET (0x0E0) /* Clock divisor register for state machine 1 */
|
||||
#define PIO_SM1_EXECCTRL_OFFSET (0x0E4) /* Execution/behavioural settings for state machine 1 */
|
||||
#define PIO_SM1_SHIFTCTRL_OFFSET (0x0E8) /* Control behaviour of the input/output shift registers for state machine 1 */
|
||||
#define PIO_SM1_ADDR_OFFSET (0x0EC) /* Current instruction address of state machine 1 */
|
||||
#define PIO_SM1_INSTR_OFFSET (0x0F0) /* Instruction currently addressed by state machine or execute an instruction immediately */
|
||||
#define PIO_SM1_PINCTRL_OFFSET (0x0F4) /* State machine pin control */
|
||||
#define PIO_SM2_CLKDIV_OFFSET (0x0F8) /* Clock divisor register for state machine 2 */
|
||||
#define PIO_SM2_EXECCTRL_OFFSET (0x0FC) /* Execution/behavioural settings for state machine 2 */
|
||||
#define PIO_SM2_SHIFTCTRL_OFFSET (0x100) /* Control behaviour of the input/output shift registers for state machine 2 */
|
||||
#define PIO_SM2_ADDR_OFFSET (0x104) /* Current instruction address of state machine 2 */
|
||||
#define PIO_SM2_INSTR_OFFSET (0x108) /* Instruction currently addressed by state machine or execute an instruction immediately */
|
||||
#define PIO_SM2_PINCTRL_OFFSET (0x10C) /* State machine pin control */
|
||||
#define PIO_SM3_CLKDIV_OFFSET (0x110) /* Clock divisor register for state machine 3 */
|
||||
#define PIO_SM3_EXECCTRL_OFFSET (0x114) /* Execution/behavioural settings for state machine 3 */
|
||||
#define PIO_SM3_SHIFTCTRL_OFFSET (0x118) /* Control behaviour of the input/output shift registers for state machine 3 */
|
||||
#define PIO_SM3_ADDR_OFFSET (0x11C) /* Current instruction address of state machine 3 */
|
||||
#define PIO_SM3_INSTR_OFFSET (0x120) /* Instruction currently addressed by state machine or execute an instruction immediately */
|
||||
#define PIO_SM3_PINCTRL_OFFSET (0x124) /* State machine pin control */
|
||||
|
||||
#define PIO_INTR_OFFSET (0x128) /* Raw Interrupts */
|
||||
#define PIO_IRQ0_INTE_OFFSET (0x12C) /* Interrupt Enable for irq0 */
|
||||
#define PIO_IRQ0_INTF_OFFSET (0x130) /* Interrupt Force for irq0 */
|
||||
#define PIO_IRQ0_INTS_OFFSET (0x134) /* Interrupt status after masking & forcing for irq0 */
|
||||
#define PIO_IRQ1_INTE_OFFSET (0x138) /* Interrupt Enable for irq1 */
|
||||
#define PIO_IRQ1_INTF_OFFSET (0x13C) /* Interrupt Force for irq1 */
|
||||
#define PIO_IRQ1_INTS_OFFSET (0x140) /* Interrupt status after masking & forcing for irq1 */
|
||||
|
||||
/* PIO_CTRL_OFFSET @0x000*/
|
||||
#define PIO_SM_ENABLE_POS (0U)
|
||||
#define PIO_SM_ENABLE_MASK (0xF << PIO_SM_ENABLE_POS)
|
||||
#define PIO_SM_RESTART_POS (4U)
|
||||
#define PIO_SM_RESTART_MASK (0xF << PIO_SM_RESTART_POS)
|
||||
#define PIO_CLKDIV_RESTART_POS (8U)
|
||||
#define PIO_CLKDIV_RESTART_MASK (0xF << PIO_CLKDIV_RESTART_POS)
|
||||
|
||||
/* PIO_FLEVEL_OFFSET @0x00C*/
|
||||
#define PIO_FLEVEL_TX0_POS (0U)
|
||||
#define PIO_FLEVEL_TX0_MASK (0xF << PIO_FLEVEL_TX0_POS)
|
||||
#define PIO_FLEVEL_RX0_POS (4U)
|
||||
#define PIO_FLEVEL_RX0_MASK (0xF << PIO_FLEVEL_RX0_POS)
|
||||
#define PIO_FLEVEL_TX1_POS (8U)
|
||||
#define PIO_FLEVEL_TX1_MASK (0xF << PIO_FLEVEL_TX1_POS)
|
||||
#define PIO_FLEVEL_RX1_POS (12U)
|
||||
#define PIO_FLEVEL_RX1_MASK (0xF << PIO_FLEVEL_RX1_POS)
|
||||
#define PIO_FLEVEL_TX2_POS (16U)
|
||||
#define PIO_FLEVEL_TX2_MASK (0xF << PIO_FLEVEL_TX2_POS)
|
||||
#define PIO_FLEVEL_RX2_POS (20U)
|
||||
#define PIO_FLEVEL_RX2_MASK (0xF << PIO_FLEVEL_RX2_POS)
|
||||
#define PIO_FLEVEL_TX3_POS (24U)
|
||||
#define PIO_FLEVEL_TX3_MASK (0xF << PIO_FLEVEL_TX3_POS)
|
||||
#define PIO_FLEVEL_RX3_POS (28U)
|
||||
#define PIO_FLEVEL_RX3_MASK (0xF << PIO_FLEVEL_RX3_POS)
|
||||
|
||||
/* PIO_SM0/1/2/3_CLKDIV_OFFSET @0x0C8/0x0E0/0x0F8/0x110 */
|
||||
#define PIO_CLKDIV_FRAC_POS (8U)
|
||||
#define PIO_CLKDIV_FRAC_MASK (0xFF << PIO_CLKDIV_FRAC_POS)
|
||||
#define PIO_CLKDIV_INT_POS (16U)
|
||||
#define PIO_CLKDIV_INT_MASK (0xFFFF << PIO_CLKDIV_INT_POS)
|
||||
|
||||
/* PIO_SM0/1/2/3_EXECCTRL_OFFSET @0x0CC/0x0E4/0x0FC/0x114 */
|
||||
#define PIO_STATUS_N_POS (0U)
|
||||
#define PIO_STATUS_N_MASK (0xF << PIO_STATUS_N_POS)
|
||||
#define PIO_STATUS_SEL (1 << 4U)
|
||||
#define PIO_WRAP_BOTTOM_POS (7U)
|
||||
#define PIO_WRAP_BOTTOM_MASK (0x1F << PIO_WRAP_BOTTOM_POS)
|
||||
#define PIO_WRAP_TOP_POS (12U)
|
||||
#define PIO_WRAP_TOP_MASK (0x1F << PIO_WRAP_TOP_POS)
|
||||
#define PIO_OUT_STICKY (1 << 17U)
|
||||
#define PIO_INLINE_OUT_EN (1 << 18U)
|
||||
#define PIO_OUT_EN_SEL_POS (19U)
|
||||
#define PIO_OUT_EN_SEL_MASK (0x1F << PIO_OUT_EN_SEL_POS)
|
||||
#define PIO_JMP_PIN_POS (24U)
|
||||
#define PIO_JMP_PIN_MASK (0x1F << PIO_JMP_PIN_POS)
|
||||
#define PIO_SIDE_PINDIR (1 << 29U)
|
||||
#define PIO_SIDE_EN (1 << 30U)
|
||||
#define PIO_EXEC_STALLED (1 << 31U)
|
||||
|
||||
/* PIO_SM0/1/2/3_SHIFTCTRL_OFFSET @0x0D0/0x0E8/0x100/0x118 */
|
||||
#define PIO_AUTOPUSH (1 << 16U)
|
||||
#define PIO_AUTOPULL (1 << 17U)
|
||||
#define PIO_IN_SHIFTDIR (1 << 18U)
|
||||
#define PIO_OUT_SHIFTDIR (1 << 19U)
|
||||
#define PIO_PUSH_THRESH_POS (20U)
|
||||
#define PIO_PUSH_THRESH_MASK (0x1F << PIO_PUSH_THRESH_POS)
|
||||
#define PIO_PULL_THRESH_POS (25U)
|
||||
#define PIO_PULL_THRESH_MASK (0x1F << PIO_PULL_THRESH_POS)
|
||||
#define PIO_FJOIN_TX (1 << 30U)
|
||||
#define PIO_FJOIN_RX (1 << 31U)
|
||||
|
||||
/* PIO_SM0/1/2/3_ADDR_OFFSET @0x0D4/0x0EC/0x104/0x11C */
|
||||
#define PIO_ADDR_POS (0U)
|
||||
#define PIO_ADDR_MASK (0x1F << PIO_ADDR_POS)
|
||||
|
||||
/* PIO_SM0/1/2/3_INSTR_OFFSET @0x0D8/0x0F0/0x108/0x120 */
|
||||
#define PIO_INSTR_POS (0U)
|
||||
#define PIO_INSTR_MASK (0xFFFF << PIO_INSTR_POS)
|
||||
|
||||
/* PIO_SM0/1/2/3_PINCTRL_OFFSET @0x0DC/0x0F4/0x10C/0x124 */
|
||||
#define PIO_OUT_BASE_POS (0U)
|
||||
#define PIO_OUT_BASE_MASK (0x1F << PIO_OUT_BASE_POS)
|
||||
#define PIO_SET_BASE_POS (5U)
|
||||
#define PIO_SET_BASE_MASK (0x1F << PIO_SET_BASE_POS)
|
||||
#define PIO_SIDESET_BASE_POS (10U)
|
||||
#define PIO_SIDESET_BASE_MASK (0x1F << PIO_SIDESET_BASE_POS)
|
||||
#define PIO_IN_BASE_POS (15U)
|
||||
#define PIO_IN_BASE_MASK (0x1F << PIO_IN_BASE_POS)
|
||||
#define PIO_OUT_COUNT_POS (20U)
|
||||
#define PIO_OUT_COUNT_MASK (0x3F << PIO_OUT_COUNT_POS)
|
||||
#define PIO_SET_COUNT_POS (26U)
|
||||
#define PIO_SET_COUNT_MASK (0x7 << PIO_SET_COUNT_POS)
|
||||
#define PIO_SIDESET_COUNT_POS (29U)
|
||||
#define PIO_SIDESET_COUNT_MASK (0x7 << PIO_SIDESET_COUNT_POS)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HARDWARE_PIO_REG_H__ */
|
||||
@ -6,6 +6,9 @@
|
||||
#define DISABLE (0)
|
||||
#define ENABLE (1)
|
||||
|
||||
#define FALSE (0)
|
||||
#define TRUE (1)
|
||||
|
||||
#define getreg8(a) (*(volatile uint8_t *)(uintptr_t)(a))
|
||||
#define putreg8(v, a) (*(volatile uint8_t *)(uintptr_t)(a) = (v))
|
||||
#define getreg16(a) (*(volatile uint16_t *)(uintptr_t)(a))
|
||||
|
||||
33
driver/inc/reg/timer_reg.h
Normal file
33
driver/inc/reg/timer_reg.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef __HARDWARE_TIMER_REG_H__
|
||||
#define __HARDWARE_TIMER_REG_H__
|
||||
|
||||
#define TIMER_TIMEHW_OFFSET (0x000)
|
||||
#define TIMER_TIMELW_OFFSET (0x004)
|
||||
#define TIMER_TIMEHR_OFFSET (0x008)
|
||||
#define TIMER_TIMELR_OFFSET (0x00C)
|
||||
#define TIMER_ALARM0_OFFSET (0x010)
|
||||
#define TIMER_ALARM1_OFFSET (0x014)
|
||||
#define TIMER_ALARM2_OFFSET (0x018)
|
||||
#define TIMER_ALARM3_OFFSET (0x01C)
|
||||
#define TIMER_ARMED_OFFSET (0x020)
|
||||
#define TIMER_TIMERAWH_OFFSET (0x024)
|
||||
#define TIMER_TIMERAWL_OFFSET (0x028)
|
||||
#define TIMER_DBGPAUSE_OFFSET (0x02C)
|
||||
#define TIMER_PAUSE_OFFSET (0x030)
|
||||
#define TIMER_INTR_OFFSET (0x034)
|
||||
#define TIMER_INTE_OFFSET (0x038)
|
||||
#define TIMER_INTF_OFFSET (0x03C)
|
||||
#define TIMER_INTS_OFFSET (0x040)
|
||||
|
||||
/* TIMER_PAUSE_OFFSET @0x030 */
|
||||
#define TIMER_PAUSE (1 << 0U)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HARDWARE_TIMER_REG_H__ */
|
||||
36
driver/inc/timer.h
Normal file
36
driver/inc/timer.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef __HARDWARE_TIMER_H__
|
||||
#define __HARDWARE_TIMER_H__
|
||||
|
||||
#include "reg.h"
|
||||
#include "timer_reg.h"
|
||||
|
||||
#define TIMER_ALARM_0 (0)
|
||||
#define TIMER_ALARM_1 (1)
|
||||
#define TIMER_ALARM_2 (2)
|
||||
#define TIMER_ALARM_3 (3)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void timer_count_write(uint64_t count);
|
||||
uint64_t timer_count_read(void);
|
||||
uint32_t timer_count_l_read_raw(void);
|
||||
uint32_t timer_count_h_read_raw(void);
|
||||
void timer_start(void);
|
||||
void timer_stop(void);
|
||||
int timer_is_stopped(void);
|
||||
|
||||
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count);
|
||||
uint32_t timer_alarm_get(uint8_t alarm_id);
|
||||
|
||||
void timer_alarm_disarm(uint8_t alarm_id);
|
||||
void timer_alarm_disarm_multi(uint32_t alarm_id_multi);
|
||||
int timer_alarm_is_armed(uint8_t alarm_id);
|
||||
uint32_t timer_alarm_is_armed_multi(uint32_t alarm_id_multi);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HARDWARE_TIMER_H__ */
|
||||
350
driver/src/pio.c
Normal file
350
driver/src/pio.c
Normal file
@ -0,0 +1,350 @@
|
||||
#include "pio.h"
|
||||
|
||||
void pio_init(struct pio_cfg_s *cfg)
|
||||
{
|
||||
uint32_t val;
|
||||
uint8_t sm = cfg->sm;
|
||||
|
||||
/* step1: config clock division */
|
||||
val = getreg32(cfg->pio_base + PIO_SM0_CLKDIV_OFFSET + (PIO_SM1_CLKDIV_OFFSET - PIO_SM0_CLKDIV_OFFSET) * sm);
|
||||
val &= ~PIO_CLKDIV_FRAC_MASK;
|
||||
val |= (cfg->clkdiv_frac << PIO_CLKDIV_FRAC_POS);
|
||||
val &= ~PIO_CLKDIV_INT_MASK;
|
||||
val |= (cfg->clkdiv_int << PIO_CLKDIV_INT_POS);
|
||||
putreg32(val, cfg->pio_base + PIO_SM0_CLKDIV_OFFSET + (PIO_SM1_CLKDIV_OFFSET - PIO_SM0_CLKDIV_OFFSET) * sm);
|
||||
|
||||
/* step2: disable state machine and restart */
|
||||
val = getreg32(cfg->pio_base + PIO_CTRL_OFFSET);
|
||||
val &= ~(1 << (PIO_SM_ENABLE_POS + sm));
|
||||
val |= (1 << (PIO_SM_RESTART_POS + sm));
|
||||
val |= (1 << (PIO_CLKDIV_RESTART_POS + sm));
|
||||
putreg32(val, cfg->pio_base + PIO_CTRL_OFFSET);
|
||||
|
||||
/* step 3: config execution settings for state machine */
|
||||
val = getreg32(cfg->pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm);
|
||||
val &= ~PIO_STATUS_N_MASK;
|
||||
val |= (cfg->mov_status_level << PIO_STATUS_N_POS);
|
||||
if (cfg->mov_status_sel_rx) {
|
||||
val |= PIO_STATUS_SEL;
|
||||
} else {
|
||||
val &= ~PIO_STATUS_SEL;
|
||||
}
|
||||
val &= ~PIO_WRAP_BOTTOM_MASK;
|
||||
val |= (cfg->wrap_bottom << PIO_WRAP_BOTTOM_POS);
|
||||
val &= ~PIO_WRAP_TOP_MASK;
|
||||
val |= (cfg->wrap_top << PIO_WRAP_TOP_POS);
|
||||
if (cfg->out_sticky) {
|
||||
val |= PIO_OUT_STICKY;
|
||||
} else {
|
||||
val &= ~PIO_OUT_STICKY;
|
||||
}
|
||||
if (cfg->inline_outen) {
|
||||
val |= PIO_INLINE_OUT_EN;
|
||||
} else {
|
||||
val &= ~PIO_INLINE_OUT_EN;
|
||||
}
|
||||
val &= ~PIO_OUT_EN_SEL_MASK;
|
||||
val |= (cfg->outen_sel << PIO_OUT_EN_SEL_POS);
|
||||
val &= ~PIO_JMP_PIN_MASK;
|
||||
val |= (cfg->pin_jmp << PIO_JMP_PIN_POS);
|
||||
if (cfg->side_dest_pindir) {
|
||||
val |= PIO_SIDE_PINDIR;
|
||||
} else {
|
||||
val &= ~PIO_SIDE_PINDIR;
|
||||
}
|
||||
if (cfg->side_optional) {
|
||||
val |= PIO_SIDE_EN;
|
||||
} else {
|
||||
val &= ~PIO_SIDE_EN;
|
||||
}
|
||||
putreg32(val, cfg->pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm);
|
||||
|
||||
/* step 4: config shift registers for state machine */
|
||||
val = getreg32(cfg->pio_base + PIO_SM0_SHIFTCTRL_OFFSET + (PIO_SM1_SHIFTCTRL_OFFSET - PIO_SM0_SHIFTCTRL_OFFSET) * sm);
|
||||
if (cfg->auto_push) {
|
||||
val |= PIO_AUTOPUSH;
|
||||
} else {
|
||||
val &= ~PIO_AUTOPUSH;
|
||||
}
|
||||
if (cfg->auto_pull) {
|
||||
val |= PIO_AUTOPULL;
|
||||
} else {
|
||||
val &= ~PIO_AUTOPULL;
|
||||
}
|
||||
if (cfg->in_dir_to_right) {
|
||||
val |= PIO_IN_SHIFTDIR;
|
||||
} else {
|
||||
val &= ~PIO_IN_SHIFTDIR;
|
||||
}
|
||||
if (cfg->out_dir_to_right) {
|
||||
val |= PIO_OUT_SHIFTDIR;
|
||||
} else {
|
||||
val &= ~PIO_OUT_SHIFTDIR;
|
||||
}
|
||||
val &= ~PIO_PUSH_THRESH_MASK;
|
||||
val |= (cfg->thresh_bits_push << PIO_PUSH_THRESH_POS);
|
||||
val &= ~PIO_PULL_THRESH_MASK;
|
||||
val |= (cfg->thresh_bits_pull << PIO_PULL_THRESH_POS);
|
||||
if (cfg->fifo_join == PIO_FIFO_JOIN_NONE) {
|
||||
val &= ~(PIO_FJOIN_TX | PIO_FJOIN_RX);
|
||||
} else if (cfg->fifo_join == PIO_FIFO_RX_JOIN_TX) {
|
||||
val |= PIO_FJOIN_TX;
|
||||
val &= ~PIO_FJOIN_RX;
|
||||
} else if (cfg->fifo_join == PIO_FIFO_TX_JOIN_RX) {
|
||||
val &= ~PIO_FJOIN_TX;
|
||||
val |= PIO_FJOIN_RX;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
putreg32(val, cfg->pio_base + PIO_SM0_SHIFTCTRL_OFFSET + (PIO_SM1_SHIFTCTRL_OFFSET - PIO_SM0_SHIFTCTRL_OFFSET) * sm);
|
||||
|
||||
/* step 5: config state machine pin */
|
||||
val = getreg32(cfg->pio_base + PIO_SM0_PINCTRL_OFFSET + (PIO_SM1_PINCTRL_OFFSET - PIO_SM0_PINCTRL_OFFSET) * sm);
|
||||
val &= ~PIO_OUT_BASE_MASK;
|
||||
val |= (cfg->pin_out_base << PIO_OUT_BASE_POS);
|
||||
val &= ~PIO_SET_BASE_MASK;
|
||||
val |= (cfg->pin_set_base << PIO_SET_BASE_POS);
|
||||
val &= ~PIO_SIDESET_BASE_MASK;
|
||||
val |= (cfg->pin_side_base << PIO_SIDESET_BASE_POS);
|
||||
val &= ~PIO_IN_BASE_MASK;
|
||||
val |= (cfg->pin_in_base << PIO_IN_BASE_POS);
|
||||
val &= ~PIO_OUT_COUNT_MASK;
|
||||
val |= (cfg->pin_out_count << PIO_OUT_COUNT_POS);
|
||||
val &= ~PIO_SET_COUNT_MASK;
|
||||
val |= (cfg->pin_set_count << PIO_SET_COUNT_POS);
|
||||
val &= ~PIO_SIDESET_COUNT_MASK;
|
||||
val |= (cfg->pin_side_count << PIO_SIDESET_COUNT_POS);
|
||||
putreg32(val, cfg->pio_base + PIO_SM0_PINCTRL_OFFSET + (PIO_SM1_PINCTRL_OFFSET - PIO_SM0_PINCTRL_OFFSET) * sm);
|
||||
}
|
||||
|
||||
void pio_enable(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (1 << (PIO_SM_ENABLE_POS + sm));
|
||||
val |= (1 << (PIO_SM_RESTART_POS + sm));
|
||||
val |= (1 << (PIO_CLKDIV_RESTART_POS + sm));
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_disable(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val &= ~(1 << (PIO_SM_ENABLE_POS + sm));
|
||||
val |= (1 << (PIO_SM_RESTART_POS + sm));
|
||||
val |= (1 << (PIO_CLKDIV_RESTART_POS + sm));
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_enable_multi(uint32_t pio_base, uint8_t sms)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (sms << PIO_SM_ENABLE_POS);
|
||||
val |= (sms << PIO_SM_RESTART_POS);
|
||||
val |= (sms << PIO_CLKDIV_RESTART_POS);
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_disable_multi(uint32_t pio_base, uint8_t sms)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val &= ~(sms << PIO_SM_ENABLE_POS);
|
||||
val |= (sms << PIO_SM_RESTART_POS);
|
||||
val |= (sms << PIO_CLKDIV_RESTART_POS);
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_restart(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (1 << (PIO_SM_RESTART_POS + sm));
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_restart_multi(uint32_t pio_base, uint8_t sms)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (sms << PIO_SM_RESTART_POS);
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_clkdiv_restart(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (1 << (PIO_CLKDIV_RESTART_POS + sm));
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
void pio_clkdiv_restart_multi(uint32_t pio_base, uint8_t sms)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_CTRL_OFFSET);
|
||||
val |= (sms << PIO_CLKDIV_RESTART_POS);
|
||||
putreg32(val, pio_base + PIO_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
uint32_t pio_fifo_get_status(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
return getreg32(pio_base + PIO_FSTAT_OFFSET);
|
||||
}
|
||||
|
||||
uint8_t pio_fifo_get_tx_level(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_FLEVEL_OFFSET);
|
||||
val >>= ((PIO_FLEVEL_TX1_POS - PIO_FLEVEL_TX0_POS) * sm);
|
||||
val &= PIO_FLEVEL_TX0_MASK;
|
||||
val >>= PIO_FLEVEL_TX0_POS;
|
||||
return (uint8_t)val;
|
||||
}
|
||||
|
||||
uint8_t pio_fifo_get_rx_level(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_FLEVEL_OFFSET);
|
||||
val >>= ((PIO_FLEVEL_RX1_POS - PIO_FLEVEL_RX0_POS) * sm);
|
||||
val &= PIO_FLEVEL_RX0_MASK;
|
||||
val >>= PIO_FLEVEL_RX0_POS;
|
||||
return (uint8_t)val;
|
||||
}
|
||||
|
||||
void pio_fifo_write(uint32_t pio_base, uint8_t sm, uint32_t value)
|
||||
{
|
||||
putreg32(value, pio_base + PIO_TXF0_OFFSET + (PIO_TXF1_OFFSET - PIO_TXF0_OFFSET) * sm);
|
||||
}
|
||||
|
||||
uint32_t pio_fifo_read(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
return getreg32(pio_base + PIO_RXF0_OFFSET + (PIO_RXF1_OFFSET - PIO_RXF0_OFFSET) * sm);
|
||||
}
|
||||
|
||||
void pio_flag_clear(uint32_t pio_base, uint8_t flag)
|
||||
{
|
||||
putreg32(1 << flag, pio_base + PIO_IRQ_OFFSET);
|
||||
}
|
||||
|
||||
void pio_flag_set(uint32_t pio_base, uint8_t flag)
|
||||
{
|
||||
putreg32(1 << flag, pio_base + PIO_IRQ_FORCE_OFFSET);
|
||||
}
|
||||
|
||||
void pio_flag_clear_multi(uint32_t pio_base, uint8_t flags)
|
||||
{
|
||||
putreg32(flags, pio_base + PIO_IRQ_OFFSET);
|
||||
}
|
||||
|
||||
void pio_flag_set_multi(uint32_t pio_base, uint8_t flags)
|
||||
{
|
||||
putreg32(flags, pio_base + PIO_IRQ_FORCE_OFFSET);
|
||||
}
|
||||
|
||||
uint8_t pio_addr_get(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_SM0_ADDR_OFFSET + (PIO_SM1_ADDR_OFFSET - PIO_SM0_ADDR_OFFSET) * sm);
|
||||
val &= PIO_ADDR_MASK;
|
||||
val >>= PIO_ADDR_POS;
|
||||
return (uint8_t)val;
|
||||
}
|
||||
|
||||
uint16_t pio_instr_get(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_SM0_INSTR_OFFSET + (PIO_SM1_INSTR_OFFSET - PIO_SM0_INSTR_OFFSET) * sm);
|
||||
val &= PIO_INSTR_MASK;
|
||||
val >>= PIO_INSTR_POS;
|
||||
return (uint16_t)val;
|
||||
}
|
||||
|
||||
void pio_instr_insert(uint32_t pio_base, uint8_t sm, uint16_t instr)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_SM0_INSTR_OFFSET + (PIO_SM1_INSTR_OFFSET - PIO_SM0_INSTR_OFFSET) * sm);
|
||||
val &= ~PIO_INSTR_MASK;
|
||||
val |= (instr << PIO_INSTR_POS);
|
||||
putreg32(val, pio_base + PIO_SM0_INSTR_OFFSET);
|
||||
}
|
||||
|
||||
int pio_instr_is_complete(uint32_t pio_base, uint8_t sm)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm);
|
||||
val &= PIO_EXEC_STALLED;
|
||||
if (val) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void pio_instr_place(uint32_t pio_base, uint8_t addr, uint16_t instr)
|
||||
{
|
||||
putreg32(instr, pio_base + PIO_INSTR_MEM0_OFFSET + (PIO_INSTR_MEM1_OFFSET - PIO_INSTR_MEM0_OFFSET) * addr);
|
||||
}
|
||||
|
||||
uint32_t pio_int_get_raw_status(uint32_t pio_base)
|
||||
{
|
||||
return getreg32(pio_base + PIO_INTR_OFFSET);
|
||||
}
|
||||
|
||||
uint32_t pio_int_get_status(uint32_t pio_base, uint8_t int_group)
|
||||
{
|
||||
return getreg32(pio_base + PIO_IRQ0_INTS_OFFSET + (PIO_IRQ1_INTS_OFFSET - PIO_IRQ0_INTS_OFFSET) * int_group);
|
||||
}
|
||||
|
||||
void pio_int_enable(uint32_t pio_base, uint8_t int_group, uint32_t int_type)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group);
|
||||
val |= int_type;
|
||||
putreg32(val, pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group);
|
||||
}
|
||||
|
||||
void pio_int_disable(uint32_t pio_base, uint8_t int_group, uint32_t int_type)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group);
|
||||
val &= ~int_type;
|
||||
putreg32(val, pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group);
|
||||
}
|
||||
|
||||
void pio_int_force(uint32_t pio_base, uint8_t int_group, uint32_t int_type)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group);
|
||||
val |= int_type;
|
||||
putreg32(val, pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group);
|
||||
}
|
||||
|
||||
void pio_int_deforce(uint32_t pio_base, uint8_t int_group, uint32_t int_type)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group);
|
||||
val &= ~int_type;
|
||||
putreg32(val, pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group);
|
||||
}
|
||||
|
||||
87
driver/src/timer.c
Normal file
87
driver/src/timer.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include "timer.h"
|
||||
|
||||
void timer_count_write(uint64_t count)
|
||||
{
|
||||
putreg32((uint32_t)(count & 0xFFFFFFFF), TIMER_BASE + TIMER_TIMELW_OFFSET);
|
||||
putreg32((uint32_t)((count >> 32) & 0xFFFFFFFF), TIMER_BASE + TIMER_TIMEHW_OFFSET);
|
||||
}
|
||||
|
||||
uint64_t timer_count_read(void)
|
||||
{
|
||||
uint32_t high, low;
|
||||
|
||||
low = getreg32(TIMER_BASE + TIMER_TIMELR_OFFSET);
|
||||
high = getreg32(TIMER_BASE + TIMER_TIMEHR_OFFSET);
|
||||
return (((uint64_t)high << 32) | ((uint64_t)low));
|
||||
}
|
||||
|
||||
uint32_t timer_count_l_read_raw(void)
|
||||
{
|
||||
return getreg32(TIMER_BASE + TIMER_TIMERAWL_OFFSET);
|
||||
}
|
||||
|
||||
uint32_t timer_count_h_read_raw(void)
|
||||
{
|
||||
return getreg32(TIMER_BASE + TIMER_TIMERAWH_OFFSET);
|
||||
}
|
||||
|
||||
void timer_start(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(TIMER_BASE + TIMER_PAUSE_OFFSET);
|
||||
val &= ~TIMER_PAUSE;
|
||||
putreg32(val, TIMER_BASE + TIMER_PAUSE_OFFSET);
|
||||
}
|
||||
|
||||
void timer_stop(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = getreg32(TIMER_BASE + TIMER_PAUSE_OFFSET);
|
||||
val |= TIMER_PAUSE;
|
||||
putreg32(val, TIMER_BASE + TIMER_PAUSE_OFFSET);
|
||||
}
|
||||
|
||||
int timer_is_stopped(void)
|
||||
{
|
||||
if (getreg32(TIMER_BASE + TIMER_PAUSE_OFFSET) & TIMER_PAUSE) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count)
|
||||
{
|
||||
putreg32(alarm_count, TIMER_BASE + TIMER_ALARM0_OFFSET + (TIMER_ALARM1_OFFSET - TIMER_ALARM0_OFFSET) * alarm_id);
|
||||
}
|
||||
|
||||
uint32_t timer_alarm_get(uint8_t alarm_id)
|
||||
{
|
||||
return getreg32(TIMER_BASE + TIMER_ALARM0_OFFSET + (TIMER_ALARM1_OFFSET - TIMER_ALARM0_OFFSET) * alarm_id);
|
||||
}
|
||||
|
||||
void timer_alarm_disarm(uint8_t alarm_id)
|
||||
{
|
||||
putreg32(1 << alarm_id, TIMER_BASE + TIMER_ARMED_OFFSET);
|
||||
}
|
||||
|
||||
void timer_alarm_disarm_multi(uint32_t alarm_id_multi)
|
||||
{
|
||||
putreg32(alarm_id_multi, TIMER_BASE + TIMER_ARMED_OFFSET);
|
||||
}
|
||||
|
||||
int timer_alarm_is_armed(uint8_t alarm_id)
|
||||
{
|
||||
if (getreg32(TIMER_BASE + TIMER_ARMED_OFFSET) & (1 << alarm_id)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t timer_alarm_is_armed_multi(uint32_t alarm_id_multi)
|
||||
{
|
||||
return (getreg32(TIMER_BASE + TIMER_ARMED_OFFSET) & alarm_id_multi);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user