Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: How can I use RTOS in Teensy 4.0?

  1. #1
    Junior Member
    Join Date
    Aug 2020
    Posts
    9

    How can I use RTOS in Teensy 4.0?

    I need to use an RTOS in my Teensy 4.0 that has some scheduling algorithm such as Free-RTOS,
    one of the most famous that can be implemented in the arduino IDE.

    I have been using these libraries without any success:

    https://github.com/discord-intech/FreeRTOS-Teensy4
    https://github.com/greiman/FreeRTOS-Arduino
    https://github.com/tsandmann/freertos-teensy

    I read in some threads like this:
    https://forum.pjrc.com/threads/41504...-first-release

    I can use this library to do parallel processes, however I see that since it does not have a scheduling algorithm,
    I cannot synchronize the tasks properly as a mutex or a semaphore would do.

    Code:
    #include <Arduino.h>
    #include "TeensyThreads.h"
    
    const int LED_RED = 15;
    const int LED_GREEN = 19;
    const int PUSH = 23;
    int count = 0;
    
    void blinkRed(){
      while (1) {
        digitalWrite(LED_RED, HIGH);
        threads.delay(250);
        digitalWrite(LED_RED, LOW);
        threads.delay(250);
        threads.yield();
      }
    }
    void blinkGreen() {
      while (1) {
        digitalWrite(LED_GREEN, HIGH);
        threads.delay(500);
        digitalWrite(LED_GREEN, LOW);
        threads.delay(500);
        threads.yield();
      }
    }
    void push() {
      while (1) {
        if(digitalRead(PUSH) == 0){
          while(digitalRead(PUSH) == 0){
              count++;
              Serial.print("TOCO ");
              Serial.println(count);
              threads.delay(250); // efecto rebote
          }
        }
        threads.yield();
      }
    }
    void setup() {
      pinMode(LED_GREEN, OUTPUT);
      pinMode(LED_RED, OUTPUT);
      pinMode(PUSH, INPUT_PULLUP);
      threads.addThread(blinkRed);
      threads.addThread(blinkGreen);
      threads.addThread(push);
    }
    
    void loop() {
      // nada
    }
    As can be seen in the code, there are 2 trains of square pulses, one has twice the frequency of the other, and when reviewing it through an oscilloscope, I observe that one of the pulses with form passes over time and moves with respect to the other , that is, it gets out of sync after a while.
    I need the pulse trains to be synchronized or in phase always and working in parallel with other tasks.
    In my opinion, if I am able to use a scheduler like the one offered by Free-RTOS, I will be able to solve my problem.
    How can I implement Free-RTOS or other RTOS on Teensy 4.0?

    Thank you very much in advance for your attention.

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,701
    teensythreads has mutexes

  3. #3
    Junior Member
    Join Date
    Aug 2020
    Posts
    9
    Quote Originally Posted by tonton81 View Post
    teensythreads has mutexes
    Hello, thank you very much for answering.
    What worries me is that the square signals in my described code get out of sync, so what I would like to know is if TeensyThreads is a sufficient tool to achieve real-time processing or am I still looking to use Free-RTOS.
    On the other hand, does this mean that there is no library to use Free-RTOS?
    Do you know any that can be used to implement Real Time?

    My ultimate goal is to be able to implement tasks in real time.

  4. #4
    Senior Member
    Join Date
    Sep 2015
    Posts
    123
    NXP has development tools for the 1062 used in the Teensy 4 that includes FreeRTOS support, but I don't know how much work it would be to get it moved over. https://www.nxp.com/design/software/...MCUXpresso-SDK

  5. #5
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    200
    Have a look at this.

    I just did as search for "teensy rtos" and that was one of the few things thrown up.

  6. #6
    Junior Member
    Join Date
    Aug 2020
    Posts
    9
    Quote Originally Posted by ecurtz View Post
    NXP has development tools for the 1062 used in the Teensy 4 that includes FreeRTOS support, but I don't know how much work it would be to get it moved over. https://www.nxp.com/design/software/...MCUXpresso-SDK
    It is a possible solution but rewriting the libraries that I already have modified for my application could be much more painful.
    Thank you very much for giving me a possible solution.

  7. #7
    Junior Member
    Join Date
    Aug 2020
    Posts
    9
    Quote Originally Posted by BriComp View Post
    Have a look at this.

    I just did as search for "teensy rtos" and that was one of the few things thrown up.
    Hey, thanks. I will try that, as soon as I have results I will comment on them.
    It is worth mentioning that I had seen this library before:
    https://github.com/greiman/ChibiOS-Arduino
    It was announced in this thread:
    https://forum.pjrc.com/threads/53662...highlight=RTOS
    However, since I saw that only AVR, Due, and Teensy 3.x were supported, I didn't try it.


    As you mentioned, I will try to use this library for Teensy 4.0 by same author:
    https://github.com/greiman/ChRt
    which is the one that states the thread that you share with me.

  8. #8
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,701
    you could try:
    https://github.com/geky/coru

    Speeduino users use it in their code, works accross several MCUs

  9. #9
    Junior Member
    Join Date
    Aug 2020
    Posts
    9
    Quote Originally Posted by BriComp View Post
    Have a look at this.

    I just did as search for "teensy rtos" and that was one of the few things thrown up.
    Sorry to answer so late. However, I was learning how to use the ChibiOS library, since finally that was the library that helped me solve my problem.
    https://github.com/greiman/ChRt
    I will append some codes to help someone who may be looking for the same answers as me.

    First of all, I want to clarify that the use of mutex with the TeensyThreads library did not help me to do parallel processes since the mutex blocks the used resource to prevent other threads in execution from interfering.

    Code:
    #include <Arduino.h>
    #include "TeensyThreads.h"
    
    const int LED_RED = 15;
    const int LED_GREEN = 19;
    const int PUSH = 23;
    int count = 0;
    Threads::Mutex mutExample;
    void blinkRed(){
      while (1) {
        mutExample.lock();
        digitalWrite(LED_RED, HIGH);
        //mutExample.unlock();
        //threads.delay(250);
        delay(250);
        //mutExample.lock();
        digitalWrite(LED_RED, LOW);
        mutExample.unlock();
        threads.delay(250); 
        //delay(250);
        //mutExample.unlock();
        threads.yield();
      }
    }
    void blinkGreen() {
      while (1) {
        mutExample.lock();
        digitalWrite(LED_GREEN, HIGH);
        //mutExample.unlock();
        //threads.delay(500);
        delay(500);
        //mutExample.lock();
        digitalWrite(LED_GREEN, LOW);
        mutExample.unlock();
        threads.delay(500);
        //delay(500);
        //mutExample.unlock();
        threads.yield();
      }
    }
    void push() {
      while (1) {
        if(digitalRead(PUSH) == 0){
          while(digitalRead(PUSH) == 0){
              count++;
              Serial.print("TOCO ");
              Serial.println(count);
              threads.delay(250); // efecto rebote
          }
        }
        threads.yield();
      }
    }
    void setup() {
      pinMode(LED_GREEN, OUTPUT);
      pinMode(LED_RED, OUTPUT);
      pinMode(PUSH, INPUT_PULLUP);
      threads.addThread(blinkRed);
      threads.addThread(blinkGreen);
      threads.addThread(push);
    }
    
    void loop() {
      // nada
    }
    The result was that although now the pulses are mutually synchronized, the processes do not interfere with each other, that is, as if it were a kind of algorithm without preemtive.
    Click image for larger version. 

