esp8266在后台运行下载的二进制文件

时间:2018-06-16 17:21:32

标签: esp8266 background-task

梗概:

我所有基于ESP8266 / 32的设备(我有大约1000个)正在读取传感器,进行边缘计算并将数据发送回中央服务器。

但大部分时间他们都在空转。

所以我想如果可能出现以下情况:

  1. 我编写了一个从服务器轮询任务的库
  2. 如果找到任务,则下载任务
  3. 任务在ESP的后台运行(主循环逻辑的背景)
  4. 任务完成后,数据将发送回任务服务器
  5. 问题出在第3点。

    是否有可能在背景中“运行”一个单独的bin文件(比如SPIFFS),类似于linux:

     pid_t pid = fork();
     execv
    

    如果没有(我猜它不是),你还能想到其他选择吗? (就像后台任务一样)?

1 个答案:

答案 0 :(得分:1)

ESP8266是一款非常简单的处理器。 Linux fork()拥有大量硬件支持,可为进程隔离地址空间并支持抢占式多任务处理。 ESP8266没有硬件支持来执行此操作,并且它运行的操作系统没有过程模型。因此,无论如何,您都不会使用fork()

如果您正在使用Arduino SDK,那么您还可以使用构建Arduino SDK的"Non-OS" SDK。非OS SDK甚至没有任何内部概念的任务或协同例程。因此,如果您使用的是Arduino SDK或在非操作系统SDK上构建的任何其他SDK,则您需要实施自己的背景"处理

在Arduino SDK中,您重写了loop()代码,以便检查是否有正常的前台工作,处理该代码,然后执行一定量的后台工作。在返回前台工作之前,您需要确定可以执行的后台工作量。此外,您还需要确保后台工作偶尔调用yield()delay(),以便看门狗计时器不会被激活。

它不会很漂亮。

所以你的代码看起来像是:

#define ELAPSED_WORK_TIME (millis() - work_start_time)

// maximum milliseconds before we must check if there's foreground work
// or yield() to keep the watchdog timer happy
#define MAX_WORK_TIME  1000

void loop() {
  while(foreground_work_is_available()) {
    do_foreground_work();
    yield();
  }

  if(background_work_is_available()) {
    unsigned long work_start_time = millis();

    do_some_work();

    if(ELAPSED_WORK_TIME > MAX_WORK_TIME)
      return;

    do_some_more_work();

    if(ELAPSED_WORK_TIME > MAX_WORK_TIME)
      return;
  }
}

或者如果你可以确定你的后台代码块运行时间太长你可以在循环中使用状态变量,当你运行一大块背景代码时,设置状态变量来指示下一个要运行的块并返回以允许loop()继续。

这样的事情:

#define STATE_CHUNK1 1
#define STATE_CHUNK2 2
#define STATE_CHUNK3 3
#define STATE_CHUNK4 4

void loop() {
  static int background_work_state = STATE_CHUNK1;

  while(foreground_work_is_available()) {
    do_foreground_work();
    yield();
  }

  switch(loop_state) {
    case STATE_CHUNK1:
      work_chunk1();
      background_work_state = STATE_CHUNK2;
      return;

    case STATE_CHUNK2:
      work_chunk2();
      background_work_state = STATE_CHUNK3;
      return;

    case STATE_CHUNK3:
      work_chunk3();
      background_work_state = STATE_CHUNK3;
      return;

    case STATE_CHUNK4:
      work_chunk4();
      background_work_state = STATE_CHUNK4;
      return;
   }
}

如果需要,您可以使状态机更加复杂。可能work_chunk2()可能会失败并且您希望下次返回work_chunk1() - 然后您要测试其返回值以决定是否将background_work_state设置为{{ 1}}或STATE_CHUNK1

还有另一个用于ESP8266的SDK,称为"RTOS" SDK - 实时操作系统 - 文档为here。它可能更适合做你想做的事情。您仍然无法使用STATE_CHUNK3或抢占式多任务处理,但它更加异步,并且有一个编程模型,允许您将代码分解为单独的任务,为你奔跑。缺点是它比Arduino环境更复杂,记录更少,您几乎肯定必须完全重写现有代码才能使用它。