Variable doesn't update between cores

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Variable doesn't update between cores

Postby spyder0069 » Mon Apr 01, 2019 2:18 am

I came across this and am looking for some insight. Using arduino to program I have set up two tasks each pinned to a separate core. My application was to check if the core1 stops responding. So in that core I set a variable. In core 0 I check to see if that variable has been set and if so I clear it. However, in this example it does not set the variable unless you have a delay or some other statement also in that loop. Here is the code:

Code: Select all


TaskHandle_t Task0;
TaskHandle_t Task1;

byte variable1=0;
byte variable2=0;


void setup(void) {
  Serial.begin(115200);


  
  //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
  xTaskCreatePinnedToCore(
                    Task0code,   /* Task function. */
                    "Task0",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    &Task0,      /* 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(
                    Task1code,   /* Task function. */
                    "Task1",     /* name of task. */
                    10000,       /* Stack size of task */
                    NULL,        /* parameter of the task */
                    2,           /* priority of the task */
                    // when priority was set to 100 then network scan would not complete
                    &Task1,      /* Task handle to keep track of created task */
                    1);          /* pin task to core 1 */
    delay(500); 
}



void loop() {
  // put your main code here, to run repeatedly:

}



void Task0code( void * pvParameters ){
  delay(1000);
  for (;;){  //create an infinate loop
    //Serial.println("variable1=" + String(variable1));
    if(variable1>0){
      variable1=0;
    }else{
      variable2=1;
    }
    delay(5);

    if(variable2==1){
      Serial.println("error");
      delay(1000);
    }
    
  }
}



void Task1code( void * pvParameters ){
  for (;;){  //create an infinate loop
    variable1=1;    
    //delayMicroseconds(1);
  }
}
Running this code variable1 will always equal zero and give the error. However, if you uncomment the delay in the Task1code it works properly and does not produce an error. Something is funky. Why would it not adjust the variable1 in task1code unless a delay or some other commands are added after it?

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: Variable doesn't update between cores

Postby WiFive » Mon Apr 01, 2019 3:17 am

Compiler thinks it is a dumb thing to do and optimizes it out.

ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: Variable doesn't update between cores

Postby ESP_Angus » Mon Apr 01, 2019 5:11 am

More helpful answer: You need to tell the compiler that the variables "variable1", "variable2" may be updated by other running code at any time. Do this by declaring them "volatile byte variable1;", etc.

You can search online for "volatile Arduino" to find some explanations of "volatile" for Arduino programmers. They're usually talking about interrupts, but updating from the other core is similar.

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Variable doesn't update between cores

Postby spyder0069 » Mon Apr 01, 2019 5:32 am

Thank you for the reply. I will look into this. I have been trouble shooting a project of mine which works perfectly fine for days and then sometimes my flag goes off. I suspect this may not be the cause of the problem if this is only having to do with the compiler editing out the code.

My main project will occasional flag that the other core stopped responding because the variable is not incremented. Is there a preferred method for the two cores to do this? If the variable is in the process of being changed in one core and the other core goes to read it will it wait or will there be a corrupted variable?

markkuk
Posts: 37
Joined: Wed Mar 27, 2019 11:50 am

Re: Variable doesn't update between cores

Postby markkuk » Mon Apr 01, 2019 9:55 am