Name:	TeensyThreadsScope.jpg 
Views:	1 
Size:	91.0 KB 
ID:	24726
    However, it is not what I wish to achieve.

    Finally, I tried the ChibiOS library which I attached both by zip file, an example with the same TeensyThreads application and by the link of its original creator on GitHub.

    Code:
    #include "ChRt.h"
    
    const int PUSH = 23;
    int count = 0;
    
    static THD_WORKING_AREA(waTh1, 100); //100 Bytes
    static THD_WORKING_AREA(waTh2, 100);
    
    /*struct threadData{
      int _blinkTime;
      int _lightPin;
      int _fadeTime;
    };*/
    
    
    
    
    static THD_FUNCTION (blinkerThread, arg) {
      //setup thread vars
      /*threadData *thisData = (threadData*)arg;
      int lightPin = thisData->_lightPin;
      int blinkTime = thisData->_blinkTime;*/
      (void)arg;
      //set the LED pinMode
      //pinMode(lightPin, OUTPUT);
      pinMode(15, OUTPUT);
      while(1){
    
        //blink
        /*digitalWrite(lightPin, HIGH);
        chThdSleepMilliseconds(blinkTime);
        digitalWrite(lightPin, LOW);
        chThdSleepMilliseconds(blinkTime);*/
        digitalWrite(15, HIGH);
        chThdSleepMilliseconds(500);
        digitalWrite(15, LOW);
        chThdSleepMilliseconds(500);
      }
    }
    
    
    
    static THD_FUNCTION (fadeThread, arg){
      /*threadData *thisData = (threadData*)arg;
      int lightPin = thisData->_lightPin;
      int fadeTime = thisData->_fadeTime;*/
      (void)arg;
    
      //pinMode(lightPin, OUTPUT);
      pinMode(19, OUTPUT);
      while(1){
        digitalWrite(19, HIGH);
        chThdSleepMilliseconds(250);
        digitalWrite(19, LOW);
        chThdSleepMilliseconds(250);
        /*for(int i = 0; i < 255; i+=5){
          analogWrite(lightPin, i);
          chThdSleepMilliseconds(fadeTime);
        }
        for(int i = 255; i > 0; i-=5){
          analogWrite(lightPin, i);
          chThdSleepMilliseconds(fadeTime);
        }*/
      }
    }
    
    
    
    
    
    
    
    
    
    
    //------------------------------------------------------------------------------
    void setup() {
      // inicializa el SerialPort
      Serial.begin(9600);
      // Wait for USB Serial.
      while (!Serial) {}
      // push buttom pin
      pinMode(PUSH, INPUT_PULLUP);
      // initialize and start ChibiOS
      chBegin(chSetup);
      
      // should not return
      while(1);
    }
    
    
    //------------------------------------------------------------------------------
    void chSetup() {
      /*threadData set1;
      set1._lightPin = 15;
      set1._blinkTime = 300;*/
    
      /*threadData set2;
      set2._lightPin = 19;
      set2._fadeTime = 10;*/
    
    
      //schedule thread 2 
      //chThdCreateStatic(waTh1, sizeof(waTh1), NORMALPRIO, blinkerThread, (void*)&set1);
      chThdCreateStatic(waTh1, sizeof(waTh1), NORMALPRIO + 1, blinkerThread, NULL);//Mas prioridad
    
      //schedule thread 3 (fading)
      //chThdCreateStatic(waTh2, sizeof(waTh2), NORMALPRIO, fadeThread, (void*)&set2);
      chThdCreateStatic(waTh2, sizeof(waTh2), NORMALPRIO+1, fadeThread, NULL);//Menos prioridad
    
    
    
      //while(1){ // Se ejecuta con una prioridad normal NORMALPRIO
      //  chThdSleepMilliseconds(10000); // lo que sea
    //    if(digitalRead(PUSH) == 0){
    //      while(digitalRead(PUSH) == 0){
    //          count++;
    //          Serial.print("TOCO ");
    //          Serial.println(count);
    //          chThdSleepMilliseconds(250); // efecto rebote
    //      }
    //    }
      //}
    }
    //------------------------------------------------------------------------------
    void loop() {// Se ejecuta con una prioridad normal NORMALPRIO
      if(digitalRead(PUSH) == 0){
        while(digitalRead(PUSH) == 0){
            count++;
            Serial.print("TOCO ");
            Serial.println(count);
            chThdSleepMilliseconds(250); // efecto rebote
        }
      }
    }
    Finally, the result achieved was satisfactory. The context change is immediate, the processes are synchronized running in parallel and you can give it different execution priorities.
    Click image for larger version. 

Name:	ChibiOSScope.jpg 
Views:	1 
Size:	91.0 KB 
ID:	24728

    Thanks to everyone who took the time to help me.
    I hope this information can be useful to someone on the web.
    Attached Files Attached Files

  10. #10
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,701
    if you put a delay in a mutex block and share that block accross other threads, of course the mutex would block and not run in parallel, and that output would be expected

  11. #11
    Junior Member
    Join Date
    Aug 2020
    Posts
    9
    Quote Originally Posted by tonton81 View Post
    if you put a delay in a mutex block and share that block accross other threads, of course the mutex would block and not run in parallel, and that output would be expected
    That's right, I forgot to specify that I didn't spend a lot of time on that algorithm, if you can reproduce the same output that I got with ChibiOS using TeensyThreads I'd really appreciate it if you shared it.

  12. #12
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,701
    I dont have a scope just mentioning it

    it probably should look better without the mutex, because the way you had it it would wait for a release before toggling. I don't see you do this in chibios and since your using 2 different digital pins, you dont really need a mutex for that (unless you use gpio port accesses) but no delay calls within the mutex regardless, you dont need the mutex here

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •