mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #14888 from bergzand/pr/fe310/gpio_atomics
fe310: Use read-modify-store instruction for GPIO bitwise operations
This commit is contained in:
commit
f264b049aa
@ -37,6 +37,20 @@ static gpio_flank_t isr_flank[GPIO_NUMOF];
|
||||
static gpio_isr_ctx_t isr_ctx[GPIO_NUMOF];
|
||||
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
||||
|
||||
/* Really always inline these functions These two should be only a few
|
||||
* instructions as the atomic_fetch_or is a single instruction on rv32imac */
|
||||
static __attribute((always_inline)) inline
|
||||
void _set_pin_reg(uint32_t offset, gpio_t pin)
|
||||
{
|
||||
__atomic_fetch_or(&GPIO_REG(offset), 1 << pin, __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
static __attribute((always_inline)) inline
|
||||
void _clr_pin_reg(uint32_t offset, gpio_t pin)
|
||||
{
|
||||
__atomic_fetch_and(&GPIO_REG(offset), ~(1 << pin), __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
{
|
||||
/* Check for valid pin */
|
||||
@ -45,23 +59,24 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
}
|
||||
|
||||
/* Configure the mode */
|
||||
|
||||
switch (mode) {
|
||||
case GPIO_IN:
|
||||
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin);
|
||||
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin);
|
||||
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin);
|
||||
_set_pin_reg(GPIO_INPUT_EN, pin);
|
||||
_clr_pin_reg(GPIO_OUTPUT_EN, pin);
|
||||
_clr_pin_reg(GPIO_PULLUP_EN, pin);
|
||||
break;
|
||||
|
||||
case GPIO_IN_PU:
|
||||
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin);
|
||||
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin);
|
||||
GPIO_REG(GPIO_PULLUP_EN) |= (1 << pin);
|
||||
_clr_pin_reg(GPIO_OUTPUT_EN, pin);
|
||||
_set_pin_reg(GPIO_INPUT_EN, pin);
|
||||
_set_pin_reg(GPIO_PULLUP_EN, pin);
|
||||
break;
|
||||
|
||||
case GPIO_OUT:
|
||||
GPIO_REG(GPIO_INPUT_EN) &= ~(1 << pin);
|
||||
GPIO_REG(GPIO_OUTPUT_EN) |= (1 << pin);
|
||||
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin);
|
||||
_set_pin_reg(GPIO_OUTPUT_EN, pin);
|
||||
_clr_pin_reg(GPIO_INPUT_EN, pin);
|
||||
_clr_pin_reg(GPIO_PULLUP_EN, pin);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -69,8 +84,8 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
}
|
||||
|
||||
/* Configure the pin muxing for the GPIO */
|
||||
GPIO_REG(GPIO_IOF_EN) &= ~(1 << pin);
|
||||
GPIO_REG(GPIO_IOF_SEL) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_IOF_EN, pin);
|
||||
_clr_pin_reg(GPIO_IOF_SEL, pin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -82,26 +97,26 @@ int gpio_read(gpio_t pin)
|
||||
|
||||
void gpio_set(gpio_t pin)
|
||||
{
|
||||
GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_OUTPUT_VAL, pin);
|
||||
}
|
||||
|
||||
void gpio_clear(gpio_t pin)
|
||||
{
|
||||
GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_OUTPUT_VAL, pin);
|
||||
}
|
||||
|
||||
void gpio_toggle(gpio_t pin)
|
||||
{
|
||||
GPIO_REG(GPIO_OUTPUT_VAL) ^= (1 << pin);
|
||||
__atomic_fetch_xor(&GPIO_REG(GPIO_OUTPUT_VAL), (1 << pin), __ATOMIC_RELAXED);
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t pin, int value)
|
||||
{
|
||||
if (value) {
|
||||
GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_OUTPUT_VAL, pin);
|
||||
}
|
||||
else {
|
||||
GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_OUTPUT_VAL, pin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,16 +133,16 @@ void gpio_isr(int num)
|
||||
/* Clear interrupt */
|
||||
switch (isr_flank[pin]) {
|
||||
case GPIO_FALLING:
|
||||
GPIO_REG(GPIO_FALL_IP) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_FALL_IP, pin);
|
||||
break;
|
||||
|
||||
case GPIO_RISING:
|
||||
GPIO_REG(GPIO_RISE_IP) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_RISE_IP, pin);
|
||||
break;
|
||||
|
||||
case GPIO_BOTH:
|
||||
GPIO_REG(GPIO_FALL_IP) |= (1 << pin);
|
||||
GPIO_REG(GPIO_RISE_IP) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_FALL_IP, pin);
|
||||
_set_pin_reg(GPIO_RISE_IP, pin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -172,16 +187,16 @@ void gpio_irq_enable(gpio_t pin)
|
||||
/* Enable interrupt for pin */
|
||||
switch (isr_flank[pin]) {
|
||||
case GPIO_FALLING:
|
||||
GPIO_REG(GPIO_FALL_IE) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_FALL_IE, pin);
|
||||
break;
|
||||
|
||||
case GPIO_RISING:
|
||||
GPIO_REG(GPIO_RISE_IE) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_RISE_IE, pin);
|
||||
break;
|
||||
|
||||
case GPIO_BOTH:
|
||||
GPIO_REG(GPIO_FALL_IE) |= (1 << pin);
|
||||
GPIO_REG(GPIO_RISE_IE) |= (1 << pin);
|
||||
_set_pin_reg(GPIO_FALL_IE, pin);
|
||||
_set_pin_reg(GPIO_RISE_IE, pin);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -199,16 +214,16 @@ void gpio_irq_disable(gpio_t pin)
|
||||
/* Disable interrupt for pin */
|
||||
switch (isr_flank[pin]) {
|
||||
case GPIO_FALLING:
|
||||
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_FALL_IE, pin);
|
||||
break;
|
||||
|
||||
case GPIO_RISING:
|
||||
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_RISE_IE, pin);
|
||||
break;
|
||||
|
||||
case GPIO_BOTH:
|
||||
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin);
|
||||
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin);
|
||||
_clr_pin_reg(GPIO_FALL_IE, pin);
|
||||
_clr_pin_reg(GPIO_RISE_IE, pin);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user