rp2040/driver/src/gpio.c

467 lines
12 KiB
C

#include "gpio.h"
uint8_t gpio_read(uint8_t pin)
{
uint32_t val;
val = getreg32(SIO_BASE + SIO_GPIO_IN_OFFSET);
val = val & (1 << pin);
if (val) {
return 1;
} else {
return 0;
}
}
void gpio_write(uint8_t pin, uint8_t value)
{
if (value) {
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OUT_SET_OFFSET);
} else {
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OUT_CLR_OFFSET);
}
}
void gpio_set(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OUT_SET_OFFSET);
}
void gpio_clear(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OUT_CLR_OFFSET);
}
void gpio_toggle(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OUT_XOR_OFFSET);
}
void gpio_oe_write(uint8_t pin, uint8_t value)
{
if (value) {
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OE_SET_OFFSET);
} else {
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OE_CLR_OFFSET);
}
}
void gpio_oe_set(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OE_SET_OFFSET);
}
void gpio_oe_clear(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OE_CLR_OFFSET);
}
void gpio_oe_toggle(uint8_t pin)
{
putreg32(1 << pin, SIO_BASE + SIO_GPIO_OE_XOR_OFFSET);
}
uint32_t gpio_read_multi(void)
{
return getreg32(SIO_BASE + SIO_GPIO_IN_OFFSET);
}
void gpio_write_multi(uint32_t value)
{
putreg32(value, SIO_BASE + SIO_GPIO_OUT_OFFSET);
}
void gpio_set_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OUT_SET_OFFSET);
}
void gpio_clear_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OUT_CLR_OFFSET);
}
void gpio_toggle_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OUT_XOR_OFFSET);
}
void gpio_oe_write_multi(uint32_t value)
{
putreg32(value, SIO_BASE + SIO_GPIO_OE_OFFSET);
}
void gpio_oe_set_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OE_SET_OFFSET);
}
void gpio_oe_clear_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OE_CLR_OFFSET);
}
void gpio_oe_toggle_multi(uint32_t pins)
{
putreg32(pins, SIO_BASE + SIO_GPIO_OE_XOR_OFFSET);
}
uint32_t gpio_get_status(uint8_t pin, uint32_t status)
{
uint32_t val;
val = getreg32(IO_BANK0_BASE + GPIO_STATUS_OFFSET + pin * 8);
return (val & status);
}
void gpio_func_sel(uint8_t pin, uint8_t func)
{
uint32_t addr;
uint32_t val;
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET + pin * 8;
val = getreg32(addr);
val &= ~(GPIO_FUNC_MASK << GPIO_FUNC_POS);
val |= (uint32_t)func << GPIO_FUNC_POS;
putreg32(val, addr);
}
void gpio_over_out_set(uint8_t pin, uint8_t over)
{
uint32_t addr;
uint32_t val;
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET + pin * 8;
val = getreg32(addr);
val &= ~(GPIO_OVER_OUT_MASK << GPIO_OVER_OUT_POS);
val |= (uint32_t)over << GPIO_OVER_OUT_POS;
putreg32(val, addr);
}
void gpio_over_oe_set(uint8_t pin, uint8_t over)
{
uint32_t addr;
uint32_t val;
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET + pin * 8;
val = getreg32(addr);
val &= ~(GPIO_OVER_OE_MASK << GPIO_OVER_OE_POS);
val |= (uint32_t)over << GPIO_OVER_OE_POS;
putreg32(val, addr);
}
void gpio_over_in_set(uint8_t pin, uint8_t over)
{
uint32_t addr;
uint32_t val;
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET + pin * 8;
val = getreg32(addr);
val &= ~(GPIO_OVER_IN_MASK << GPIO_OVER_IN_POS);
val |= (uint32_t)over << GPIO_OVER_IN_POS;
putreg32(val, addr);
}
void gpio_over_irq_set(uint8_t pin, uint8_t over)
{
uint32_t addr;
uint32_t val;
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET + pin * 8;
val = getreg32(addr);
val &= ~(GPIO_OVER_IRQ_MASK << GPIO_OVER_IRQ_POS);
val |= (uint32_t)over << GPIO_OVER_IRQ_POS;
putreg32(val, addr);
}
void gpio_init(struct gpio_cfg_s *cfg)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
if (cfg->sio_dir == GPIO_SIO_DIR_OUT) {
gpio_oe_set(cfg->pin);
} else {
gpio_oe_clear(cfg->pin);
}
offset = cfg->pin << 3; /* cfg->pin * 8 */
addr = IO_BANK0_BASE + GPIO_CTRL_OFFSET;
val = cfg->funcsel << GPIO_FUNC_POS;
val |= cfg->over_out << GPIO_OVER_OUT_POS;
val |= cfg->over_oe << GPIO_OVER_OE_POS;
val |= cfg->over_in << GPIO_OVER_IN_POS;
val |= cfg->over_irq << GPIO_OVER_IRQ_POS;
putreg32(val, addr + offset);
offset = cfg->pin << 2; /* cfg->pin * 4 */
addr = PADS_BANK0_BASE + GPIO_PADS_CTRL_OFFSET;
val = cfg->slew_rate << GPIO_PADS_SLEW_RATE_POS;
val |= cfg->schmitt << GPIO_PADS_SCHMITT_POS;
val |= cfg->pull_down << GPIO_PADS_PULL_DOWN_POS;
val |= cfg->pull_up << GPIO_PADS_PULL_UP_POS;
val |= cfg->drive << GPIO_PADS_DRIVE_POS;
val |= cfg->ie << GPIO_PADS_IE_POS;
val |= cfg->od << GPIO_PADS_OD_POS;
putreg32(val, addr + offset);
}
void gpio_init_simple(uint8_t pin, uint8_t func, uint8_t pulldown, uint8_t pullup)
{
struct gpio_cfg_s cfg = {
.pin = pin,
.sio_dir = GPIO_SIO_DIR_IN,
.funcsel = func,
.over_out = GPIO_OVER_OUT_PERIPHERAL,
.over_oe = GPIO_OVER_OE_PERIPHERAL,
.over_in = GPIO_OVER_IN_PERIPHERAL,
.over_irq = GPIO_OVER_IRQ_NORMAL,
.slew_rate = GPIO_PADS_SLEW_RATE_SLOW, /* slew rate control, slow or fast */
.schmitt = ENABLE, /* enable or disable schmitt */
.pull_down = pulldown, /* enable or disable pull down */
.pull_up = pullup, /* enable or disable pull up */
.drive = GPIO_PADS_DRIVE_STRENGTH_4MA, /* drive strength */
.ie = DISABLE, /* enable or disable input */
.od = DISABLE, /* output disable, has priority over output enable from peripherals */
};
gpio_init(&cfg);
}
uint8_t gpio_irq_get_raw_status(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTR_OFFSET;
val = getreg32(addr + offset);
return (uint8_t)((val >> pos) & irq);
}
void gpio_irq_raw_status_clear(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTR_OFFSET;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_enable_proc0(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_PROC0_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_disable_proc0(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_PROC0_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_force_proc0(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_PROC0_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_deforce_proc0(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_PROC0_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
uint8_t gpio_irq_get_status_proc0(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTS_PROC0_OFFSET;
val = getreg32(addr + offset);
return (uint8_t)((val >> pos) & irq);
}
void gpio_irq_enable_proc1(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_PROC1_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_disable_proc1(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_PROC1_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_force_proc1(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_PROC1_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_deforce_proc1(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_PROC1_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
uint8_t gpio_irq_get_status_proc1(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTS_PROC1_OFFSET;
val = getreg32(addr + offset);
return (uint8_t)((val >> pos) & irq);
}
void gpio_irq_enable_dormant(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_DORMANT_WAKE_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_disable_dormant(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTE_DORMANT_WAKE_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_force_dormant(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_DORMANT_WAKE_OFFSET + REG_ALIAS_SET_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
void gpio_irq_deforce_dormant(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTF_DORMANT_WAKE_OFFSET + REG_ALIAS_CLR_BITS;
val = (uint32_t)irq << pos;
putreg32(val, addr + offset);
}
uint8_t gpio_irq_get_status_dormant(uint8_t pin, uint8_t irq)
{
uint32_t addr;
uint32_t val;
uint32_t offset;
uint32_t pos;
offset = (pin >> 3) << 2; /* offset = pin / 8 * 4 */
pos = (pin & 7) << 2; /* pos = (pin % 8) * 4 */
addr = IO_BANK0_BASE + GPIO_INTS_DORMANT_WAKE_OFFSET;
val = getreg32(addr + offset);
return (uint8_t)((val >> pos) & irq);
}