Reputation: 109
I'm using esp32 module and on which I am implementing interrupt functionality. So, basically whenever interrupt comes the led should glow and if not the led should be in the off state. Surprisingly, if I try the reverse that is "If interrupt come from a switch then led turns off and normally it is in turned on position " this works.
Here's my code.:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#define op 18
#define ip 4
#define OP_PIN_SEL 1ULL<<op
#define IP_PIN_SEL 1ULL<<ip
#define ESP_INTR_FLAG_DEFAULT 0
static void gpio_isr_handler(void )
{
printf("Intrpt Act\n");
gpio_set_level(op,0);
vTaskDelay(1000/portTICK_PERIOD_MS);
fflush(stdout);
}
void app_main()
{
gpio_config_t io_conf;
// io_conf=malloc(0);
gpio_pad_select_gpio(op);
gpio_pad_select_gpio(ip);
gpio_set_direction (op,GPIO_MODE_OUTPUT);
gpio_set_direction(ip,GPIO_MODE_INPUT);
io_conf.intr_type=GPIO_PIN_INTR_ANYEDGE;
io_conf.mode=GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask=OP_PIN_SEL;
io_conf.pull_down_en=1;
io_conf.pull_up_en=0;
gpio_config(&io_conf);
gpio_set_intr_type(ip,GPIO_INTR_POSEDGE);
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(ip,gpio_isr_handler,(void*)ip);
int cnt=0;
while(1)
{
printf("cnt: %d",cnt++);
gpio_set_level(op,1);
vTaskDelay(1000/portTICK_RATE_MS);
fflush(stdout);
}
}
Also this error occurs when I trigger an interrupt through switch:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/dhananjay/esp/esp-idf/tools/idf_monitor.py", line 133, in _run_outer
self.run()
File "/home/dhananjay/esp/esp-idf/tools/idf_monitor.py", line 226, in run
data = self.serial.read(self.serial.in_waiting or 1)
File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 495, in read
raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
Upvotes: 1
Views: 3626
Reputation: 7054
At the least, you're doing way too much in your interrupt handler (gpio_isr_handler()
).
Interrupt handlers interrupt the flow of whatever code is currently running. They can happen at any time, between instructions in a subroutine. Unless code takes precautions to make sure that it keeps its data structures in a consistent state, you're asking for data corruption and crashes. To do that it has to lock out interrupts in "critical sections", which is a very expensive operation and can lead to missed interrupts. So system routines will very rarely do this.
You also want to keep interrupt handlers brief because they block all other activity on the system - so the network stack and other housekeeping functions can't happen while you're still in the interrupt handler.
You absolutely should not call vTaskDelay()
from an interrupt handler. What does that even mean? At best it would affect whatever task was interrupted, which, if there are several tasks running would be a random task.
You also should not call any stdio functions from an interrupt handler. Again, you may interrupt another stdio function; its data structures may be in an inconsistent state and if it's using a serial port it's possible the hardware may also be in an inconsistent state.
The right way to do this is to have the interrupt service routine just wake up a task. Put your current code from gpio_isr_handler()
in a task in an infinite loop with a , start the task in app_main()
and have gpio_isr_handler()
just wake the task. Use vTaskSuspend()
at the start of the loop to have the task wait till it's woken up.
You can safely wake a task from an interrupt handler with one of:
Start with xTaskResumeFromISR()
, it's the simplest way to wake a task from an interrupt handler.
Structurally you should also move the while()
loop out of app_main()
into its own task, which is the task that your code that used to live in gpio_isr_handler()
should resume.
Upvotes: 5