ESP-IDF Hardware Timers
Posted: Fri Jan 18, 2019 5:32 pm
Hi guys,
this is my first post here. So if I'm in the wrong topic or anything else feel free to correct me .
Normally I am working with Atmel Xmega controllers, but as soon as i discovered the ESP32 I fell in love with it . So here I am, trying to understand FreeRtos and the ESP-IDF API. After reading the FreeRtos Tutorial, I am currently trying to get the hardware timers to work. At the moment everything works fine, as long as I am using 1 Timer out of 1 group. When I try to use both timers, some weird things are happening (stuck in Interrupt?)
Here's my library for the timers:
This is my main:
If I uncomment one of the Timer_Init functions, then the timer works fine. (picture shows timer0)
As soon as I try to init both timers this happens:
It seems, that the Handler2 function always gets its task notification.
But why? Does the interrupt get constantly triggered?
Greetings from Germany,
Florian
this is my first post here. So if I'm in the wrong topic or anything else feel free to correct me .
Normally I am working with Atmel Xmega controllers, but as soon as i discovered the ESP32 I fell in love with it . So here I am, trying to understand FreeRtos and the ESP-IDF API. After reading the FreeRtos Tutorial, I am currently trying to get the hardware timers to work. At the moment everything works fine, as long as I am using 1 Timer out of 1 group. When I try to use both timers, some weird things are happening (stuck in Interrupt?)
Here's my library for the timers:
Code: Select all
#ifndef HW_Timer_H
#define HW_Timer_H
#include <stdio.h>
#include "driver/timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
//define Struct
typedef struct
{
timer_idx_t Timer_id;
TaskHandle_t Taskptr;
}Timer_Spec_t;
/*Timer Init
Timer is counting up!
Timer Group = TIMER_GROUP_0 or TIMER_GROUP_1
Timer_id= TIMER_0 or TIMER_1
Division= Division Faktor on the 80Mhz Pher-Clock
Timer_Ovfl= Value when the ISR is triggered
Timer_reload= TIMER_AUTORELOAD_EN/TIMER_AUTORELOAD_DIS
*/
void Timer_Init(timer_group_t Timer_Group, timer_idx_t Timer_id, uint32_t Divider, uint64_t Timer_Ovfl, bool Timer_reload,TaskHandle_t *Taskptr);
//ISR Handling Routine of Timer_Group_0
void IRAM_ATTR timer_group0_isr(void *para);
#endif // !HW_Timer_H
Code: Select all
#include "HW_Timers2.h"
//*************************************************************************************************************************/
// FUNKTIONEN
//*************************************************************************************************************************/
void Timer_Init(timer_group_t Timer_Group, timer_idx_t Timer_id, uint32_t Divider, uint64_t Timer_Ovfl, bool Timer_reload, TaskHandle_t *Taskptr)
{
//define Struct for ISR Pointer
static Timer_Spec_t Timer_Specs;
Timer_Specs.Taskptr = *Taskptr;
Timer_Specs.Timer_id = Timer_id;
//Timer Init. Group0, Timer0
timer_config_t Zeitbasis;
Zeitbasis.divider = Divider;
Zeitbasis.counter_dir = TIMER_COUNT_UP;
Zeitbasis.counter_en = TIMER_PAUSE;
Zeitbasis.alarm_en = TIMER_ALARM_EN;
Zeitbasis.auto_reload = Timer_reload;
Zeitbasis.intr_type = TIMER_INTR_LEVEL;
//Init Timer
timer_init(Timer_Group, Timer_id, &Zeitbasis);
//Set timer to start value
timer_set_counter_value(Timer_Group, Timer_id, 0x00000000ULL);
//Set timer alarm
timer_set_alarm_value(Timer_Group, Timer_id, Timer_Ovfl);
//Interrupt enable
timer_enable_intr(Timer_Group, Timer_id);
if (Timer_Group == TIMER_GROUP_0)
{
timer_isr_register(Timer_Group, Timer_id, timer_group0_isr, (void *) &Timer_Specs, ESP_INTR_FLAG_IRAM, NULL);
}
else
{
//TODO
}
//Timer start
timer_start(Timer_Group, Timer_id);
}
//*************************************************************************************************************************/
// Interrupt Service
//*************************************************************************************************************************/
void IRAM_ATTR timer_group0_isr(void *para)
{
//save the data from the pointer
Timer_Spec_t Settings = *((Timer_Spec_t *) para);
//Get interrupt status
uint32_t intr_status = TIMERG0.int_st_timers.val;
//Delete interrupt flags
if((intr_status & BIT(Settings.Timer_id)) && (Settings.Timer_id) == TIMER_0)
{
TIMERG0.int_clr_timers.t0 = 1;
}
else if((intr_status & BIT(Settings.Timer_id)) && (Settings.Timer_id) == TIMER_1)
{
TIMERG0.int_clr_timers.t1 = 1;
}
//Reactivate alarm
TIMERG0.hw_timer[Settings.Timer_id].config.alarm_en = TIMER_ALARM_EN;
//TaskNotify
xTaskNotifyFromISR(Settings.Taskptr,0x00,eNoAction,NULL);
portYIELD_FROM_ISR();
}
Code: Select all
#include <stdio.h>
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "soc/timer_group_struct.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include "HW_Timers2.h"
void Handler(void *para)
{
static int i;
while (true)
{
xTaskNotifyWait(0x00, 0xffffffff, NULL, portMAX_DELAY);
if (i == 0)
{
i = 1;
gpio_set_level(2, 0);
}
else
{
i = 0;
gpio_set_level(2, 1);
}
}
}
void Handler2(void *para)
{
static int i;
while (true)
{
xTaskNotifyWait(0x00, 0xffffffff, NULL, portMAX_DELAY);
if (i == 0)
{
i = 1;
gpio_set_level(4, 0);
}
else
{
i = 0;
gpio_set_level(4, 1);
}
}
}
void app_main()
{
TaskHandle_t Handle;
TaskHandle_t Handle2;
//Debug
gpio_pad_select_gpio(2);
gpio_set_direction(2, GPIO_MODE_OUTPUT);
gpio_set_level(2, 0);
gpio_pad_select_gpio(4);
gpio_set_direction(4, GPIO_MODE_OUTPUT);
gpio_set_level(4, 0);
xTaskCreate(Handler, "Handler_task", 2048, NULL, 4, &Handle);
xTaskCreate(Handler2, "Handler_task2", 2048, NULL, 3, &Handle2);
Timer_Init(TIMER_GROUP_0, TIMER_0, 16, 12140, TIMER_AUTORELOAD_EN,&Handle);
Timer_Init(TIMER_GROUP_0, TIMER_1, 64, 23150, TIMER_AUTORELOAD_EN, &Handle2);
}
But why? Does the interrupt get constantly triggered?
Greetings from Germany,
Florian