Skip to content

hw_timer frc1 with reload mode false and CLKDIV_256 causes WDT (GIT8266O-664) #1086

Open
@jvh003

Description

@jvh003

Environment

  • Development Kit: NodemcuV2
  • IDF version: 8b6329d (latest on April 25, 2021)
  • Development Env: [Make and Eclipse]
  • Operating System: [Windows-10]
  • Power Supply: [USB]

Problem Description

Trying to use the frc1 hardware timer with CLKDIV 256 in single shot mode to set a delay of 20s. My test interrupt service routine enables 2 GPIO pins for debug, and also sends a message to a message queue.
Changed my test code to use a 1s delay for testing.

As a small (minor) thing I also noticed while try to work on this:
The comment on line 27 in timer_struct.h is in-correct.
The FRC1 is a 23 bit timer, not 24 as stated in the include file.

/* ESP8266 FRC Register Definitions */
// FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero.

Expected Behavior

After 1s the interrupt service routine should fire, turn on the 2 GPIO pins, and send my test msg to the queue. See function hw_timer_callback() below.
This timer should work in either reload true or false mode.

Actual Behavior

This timer only works properly in reload true mode.
If the reload mode is false:

  • After 1s, I can see that the GPIO pins are enabled, as I have 2 LEDs wired up.
  • I assume that the msg is sent to the queue, but I don't know this for certain.
  • My msgTask task is not unblocked to process the msg from the queue as I don't see my log.
  • The board eventually restarts as triggered by a WDT.

Steps to repropduce

Load the code and run it.
The code was modified from the example code found here: hw_timer_example_main.c
However, since I wanted to code up a larger delay ie: 20s, I modified the example to explicitly call all the hw_timer functions that the function hw_timer_alarm_us() was calling internally. (see below).

Code to reproduce this issue

#include <stdio.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "appMain.h"
#include "LedControl.h"
#include "driver/hw_timer.h"


#define LED_ON_BOARD_BLUE   GPIO_NUM_2   // D4 - Esp12e onboard blue led
#define LEFT_LED            GPIO_NUM_0   // D3 - Left red Led
#define RIGHT_LED           GPIO_NUM_15  // D8 - Right red Led
#define GPIO_OUTPUT_IO_0    LEFT_LED
#define GPIO_OUTPUT_IO_1    RIGHT_LED

static const char TAG[] = "main";
static QueueHandle_t MsgQueue = NULL;

void initPin(gpio_num_t pin)
{
   gpio_config_t config;
   memset((void*)&config, 0, sizeof(config));
   config.intr_type = GPIO_INTR_DISABLE;
   config.mode = GPIO_MODE_OUTPUT;
   config.pin_bit_mask = (1UL << pin);
   config.pull_down_en = GPIO_PULLDOWN_DISABLE;
   config.pull_up_en = GPIO_PULLUP_DISABLE;
   gpio_config(&config);
   gpio_set_level(pin, 0);
}

void ledsOn()
{
   gpio_set_level(LED_ON_BOARD_BLUE, 0);  // active low
   gpio_set_level(LEFT_LED, 1);
   gpio_set_level(RIGHT_LED, 1);
}

void ledsOff()
{
   gpio_set_level(LED_ON_BOARD_BLUE, 1);  // active low
   gpio_set_level(LEFT_LED, 0);
   gpio_set_level(RIGHT_LED, 0);
}

void hw_timer_callback(void *arg)
{
    gpio_set_level(GPIO_OUTPUT_IO_0, 1);
    xQueueSendFromISR(MsgQueue, &arg, NULL);
    gpio_set_level(GPIO_OUTPUT_IO_1, 1);
}


void msgTask(void *arg)
{
   void *pMsg;
   uint32_t value;
   printf("msgTask() start\n");
   while (true)
   {
      xQueueReceive(MsgQueue, &pMsg, portMAX_DELAY);
      value = *((uint32_t *)pMsg);
      ESP_LOGW(TAG, "msg rec'd %u from %u", value, (uint32_t)pMsg);
      ledsOff();
   }
}


