More convenient GPIO interrupt handlers
This commit is contained in:
parent
53f85d0a2c
commit
a61af52d96
4 changed files with 37 additions and 92 deletions
|
@ -56,3 +56,34 @@ void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
|
|||
iomux_set_pullup_flags(gpio_to_iomux(gpio_num), flags);
|
||||
}
|
||||
|
||||
static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 };
|
||||
|
||||
static void IRAM _gpio_intr_internal_handler(void)
|
||||
{
|
||||
uint32_t status_reg = GPIO.STATUS;
|
||||
GPIO.STATUS_CLEAR = status_reg;
|
||||
|
||||
uint8_t gpio_idx;
|
||||
while((gpio_idx = __builtin_ffs(status_reg)))
|
||||
{
|
||||
gpio_idx--;
|
||||
status_reg &= ~BIT(gpio_idx);
|
||||
if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
|
||||
gpio_interrupt_handler_t handler = gpio_interrupt_handlers[gpio_idx];
|
||||
if (handler) {
|
||||
handler(gpio_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, gpio_interrupt_handler_t handler)
|
||||
{
|
||||
gpio_interrupt_handlers[gpio_num] = handler;
|
||||
|
||||
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
|
||||
if(int_type != GPIO_INTTYPE_NONE && handler) {
|
||||
_xt_isr_attach(INUM_GPIO, _gpio_intr_internal_handler);
|
||||
_xt_isr_unmask(1<<INUM_GPIO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/* ESP GPIO interrupts.
|
||||
|
||||
Use with gpio_set_interrupt(), defined in esp/gpio.h
|
||||
|
||||
These interrupt vectors are default implementations with weak
|
||||
linkage. If you write your own GPIO interrupt vectors in your program
|
||||
then they will replace these at link time.
|
||||
|
||||
Look in examples/button/ for a simple GPIO interrupt example.
|
||||
|
||||
You can implement GPIO interrupt handlers in either of two ways:
|
||||
|
||||
- Implement gpXX_interrupt_handler() for each GPIO pin number that
|
||||
you want to use interrupt with. This is simple but it may not
|
||||
be enough in all cases.
|
||||
|
||||
void gpio01_interrupt_handler(void) {
|
||||
// Do something when GPIO 01 changes
|
||||
}
|
||||
|
||||
void gpio12_interrupt_handler(void) {
|
||||
// Do something when GPIO 12 changes
|
||||
}
|
||||
|
||||
OR
|
||||
|
||||
- Implement a single function named gpio_interrupt_handler(). This
|
||||
will need to manually check GPIO.STATUS and clear any status
|
||||
bits after handling interrupts. This gives you full control, but
|
||||
you can't combine it with the first approach.
|
||||
|
||||
|
||||
Part of esp-open-rtos
|
||||
Copyright (C) 2015 Superhouse Automation Pty Ltd
|
||||
BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#include "esp8266.h"
|
||||
|
||||
void gpio_interrupt_handler(void);
|
||||
void gpio_noop_interrupt_handler(void) { }
|
||||
void gpio00_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio01_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio02_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio03_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio04_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio05_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio06_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio07_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio08_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio09_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio10_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio11_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio12_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio13_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio14_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
void gpio15_interrupt_handler(void) __attribute__((weak, alias("gpio_noop_interrupt_handler")));
|
||||
|
||||
typedef void (* gpio_interrupt_handler_t)(void);
|
||||
|
||||
const gpio_interrupt_handler_t gpio_interrupt_handlers[16] = {
|
||||
gpio00_interrupt_handler, gpio01_interrupt_handler, gpio02_interrupt_handler,
|
||||
gpio03_interrupt_handler, gpio04_interrupt_handler, gpio05_interrupt_handler,
|
||||
gpio06_interrupt_handler, gpio07_interrupt_handler, gpio08_interrupt_handler,
|
||||
gpio09_interrupt_handler, gpio10_interrupt_handler, gpio11_interrupt_handler,
|
||||
gpio12_interrupt_handler, gpio13_interrupt_handler, gpio14_interrupt_handler,
|
||||
gpio15_interrupt_handler };
|
||||
|
||||
void __attribute__((weak)) IRAM gpio_interrupt_handler(void)
|
||||
{
|
||||
uint32_t status_reg = GPIO.STATUS;
|
||||
GPIO.STATUS_CLEAR = status_reg;
|
||||
uint8_t gpio_idx;
|
||||
while((gpio_idx = __builtin_ffs(status_reg)))
|
||||
{
|
||||
gpio_idx--;
|
||||
status_reg &= ~BIT(gpio_idx);
|
||||
if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx]))
|
||||
gpio_interrupt_handlers[gpio_idx]();
|
||||
}
|
||||
}
|
|
@ -127,21 +127,14 @@ static inline bool gpio_read(const uint8_t gpio_num)
|
|||
return GPIO.IN & BIT(gpio_num);
|
||||
}
|
||||
|
||||
extern void gpio_interrupt_handler(void);
|
||||
typedef void (* gpio_interrupt_handler_t)(uint8_t gpio_num);
|
||||
|
||||
/* Set the interrupt type for a given pin
|
||||
*
|
||||
* If int_type is not GPIO_INTTYPE_NONE, the gpio_interrupt_handler will be
|
||||
* attached and unmasked.
|
||||
*/
|
||||
static inline void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type)
|
||||
{
|
||||
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
|
||||
if(int_type != GPIO_INTTYPE_NONE) {
|
||||
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler);
|
||||
_xt_isr_unmask(1<<INUM_GPIO);
|
||||
}
|
||||
}
|
||||
void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, gpio_interrupt_handler_t handler);
|
||||
|
||||
/* Return the interrupt type set for a pin */
|
||||
static inline gpio_inttype_t gpio_get_interrupt(const uint8_t gpio_num)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
const int gpio = 0; /* gpio 0 usually has "PROGRAM" button attached */
|
||||
const int active = 0; /* active == 0 for active low */
|
||||
const gpio_inttype_t int_type = GPIO_INTTYPE_EDGE_NEG;
|
||||
#define GPIO_HANDLER gpio00_interrupt_handler
|
||||
|
||||
|
||||
/* This task polls for the button and prints the tick
|
||||
|
@ -39,6 +38,8 @@ void buttonPollTask(void *pvParameters)
|
|||
}
|
||||
}
|
||||
|
||||
void gpio_intr_handler(uint8_t gpio_num);
|
||||
|
||||
/* This task configures the GPIO interrupt and uses it to tell
|
||||
when the button is pressed.
|
||||
|
||||
|
@ -51,7 +52,7 @@ void buttonIntTask(void *pvParameters)
|
|||
{
|
||||
printf("Waiting for button press interrupt on gpio %d...\r\n", gpio);
|
||||
QueueHandle_t *tsqueue = (QueueHandle_t *)pvParameters;
|
||||
gpio_set_interrupt(gpio, int_type);
|
||||
gpio_set_interrupt(gpio, int_type, gpio_intr_handler);
|
||||
|
||||
uint32_t last = 0;
|
||||
while(1) {
|
||||
|
@ -67,7 +68,7 @@ void buttonIntTask(void *pvParameters)
|
|||
|
||||
static QueueHandle_t tsqueue;
|
||||
|
||||
void GPIO_HANDLER(void)
|
||||
void gpio_intr_handler(uint8_t gpio_num)
|
||||
{
|
||||
uint32_t now = xTaskGetTickCountFromISR();
|
||||
xQueueSendToBackFromISR(tsqueue, &now, NULL);
|
||||
|
|
Loading…
Reference in a new issue