任务看门狗被触发 - 任务没有及时重置看门狗

问题描述 投票:0回答:4

我正在尝试编写一个小型异步Web服务器。让我简单描述一下场景:

我的ESP32也是路由器。因此,如果我用手机连接 ESP32 正在传播的 WiFi,并使用浏览器调用 IP 地址和特殊路径,就会发送一个网站。这里显示一个按钮。到目前为止,它运行得很好。现在,如果我单击该按钮,则会将 HTTPS Web 请求(方法:GET)发送到特殊机器。本机应答并返回 JSON。这可能会持续几秒钟。从 JSON 字符串中提取值后,应显示该值。

为了实现这一目标,我使用以下库:

我知道(通过另一个草图)最后三个可以正常工作。

不幸的是,当我单击按钮时,以下输出出现在我的串行监视器上:

开始连接到服务器...
[HTTPS]开始...路径:https://192.168.4.101/api/unlock/generate_pin
[HTTPS] 获取...
E (137906) task_wdt:任务看门狗被触发。以下任务没有及时重置看门狗:
E(137906)task_wdt:-async_tcp(CPU 0/1)
E(137906)task_wdt:当前正在运行的任务:
E(137906)task_wdt:CPU 0:IDLE0
E(137906)task_wdt:CPU 1:loopTask
E(137906)task_wdt:正在中止。
abort() 在核心 0 上的 PC 0x400e08af 处被调用

回溯:0x4008cc18:0x3ffbe170 0x4008ce49:0x3ffbe190 0x400e08af:0x3ffbe1b0 0x40084f21:0x3ffbe1d0 0x4016581b:0x3ffbc120 0x400e1c66:0x3ffbc140 0 x4008ab21:0x3ffbc160 0x4008932d:0x3ffbc180

正在重启...
2016 年 6 月 8 日 00:22:57

首先:0xc(SW_CPU_RESET),启动:0x17(SPI_FAST_FLASH_BOOT)
配置sip:0,SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
模式:DIO,时钟分频:1
负载:0x3fff0018,长度:4
负载:0x3fff001c,长度:1044
负载:0x40078000,长度:8896
负载:0x40080400,长度:5816
条目 0x400806ac
串行初始完成

有人知道发生了什么事以及如何解决这个问题吗?以便正确发送 GET 请求/收到应答?

我正在使用 Heltec WiFi 套件 32

对每一个答案都会非常高兴,提前致谢。

致以诚挚的问候

P.S.:请让我最后添加我的代码:

#include <heltec.h>
#include "WiFi.h"
#include "ESPAsyncWebServer.h"

#include <WiFiClientSecure.h>
#include <HTTPClient.h>
 
const char* ssid = "MyWiFiSSID";
const char* password =  "MyWiFiPW";
 
AsyncWebServer server(80);

void setup() {

  Heltec.begin(true, false, true, true, 470E6);

  WiFi.softAP(ssid, password);
  
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AccessPoint IP address: ");
  Serial.println(IP);
  
  server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    
    request->send(200, "text/html", "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" charset=\"UTF-8\"><link rel=\"icon\" href=\"data:,\"><style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}.button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}</style></head><body><h1>Welcome to the Landing Page of the Web Server</h1><p><a href=\"/get_unlock_pin\"><button class=\"button\">Click Me</button></a></p></body></html>");
  });

  server.on("/get_unlock_pin", HTTP_GET, [](AsyncWebServerRequest *request){

    String firstpartofrawhtmlcode = "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" charset=\"UTF-8\"><link rel=\"icon\" href=\"data:,\"><style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}.button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}</style></head><body><h2>Received Pin: </h2><h2 style=\"color: #FF0000\">";
    String receivedPin = getPin("192.168.4.101");
    String secondpartofrawhtmlcode = "</h2></body></html>";
    String fullrawhtmlcode;
    firstpartofrawhtmlcode = firstpartofrawhtmlcode.concat(receivedPin);
    fullrawhtmlcode = firstpartofrawhtmlcode.concat(secondpartofrawhtmlcode);
    request->send(200, "text/html", fullrawhtmlcode);
  });
 
  server.begin();
}

void loop() {

}

String getPin(String ip){
    Serial.println("\nStarting connection to server...");  
    WiFiClientSecure *wificlient = new WiFiClientSecure;

    HTTPClient https;
    https.setAuthorization("MyUserName", "MyPassword");

    String path = "https://" + ip + "/api/unlock/generate_pin";
      
    Serial.print("[HTTPS] begin... Path: " + path + "\n");
    if (https.begin(*wificlient, path)) { 
        Serial.print("[HTTPS] GET...\n");
        int httpCode = https.GET();
        if (httpCode > 0) {
          Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
  
          if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
            String payload = https.getString();
            Serial.println(payload);
            //Extract Pin from JSON
            String tmp = payload.substring(payload.indexOf(':'), payload.indexOf('}'));
            String tmp2 = tmp.substring(tmp.indexOf('"')+1,tmp.lastIndexOf('"')); 
            if(tmp2.substring(0,1) == "-"){
               return "-";
            }else{
               return tmp2;
            }              
          }
        } else {
               Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }  
        https.end();
    } else {
        Serial.printf("[HTTPS] Unable to connect\n");
    }
}
asynchronous webserver task esp32 watchdog
4个回答
6
投票

ESPAsyncWebServer 回调可防止看门狗计时器在运行时重置。这意味着它们不适合进行任何实际处理。注册请求并将处理推迟到主循环(或其他线程)。看看这个问题了解详情。


4
投票

深入研究这个问题后;我找到了一个相当简单的解决方案;

只需添加:

#include "soc/rtc_wdt.h"
到库中。

然后做:

rtc_wdt_protect_off();    // Turns off the automatic wdt service
rtc_wdt_enable();         // Turn it on manually
rtc_wdt_set_time(RTC_WDT_STAGE0, 20000);  // Define how long you desire to let dog wait.

然后你需要做

rtc_wdt_feed();
去某个你认为它跑得比狗等待时间还快的地方喂狗。


1
投票

我在菜单配置中找到了这个:

CONFIG_ESP_INT_WDT_TIMEOUT_MS
,以及其他一些相关项目,正如一些人已经提到的,但这一个因其描述而引起了我的注意:

看门狗的超时时间,以毫秒为单位。 使其高于 FreeRTOS 滴答率

FreeRTOS 滴答率 (

FREERTOS_HZ
):

FreeRTOS 进行抢占式上下文切换的滴答率。

在menuconfig中默认设置为100Hz,但低于1000Hz将无法闪烁。

既然如此,

CONFIG_ESP_INT_WDT_TIMEOUT_MS
的300毫秒默认值就没有多大意义。我将其更改为 1300 毫秒,并将
CONFIG_ESP_TASK_WDT_TIMEOUT_S
更改为 10 秒。

这些变化让我的情况变得更好,但如果任务阻塞时间太长,它仍然会中止。


0
投票

我想到了一个有趣的事情:问题不在于某件事花费了太长时间,而是给定的任务无关。我到处都有一件事,只是偶尔根据变量中的值触发,如果不满足条件,就会发生所描述的问题。我认为如果循环本质上是空的,那么它永远不会重置看门狗。只是没有时间。

© www.soinside.com 2019 - 2024. All rights reserved.