Updated versions of ChibiOS/RT, NilRTOS, and FreeRTOS

fat16lib:
The argument should be a BMP085 mode, not an I2C speed. I don't know if that would make a difference.

This is how I set up the bmp now:

//#include <Wire.h>
#include <TwiMaster.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
..
void setup() {
  Serial.begin(115200);
  bmp.begin(BMP085_ULTRAHIGHRES); 
..

Still hangs at bmp.begin()..

Enclosed the sketch you may try with ie Mega (you want to decrease the buffer size).

nilSdLogger_4.zip (2.36 KB)

Strange! On an Uno this sketch:

#include <TwiMaster.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;

void setup() {
  Serial.begin(115200);
  if (!bmp.begin(BMP085_ULTRAHIGHRES)) {
    Serial.println("bmp.begin failed");
    while(1);
  }
  Serial.print("Altitude: ");
  Serial.println(bmp.readAltitude());
}
void loop() {}

Prints:

Altitude: 82.33

The only change to the library is this in Adafruit_BMP085.h:

#include "TwiMaster.h"
//#include "Wire.h"

With 1.5.1r2 and mighty 1284p:

#include <TwiMaster.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;

void setup() {
  Serial.begin(115200);
 // if (!bmp.begin(BMP085_ULTRAHIGHRES)) {
 //   Serial.println("bmp.begin failed");
 //   while(1); }
 
  bmp.begin(BMP085_ULTRAHIGHRES);
   
  
  Serial.print("Altitude: ");
  Serial.println(bmp.readAltitude(99500, 101350));
}
void loop() {}
Altitude: 155.14

With your original sketch I get errors during build..
PS: It seems my BMP lib is older one, with the latest I get with your original sketch:

Altitude: 200.40

I understand the problem. TwiMaster uses a semaphore when linked with Nil RTOS so Nil RTOS must be started to do I2C I/O.

Move bmp.begin() here:

// Declare thread function for thread 1.
NIL_THREAD(Thread1, arg) {
  
  bmp.begin(BMP085_HIGHRES); 
  // Start timer 1 with a period of PERIOD_USEC.
  nilTimer1Start(PERIOD_USEC);

bmp.begin() does lots of I/O.

I understand the problem. TwiMaster uses a semaphore when linked with Nil RTOS so Nil RTOS must be started to do I2C I/O.

Move bmp.begin() here:

Yep, it works now.
Bmp stuff takes 22ms now (35ms with wire).

A high time to replace _delay_ms() with chThdSleep() in the bmp driver..
Not easy, though.. :roll_eyes:

I will put problems like these on my to-think-about list.

I am experimenting with using a weak symbol for delay. The weak symbol would use the standard Arduino delay.

When you link a library with an RTOS, the weak symbol would be replaced by the appropriate sleep or delay function in the RTOS.

This way you can have a single library and it will work with standard Arduino sketches or any RTOS that defines the override for the weak delay.

Is it possible to use the RTOS you have ported with Atmel Studio?
If it is possible do you have any guide of how to do it? Or I just can copy the folder and place it in my project.
What I want to do is use Arduino Due with Atmel Studio.

I think it would be better to use the unmodified versions of FreeRTOS or ChibiOS with Atmel Studio. Both of theses systems have AVR ports and examples.

I know FreeRTOS and Atmel are cooperating to make their products work together.

I really like ChibiOS/RT on Due. It is fast, takes a bit less memory than FreeRTOS but has more features.

Nill RTOS is great when you need minimal memory use and simple features are adequate.

Nil RTOS is experimental and not really supported yet by the author. I am personally supporting Nill RTOS mods for the Arduino core.

I assume you are not using the Arduino core software. My mods were to allow use of an RTOS with the Arduino core and Arduino libraries.

Hi, fat16lib,

Thanks a LOT for so useful contribution!
I just come across your work. May I ask you few quick questions?

  1. Which Arduino libraries known NOT to work with FreeRTOS, or have timing issues?
  2. Which Arduino would you recommend to handle 3 step motors (at speed up to 2000 rpm), 2 rotary encoders and 2 magnetic hall sensors with any of RTOS? Probably Arduino Due is a minimum?

Thanks in advance for any suggestion(s).

I don't have a list of libraries that don't work.

Any library that calls delay() or has a wait loop for something to complete will block all lower priority threads.

The ideal way to handle devices with an RTOS is to start an operation in a thread then wait on a semaphore. When the operation completes, an interrupt occurs and the device ISR signals with the semaphore to wake the waiting thread. This means many Arduino libraries need some mods for optimum performance.

The malloc() included with new versions of the Arduino IDE will not work in threads. This is O.K. since dynamic memory is not a good idea in real-time systems after setup.

FreeRTOS uses the most RAM and flash, ChibiOS/RT is smaller, faster, and has more features. Nil RTOS is the smallest but has few features and probably is not appropriate for your system.

Certainly Due is the minimum but I can't guess what you will need.

Hi, fat16lib,

I'm currently stuck with something damn simple on Due, your latest FreeRTOS ARM, and 1.52 IDE.

I have an early draft for a software which should control 2 step motors, display data on TM1639, and exchange data via Firmata with Linux PC (3rd feature is not written yet). Currently I have only 1 step motor and TM1638 LED connected, and both work wit conventional Arduino setup.

I took a FreeRTOS example which basically spawns 2 threads, and in my case call of vTaskStartScheduler() hangs Due. I even removed all TM1639 calls, result is still the same.

void setup(void) {
portBASE_TYPE s1, s2;
Serial.begin(9600);

pinMode(MOTORCLK, OUTPUT);

s1 = xTaskCreate(vNumericLED, (signed char*)"Task 1", 200, NULL, 1, NULL);
s2 = xTaskCreate(vRunStepMotor1, (signed char*)"Task 2", 200, NULL, 2, NULL);

if (s1 != pdPASS || s2 != pdPASS ) {
Serial.println(F("Creation problem"));
// while(1);
}
else
Serial.println(F("Creation OK"));;

vTaskStartScheduler();

for (;;);
}

static void vNumericLED(void *pvParameters)
{}

static void vRunStepMotor1(void *pvParameters)
{
digitalWrite(MOTORCLK, HIGH);
vTaskDelay(20000 * 250 / portTICK_RATE_MS);
digitalWrite(MOTORCLK, LOW);
vTaskDelay(20000 * 250 / portTICK_RATE_MS);
}

extern "C"{
void vApplicationIdleHook(void) {}
}

Anything after vTaskStartScheduler() is not executed, so I assume its a system freeze. Please correct if I'm wrong here.

Any idea what might get wrong?

Thanks in advance.

vTaskStartScheduler() never returns. Please see the FreeRTOS documentation for details of API functions.

Here is a link to vTaskStartScheduler() The FreeRTOS vTaskStartScheduler() RTOS API function which is part of the RTOS scheduler control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers..

fat16lib:
vTaskStartScheduler() never returns. Please see the FreeRTOS documentation for details of API functions.

Here is a link to vTaskStartScheduler() The FreeRTOS vTaskStartScheduler() RTOS API function which is part of the RTOS scheduler control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers..

I meant task themselves are not executed, call of vTaskStartScheduler() hangs Due.

I suspect one of your tasks crashes the system when it returns.

You should read the FreeRTOS documentation for task structure. Here is a link Writing RTOS tasks in FreeRTOS - implementing tasks as forever loops.

Here is a quote from the documentation for xTaskCreate():

pvTaskCode Pointer to the task entry function. Tasks must be implemented to never return (i.e. continuous loop).

Here is a link to more details This page describes the RTOS xTaskCreate() FreeRTOS API function which is part of the RTOS task control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers..

fat16lib:
I suspect one of your tasks crashes the system when it returns.

Bingo ! One of my tasks really exited from the loop.
Another thing - I had to increase stack size to 2048.

Thanks a lot, fat16lib !

From the html manual:
On ARM Due you must connect pin 2 to pin 3

Is it necessary only for attachInterrupt() examples?

With help of fat16lib, I loaded Due with damn simple simple program which controls bipolar step motor and scrolls text on TM1638 LED (with TM1638 library).
Looks like FreeRTOS have very high latency on Due or I'm being missing something.

  1. I can't get step motor running with speed over 75 rpm, even with smooth long-time acceleration. This is certainly problem related to FreeRTOS, since without FreeRTOS I can get much faster speed from the same motor.

  2. Scrolling text on TM1638 LED (running as separate task) creates audible ticks and vibration (with frequency equal to scroll text speed) on running step motor. Bypassing scroll code in this task removed problem with ticking step motor.

Step motor have priority 1, scrolling text - 2.


// Motor run code:
while (1) {
digitalWrite(MOTORCLK, HIGH);
vTaskDelayUntil(&xLastWakeTime, xTargetFreq / 2);
digitalWrite(MOTORCLK, LOW);
vTaskDelayUntil(&xLastWakeTime, xTargetFreq / 2);
};


// TM1638 scroll function
static void vNumericLED(void *pvParameters)
{
portTickType xLastWakeTime = xTaskGetTickCount();

while (1) {

for (int i = 0; i < MODULES; i++) {
const char* pos = string + base + (i * 8);

if (pos >= string && pos + 8 < string + sizeof(string)) {
modules*.setDisplayToString(pos);*

  • } else {*
    _ modules*.clearDisplay();_
    _
    }_
    _
    }*_

* base++;*

* if (base == sizeof(string) - 8) {*
_ base = -MODULES * 8;_
* }*

* vTaskDelayUntil(&xLastWakeTime, (1000 / portTICK_RATE_MS) / 2);
_
};_
_
}_
_
-------------------------------------------------------------------------*_
Should I try ChibliOS, NilRTOS, or I just did something wrong with FreeRTOS on Due?

Looks like FreeRTOS have very high latency on Due or I'm being missing something.

FreeRTOS has very fast context switch time on Due. ChibiOS is a bit faster but I don't think this is your problem. ChibiOS is in the one microsecond range and FreeRTOS is under two microseconds on Due.

Step motor have priority 1, scrolling text - 2.

So why run the step motor task at lower priority than the display? Read about task priorities here RTOS task priorities in FreeRTOS for pre-emptive and co-operative real time operation.

Scrolling text on TM1638 LED (running as separate task) creates audible ticks and vibration (with frequency equal to scroll text speed) on running step motor. Bypassing scroll code in this task removed problem with ticking step motor.

This is the result of running the scroll task at higher priority. The RTOS is doing what you asked it to do, give the scrolling highest priority.

G'day,

Is there likely to be a working Ethernet Library for Chibios by any chance? What would be required to get one working. I think the next evolution for Arduino is multitasking.... it can then find a good commercial footing and an OS like CHibios might be the key as opposed to using FreeRTOS with its overheads...

Sid

fat16lib:
I don't recall a post about the Ethernet library.

Many Arduino libraries are not RTOS friendly but that doesn't mean you can't use them.

Here is an example from the Ethernet library:

    // Wait for a response packet

while(iUdp.parsePacket() <= 0)
    {
        if((millis() - startTime) > aTimeout)
            return TIMED_OUT;
        delay(50);
    }




This loop has a delay(50) call that will block lower priority threads. If the delay were replaced by a chThdSleep(50) call, lower priority threads could use the CPU time.

I think a web server is an ideal candidate for RTOS use. I would love to have a well designed web server as an example.

I hope to write a "How To" for making minimal changes to libraries that will improve their performance with an RTOS.

Hi All,

I'm currently building an little app with four threads using NilRTOS and using ethernet.
Lots of blocking with one thread whilst using the network, so I had a look at the ethernet library and straight away, the W5100:Class::init has a 300 millisecond delay in it. After a bit of fiddling I took fat16lib's cue and altered it to use nilThdSleepMilliseconds() instead of delay() - all good. Except for the now non-portable ethernet library - it doesn't work if you don't include the NilRTOS headers at the top of the library..... including them at the top of your sketch doesn't work, even if the Ethernet library is included further down.

So after some more fiddling about, here's a few steps for the not-everyday-programmers :stuck_out_tongue: to do it in a more transparent fashion:
Put your #include <NilRTOS.h> that you have at the top of your sketch into a new header file (made by pressing the 'new' button with your existing sketch open. I had one already as I defined a few types for passing data back and forth.)
Include this new file in your sketch at the top eg. #include "MyTypes.h" - note the " instead of the <>

Open up your library .cpp file (under \Libraries\ in your arduino program directory) with notepad or your favorite C editor and poke about in it. Maybe save a backup copy somewhere :slight_smile:

Everywhere you see a delay() in your library put something like:

// make it a little bit more friendly to NilRTOS.
#if defined(__NIL__)
  nilThdSleepMilliseconds(300);
#elseif
  delay(300);
#endif

When this is compiled, if NIL is defined (as it is in NilRTOS.h), the NilRTOS library is there and you can use it's functions, otherwise the library will just use the normal delay and all your 'normal'' sketches will run as-is.

This makes threading much nicer with the Ethernet library.... I might go through the LCD one as well as there are delays liberally sprinkled through it.

Hope this helps, and if anyone knows the 'right' way to do this, let me know :stuck_out_tongue: