arch/xtensa/esp32s2: Add support for RTC IRQs
This commit is contained in:
parent
7df663bff8
commit
1e3af48fff
@ -295,9 +295,53 @@
|
||||
# define ESP32S2_NIRQ_GPIO 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
|
||||
/* Second level RTC interrupts. RTC interrupts are decoded and dispatched
|
||||
* as a second level of decoding: The first level dispatches to the RTC
|
||||
* interrupt handler. The second to the decoded RTC interrupt handler.
|
||||
* A third level might be required to be implemented on the driver (e.g.
|
||||
* Touch pads)
|
||||
*/
|
||||
|
||||
# define ESP32S2_NIRQ_RTCIO_PERIPH 20
|
||||
# define ESP32S2_NIRQ_RTCIO_TOUCHPAD 15
|
||||
# define ESP32S2_NIRQ_RTCIO (ESP32S2_NIRQ_RTCIO_PERIPH+ESP32S2_NIRQ_RTCIO_TOUCHPAD)
|
||||
|
||||
# define ESP32S2_FIRST_RTCIOIRQ_PERIPH (XTENSA_NIRQ_INTERNAL+ESP32S2_NIRQ_PERIPH+ESP32S2_NIRQ_GPIO)
|
||||
# define ESP32S2_LAST_RTCIOIRQ_PERIPH (ESP32S2_FIRST_RTCIOIRQ_PERIPH+ESP32S2_NIRQ_RTCIO_PERIPH-1)
|
||||
# define ESP32S2_IRQ_RTC_SLP_WAKEUP (ESP32S2_FIRST_RTCIOIRQ_PERIPH+0)
|
||||
# define ESP32S2_IRQ_RTC_SLP_REJECT (ESP32S2_FIRST_RTCIOIRQ_PERIPH+1)
|
||||
# define ESP32S2_IRQ_RTC_SDIO_IDLE (ESP32S2_FIRST_RTCIOIRQ_PERIPH+2)
|
||||
# define ESP32S2_IRQ_RTC_WDT (ESP32S2_FIRST_RTCIOIRQ_PERIPH+3)
|
||||
# define ESP32S2_IRQ_RTC_TOUCH_SCAN_DONE (ESP32S2_FIRST_RTCIOIRQ_PERIPH+4)
|
||||
# define ESP32S2_IRQ_RTC_ULP_CP (ESP32S2_FIRST_RTCIOIRQ_PERIPH+5)
|
||||
# define ESP32S2_IRQ_RTC_TOUCH_DONE (ESP32S2_FIRST_RTCIOIRQ_PERIPH+6)
|
||||
# define ESP32S2_IRQ_RTC_TOUCH_ACTIVE (ESP32S2_FIRST_RTCIOIRQ_PERIPH+7)
|
||||
# define ESP32S2_IRQ_RTC_TOUCH_INACTIVE (ESP32S2_FIRST_RTCIOIRQ_PERIPH+8)
|
||||
# define ESP32S2_IRQ_RTC_BROWN_OUT (ESP32S2_FIRST_RTCIOIRQ_PERIPH+9)
|
||||
# define ESP32S2_IRQ_RTC_MAIN_TIMER (ESP32S2_FIRST_RTCIOIRQ_PERIPH+10)
|
||||
# define ESP32S2_IRQ_RTC_SARADC1 (ESP32S2_FIRST_RTCIOIRQ_PERIPH+11)
|
||||
# define ESP32S2_IRQ_RTC_TSENS (ESP32S2_FIRST_RTCIOIRQ_PERIPH+12)
|
||||
# define ESP32S2_IRQ_RTC_COCPU (ESP32S2_FIRST_RTCIOIRQ_PERIPH+13)
|
||||
# define ESP32S2_IRQ_RTC_SARADC2 (ESP32S2_FIRST_RTCIOIRQ_PERIPH+14)
|
||||
# define ESP32S2_IRQ_RTC_SWD (ESP32S2_FIRST_RTCIOIRQ_PERIPH+15)
|
||||
# define ESP32S2_IRQ_RTC_XTAL32K_DEAD (ESP32S2_FIRST_RTCIOIRQ_PERIPH+16)
|
||||
# define ESP32S2_IRQ_RTC_COCPU_TRAP (ESP32S2_FIRST_RTCIOIRQ_PERIPH+17)
|
||||
# define ESP32S2_IRQ_RTC_TOUCH_TIMEOUT (ESP32S2_FIRST_RTCIOIRQ_PERIPH+18)
|
||||
# define ESP32S2_IRQ_RTC_GLITCH_DET (ESP32S2_FIRST_RTCIOIRQ_PERIPH+19)
|
||||
|
||||
# define ESP32S2_FIRST_RTCIOIRQ_TOUCHPAD (ESP32S2_LAST_RTCIOIRQ_PERIPH+1)
|
||||
# define ESP32S2_LAST_RTCIOIRQ_TOUCHPAD (ESP32S2_FIRST_RTCIOIRQ_TOUCHPAD+ESP32S2_NIRQ_RTCIO_TOUCHPAD-1)
|
||||
# define ESP32S2_TOUCHPAD2IRQ(t) ((t) + ESP32S2_FIRST_RTCIOIRQ_TOUCHPAD)
|
||||
# define ESP32S2_IRQ2TOUCHPAD(i) ((i) - ESP32S2_FIRST_RTCIOIRQ_TOUCHPAD)
|
||||
#else
|
||||
# define ESP32S2_NIRQ_RTCIO 0
|
||||
#endif
|
||||
|
||||
/* Total number of interrupts */
|
||||
|
||||
#define NR_IRQS (XTENSA_NIRQ_INTERNAL + ESP32S2_NIRQ_PERIPH + ESP32S2_NIRQ_GPIO)
|
||||
#define NR_IRQS (XTENSA_NIRQ_INTERNAL + ESP32S2_NIRQ_PERIPH + ESP32S2_NIRQ_GPIO + ESP32S2_NIRQ_RTCIO)
|
||||
|
||||
/* Xtensa CPU Interrupts.
|
||||
*
|
||||
|
@ -408,6 +408,7 @@ config ESP32S2_RWDT
|
||||
bool "RTC Watchdog Timer"
|
||||
default n
|
||||
select ESP32S2_WDT
|
||||
select ESP32S2_RTCIO_IRQ
|
||||
---help---
|
||||
Includes RWDT. This watchdog timer is from the RTC module.
|
||||
When it is selected, if the developer sets it to reset on expiration
|
||||
@ -465,6 +466,12 @@ config ESP32S2_GPIO_IRQ
|
||||
---help---
|
||||
Enable support for interrupting GPIO pins.
|
||||
|
||||
config ESP32S2_RTCIO_IRQ
|
||||
bool "RTC IO interrupts"
|
||||
default n
|
||||
---help---
|
||||
Enable support for RTC peripherals interruptions.
|
||||
|
||||
menu "SPI configuration"
|
||||
depends on ESP32S2_SPI
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#ifdef CONFIG_ESP32S2_GPIO_IRQ
|
||||
#include "esp32s2_gpio.h"
|
||||
#endif
|
||||
#include "esp32s2_rtc_gpio.h"
|
||||
#include "esp32s2_irq.h"
|
||||
#include "hardware/esp32s2_soc.h"
|
||||
#include "hardware/esp32s2_system.h"
|
||||
@ -299,6 +300,10 @@ void up_irqinitialize(void)
|
||||
esp32s2_gpioirqinitialize();
|
||||
#endif
|
||||
|
||||
/* Initialize RTCIO interrupt support */
|
||||
|
||||
esp32s2_rtcioirqinitialize();
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
/* And finally, enable interrupts. Also clears PS.EXCM */
|
||||
|
||||
|
@ -31,8 +31,10 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "esp32s2_irq.h"
|
||||
#include "esp32s2_rtc_gpio.h"
|
||||
#include "hardware/esp32s2_rtc_io.h"
|
||||
#include "hardware/esp32s2_sens.h"
|
||||
@ -58,6 +60,11 @@ enum rtcio_lh_out_mode_e
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
static int g_rtcio_cpuint;
|
||||
static uint32_t last_status;
|
||||
#endif
|
||||
|
||||
static const uint32_t rtc_gpio_to_addr[] =
|
||||
{
|
||||
RTCIO_RTC_GPIO_PIN0_REG,
|
||||
@ -94,6 +101,12 @@ static const uint32_t rtc_gpio_to_addr[] =
|
||||
* Description:
|
||||
* Determine if the specified rtcio_num is a valid RTC GPIO.
|
||||
*
|
||||
* Input Parameters:
|
||||
* rtcio_num - RTC GPIO to be checked.
|
||||
*
|
||||
* Returned Value:
|
||||
* True if valid. False otherwise.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool is_valid_rtc_gpio(uint32_t rtcio_num)
|
||||
@ -101,6 +114,85 @@ static inline bool is_valid_rtc_gpio(uint32_t rtcio_num)
|
||||
return (rtcio_num < RTC_GPIO_NUMBER);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtcio_dispatch
|
||||
*
|
||||
* Description:
|
||||
* Second level dispatch for the RTC interrupt.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - The IRQ number;
|
||||
* reg_status - Pointer to a copy of the interrupt status register.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
static void rtcio_dispatch(int irq, uint32_t *reg_status)
|
||||
{
|
||||
uint32_t status = *reg_status;
|
||||
uint32_t mask;
|
||||
int i;
|
||||
|
||||
/* Check each bit in the status register */
|
||||
|
||||
for (i = 0; i < ESP32S2_NIRQ_RTCIO_PERIPH && status != 0; i++)
|
||||
{
|
||||
/* Check if there is an interrupt pending for this type */
|
||||
|
||||
mask = (UINT32_C(1) << i);
|
||||
if ((status & mask) != 0)
|
||||
{
|
||||
/* Yes... perform the second level dispatch. The IRQ context will
|
||||
* contain the contents of the status register.
|
||||
*/
|
||||
|
||||
irq_dispatch(irq + i, (void *)reg_status);
|
||||
|
||||
/* Clear the bit in the status so that we might execute this loop
|
||||
* sooner.
|
||||
*/
|
||||
|
||||
status &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rtcio_interrupt
|
||||
*
|
||||
* Description:
|
||||
* RTC interrupt handler.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - The IRQ number;
|
||||
* context - The interrupt context;
|
||||
* args - The arguments passed to the handler.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
static int rtcio_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
/* Read and clear the lower RTC interrupt status */
|
||||
|
||||
last_status = getreg32(RTC_CNTL_INT_ST_RTC_REG);
|
||||
putreg32(last_status, RTC_CNTL_INT_CLR_RTC_REG);
|
||||
|
||||
/* Dispatch pending interrupts in the RTC status register */
|
||||
|
||||
rtcio_dispatch(ESP32S2_FIRST_RTCIOIRQ_PERIPH, &last_status);
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -249,3 +341,94 @@ int esp32s2_configrtcio(int rtcio_num, rtcio_pinattr_t attr)
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support a second level of interrupt decoding for
|
||||
* RTC interrupts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqinitialize(void)
|
||||
{
|
||||
/* Setup the RTCIO interrupt. */
|
||||
|
||||
g_rtcio_cpuint = esp32s2_setup_irq(ESP32S2_PERIPH_RTC_CORE,
|
||||
1, ESP32S2_CPUINT_LEVEL);
|
||||
DEBUGASSERT(g_rtcio_cpuint >= 0);
|
||||
|
||||
/* Attach and enable the interrupt handler */
|
||||
|
||||
DEBUGVERIFY(irq_attach(ESP32S2_IRQ_RTC_CORE, rtcio_interrupt, NULL));
|
||||
up_enable_irq(ESP32S2_IRQ_RTC_CORE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable the interrupt for a specified RTC IRQ
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqenable(int irq)
|
||||
{
|
||||
uintptr_t regaddr = RTC_CNTL_INT_ENA_RTC_REG;
|
||||
uint32_t regval;
|
||||
int bit;
|
||||
|
||||
DEBUGASSERT(irq >= ESP32S2_FIRST_RTCIOIRQ_PERIPH &&
|
||||
irq <= ESP32S2_LAST_RTCIOIRQ_PERIPH);
|
||||
|
||||
/* Convert the IRQ number to the corresponding bit */
|
||||
|
||||
bit = irq - ESP32S2_FIRST_RTCIOIRQ_PERIPH;
|
||||
|
||||
/* Get the address of the GPIO PIN register for this pin */
|
||||
|
||||
up_disable_irq(ESP32S2_IRQ_RTC_CORE);
|
||||
|
||||
regval = getreg32(regaddr) | (UINT32_C(1) << bit);
|
||||
putreg32(regval, regaddr);
|
||||
|
||||
up_enable_irq(ESP32S2_IRQ_RTC_CORE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable the interrupt for a specified RTC IRQ
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqdisable(int irq)
|
||||
{
|
||||
uintptr_t regaddr = RTC_CNTL_INT_ENA_RTC_REG;
|
||||
uint32_t regval;
|
||||
int bit;
|
||||
|
||||
DEBUGASSERT(irq >= ESP32S2_FIRST_RTCIOIRQ_PERIPH &&
|
||||
irq <= ESP32S2_LAST_RTCIOIRQ_PERIPH);
|
||||
|
||||
/* Convert the IRQ number to the corresponding bit */
|
||||
|
||||
bit = irq - ESP32S2_FIRST_RTCIOIRQ_PERIPH;
|
||||
|
||||
/* Disable IRQ */
|
||||
|
||||
up_disable_irq(ESP32S2_IRQ_RTC_CORE);
|
||||
|
||||
regval = getreg32(regaddr) & (~(UINT32_C(1) << bit));
|
||||
putreg32(regval, regaddr);
|
||||
|
||||
up_enable_irq(ESP32S2_IRQ_RTC_CORE);
|
||||
}
|
||||
#endif
|
||||
|
@ -574,5 +574,48 @@ static const rtc_io_desc_t g_rtc_io_desc[RTC_GPIO_NUMBER] =
|
||||
|
||||
int esp32s2_configrtcio(int rtcio_num, rtcio_pinattr_t attr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support a second level of interrupt decoding for
|
||||
* RTC IRQs.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqinitialize(void);
|
||||
#else
|
||||
# define esp32s2_rtcioirqinitialize()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable the interrupt for the specified RTC peripheral IRQ
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqenable(int irq);
|
||||
#else
|
||||
# define esp32s2_rtcioirqenable(irq)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s2_rtcioirqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable the interrupt for the specified RTC peripheral IRQ
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTCIO_IRQ
|
||||
void esp32s2_rtcioirqdisable(int irq);
|
||||
#else
|
||||
# define esp32s2_rtcioirqdisable(irq)
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_RTC_GPIO_H */
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "esp32s2_irq.h"
|
||||
#include "esp32s2_rtc_gpio.h"
|
||||
#include "esp32s2_wdt.h"
|
||||
#include "hardware/esp32s2_efuse.h"
|
||||
#include "hardware/esp32s2_rtccntl.h"
|
||||
@ -166,7 +167,7 @@ struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
|
||||
.ops = &esp32s2_rwdt_ops,
|
||||
.base = RTC_CNTL_OPTIONS0_REG,
|
||||
.periph = ESP32S2_PERIPH_RTC_CORE,
|
||||
.irq = ESP32S2_IRQ_RTC_CORE,
|
||||
.irq = ESP32S2_IRQ_RTC_WDT,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
};
|
||||
@ -634,13 +635,23 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
|
||||
|
||||
if (wdt->cpuint >= 0)
|
||||
{
|
||||
/* Disable CPU Interrupt, free a previously allocated
|
||||
* CPU Interrupt
|
||||
*/
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
||||
{
|
||||
esp32s2_rtcioirqdisable(wdt->irq);
|
||||
irq_detach(wdt->irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Disable CPU Interrupt, free a previously allocated
|
||||
* CPU Interrupt
|
||||
*/
|
||||
|
||||
up_disable_irq(wdt->irq);
|
||||
esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
|
||||
irq_detach(wdt->irq);
|
||||
up_disable_irq(wdt->irq);
|
||||
esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
|
||||
irq_detach(wdt->irq);
|
||||
}
|
||||
}
|
||||
|
||||
goto errout;
|
||||
@ -652,27 +663,46 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
|
||||
{
|
||||
/* Set up to receive peripheral interrupts on the current CPU */
|
||||
|
||||
wdt->cpuint = esp32s2_setup_irq(wdt->periph, 1, ESP32S2_CPUINT_LEVEL);
|
||||
if (wdt->cpuint < 0)
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
||||
{
|
||||
wderr("ERROR: No CPU Interrupt available");
|
||||
ret = wdt->cpuint;
|
||||
goto errout;
|
||||
ret = irq_attach(wdt->irq, handler, arg);
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
esp32s2_rtcioirqdisable(wdt->irq);
|
||||
tmrerr("ERROR: Failed to associate an IRQ Number");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
esp32s2_rtcioirqenable(wdt->irq);
|
||||
}
|
||||
|
||||
/* Associate an IRQ Number (from the WDT) to an ISR */
|
||||
|
||||
ret = irq_attach(wdt->irq, handler, arg);
|
||||
if (ret != OK)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
|
||||
wderr("ERROR: Failed to associate an IRQ Number");
|
||||
goto errout;
|
||||
wdt->cpuint = esp32s2_setup_irq(wdt->periph, 1,
|
||||
ESP32S2_CPUINT_LEVEL);
|
||||
if (wdt->cpuint < 0)
|
||||
{
|
||||
wderr("ERROR: No CPU Interrupt available");
|
||||
ret = wdt->cpuint;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Associate an IRQ Number (from the WDT) to an ISR */
|
||||
|
||||
ret = irq_attach(wdt->irq, handler, arg);
|
||||
if (ret != OK)
|
||||
{
|
||||
esp32s2_teardown_irq(wdt->periph, wdt->cpuint);
|
||||
wderr("ERROR: Failed to associate an IRQ Number");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Enable the CPU Interrupt that is linked to the WDT */
|
||||
|
||||
up_enable_irq(wdt->irq);
|
||||
}
|
||||
|
||||
/* Enable the CPU Interrupt that is linked to the WDT */
|
||||
|
||||
up_enable_irq(wdt->irq);
|
||||
}
|
||||
|
||||
errout:
|
||||
|
Loading…
x
Reference in New Issue
Block a user