Changing GPIO inside task with GPIO interrupts bug?

FrenkR
Posts: 44
Joined: Thu Dec 04, 2014 9:25 am

Changing GPIO inside task with GPIO interrupts bug?

Postby FrenkR » Fri Jan 02, 2015 1:29 am

have following situation. On GPIO13, button is defined(input, pullup). interrupt trigger is set to GPIO13. trigger posts "message" to a task. inside task routine, GPIO14 is set to 0/1 (relay). After pressing a button on GPIO13 few times, module resets itself:

Code: Select all

rst cause:4, boot mode:(1,7)
wdt reset

Also interrupt routine is called too many times( interrupt state is "GPIO_PIN_INTR_POSEDGE", so after pressing a button, only events with _gpioState->GPIOState with value 8192 should be posted, not with value 0).

code is as follows:

Code: Select all

#include "osapi.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "user_config.h"
#include "eagle_soc.h"
#include "ets_sys.h"
#include "gpio.h"
#include "mem.h"


//static volatile os_timer_t tmrSstart;
//static uint32_t m_Counter = 0;
static bool m_GPIO14 = false;

os_event_t user_procTaskQueue[user_procTaskQueueLen];

//Main code function
static void ICACHE_FLASH_ATTR
loop(os_event_t *events)
{
   os_printf("Task sig=%u, par=%u!\r\n",events->sig, events->par);

   GPIOState * _gpioState = (GPIOState *)(events->par);
   if(_gpioState->GPIOState > 0){
      m_GPIO14 = !m_GPIO14;
      GPIO_OUTPUT_SET(14, m_GPIO14);
      os_printf("GPIO14 set to %u\r\n",  m_GPIO14);
   }

   os_printf("Task executed and memory disposed, RTC=%u, GPIO=%u!\r\n", _gpioState->RtcTime, _gpioState->GPIOState);
   os_free(_gpioState);
}

// GPIO interrupt handler:store local data and start task
static void ICACHE_FLASH_ATTR
iw_GPIO_handler(int8_t key){
   uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
   uint32_t rtc_now = system_get_rtc_time();

   GPIOState * _gpioState = (GPIOState *)os_zalloc(sizeof(GPIOState));

   _gpioState->GPIOState = gpio_status;
   _gpioState->RtcTime = rtc_now;

   // activate task
   if (!system_os_post(user_procTaskPrio, 0, (uint32_t)_gpioState)){
      os_free(_gpioState);
      os_printf("Task \"post\" failed\r\n");
   } else
      os_printf("Task \"post\" succeed, RTC=%u, GPIO=%u\r\n", rtc_now, gpio_status);

   // set last interrupt state
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
}



//Init function
void ICACHE_FLASH_ATTR
user_init()
{
   uart_init(BIT_RATE_115200, BIT_RATE_115200);
   os_delay_us(1000);

   uart0_sendStr("Start!\r\n");
   
   //Start os task
   system_os_task(loop, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);


   // set interrupt routine
   // start first run with timer(otherwise doesn't work?)
   ETS_GPIO_INTR_DISABLE();

   // GPIO12 interrupt handler
   ETS_GPIO_INTR_ATTACH(iw_GPIO_handler, 12);

   // pin 13 setup
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // select pin to GPIO 13 mode
   GPIO_DIS_OUTPUT(13); // set pin to "input" mode
   PIN_PULLDWN_DIS(PERIPHS_IO_MUX_MTCK_U); // disable pullodwn
   PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U); // pull - up pin

   // pin 14 setup
   // low output
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); // select pin to GPIO 14 mode
   PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTMS_U);
   PIN_PULLDWN_EN(PERIPHS_IO_MUX_MTMS_U);

   //gpio_output_set( BIT14, 0, BIT14, 0 );
   GPIO_OUTPUT_SET(14, 0);

   // interrupt on GPIO 13
   gpio_pin_intr_state_set(GPIO_ID_PIN(13), GPIO_PIN_INTR_POSEDGE); // | GPIO_PIN_INTR_NEGEDGE); // Interrupt on any GPIO13 edge
   gpio_pin_intr_state_set(GPIO_ID_PIN(14), GPIO_PIN_INTR_DISABLE);

   // reset interrupt status
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(13));
   // Enable gpio interrupts
   ETS_GPIO_INTR_ENABLE();

}


ESP_Sprite
Posts: 26
Joined: Fri Oct 24, 2014 7:58 pm

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby ESP_Sprite » Mon Jan 05, 2015 6:06 pm

Perhaps a stupid question, but you are aware of contact bounce, which in this case can very well trigger quite a few interrupts?

FrenkR
Posts: 44
Joined: Thu Dec 04, 2014 9:25 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby FrenkR » Mon Jan 05, 2015 7:23 pm

this code works perfectly if output (GPIO14) change is not set in "task" routine. If you comment "GPIO_OUTPUT_SET(14, m_GPIO14);" in "loop" routine, code works perfectly.

As you can see, there is a GPIO trigger is defined only as GPIO_PIN_INTR_POSEDGE on a pin GPIO13. So, regardless "contact bounce" in GPIO14, trigger should not be raised in any way.
I also think that "gpio_pin_intr_state_set" doesn't work as is defined.

This is tested on ESP-03, SDK 0.9.5.
Rgds,
Frenk

jackon
Posts: 28
Joined: Thu Oct 23, 2014 9:05 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby jackon » Fri Jan 09, 2015 3:29 pm

hi,
have a try.

Code: Select all

// GPIO interrupt handler:store local data and start task
static void ICACHE_FLASH_ATTR
iw_GPIO_handler(int8_t key){
   uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
   uint32_t rtc_now = system_get_rtc_time();

   if (gpio_status & BIT(13)) {
   GPIOState * _gpioState = (GPIOState *)os_zalloc(sizeof(GPIOState));

   _gpioState->GPIOState = gpio_status;
   _gpioState->RtcTime = rtc_now;

   // activate task
   if (!system_os_post(user_procTaskPrio, 0, (uint32_t)_gpioState)){
      os_free(_gpioState);
      os_printf("Task \"post\" failed\r\n");
   } else
      os_printf("Task \"post\" succeed, RTC=%u, GPIO=%u\r\n", rtc_now, gpio_status);

   // set last interrupt state
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(13));
   }
}

FrenkR
Posts: 44
Joined: Thu Dec 04, 2014 9:25 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby FrenkR » Sat Jan 10, 2015 7:08 pm

problem is not in interrupt routine but on "task" routine. Also I don't understand why you added "bit" functionality to update last interrupt state. Isn't this done by "setup" routines, where you tell a system which GPIO in what change are triggering interrupt ?

costaud
Posts: 138
Joined: Fri Oct 24, 2014 7:40 pm

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby costaud » Mon Jan 12, 2015 12:25 pm

FrenkR wrote:have following situation. On GPIO13, button is defined(input, pullup). interrupt trigger is set to GPIO13. trigger posts "message" to a task. inside task routine, GPIO14 is set to 0/1 (relay). After pressing a button on GPIO13 few times, module resets itself:

Code: Select all

rst cause:4, boot mode:(1,7)
wdt reset

Also interrupt routine is called too many times( interrupt state is "GPIO_PIN_INTR_POSEDGE", so after pressing a button, only events with _gpioState->GPIOState with value 8192 should be posted, not with value 0).

code is as follows:

Code: Select all

#include "osapi.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "user_config.h"
#include "eagle_soc.h"
#include "ets_sys.h"
#include "gpio.h"
#include "mem.h"


//static volatile os_timer_t tmrSstart;
//static uint32_t m_Counter = 0;
static bool m_GPIO14 = false;

os_event_t user_procTaskQueue[user_procTaskQueueLen];

//Main code function
static void ICACHE_FLASH_ATTR
loop(os_event_t *events)
{
   os_printf("Task sig=%u, par=%u!\r\n",events->sig, events->par);

   GPIOState * _gpioState = (GPIOState *)(events->par);
   if(_gpioState->GPIOState > 0){
      m_GPIO14 = !m_GPIO14;
      GPIO_OUTPUT_SET(14, m_GPIO14);
      os_printf("GPIO14 set to %u\r\n",  m_GPIO14);
   }

   os_printf("Task executed and memory disposed, RTC=%u, GPIO=%u!\r\n", _gpioState->RtcTime, _gpioState->GPIOState);
   os_free(_gpioState);
}

// GPIO interrupt handler:store local data and start task
static void ICACHE_FLASH_ATTR
iw_GPIO_handler(int8_t key){
   uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
   uint32_t rtc_now = system_get_rtc_time();

   GPIOState * _gpioState = (GPIOState *)os_zalloc(sizeof(GPIOState));

   _gpioState->GPIOState = gpio_status;
   _gpioState->RtcTime = rtc_now;

   // activate task
   if (!system_os_post(user_procTaskPrio, 0, (uint32_t)_gpioState)){
      os_free(_gpioState);
      os_printf("Task \"post\" failed\r\n");
   } else
      os_printf("Task \"post\" succeed, RTC=%u, GPIO=%u\r\n", rtc_now, gpio_status);

   // set last interrupt state
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
}



