arm/rp2040: Add RP2040 GPIO interrupt functions
This commit is contained in:
parent
9fd0df3931
commit
174a4c1b68
@ -37,16 +37,89 @@
|
||||
#include "chip.h"
|
||||
#include "rp2040_gpio.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* GPIO interrupt initialize flag */
|
||||
|
||||
static bool g_gpio_irq_init = false;
|
||||
|
||||
/* GPIO interrupt handlers information */
|
||||
|
||||
static xcpt_t g_gpio_irq_handlers[RP2040_GPIO_NUM];
|
||||
static FAR void *g_gpio_irq_args[RP2040_GPIO_NUM];
|
||||
static int g_gpio_irq_modes[RP2040_GPIO_NUM];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp2040_gpio_interrupt
|
||||
*
|
||||
* Description:
|
||||
* GPIO interrupt handler
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rp2040_gpio_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint32_t stat;
|
||||
uint32_t gpio;
|
||||
xcpt_t handler;
|
||||
|
||||
/* Scan all GPIO interrupt status registers */
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* Get and clear pending GPIO interrupt status */
|
||||
|
||||
stat = getreg32(RP2040_IO_BANK0_PROC_INTS(i * 8, 0));
|
||||
if (i == 3)
|
||||
{
|
||||
stat &= 0x00ffffff; /* Clear reserved bits */
|
||||
}
|
||||
|
||||
putreg32(stat, RP2040_IO_BANK0_INTR(i * 8));
|
||||
|
||||
while (stat != 0)
|
||||
{
|
||||
/* Scan all GPIO pins in one register */
|
||||
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
if (stat & (0xf << (j * 4)))
|
||||
{
|
||||
stat &= ~(0xf << (j * 4));
|
||||
|
||||
gpio = i * 8 + j;
|
||||
handler = g_gpio_irq_handlers[gpio];
|
||||
|
||||
/* Call GPIO interrupt handler */
|
||||
|
||||
if (handler)
|
||||
{
|
||||
handler(gpio, context, g_gpio_irq_args[gpio]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_gpio_set_function(uint32_t gpio, uint32_t func)
|
||||
{
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
modbits_reg32(RP2040_PADS_BANK0_GPIO_IE,
|
||||
RP2040_PADS_BANK0_GPIO_IE | RP2040_PADS_BANK0_GPIO_OD,
|
||||
RP2040_PADS_BANK0_GPIO(gpio));
|
||||
@ -57,6 +130,8 @@ void rp2040_gpio_set_function(uint32_t gpio, uint32_t func)
|
||||
|
||||
void rp2040_gpio_set_pulls(uint32_t gpio, int up, int down)
|
||||
{
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
modbits_reg32((up ? RP2040_PADS_BANK0_GPIO_PUE : 0) |
|
||||
(down ? RP2040_PADS_BANK0_GPIO_PDE : 0),
|
||||
RP2040_PADS_BANK0_GPIO_PUE | RP2040_PADS_BANK0_GPIO_PDE,
|
||||
@ -65,7 +140,92 @@ void rp2040_gpio_set_pulls(uint32_t gpio, int up, int down)
|
||||
|
||||
void rp2040_gpio_init(uint32_t gpio)
|
||||
{
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
rp2040_gpio_setdir(gpio, false);
|
||||
rp2040_gpio_put(gpio, false);
|
||||
rp2040_gpio_set_function(gpio, RP2040_GPIO_FUNC_SIO);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: r2040_gpio_irq_attach
|
||||
*
|
||||
* Description:
|
||||
* Configure the interrupt generated by the specified GPIO pin.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rp2040_gpio_irq_attach(uint32_t gpio, uint32_t intrmode,
|
||||
xcpt_t isr, FAR void *arg)
|
||||
{
|
||||
if (!g_gpio_irq_init)
|
||||
{
|
||||
/* Initialize - register GPIO interrupt handler */
|
||||
|
||||
g_gpio_irq_init = true;
|
||||
irq_attach(RP2040_IO_IRQ_BANK0, rp2040_gpio_interrupt, NULL);
|
||||
up_enable_irq(RP2040_IO_IRQ_BANK0);
|
||||
}
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
DEBUGASSERT(intrmode <= RP2040_GPIO_INTR_EDGE_HIGH);
|
||||
|
||||
/* Save handler information */
|
||||
|
||||
g_gpio_irq_handlers[gpio] = isr;
|
||||
g_gpio_irq_args[gpio] = arg;
|
||||
g_gpio_irq_modes[gpio] = intrmode;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
|
||||
setbits_reg32(0xf << ((gpio % 8) * 4), RP2040_IO_BANK0_INTR(gpio));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp2040_gpio_enable_irq
|
||||
*
|
||||
* Description:
|
||||
* Enable the GPIO IRQ specified by 'gpio'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_gpio_enable_irq(uint32_t gpio)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
if (g_gpio_irq_handlers[gpio] != NULL)
|
||||
{
|
||||
/* Set interrupt enable bit */
|
||||
|
||||
reg = RP2040_IO_BANK0_PROC_INTE(gpio, 0);
|
||||
clrbits_reg32(0xf << ((gpio % 8) * 4), reg);
|
||||
setbits_reg32(0x1 << ((gpio % 8) * 4 + g_gpio_irq_modes[gpio]), reg);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp2040_gpio_disable_irq
|
||||
*
|
||||
* Description:
|
||||
* Disable the GPIO IRQ specified by 'gpio'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_gpio_disable_irq(uint32_t gpio)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
if (g_gpio_irq_handlers[gpio] != NULL)
|
||||
{
|
||||
/* Clear interrupt enable bit */
|
||||
|
||||
reg = RP2040_IO_BANK0_PROC_INTE(gpio, 0);
|
||||
clrbits_reg32(0xf << ((gpio % 8) * 4), reg);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,10 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "hardware/rp2040_sio.h"
|
||||
#include "hardware/rp2040_io_bank0.h"
|
||||
#include "hardware/rp2040_pads_bank0.h"
|
||||
@ -35,6 +39,10 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RP2040_GPIO_NUM 30 /* Number of GPIO pins */
|
||||
|
||||
/* GPIO function types ******************************************************/
|
||||
|
||||
#define RP2040_GPIO_FUNC_JTAG RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_JTAG
|
||||
#define RP2040_GPIO_FUNC_SPI RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_SPI
|
||||
#define RP2040_GPIO_FUNC_UART RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_UART
|
||||
@ -47,6 +55,13 @@
|
||||
#define RP2040_GPIO_FUNC_USB RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_USB
|
||||
#define RP2040_GPIO_FUNC_NULL RP2040_IO_BANK0_GPIO_CTRL_FUNCSEL_NULL
|
||||
|
||||
/* GPIO interrupt modes *****************************************************/
|
||||
|
||||
#define RP2040_GPIO_INTR_LEVEL_LOW 0
|
||||
#define RP2040_GPIO_INTR_LEVEL_HIGH 1
|
||||
#define RP2040_GPIO_INTR_EDGE_LOW 2
|
||||
#define RP2040_GPIO_INTR_EDGE_HIGH 3
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -74,6 +89,8 @@ static inline void rp2040_gpio_put(uint32_t gpio, int set)
|
||||
{
|
||||
uint32_t value = 1 << gpio;
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
if (set)
|
||||
{
|
||||
putreg32(value, RP2040_SIO_GPIO_OUT_SET);
|
||||
@ -88,6 +105,8 @@ static inline bool rp2040_gpio_get(uint32_t gpio)
|
||||
{
|
||||
uint32_t value = 1 << gpio;
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
return (getreg32(RP2040_SIO_GPIO_IN) & value) != 0;
|
||||
}
|
||||
|
||||
@ -95,6 +114,8 @@ static inline void rp2040_gpio_setdir(uint32_t gpio, int out)
|
||||
{
|
||||
uint32_t value = 1 << gpio;
|
||||
|
||||
DEBUGASSERT(gpio < RP2040_GPIO_NUM);
|
||||
|
||||
if (out)
|
||||
{
|
||||
putreg32(value, RP2040_SIO_GPIO_OE_SET);
|
||||
@ -113,6 +134,37 @@ void rp2040_gpio_set_function(uint32_t gpio, uint32_t func);
|
||||
void rp2040_gpio_set_pulls(uint32_t gpio, int up, int down);
|
||||
void rp2040_gpio_init(uint32_t gpio);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: r2040_gpio_irq_attach
|
||||
*
|
||||
* Description:
|
||||
* Configure the interrupt generated by the specified GPIO pin.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rp2040_gpio_irq_attach(uint32_t gpio, uint32_t intrmode,
|
||||
xcpt_t isr, FAR void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp2040_gpio_enable_irq
|
||||
*
|
||||
* Description:
|
||||
* Enable the GPIO IRQ specified by 'gpio'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_gpio_enable_irq(uint32_t gpio);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp2040_gpio_disable_irq
|
||||
*
|
||||
* Description:
|
||||
* Disable the GPIO IRQ specified by 'gpio'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void rp2040_gpio_disable_irq(uint32_t gpio);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user