ESP32S3: RTC main counter interrupt while awake

spenderIng
Posts: 7
Joined: Fri Mar 08, 2024 1:57 pm

ESP32S3: RTC main counter interrupt while awake

Postby spenderIng » Fri Mar 08, 2024 2:15 pm

Hello,
I have a problem on ESP32S3.

Statement
Write a program to receive an interrupt from the RTC main timer while ESP32S3 is awake whenever the main counter reaches some finite value.
While asleep the ESP32S3 wakes up at the alarm time that is set using the functions esp_sleep_enable_timer_wakeup() and esp_deep_sleep_start().
But while awake the ESP32S3 does not trigger an interrupt although the interrupt is activated. Refer to the source code.

Software steps

Code: Select all

idf.py set-target esp32-s3

Code: Select all

idf.py build

Code: Select all

rtc_alarm_while_awake$ ~/.espressif/python_env/idf5.1_py3.11_env/bin/python ~/repos/esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3  write_flash --flash_mode dio --flash_size 2MB --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin && idf.py -p /dev/ttyUSB0 monitor
Hardware
Official ESP32-S3-DevKitC-1 via onboard UART port.

Expected behaviour
The control reaches the function rtc_alarm_isr.

Observed behaviour
The control does not reach the function rtc_alarm_isr and causes a task watchdog (TWDT) timeout.

Thank you for your time.

ESP_Sprite
Posts: 9727
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32S3: RTC main counter interrupt while awake

Postby ESP_Sprite » Sat Mar 09, 2024 2:57 am

I think you forgot to attach or link to the source code you mention.

spenderIng
Posts: 7
Joined: Fri Mar 08, 2024 1:57 pm

Re: ESP32S3: RTC main counter interrupt while awake

Postby spenderIng » Mon Mar 11, 2024 2:04 pm

Please find attached the source code that this post relates to. Thank you.

ESP_Sprite
Posts: 9727
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32S3: RTC main counter interrupt while awake

Postby ESP_Sprite » Thu Mar 28, 2024 12:23 pm

Sorry, still nothing.

spenderIng
Posts: 7
Joined: Fri Mar 08, 2024 1:57 pm

Re: ESP32S3: RTC main counter interrupt while awake

Postby spenderIng » Thu Mar 28, 2024 12:55 pm

Hello ESP_Sprite,
because of repeated upload problems, I paste the code here. To use the code:
  • Copy the directory esp-idf/examples/get-started/hello_world to some location locally on your computer.
  • Open the file main/hello_world_main.c.
  • Delete all the contents of the file.
  • Copy the code below
  • Paste it in the main/hello_world_main.c
  • Code: Select all

    idf.py set-target esp32s3
  • Code: Select all

    idf.py build
Thanks and regards!
--------------------------------------------------------------------------------------------------------------------------------------------------------------------

Code: Select all

#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/rtc.h"
#include "esp_private/rtc_ctrl.h"
#include "hal/rtc_cntl_ll.h"
#include "driver/gptimer.h"
/* #include "soc/rtc_cntl_struct.h" */

typedef struct {
    uint64_t event_count;
} example_queue_element_t;


void rtc_alarm_isr(void * arg1);
static bool hw_timer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data);


static const char *TAG = "HIGHLIGHT";
static bool alarm_occured = false;
static bool isr_occured = false;
/* static example_queue_element_t ele; */
static QueueHandle_t queue;
static gptimer_handle_t gptimer = NULL;
static gptimer_event_callbacks_t cbs = {
  .on_alarm = hw_timer_callback,
};
static gptimer_config_t timer_config = {
  .clk_src = GPTIMER_CLK_SRC_DEFAULT,
  .direction = GPTIMER_COUNT_UP,
  .resolution_hz = 1000000, // 1MHz, 1 tick=1us
};
static gptimer_alarm_config_t alarm_config1 = {
  .alarm_count = 1000000, // period = 1s
};