void app_main()
{
   /* Print chip information */
   esp_chip_info_t chip_info;
   esp_chip_info(&chip_info);
   printf("This is ESP8266 chip with %d CPU cores, WiFi, ", chip_info.cores);
   printf("silicon revision %d, ", chip_info.revision);
   printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
          (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

   initPin(LED_ON_BOARD_BLUE);
   initPin(LEFT_LED);
   initPin(RIGHT_LED);
   ledsOff();

   MsgQueue = xQueueCreate(10, sizeof(void *));
   if (MsgQueue == NULL)
   {
      ESP_LOGE(TAG, "Failed to create queue");
   }
   xTaskCreate(&msgTask, "MsgTask", 4096, NULL, 5, NULL);

   int delay = 10; //seconds
   uint32_t arg = 30;

   for (int i=0; i<20; i++)
   {
#if 0
      ESP_LOGI(TAG, "Initialize hw_timer for callback");
      hw_timer_init(hw_timer_callback, &arg);
      ESP_LOGI(TAG, "Set hw_timer timing time 1000ms with reload: %d", TEST_RELOAD);
      hw_timer_alarm_us(1000000, TEST_RELOAD);
#else

#if 0
      // this code block works fine with reload true or false
      uint32_t value = 1000000; // 1s
      uint32_t counter = ((TIMER_BASE_CLK >> TIMER_CLKDIV_16) / 1000000) * value; // value units are micro-seconds
      ESP_LOGI(TAG, "Initialize hw_timer for callback, value %u, counter %u (0x%x)", value, counter, counter);
      hw_timer_init(hw_timer_callback, &arg);
      hw_timer_set_reload(true); // false - also works
      hw_timer_set_clkdiv(TIMER_CLKDIV_16);
      hw_timer_set_intr_type(TIMER_EDGE_INT);
      hw_timer_set_load_data(counter);
      ESP_LOGI(TAG, "Retrieved counter %u", hw_timer_get_load_data());
      hw_timer_enable(true);
#else
      // this code block works only if reload is true, it hangs and WDT if reload is false
      uint32_t value = 1;  // 1s
      uint32_t counter = (TIMER_BASE_CLK >> TIMER_CLKDIV_256) * value;  // units seconds
      ESP_LOGI(TAG, "Initialize hw_timer for callback, value %u, counter %u (0x%x)", value, counter, counter);
      hw_timer_init(hw_timer_callback, &arg);
      hw_timer_set_reload(false);  // true is ok, false hangs and causes WDT
      hw_timer_set_clkdiv(TIMER_CLKDIV_256);
      hw_timer_set_intr_type(TIMER_EDGE_INT);
      hw_timer_set_load_data(counter);
      ESP_LOGI(TAG, "Retrieved counter %u", hw_timer_get_load_data());
      hw_timer_enable(true);
#endif
#endif

      printf("Delay %ds\n", delay);
      vTaskDelay((delay * 1000)/portTICK_PERIOD_MS);
      printf("Disarm the timer\n");
      hw_timer_disarm();
      hw_timer_deinit();
      ledsOff();
   }
   
   printf("Restarting now.\n");
   fflush(stdout);
   esp_restart();
}

Debug Logs

Logs for the code running the timer in reload true mode.
This is the expected output.

I (59) boot: ESP-IDF v3.4-rc-dirty 2nd stage bootloader
I (60) boot: compile time 17:56:03
I (68) qio_mode: Enabling default flash chip QIO
I (69) boot: SPI Speed      : 40MHz
I (74) boot: SPI Mode       : QIO
I (80) boot: SPI Flash Size : 2MB
I (86) boot: Partition Table:
I (91) boot: ## Label            Usage          Type ST Offset   Length
I (103) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (114) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (126) boot:  2 factory          factory app      00 00 00010000 000f0000
I (137) boot: End of partition table
I (144) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x1c1b0 (115120) map
0x40210010: _stext at ??:?

I (196) esp_image: segment 1: paddr=0x0002c1c8 vaddr=0x4022c1c0 size=0x072cc ( 29388) map
I (207) esp_image: segment 2: paddr=0x0003349c vaddr=0x3ffe8000 size=0x00554 (  1364) load
I (208) esp_image: segment 3: paddr=0x000339f8 vaddr=0x40100000 size=0x00080 (   128) load
I (221) esp_image: segment 4: paddr=0x00033a80 vaddr=0x40100080 size=0x04fac ( 20396) load
I (241) boot: Loaded app from partition at offset 0x10000
This is ESP8266 chip with 1 CPU cores, WiFi, silicon revision 1, 2MB external flash
I (256) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (264) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (278) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
msgTask() start
I (295) main: Initialize hw_timer for callback, value 1, counter 312500 (0x4c4b4)
I (307) main: Retrieved counter 312500
Delay 10s
W (1315) main: msg rec'd 30 from 1073654908
W (2315) main: msg rec'd 30 from 1073654908
W (3315) main: msg rec'd 30 from 1073654908
W (4315) main: msg rec'd 30 from 1073654908
W (5315) main: msg rec'd 30 from 1073654908
W (6315) main: msg rec'd 30 from 1073654908
W (7315) main: msg rec'd 30 from 1073654908
W (8315) main: msg rec'd 30 from 1073654908
W (9315) main: msg rec'd 30 from 1073654908
W (10316) main: msg rec'd 30 from 1073654908
Disarm the timer
I (10317) main: Initialize hw_timer for callback, value 1, counter 312500 (0x4c4b4)
I (10323) main: Retrieved counter 312500
Delay 10s
W (11336) main: msg rec'd 30 from 1073654908
W (12336) main: msg rec'd 30 from 1073654908
W (13336) main: msg rec'd 30 from 1073654908
W (14336) main: msg rec'd 30 from 1073654908
W (15336) main: msg rec'd 30 from 1073654908
W (16336) main: msg rec'd 30 from 1073654908
W (17336) main: msg rec'd 30 from 1073654908
W (18336) main: msg rec'd 30 from 1073654908
W (19336) main: msg rec'd 30 from 1073654908
Disarm the timer

These are the logs for the code running in reload false mode with the WDT:

I (59) boot: ESP-IDF v3.4-12-g8b6329de-dirty 2nd stage bootloader
I (60) boot: compile time 17:11:26
I (68) qio_mode: Enabling default flash chip QIO
I (69) boot: SPI Speed      : 40MHz
I (75) boot: SPI Mode       : QIO
I (81) boot: SPI Flash Size : 2MB
I (87) boot: Partition Table:
I (93) boot: ## Label            Usage          Type ST Offset   Length
I (104) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (116) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (127) boot:  2 factory          factory app      00 00 00010000 000f0000
I (139) boot: End of partition table
I (145) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x1c1c4 (115140) map
0x40210010: _stext at ??:?

I (197) esp_image: segment 1: paddr=0x0002c1dc vaddr=0x4022c1d4 size=0x072e4 ( 29412) map
I (208) esp_image: segment 2: paddr=0x000334c8 vaddr=0x3ffe8000 size=0x00554 (  1364) load
I (209) esp_image: segment 3: paddr=0x00033a24 vaddr=0x40100000 size=0x00080 (   128) load
I (223) esp_image: segment 4: paddr=0x00033aac vaddr=0x40100080 size=0x04fac ( 20396) load
I (242) boot: Loaded app from partition at offset 0x10000
This is ESP8266 chip with 1 CPU cores, WiFi, silicon revision 1, 2MB external flash
I (257) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (265) gpio: GPIO[0]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (279) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
msgTask() start
I (296) main: Initialize hw_timer for callback, value 1, counter 312500 (0x4c4b4)
I (308) main: Retrieved counter 312500
Delay 10s
Task watchdog got triggered.

Guru Meditation Error: Core  0 panic'ed (IllegalInstruction). Exception was unhandled.
Core 0 register dump:
PC      : 0x4010050e  PS      : 0x00000030  A0      : 0x4010050e  A1      : 0x3ffecde0
0x4010050e: PendSV at D:/development/esp32-dev/ESP8266_RTOS_SDK/components/freertos/port/esp8266/port.c:123
0x4010050e: PendSV at D:/development/esp32-dev/ESP8266_RTOS_SDK/components/freertos/port/esp8266/port.c:123

A2      : 0x00000020  A3      : 0x00000000  A4      : 0x4010555c  A5      : 0x3ffeba9c
A6      : 0xffffffff  A7      : 0x0000000a  A8      : 0x00000000  A9      : 0x00000001
A10     : 0x4022e0f6  A11     : 0x0000000a  A12     : 0x3ffebde0  A13     : 0x00000001
A14     : 0x3ffece30  A15     : 0x00000000  SAR     : 0x00000000  EXCCAUSE: 0x00000000

Backtrace: 0x4010050e:0x3ffecde0 0x402167c4:0x3ffecdf0 0x40216ed7:0x3ffece30
0x4010050e: PendSV at D:/development/esp32-dev/ESP8266_RTOS_SDK/components/freertos/port/esp8266/port.c:123
0x402167c4: xQueueReceive at D:/development/esp32-dev/ESP8266_RTOS_SDK/components/freertos/freertos/queue.c:1345
0x40216ed7: msgTask(void*) at D:/development/eclipse-workspace/esp12-hwtimer-test/main/appMain.cpp:68

Other items if possible

Let me know if you really need/want the sdkconfig or ELF file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions