【问题标题】:Use variables with both cores and tasks ESP32对内核和任务 ESP32 使用变量
【发布时间】:2022-10-06 16:50:49
【问题描述】:

我试图从核心 0 接收的 i2c 设备读取数据,然后将该数据存储到一些全局值中,然后这些值由核心 1 读取,然后打印出来。问题是每当核心 0 尝试访问这些变量时,它都会输出“guru messenger error core 0 panic\'ed (loadprohibited). exception was unhandled\”。 2个核心可以通过什么方式相互通信?

TaskHandle_t Task1;
TaskHandle_t Task2;
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1015 ads; 
volatile int16_t adc0, adc1, adc2, adc3;
volatile float volts0, volts1, volts2, volts3;
void setup() {
  Serial.begin(115200); 
  delay(1000);
  Serial.println(\"Hello!\");
  Serial.println(\"Getting single-ended readings from AIN0..3\");
  Serial.println(\"ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115\");
  //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
  xTaskCreatePinnedToCore(
                    Task1code,   /* Task function. */
                    \"Task1\",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    1,           /* priority of the task */
                    &Task1,      /* Task handle to keep track of created task */
                    0);          /* pin task to core 0 */                  
  delay(500); 

  //create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
  xTaskCreatePinnedToCore(
                    Task2code,   /* Task function. */
                    \"Task2\",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    &Task2,      /* Task handle to keep track of created task */
                    1);          /* pin task to core 1 */
    delay(500); 
    if (!ads.begin()) {
    Serial.println(\"Failed to initialize ADS.\");
    while (1);
  }
}

void Task1code( void * pvParameters ){
  for(;;){
  Serial.print(\"Task1 running on core \");
  Serial.println(xPortGetCoreID());
adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);

  volts0 = ads.computeVolts(adc0);
  volts1 = ads.computeVolts(adc1);
  volts2 = ads.computeVolts(adc2);
  volts3 = ads.computeVolts(adc3);
  delay(100);
  }
}

void Task2code( void * pvParameters ){
  delay(500);
  Serial.print(\"Task2 running on core \");
  Serial.println(xPortGetCoreID());

  for(;;){}{
    Serial.println(\"-----------------------------------------------------------\");
  Serial.print(\"AIN0: \"); Serial.print(adc0); Serial.print(\"  \"); Serial.print(volts0); Serial.println(\"V\");
  Serial.print(\"AIN1: \"); Serial.print(adc1); Serial.print(\"  \"); Serial.print(volts1); Serial.println(\"V\");
  Serial.print(\"AIN2: \"); Serial.print(adc2); Serial.print(\"  \"); Serial.print(volts2); Serial.println(\"V\");
  Serial.print(\"AIN3: \"); Serial.print(adc3); Serial.print(\"  \"); Serial.print(volts3); Serial.println(\"V\");
  delay(100);
  }
}

void loop() {
  
}

标签: c++ multithreading arduino esp32 arduino-ide


【解决方案1】:

您可以创建一个信号量并在尝试访问变量时使用它。如果您完成访问它,您可以将其归还。当您获取信号量时,其他代码块将等待其他代码块将其返回。您可以配置它应该等待给定信号量的时间。这是一个(link)更详细地解释。

这是一个例子:

SemaphoreHandle_t i2cSemaphore;
void createSemaphore(){
    i2cSemaphore = xSemaphoreCreateMutex();
    xSemaphoreGive( ( i2cSemaphore) );
}

// Lock the variable indefinietly. ( wait for it to be accessible )
void lockVariable(){
    xSemaphoreTake(i2cSemaphore, portMAX_DELAY);
}

// give back the semaphore.
void unlockVariable(){
    xSemaphoreGive(i2cSemaphore);
}

TaskHandle_t Task1;
TaskHandle_t Task2;
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1015 ads; 
volatile int16_t adc0, adc1, adc2, adc3;
volatile float volts0, volts1, volts2, volts3;
void setup() {
  Serial.begin(115200); 
  delay(1000);
  Serial.println("Hello!");
  Serial.println("Getting single-ended readings from AIN0..3");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115");
  createSemaphore();
  //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
  xTaskCreatePinnedToCore(
                    Task1code,   /* Task function. */
                    "Task1",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    1,           /* priority of the task */
                    &Task1,      /* Task handle to keep track of created task */
                    0);          /* pin task to core 0 */                  
  delay(500); 

  //create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
  xTaskCreatePinnedToCore(
                    Task2code,   /* Task function. */
                    "Task2",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    &Task2,      /* Task handle to keep track of created task */
                    1);          /* pin task to core 1 */
    delay(500); 
    if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
}

void Task1code( void * pvParameters ){
  for(;;){
  lockVariable();
  Serial.print("Task1 running on core ");
  Serial.println(xPortGetCoreID());
adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);

  volts0 = ads.computeVolts(adc0);
  volts1 = ads.computeVolts(adc1);
  volts2 = ads.computeVolts(adc2);
  volts3 = ads.computeVolts(adc3);
  unlockVariable();
  vTaskDelay(100);
  }
}

void Task2code( void * pvParameters ){
  delay(500);
  Serial.print("Task2 running on core ");
  Serial.println(xPortGetCoreID());

  for(;;){}{
   lockVariable();
    Serial.println("-----------------------------------------------------------");
  Serial.print("AIN0: "); Serial.print(adc0); Serial.print("  "); Serial.print(volts0); Serial.println("V");
  Serial.print("AIN1: "); Serial.print(adc1); Serial.print("  "); Serial.print(volts1); Serial.println("V");
  Serial.print("AIN2: "); Serial.print(adc2); Serial.print("  "); Serial.print(volts2); Serial.println("V");
  Serial.print("AIN3: "); Serial.print(adc3); Serial.print("  "); Serial.print(volts3); Serial.println("V");
  unlockVariable();
  vTaskDelay(100);
  }
}

void loop() {
  
}

【讨论】:

    【解决方案2】:

    也许崩溃的原因不仅仅是访问内存,而是访问其他一些资源?

    我对类似任务有奇怪的问题。我预计下一个代码会出现问题,其中相同的 int 变量被两个不同内核上的三个任务更改,但代码正在运行并且没有给我任何例外:

    #include <Arduino.h>
    
    volatile int i = 0;
    char buffer[1024];
    const char* msg = "test %d \0";
    
    TaskHandle_t myTaskHandle;
    TaskHandle_t myTaskHandle2;
    
    void myTask(void * pvParameters) {
    
        log_v("Task started on %d", xPortGetCoreID());
    
        unsigned long l = 0;
    
        while(true) {
            unsigned long t = millis();
            if(t > l) {
                int s = i + 1;
                log_v("started overwriting i with %d", s);
                l = t + 450;
                while(millis() < l) {
                    i = s;
                    sprintf(buffer, msg, i);
                    vTaskDelay(1);
                }
                l = t + 900;
                log_v("%d: core %d >>\t'%s'", i, xPortGetCoreID(), buffer);
                log_v("finished changing");
                vTaskDelay(1);
            }
        }
    }
    
    void setup() {
        Serial.begin(115200);
    
        xTaskCreate(
                        myTask,             /* Task function. */
                        "myTask",           /* name of task. */
                        10000,              /* Stack size of task */
                        NULL,               /* parameter of the task */
                        0,                  /* priority of the task */
                        &myTaskHandle       /* Task handle to keep track of created task */
                        );
        log_v("Started task");
    
    
        xTaskCreate(
                        myTask,             /* Task function. */
                        "myTask2",           /* name of task. */
                        10000,              /* Stack size of task */
                        NULL,               /* parameter of the task */
                        0,                  /* priority of the task */
                        &myTaskHandle2       /* Task handle to keep track of created task */
                        );
        log_v("Started task");
    }
    
    unsigned long nextDec = 0;
    
    void loop() {
        unsigned long t = millis();
        if(t > nextDec) {
            nextDec = t + 2000;
            i--;
            sprintf(buffer, msg, i);
            log_v("%d: core %d >>\t'%s'", i, xPortGetCoreID(), buffer);
        }
    }
    

    输出:

    ...
    [203909][V][main.cpp:20] myTask(): started overwriting i with 211
    [203909][V][main.cpp:20] myTask(): started overwriting i with 211
    [204122][V][main.cpp:68] loop(): 210: core 1 >> 'test 210 '
    [204360][V][main.cpp:28] myTask(): 211: core 0 >>       'test 211 '
    [204361][V][main.cpp:29] myTask(): finished changing
    [204360][V][main.cpp:28] myTask(): 211: core 0 >>       'test 211 '
    [204365][V][main.cpp:29] myTask(): finished changing
    [204810][V][main.cpp:20] myTask(): started overwriting i with 212
    [204810][V][main.cpp:20] myTask(): started overwriting i with 212
    [205261][V][main.cpp:28] myTask(): 212: core 0 >>       'test 212 '
    [205262][V][main.cpp:29] myTask(): finished changing
    [205261][V][main.cpp:28] myTask(): 212: core 0 >>       'test 212 '
    [205266][V][main.cpp:29] myTask(): finished changing
    [205711][V][main.cpp:20] myTask(): started overwriting i with 213
    [205711][V][main.cpp:20] myTask(): started overwriting i with 213
    [206123][V][main.cpp:68] loop(): 212: core 1 >> 'test 212 '
    [206162][V][main.cpp:28] myTask(): 213: core 0 >>       'test 213 '
    [206163][V][main.cpp:29] myTask(): finished changing
    ...
    

    您可以看到核心 0 上的 myTask 正在更改整数并重写缓冲区中的字符,在核心 1 上的循环中间写入相同的变量,一切似乎都很好。

    我该怎么做才能让它崩溃? :)

    【讨论】:

      猜你喜欢
      • 2021-12-27
      • 2021-08-03
      • 2021-11-28
      • 2017-10-14
      • 2011-05-03
      • 1970-01-01
      • 2020-12-17
      • 1970-01-01
      • 2014-11-19
      相关资源
      最近更新 更多