void app_main(void)
{
  printf("\tHIGHLIGHT: Hello world!\n");
  rtc_clk_config_t rtc_cfg = RTC_CLK_CONFIG_DEFAULT();
  rtc_clk_init(rtc_cfg);

  example_queue_element_t ele;
  queue = xQueueCreate(10, sizeof(example_queue_element_t));
  if (!queue) {
    ESP_LOGE(TAG, "Creating queue failed");
    return;
  }
  ESP_LOGI(TAG, "Create timer handle");
  ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));

  ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, queue));
  ESP_LOGI(TAG, "Enable timer");
  ESP_ERROR_CHECK(gptimer_enable(gptimer));

  ESP_LOGI(TAG, "Start timer, stop it at alarm event");
  ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config1));

  /* Faithfully copied from `static void calibrate_ocode(void)` in the file
  esp-idf/components/esp_hw_support/port/esp32s3/rtc_init.c */
  soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
  printf("\tHIGHLIGHT: slow_clk_src: %d\n", slow_clk_src);
  rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
  switch (slow_clk_src)
  {
    case SOC_RTC_SLOW_CLK_SRC_XTAL32K:
    {
      cal_clk = RTC_CAL_32K_XTAL;
      break;
    }
    case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256:
    {
      cal_clk  = RTC_CAL_8MD256;
      break;
    }
    default:
    {
      /* Do nothing. Leave it to the initial value. */
      break;
    }
  }
  uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);

  uint64_t before_rtc_counter_ticks = rtc_time_get();
  /* uint64_t rtc_counter_us = rtc_time_slowclk_to_us(rtc_counter_ticks, slow_clk_period); */
  /* printf("\tHIGHLIGHT: Before delay rtc_counter_us: %llu\n", rtc_counter_us); */
  /* uint64_t before_rtc_counter_us = rtc_counter_us; */

  ESP_ERROR_CHECK(gptimer_start(gptimer));
  if (xQueueReceive(queue, &ele, portMAX_DELAY)) {
    /* ESP_LOGI(TAG, "Timer stopped, count=%llu", ele.event_count); */
  } else {
    ESP_LOGW(TAG, "Missed one count event");
  }

  uint64_t rtc_counter_ticks = rtc_time_get();
  /* rtc_counter_us = rtc_time_slowclk_to_us(rtc_counter_ticks, slow_clk_period); */
  uint64_t difference_ticks = rtc_counter_ticks - before_rtc_counter_ticks;
  uint64_t difference_us = rtc_time_slowclk_to_us(difference_ticks, slow_clk_period);
  /* printf("\tHIGHLIGHT: After delay rtc_counter_us: %llu\n", rtc_counter_us); */
  printf("\tHIGHLIGHT: Difference rtc_counter_us: %llu\n", difference_us);

  /* uint32_t NirCount = 0; */
  while (1)
  {
    if (alarm_occured)
    {
      printf("\tHIGHLIGHT: Hello from hw_timer_callback\n");
      alarm_occured = false;
      break;
    }
    else
    {
      printf("\tHIGHLIGHT: Hello from else.\n");
    }
  }

  vQueueDelete(queue);

  uint8_t arg1 = 0xF0;
  if (ESP_OK != rtc_isr_register(&rtc_alarm_isr, &arg1, RTC_CNTL_MAIN_TIMER_INT_ENA_M, 0))
  {
    printf("\tHIGHLIGHT: Could not register the rtc isr.");
  }
  rtc_counter_ticks = rtc_time_get();
  rtc_cntl_ll_set_wakeup_timer(rtc_counter_ticks + alarm_config1.alarm_count * 5);

  while(!isr_occured);

  printf("\tHIGHLIGHT: arg1: %u", arg1);
  printf("\tHIGHLIGHT: Back to app_main.");
}

static bool hw_timer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{
  BaseType_t high_task_awoken = pdFALSE;
  QueueHandle_t queue = (QueueHandle_t)user_data;
  // stop timer immediately
  gptimer_stop(timer);

  alarm_occured = true;
  // Retrieve count value and send to queue
  example_queue_element_t ele = {
      .event_count = edata->count_value
  };
  xQueueSendFromISR(queue, &ele, &high_task_awoken);
  // return whether we need to yield at the end of ISR
  return (high_task_awoken == pdTRUE);
}

void rtc_alarm_isr(void * arg1)
{
  uint8_t * argOne = arg1;
  /* printf("\tHIGHLIGHT: Before RTC arg1 is: %X\n", *argOne); */
  (*argOne)++;
  /* printf("\tHIGHLIGHT: After RTC arg1 is: %X\n", *argOne); */
  isr_occured = true;
}

ESP_Sprite
Posts: 9727
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32S3: RTC main counter interrupt while awake

Postby ESP_Sprite » Fri Mar 29, 2024 2:03 am

Why are you messing with the RTC in that way? As the header directory indicates, those functions are private to ESP-IDF; it's very likely that ESP-IDF also uses the RTC for stuff and your code interferes.

spenderIng
Posts: 7
Joined: Fri Mar 08, 2024 1:57 pm

Re: ESP32S3: RTC main counter interrupt while awake

Postby spenderIng » Thu Apr 04, 2024 9:47 am

Greetings ESP_Sprite,
thank you for the reply. The reason is, that I would like to set multiple `software timers` that track time irrespective of the sleep mode. This is possible only by the RTC timer/ counter. No other timer is working in the deep sleep mode.

The timers are successfully set and the MCU wakes up from deep sleep when the required delay is achieved. The problem that I face is I want a callback/ interrupt service routine that shall be invoked upon timeout when the MCU is awake.

ESP_Sprite
Posts: 9727
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32S3: RTC main counter interrupt while awake

Postby ESP_Sprite » Fri Apr 05, 2024 2:30 am

Hm, I think this can be done in a less intrusive manner.
* Figure out the timestamp you want to wakeup. Use clock_gettime(CLOCK_MONOTONIC) if you need a differential time ('5 minutes from now' rather than '07.59AM'), use gettimeofday() otherwise.
* When going to deep sleep, sleep for the time needed to reach the wakeup time.
* On wakeup, see if you still need time before the event. (E.g. if you also wake up from GPIOs.)
* If so, use e.g. esp_timer to set an alarm callback.

spenderIng
Posts: 7
Joined: Fri Mar 08, 2024 1:57 pm

Re: ESP32S3: RTC main counter interrupt while awake

Postby spenderIng » Fri Apr 19, 2024 9:25 am

Respected ESP_Sprite,
thank you for the hint. I could successfully use the method that you described. A disadvantage of this method is that I have to use two timers. The software complexity increases a bit. The advantage is that it works! How can I mark your answer as the accepted?

ESP_Sprite
Posts: 9727
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32S3: RTC main counter interrupt while awake

Postby ESP_Sprite » Fri Apr 19, 2024 11:40 am

Glad to hear it works. No need to mark the answer as accepted, the forum doesn't have functionality for that.

Who is online

Users browsing this forum: ESP_Roland, espmpo and 86 guests