freeRTOS with arduino board with PS2 controlled device

Hello, community,

I am running Arduino_FreeRTOS.h for multitasking in Arduino.

I am trying to run different RGB-LED patterns using this method. I am using WS2812.h for the RGB-LED control.

in my setup function

I am creating the task using xTaskCreate(LEDPatterns,"T1",256,NULL,2,NULL); API and enabling the task scheduler using this vTaskStartScheduler();

I am attaching the method of the LED pattern right here,

void LEDPatterns(void *pvParameters){

  while(1){
    if(cornerNo < 4){
      if(ledNo < 3){
        //Serial.print(cornerNo),Serial.print("\t"),Serial.println(ledNo);
        value.r = brgt[brgtC]; value.b = brgt[brgtC]; value.g = brgt[brgtC];
        C[cornerNo] -> set_crgb_at(ledNo,value);
        C[cornerNo] -> sync();
        ledNo++;
      }
      else{
        //C[cornerNo] -> sync();
        cornerNo++;
        ledNo = 0;
        
      }
    }
    else{
      cornerNo = 0;
      ledNo = 0;
      if(brgtC < 4){
          brgtC++;
      }
      else{
        brgtC = 0;
      }
    }
    vTaskDelay(100);
  }
  
}

I am also using PCINT for one of my external peripherals and that is the PS2 keyboard.

but C[cornerNo] -> sync(); this API creates some mallicoius repsonse in the response of the PS2 keyboard

I am using WS2812.h for RGB_LED control

also tried using Adafruit_neopixels and fastLED, which tends to the same behaviour of the PS2 keyboard

Hi @ruchiatavr

Is the function:

C[cornerNo]->sync();

...waiting to synchronise with some external event?

If it's the case, then it's better to use one FreeRTOS task synchronisation methods, such as task notification or binary semaphores.

Hardware interrupts (as well as PCINT interrupts) are handled outside the context of FreeRTOS operating system, however it's possible to use the FreeRTOS interrupt safe "FromISR" API functions from within the interrrupt, to synchronise or pass information from the interrupt into a FreeRTOS task.

no this function is just to turn on the LEDs by writing to the specific PORT registers, this is not the blocking function and not waiting to sync with any other event.

also I checked

C[cornerNo] -> set_crgb_at(ledNo,value);
C[cornerNo] -> sync();

these RGB LED operations taking 1ms time to execute

I previously tried using timer interrupt but that method too led to the delay in the PS2 readings

Hi @ruchiatavr

In FreeRTOS, it's possible to use external hardware interrupts to call a standard Interrupt Service Routine (ISR) function then get this to call a high priority interrupt handler task. This not only allows the interrupt handling to be prioritised, but also handled within the context of the operating system itself.

Below is an example, in this case a standard attachInterrupt() ISR that gets called every second, each time the microcontroller receives a pulse from the RTC. Note that interrupt doesn't do any data processing itself, it mearly sends a task notification to a high priority interrupt handling task. It also allows this higher priorty task to preempt the task that's currently running by using the portYIELD_FROM_ISR() macro. In this way, FreeRTOS can handle interrupts in a timely manner:

void rtcTickHandler()
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  vTaskNotifyGiveFromISR(xTimeHandle, &xHigherPriorityTaskWoken);  // Notify the RTC handler task that an RTC interrupt has occured
  if (xHigherPriorityTaskWoken == pdTRUE)         // Check if a higher priority task is in the ready state
  {
    portYIELD_FROM_ISR();                         // Yield to the higher priority task
  }
}

The interrupt handling task then immediately scheduled to run after the ISR, the task notification unblocking and executing the interrupt processing code:

void xTaskRTCInterrupt(void *pvParameters)
{
  // Intialise local variables here...

  for(;;)     // Loop forever
  {
    if (ulTaskNotifyTake(pdTRUE, portMAX_DELAY) == pdTRUE)  // Wait indefinitely to receive an interrupt from the RTC
    {
      // Process the RTC interrupt here...
    }
  }
}

After executing the code, the task loops round and blocks waiting for the next task notification from the ISR. This allows the scheduler to switch back to whatever it was doing beforehand.