You should be using the task synchronization and communication mechanisms available in ESP-IDF: https://docs.espressif.com/projects/esp ... aphore-api. See also: https://en.wikipedia.org/wiki/Synchroni ... r_science)
Here's a modified version of your code using a binary semaphore:
  1. TaskHandle_t Task0;
  2. TaskHandle_t Task1;
  3.  
  4. SemaphoreHandle_t binsem1;
  5.  
  6. void setup(void) {
  7.   Serial.begin(115200);
  8.  
  9.   // create a binary semaphore for task synchronization
  10.   binsem1 = xSemaphoreCreateBinary();
  11.  
  12.   //create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
  13.   xTaskCreatePinnedToCore(
  14.                     Task0code,   /* Task function. */
  15.                     "Task0",     /* name of task. */
  16.                     10000,       /* Stack size of task */
  17.                     NULL,        /* parameter of the task */
  18.                     2,           /* priority of the task */
  19.                     &Task0,      /* Task handle to keep track of created task */
  20.                     0);          /* pin task to core 0 */                  
  21.   delay(500);
  22.  
  23.   //create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
  24.   xTaskCreatePinnedToCore(
  25.                     Task1code,   /* Task function. */
  26.                     "Task1",     /* name of task. */
  27.                     10000,       /* Stack size of task */
  28.                     NULL,        /* parameter of the task */
  29.                     2,           /* priority of the task */
  30.                     // when priority was set to 100 then network scan would not complete
  31.                     &Task1,      /* Task handle to keep track of created task */
  32.                     1);          /* pin task to core 1 */
  33.     delay(500);
  34. }
  35.  
  36.  
  37.  
  38. void loop() {
  39.   // put your main code here, to run repeatedly:
  40.   delay(1000);
  41. }
  42.  
  43.  
  44.  
  45. void Task0code( void * pvParameters ){
  46.   delay(1000);
  47.   for (;;){  //create an infinate loop
  48.      if(xSemaphoreTake(binsem1, 5) == pdFALSE){
  49.       // the other task didn't give the semaphore within 5 ticks
  50.       Serial.println("error");
  51.       delay(1000);
  52.     }
  53.   }
  54. }
  55.  
  56.  
  57.  
  58. void Task1code( void * pvParameters ){
  59.   for (;;){  //create an infinate loop
  60.     xSemaphoreGive(binsem1);
  61.     delay(1); // prevent the idle task watchdog from triggering
  62.   }
  63. }

username
Posts: 477
Joined: Thu May 03, 2018 1:18 pm

Re: Variable doesn't update between cores

Postby username » Mon Apr 01, 2019 10:36 am

Something is funky. Why would it not adjust the variable1 in task1code unless a delay or some other commands are added after it?
You need to read more on how a RTOS operates. You have both tasks assigned the same priority, which is not a bad thing, you just need to understand more about it is all. Essentially, both tasks will be given equal priority to run on the cpu. When you don't add a delay in each task you never tell the RTOS "hey I am done here for a bit, take a breath and see if anyone else needs some CPU time. "
So whats winds up happening is its basically spending most of its time in Task1code.

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Variable doesn't update between cores

Postby spyder0069 » Mon Apr 01, 2019 1:54 pm

"So whats winds up happening is its basically spending most of its time in Task1code."

Why? Each task is assigned a different core. Both tasks should be running independently shouldn't they? Since they are on seperate cores I don't actually need anything in the loop correct?

Doe priority matter between my two tasks at that point since the tasks should not be competing against each other? I assumed it was only against what was also set for each core which for core1 which I thought has nothing else running and core0 the wifi and background tasks?

My project is using core1 to check a pin which is handling zero crossing of the AC mains. This needs to be uninterrupted but also get settings from my program running in core0. Core0 has all the interruptions from the wifi and other things happening in the background but the code running there is ok with that.

I

spyder0069
Posts: 35
Joined: Tue Jan 29, 2019 2:46 am

Re: Variable doesn't update between cores

Postby spyder0069 » Mon Apr 01, 2019 1:56 pm

"create a binary semaphore for task synchronization"

Doe this need to occur even though both tasks are running on separate cores? Shouldn't they both be able to just freely run?

markkuk
Posts: 37
Joined: Wed Mar 27, 2019 11:50 am

Re: Variable doesn't update between cores

Postby markkuk » Tue Apr 02, 2019 9:09 am

Threads can run freely as long as they don't try to access shared variables. When threads need to communicate with each other it's best to use the methods provided by the operating system (FreeRTOS/ESP-IDF in this case) instead of trying to re-invent the necessary synchronization and locking routines through trial and error.

username
Posts: 477
Joined: Thu May 03, 2018 1:18 pm

Re: Variable doesn't update between cores

Postby username » Tue Apr 02, 2019 10:45 am

Why? Each task is assigned a different core. Both tasks should be running independently shouldn't they? Since they are on seperate cores I don't actually need anything in the loop correct?
That would be true if you had 2 clock sources with one for each core. Think of it like you PC. you have multiple cores there. Yet if you overtask one of your cores, all other applications you have running will get get bogged down.

Loop is a task as well, having no delay in there is going to bog other tasks as well.

Who is online

Users browsing this forum: No registered users and 149 guests