Description
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.