//Init function
void ICACHE_FLASH_ATTR
user_init()
{
   uart_init(BIT_RATE_115200, BIT_RATE_115200);
   os_delay_us(1000);

   uart0_sendStr("Start!\r\n");
   
   //Start os task
   system_os_task(loop, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);


   // set interrupt routine
   // start first run with timer(otherwise doesn't work?)
   ETS_GPIO_INTR_DISABLE();

   // GPIO12 interrupt handler
   ETS_GPIO_INTR_ATTACH(iw_GPIO_handler, 12);

   // pin 13 setup
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // select pin to GPIO 13 mode
   GPIO_DIS_OUTPUT(13); // set pin to "input" mode
   PIN_PULLDWN_DIS(PERIPHS_IO_MUX_MTCK_U); // disable pullodwn
   PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U); // pull - up pin

   // pin 14 setup
   // low output
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); // select pin to GPIO 14 mode
   PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTMS_U);
   PIN_PULLDWN_EN(PERIPHS_IO_MUX_MTMS_U);

   //gpio_output_set( BIT14, 0, BIT14, 0 );
   GPIO_OUTPUT_SET(14, 0);

   // interrupt on GPIO 13
   gpio_pin_intr_state_set(GPIO_ID_PIN(13), GPIO_PIN_INTR_POSEDGE); // | GPIO_PIN_INTR_NEGEDGE); // Interrupt on any GPIO13 edge
   gpio_pin_intr_state_set(GPIO_ID_PIN(14), GPIO_PIN_INTR_DISABLE);

   // reset interrupt status
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(13));
   // Enable gpio interrupts
   ETS_GPIO_INTR_ENABLE();

}



Hi FrenkR,

Sorry for the delay , finally I find some time to review your question.

I think your question is why the io interrupt trigger several times even the interrupt status register is 0.

I can just tell you how to solve this problem: to clear the interrupt status once you read it out.

Code: Select all

iw_GPIO_handler(int8_t key){
   uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
   uint32_t rtc_now = system_get_rtc_time();
      GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
........

I tried your code but the compiler returns an error.
void.png
void.png (88 KiB) Viewed 15665 times


So I change the test code :

Code: Select all

#include "osapi.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "user_config.h"
#include "eagle_soc.h"
#include "ets_sys.h"
#include "gpio.h"
#include "mem.h"


//static volatile os_timer_t tmrSstart;
//static uint32_t m_Counter = 0;
static bool m_GPIO14 = false;
#define user_procTaskQueueLen  10
#define user_procTaskPrio 2
os_event_t user_procTaskQueue[user_procTaskQueueLen];

//static void ICACHE_FLASH_ATTR loop(os_event_t *events);

  //system_os_task(loop, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);


//Main code function
static void ICACHE_FLASH_ATTR
loop(os_event_t *events)
{
   os_printf("Task sig=%u, par=%u!\r\n",events->sig, events->par);

}

// GPIO interrupt handler:store local data and start task
static void ICACHE_FLASH_ATTR
iw_GPIO_handler(int8_t key){
   uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
   uint32_t rtc_now = system_get_rtc_time();
      GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);


   // activate task
  // if (!system_os_post(user_procTaskPrio, 0, (uint32_t)gpio_status)){
      //os_free(_gpioState);
    //  os_printf("Task \"post\" failed\r\n");
  // } else
    //  os_printf("Task \"post\" succeed, RTC=%u, GPIO=%u\r\n", rtc_now, gpio_status);


   system_os_post(user_procTaskPrio, 0, (uint32_t)gpio_status);
   os_printf("Task \"post\" succeed, RTC=%u, GPIO=%u\r\n", rtc_now, gpio_status);
   // set last interrupt state

}



