rp2040/driver/src/pio.c

351 lines
11 KiB
C

#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);
}