配置定时器警报一秒一次,在中断中通过信号量传递给处理任务,在定时器初始化时需要注意一个问题:
timer_config.intr_priority = 0; 该成员必须配置,设置为0 系统会分配给一个较低的优先级,如果不配置会重启报错:
E (811) gptimer: gptimer_new_timer(115): invalid interrupt priority:-2113815094
测试程序:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/gptimer.h"
#include "esp_log.h"
static const char *TAG = "example";
SemaphoreHandle_t BinarySem_Handle;
static bool IRAM_ATTR gptimer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* 重新配置报警值 */
gptimer_alarm_config_t alarm_config = {
.alarm_count = edata->alarm_value + 1000000, /* 在接下来的1秒内报警 */
};
gptimer_set_alarm_action(timer, &alarm_config);
xSemaphoreGiveFromISR(BinarySem_Handle, &xHigherPriorityTaskWoken); //发送二值信号量
/* 返回是否需要在ISR结束时让步 */
return xHigherPriorityTaskWoken == pdTRUE;
}
void init_gptimer(void)
{
gptimer_handle_t gptimer = NULL;
gptimer_config_t timer_config;
gptimer_alarm_config_t alarm_config;
timer_config.clk_src = GPTIMER_CLK_SRC_DEFAULT; //选择 APB 作为默认选项
timer_config.direction = GPTIMER_COUNT_UP; //向上计数,即从 0 到 65535
timer_config.resolution_hz = 1000000; //设置内部计数器的分辨率。计数器每滴答一次相当于 1 / resolution_hz 秒
timer_config.flags.intr_shared = false;
timer_config.intr_priority = 0; //注意这里一定要写,否则会重启
ESP_LOGI(TAG, "init_gptimer");
//实例化定时器实例并返回定时器句柄
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_event_callbacks_t cbs;
cbs.on_alarm = gptimer_callback;
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
//使能定时器
ESP_ERROR_CHECK(gptimer_enable(gptimer));
//设置报警
alarm_config.alarm_count = 1000000; // period = 1s
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config)); //配置定时器报警
ESP_ERROR_CHECK(gptimer_start(gptimer)); //开始定时器
}
void alarm_dispose(void)
{
BaseType_t xReturn = pdPASS;
while(1)
{
xReturn = xSemaphoreTake(BinarySem_Handle, portMAX_DELAY);
if(pdTRUE == xReturn)
{
printf("gptimer alarm\n");
}
}
}
void app_main(void)
{
uint32_t i= 0;
//创建一个二值信号量
BinarySem_Handle = xSemaphoreCreateBinary();
xTaskCreate((TaskFunction_t)alarm_dispose, "alarm_dispose", 2048, NULL, 1, NULL);
init_gptimer();
ESP_LOGI(TAG, "Hello World");
while(1)
{
printf("run %lu\n", i);
++i;
vTaskDelay(500);
}
}