//Init function
void ICACHE_FLASH_ATTR
user_init()
{
   uart_init(74880, 74880);
   os_delay_us(1000);

   os_printf("Start!\r\n");
   
   //Start os task
   system_os_task(loop, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);


   // set interrupt routine
   // start first run with timer(otherwise doesn't work?)
   ETS_GPIO_INTR_DISABLE();

   // GPIO12 interrupt handler
   ETS_GPIO_INTR_ATTACH(iw_GPIO_handler, 12);

   // pin 13 setup
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // select pin to GPIO 13 mode
   GPIO_DIS_OUTPUT(13); // set pin to "input" mode
   PIN_PULLDWN_DIS(PERIPHS_IO_MUX_MTCK_U); // disable pullodwn
   PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U); // pull - up pin

   // pin 14 setup
   // low output
   PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); // select pin to GPIO 14 mode
   PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTMS_U);
   PIN_PULLDWN_EN(PERIPHS_IO_MUX_MTMS_U);

   //gpio_output_set( BIT14, 0, BIT14, 0 );
   GPIO_OUTPUT_SET(14, 0);

   // interrupt on GPIO 13
   gpio_pin_intr_state_set(GPIO_ID_PIN(13), GPIO_PIN_INTR_POSEDGE); // | GPIO_PIN_INTR_NEGEDGE); // Interrupt on any GPIO13 edge
   gpio_pin_intr_state_set(GPIO_ID_PIN(14), GPIO_PIN_INTR_DISABLE);

   // reset interrupt status
   GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(13));
   // Enable gpio interrupts
   ETS_GPIO_INTR_ENABLE();

}


And the log is always 8192 :

Code: Select all

Task sig=0, par=8192!
Task sig=0, par=8192!
Task "post" succeed, RTC=78107212, GPIO=8192
Task "post" succeed, RTC=78107239, GPIO=8192
Task "post" succeed, RTC=78107263, GPIO=8192
 sig=0, par=8192!
Task sig=0, par=8192!
Task sig=0, par=8192!
Task "post" succeed, RTC=78190765, GPIO=8192
Task "post" succeed, RTC=78190791, GPIO=8192
Task sig=0, par=8192!
Task sig=0, par=8192!
Task "post" succeed, RTC=78220619, GPIO=8192
Task "post" succeed, RTC=78220643, GPIO=8192
Task sig=0, par=8192!
Task sig=0, par=8192!

FrenkR
Posts: 44
Joined: Thu Dec 04, 2014 9:25 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby FrenkR » Tue Jan 13, 2015 6:39 am

thank you. It looks much better now.

brucehvn
Posts: 3
Joined: Tue Dec 30, 2014 9:20 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby brucehvn » Wed Jan 14, 2015 11:00 am

Ok, I'm new to this chip and programming it and I have what might be a dumb question. But if you want to handle interrupts on GPIO13 when the button is pressed, what is the code for GPIO12 about? It seems the interrupt handler is associated with GPIO12, you are setting the interrupt condtion for GPIO13 and disabling interrupt handling on GPIO14. But what is GPIO12 got to with anything? When you want to apply an interrupt handler, does it need to use up another GPIO pin for some reason?

Code: Select all

   // GPIO12 interrupt handler
   ETS_GPIO_INTR_ATTACH(iw_GPIO_handler, 12);

   ...

    // interrupt on GPIO 13
   gpio_pin_intr_state_set(GPIO_ID_PIN(13), GPIO_PIN_INTR_POSEDGE); // | GPIO_PIN_INTR_NEGEDGE); // Interrupt on any GPIO13 edge
   gpio_pin_intr_state_set(GPIO_ID_PIN(14), GPIO_PIN_INTR_DISABLE);
 


Bruce

FrenkR
Posts: 44
Joined: Thu Dec 04, 2014 9:25 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby FrenkR » Thu Jan 15, 2015 7:42 am

12 is just a "some" number that is passed to INT routine and has nothing to do with GPIO or INT functionality. Check documentation.

brucehvn
Posts: 3
Joined: Tue Dec 30, 2014 9:20 am

Re: Changing GPIO inside task with GPIO interrupts bug?

Postby brucehvn » Fri Jan 16, 2015 7:16 pm

FrenkR wrote:12 is just a "some" number that is passed to INT routine and has nothing to do with GPIO or INT functionality. Check documentation.


Thanks Frenk,

The documentation I have so far shows this:

Code: Select all

ETS_GPIO_INTR_ATTACH (func, arg)
Sign GPIO interrupt handler


So, I'm guessing whatever gets passed in as "arg", ends up being "key" in the interrupt handler:

Code: Select all

// GPIO interrupt handler:store local data and start task
static void ICACHE_FLASH_ATTR
iw_GPIO_handler(int8_t key){


which in your case is not used.

Bruce

Who is online

Users browsing this forum: No registered users and 203 guests