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:
Alexandre Abadie 2020-08-31 11:11:54 +02:00 committed by GitHub
commit f264b049aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -37,6 +37,20 @@ static gpio_flank_t isr_flank[GPIO_NUMOF];
static gpio_isr_ctx_t isr_ctx[GPIO_NUMOF]; static gpio_isr_ctx_t isr_ctx[GPIO_NUMOF];
#endif /* MODULE_PERIPH_GPIO_IRQ */ #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) int gpio_init(gpio_t pin, gpio_mode_t mode)
{ {
/* Check for valid pin */ /* Check for valid pin */
@ -45,23 +59,24 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
} }
/* Configure the mode */ /* Configure the mode */
switch (mode) { switch (mode) {
case GPIO_IN: case GPIO_IN:
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin); _set_pin_reg(GPIO_INPUT_EN, pin);
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin); _clr_pin_reg(GPIO_OUTPUT_EN, pin);
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin); _clr_pin_reg(GPIO_PULLUP_EN, pin);
break; break;
case GPIO_IN_PU: case GPIO_IN_PU:
GPIO_REG(GPIO_INPUT_EN) |= (1 << pin); _clr_pin_reg(GPIO_OUTPUT_EN, pin);
GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << pin); _set_pin_reg(GPIO_INPUT_EN, pin);
GPIO_REG(GPIO_PULLUP_EN) |= (1 << pin); _set_pin_reg(GPIO_PULLUP_EN, pin);
break; break;
case GPIO_OUT: case GPIO_OUT:
GPIO_REG(GPIO_INPUT_EN) &= ~(1 << pin); _set_pin_reg(GPIO_OUTPUT_EN, pin);
GPIO_REG(GPIO_OUTPUT_EN) |= (1 << pin); _clr_pin_reg(GPIO_INPUT_EN, pin);
GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << pin); _clr_pin_reg(GPIO_PULLUP_EN, pin);
break; break;
default: default:
@ -69,8 +84,8 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
} }
/* Configure the pin muxing for the GPIO */ /* Configure the pin muxing for the GPIO */
GPIO_REG(GPIO_IOF_EN) &= ~(1 << pin); _clr_pin_reg(GPIO_IOF_EN, pin);
GPIO_REG(GPIO_IOF_SEL) &= ~(1 << pin); _clr_pin_reg(GPIO_IOF_SEL, pin);
return 0; return 0;
} }
@ -82,26 +97,26 @@ int gpio_read(gpio_t pin)
void gpio_set(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) 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) 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) void gpio_write(gpio_t pin, int value)
{ {
if (value) { if (value) {
GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << pin); _set_pin_reg(GPIO_OUTPUT_VAL, pin);
} }
else { 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 */ /* Clear interrupt */
switch (isr_flank[pin]) { switch (isr_flank[pin]) {
case GPIO_FALLING: case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IP) |= (1 << pin); _set_pin_reg(GPIO_FALL_IP, pin);
break; break;
case GPIO_RISING: case GPIO_RISING:
GPIO_REG(GPIO_RISE_IP) |= (1 << pin); _set_pin_reg(GPIO_RISE_IP, pin);
break; break;
case GPIO_BOTH: case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IP) |= (1 << pin); _set_pin_reg(GPIO_FALL_IP, pin);
GPIO_REG(GPIO_RISE_IP) |= (1 << pin); _set_pin_reg(GPIO_RISE_IP, pin);
break; break;
} }
} }
@ -172,16 +187,16 @@ void gpio_irq_enable(gpio_t pin)
/* Enable interrupt for pin */ /* Enable interrupt for pin */
switch (isr_flank[pin]) { switch (isr_flank[pin]) {
case GPIO_FALLING: case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IE) |= (1 << pin); _set_pin_reg(GPIO_FALL_IE, pin);
break; break;
case GPIO_RISING: case GPIO_RISING:
GPIO_REG(GPIO_RISE_IE) |= (1 << pin); _set_pin_reg(GPIO_RISE_IE, pin);
break; break;
case GPIO_BOTH: case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IE) |= (1 << pin); _set_pin_reg(GPIO_FALL_IE, pin);
GPIO_REG(GPIO_RISE_IE) |= (1 << pin); _set_pin_reg(GPIO_RISE_IE, pin);
break; break;
default: default:
@ -199,16 +214,16 @@ void gpio_irq_disable(gpio_t pin)
/* Disable interrupt for pin */ /* Disable interrupt for pin */
switch (isr_flank[pin]) { switch (isr_flank[pin]) {
case GPIO_FALLING: case GPIO_FALLING:
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin); _clr_pin_reg(GPIO_FALL_IE, pin);
break; break;
case GPIO_RISING: case GPIO_RISING:
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin); _clr_pin_reg(GPIO_RISE_IE, pin);
break; break;
case GPIO_BOTH: case GPIO_BOTH:
GPIO_REG(GPIO_FALL_IE) &= ~(1 << pin); _clr_pin_reg(GPIO_FALL_IE, pin);
GPIO_REG(GPIO_RISE_IE) &= ~(1 << pin); _clr_pin_reg(GPIO_RISE_IE, pin);
break; break;
default: default: