I have trouble using the freertos software timer(h[url]ttps://www.freertos.org/FreeRTOS-Software-Time ... tions.html)[/url].
Here's the scenario. I've attached a button to ESP32 and activated the ESP's internal pull-up. The button's other terminal is attached to ground. I want the ESP to start a configuration task (this won't happen very often) if the button is pushed for at least three seconds. This way I want to eliminate accidental pushes.
My thinking was as follows: Execute an ISR when the button is pushed. When inside the ISR disable it, so it doesn't get triggered multiple times and start the timer from inside the ISR. When the timer has expired a callback function is called which is located outside the ISR. The callback function reads the level of the pin the button is attached to. If it is still low, the task will be created. If not, the software interrupt is enabled again and the software continues normal operation.
The timer and pin configuration is done inside an init function
Here's the corresponding code
Code: Select all
#define USER_SWITCH 26 /* pin the button is attached to */
#define ESP_INTR_FLAG_DEFAULT 0
bool intentional_press;
TimerHandle_t button_timer;
void * button_timer_id;
gpio_pad_select_gpio(USER_SWITCH);
ESP_ERROR_CHECK(gpio_set_direction(USER_SWITCH,GPIO_MODE_INPUT));
ESP_ERROR_CHECK(gpio_set_pull_mode(USER_SWITCH,GPIO_PULLUP_ONLY));
ESP_ERROR_CHECK(gpio_set_intr_type(USER_SWITCH,GPIO_PIN_INTR_NEGEDGE));
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(USER_SWITCH, user_switch_isr_handler, (void*) USER_SWITCH);
intentional_press = 0;
button_timer = xTimerCreate("button_timer",3000/portTICK_PERIOD_MS,pdFALSE,button_timer_id,button_timer_callback);
Code: Select all
void IRAM_ATTR user_switch_isr_handler(void* arg)
{
printf("Servicing ISR\n");
gpio_intr_disable(USER_SWITCH);
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(xTimerStartFromISR(button_timer,&xHigherPriorityTaskWoken)!= pdPASS)
{
printf("Error while starting Timer!\n");
}/*(xTimerStartFromISR(button_timer,&xHigherPriorityTaskWoken)!= pdPASS)*/
if( xHigherPriorityTaskWoken != pdFALSE)
{
printf("Impeded a higher priority task from execution!");
}/* if( xHigherPriorityTaskWoken != pdFALSE) */
} /* end user_switch_isr_handler */
Code: Select all
if( xHigherPriorityTaskWoken != pdFALSE)
Second problem, if I run the program and push the button shortly, I get the following error:
abort() was called at PC 0x4008251d on core 0
Backtrace: 0x40086798:0x3ffb04c0 0x40086897:0x3ffb04e0 0x4008251d:0x3ffb0500 0x4
008263d:0x3ffb0530 0x400d266a:0x3ffb0550 0x400d26c5:0x3ffb0590 0x4008247a:0x3ffb
05b0 0x400835fa:0x3ffb05e0 0x40081dde:0x3ffb0600 0x400d1a67:0x00000000
Rebooting...
So I loaded the binary with GDB and ran: list* 0x4008251d.
What I got was
Code: Select all
0x4008251d is in lock_acquire_generic (~/esp/esp-idf/components/newlib/./locks.c:141).
136
137 BaseType_t success;
138 if (xPortInIsrContext()) {
139 /* In ISR Context */
140 if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
141 abort(); /* recursive mutexes make no sense in ISR context */
142 }
143 BaseType_t higher_task_woken = false;
144 success = xSemaphoreTakeFromISR(h, &higher_task_woken);
145 if (!success && delay > 0) {
Help would be appriciated.
Chris