diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index 7b021a7..b712714 100644 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -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) diff --git a/driver/inc/pio.h b/driver/inc/pio.h new file mode 100644 index 0000000..5001499 --- /dev/null +++ b/driver/inc/pio.h @@ -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__ */ diff --git a/driver/inc/pio_instr.h b/driver/inc/pio_instr.h new file mode 100644 index 0000000..08d9eb3 --- /dev/null +++ b/driver/inc/pio_instr.h @@ -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__ */ diff --git a/driver/inc/reg/pio_reg.h b/driver/inc/reg/pio_reg.h new file mode 100644 index 0000000..c6e9000 --- /dev/null +++ b/driver/inc/reg/pio_reg.h @@ -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__ */ diff --git a/driver/inc/reg/reg.h b/driver/inc/reg/reg.h index 644362d..b77f2ae 100644 --- a/driver/inc/reg/reg.h +++ b/driver/inc/reg/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)) diff --git a/driver/inc/reg/timer_reg.h b/driver/inc/reg/timer_reg.h new file mode 100644 index 0000000..0da853e --- /dev/null +++ b/driver/inc/reg/timer_reg.h @@ -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__ */ diff --git a/driver/inc/timer.h b/driver/inc/timer.h new file mode 100644 index 0000000..45347b6 --- /dev/null +++ b/driver/inc/timer.h @@ -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__ */ diff --git a/driver/src/pio.c b/driver/src/pio.c new file mode 100644 index 0000000..428b955 --- /dev/null +++ b/driver/src/pio.c @@ -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); +} + diff --git a/driver/src/timer.c b/driver/src/timer.c new file mode 100644 index 0000000..0798234 --- /dev/null +++ b/driver/src/timer.c @@ -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); +}