Updated versions of ChibiOS/RT, NilRTOS, and FreeRTOS

I have created a Google Code project for the Real Time Operating Systems that I have ported to Arduino here Google Code Archive - Long-term storage for Google Code Project Hosting..

I have posted the most recent versions of NilRTOS, ChibiOS/RT, and FreeRTOS on this site. There are new and improved examples for all of these systems.

I am very excited by results of running NilRTOS on Uno Arduinos. Here are some features of Nil:

NilRTOS is a tiny fast RTOS written by Giovanni Di Sirio, the author of ChibiOS/RT.

"Smaller than ChibiOS/RT, so small it's almost nil."

NilRTOS runs on AVR Arduinos and is the best choice for Uno.

NilRTOS features:
•Fastest and smallest of the three on AVR Arduinos
•Static architecture, everything is statically allocated at compile time
•Preemptive multithreading
•Counting semaphores with timeouts
•Flexible FIFO class
•Efficient analogRead() that sleeps during ADC conversion
•API access from interrupt handlers
•Tiny unbuffered NilSerial as an alternative to Arduino Serial

I want to thank you for exploring, porting, and advertising these RTOS and RTOS-like utilities.
I don't know whether I'll ever be in a position to want to use them, but it's providing a lot of "warm fuzzies" to know that they're out there, that someone has made them work, and found them to be usable!

Hello fat16lib,
First of all I want to thank you for your effort of porting these RTOS to Arduino; it will help many people like myself to learn about them.

I have some questions I’d like to answer if you could:

Regarding your FreeRTOS port:

  • Did you have to leave out any original full FreeRTOS characteristic on the Arduino port you built? If any, what were they?

Regarding how to port these RTOS: I would like to port FreeRTOS or other RTOS to my PIC32MX250F128 Pinguino platform, that is similar to arduino but running on PIC32MX (http://wiki.pinguino.cc/index.php/PIC32MX).

  • Could you tell me the basic steps you took to port FreeRTOS?
  • What hardware specific files did you have to modify and was left untouched?
  • Do you consider I should start from your port (considering pinguino platform is similar to arduino), or from scratch downloading a FreeRTOS folder structure?
  • Is ChibiOS/RT easier to port than FreeRTOS?

It would be very helpful to be able to understand the porting process and to have these tools running on Pinguino, because its processors are powerful, cheap, and come in DIP packages too.

Thank you in advance,
Pablo

Thanks for all of your amazing work porting these RTOSs to arduino.

pablocotan,

You need to go to the FreeRTOS site and download the distribution. There may be a PIC32MX port or something close.

Your best source of help for your port is the FreeRTOS forum.

I have posted a new version of Nil RTOS as NilRTOS20130214.zip Google Code Archive - Long-term storage for Google Code Project Hosting..

This version has a new I2C library, TwiMaster, and mods for Arduino 1.5.2 beta.

TwiMaster is an I2C master mode library that operates at 100 kHz or 400 kHz. The native API allows any size transfer, Wire has a 32 byte limit. TwiMaster has a class wrapper to provide a Wire compatible API.

The TwiMaster library is very efficient in RTOS threads since the calling thread sleeps during the I2C transfer. At 100 kHz, 85% of the transfer time is available to other threads.

TwiMaster can be used standalone, without an RTOS, in regular Arduino sketches. Several examples demonstrate standalone use.

I downloaded your code and tried to compile the examples without success. I'm getting the following errors and was wondering if you had any suggestions:

C:\Users\AppData\Local\Temp\build4893843428045478444.tmp/core.a(cortex_handlers.c.o): In function SVC_Handler': C:\Users\Downloads\arduino-1.5.2\hardware\arduino\sam\cores\arduino/cortex_handlers.c:43: multiple definition of SVC_Handler'
ChibiOS_ARM\utility\chcore_v7m.c.o:C:\Users\Downloads\arduino-1.5.2\libraries\ChibiOS_ARM\utility/chcore_v7m.c:91: first defined here
C:\Users\AppData\Local\Temp\build4893843428045478444.tmp/core.a(wiring.c.o): In function SysTick_Handler': C:\Users\Downloads\arduino-1.5.2\hardware\arduino\sam\cores\arduino/wiring.c:77: multiple definition of SysTick_Handler'
C:\Users\AppData\Local\Temp\build4893843428045478444.tmp/core.a(cortex_handlers.c.o):C:\Users\Downloads\arduino-1.5.2\hardware\arduino\sam\cores\arduino/cortex_handlers.c:47: first defined here
collect2: ld returned 1 exit status

Thank you very much for your efforts. I've been trying to figure out how to better utilize the capabilities of the DUE and I think this is the way to go...

It seems it crashes with 1284p (1.5.1r2). The BMP085 logger works fine with original Wire. When replacing Wire.h with the TwiMaster.h it compiles w/o error, but crashes. It does not show the initial "type any...", the bmp.begin() crashes (adafruit's BPM085 driver):

   bmp.begin(I2C_100KHZ); 
    Serial.println(F("type any character to begin"));

The twiScanI2cBus works (BMP085 and PCF8563T rtc):

Device at address: 0XA2 responds to Read and Write.
Device at address: 0XEE responds to Read and Write.
Done

PS: 0xEE address probably wrong (BMP085 address is 0x77)
PS1: the same with 1.5.2
PS2: my read_pcf8563 works, so there must be something in bmp.begin() not wrapped..

pito,

twiScanI2Cbus uses the standard I2C address format. So 0XEE is Wire address 0X77.

The TwiMaster native API follows the I2C standard http://www.nxp.com/documents/user_manual/UM10204.pdf:

3.1.10 The slave address and R/W bit

Data transfers follow the format shown in Figure 9. After the START condition (S), a slave
address is sent. This address is seven bits long followed by an eighth bit which is a data
direction bit (R/W) — a ‘zero’ indicates a transmission (WRITE), a ‘one’ indicates a
request for data (READ) (refer to Figure 10). A data transfer is always terminated by a
STOP condition (P) generated by the master. However, if a master still wishes to
communicate on the bus, it can generate a repeated START condition (Sr) and address
another slave without first generating a STOP condition. Various combinations of
read/write formats are then possible within such a transfer.

Datasheet for BMP085:

4.2 Device and register address
The BMP085 module address is shown below. The LSB of the device address distinguishes between read(1) and write(0) operation, corresponding to address 0xEF (read) and 0xEE (write).

The datasheet for PCF8563:

I2C-bus slave address: read A3h and write A2h.

The Wire wrapper uses the address shifted to be compatible with the standard Wire library. I follow that so the addresses for Wire are 0x51 and 0x77.

I forgot that I have a BMP085 somewhere. I will search for it and try to debug with the Adafruit library and the Wire wrapper for TwiMaster.

Edit: I looked at the Adafruit library and found bugs but they seems to be harmless with Wire.

The read routines have a write of zero bytes around the reads.

uint8_t Adafruit_BMP085::read8(uint8_t a) {
  uint8_t ret;

  Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device 
.
.
.
  Wire.endTransmission(); // end transmission

  return ret;
}

The beginTransmission() and endTransmission() should not be in this read function or in uint16_t Adafruit_BMP085::read16(uint8_t a).

I need to understand what happens in Wire.

bbbowden,

Are you using ChibiOS20130208.zip from Google Code Archive - Long-term storage for Google Code Project Hosting.?

pito,

I haven't found my BMP085 yet and don't have much time for a few days to work on Ardunio.

I looked more at the Adafruit library and speeding it up won't work. The BMP085 has a very slow ADC so the driver is salted with delay loops. Changing the timing will make it fail. Here is an example:

uint32_t Adafruit_BMP085::readRawPressure(void) {
  uint32_t raw;

  write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6));

  if (oversampling == BMP085_ULTRALOWPOWER) 
    _delay_ms(5);
  else if (oversampling == BMP085_STANDARD) 
    _delay_ms(8);
  else if (oversampling == BMP085_HIGHRES) 
    _delay_ms(14);
  else 
    _delay_ms(26);

  raw = read16(BMP085_PRESSUREDATA);
  .
  .
  .

I will see what I can do since this is probably a typical problem people will run into with an RTOS in Arduino.

At a minimum I can write a RTOS friendly BMP085 driver that sleeps instead of using delay loops and probably find a bug in TwiMaster.

Thanks for trying the software, it really helps me improve it.

..there are dozens of i2c devices and drivers which are not rtos friendly.. so it has no sense to mess with bmp085 alone.. the CSF for an rtos deployment in such ecosystem as the arduino is the ability to write the drivers, though.. :cold_sweat:

I don't plan on writing a lot of device libraries.

I just want to understand the problem so I know the the TwiMaster I2C library works and so I can write a "How To" for making existing libraries more RTOS friendly.

The BMP085 is an good example since its ADC is so slow that it needs delay loops.

Other I2C libraries I have tried automatically work better since TwiMaster sleeps while the actual I2C transfer takes place. All you need to do is change the include from Wire.h to TwiMaster.h.

I hope most device libraries improve a lot if you change delay calls to sleep and change the include from Wire to the new library.

Edit: I decided to write new software(bit-bang) I2C libraries since I have my logic analyzer and scope setup for I2C testing.

I clear the PORT bit for sda and scl. I then set the DDR bit to pull either scl or sda low and clear the DDR bit to put scl or sda in high Z mode.

So it acts like an open drain/collector bus. I never drive a line high. I have a 100 kHz and 400 kHz version that runs using any pins for scl sda. The 400 kHz version will only run at full speed on "low address" pins since it uses bit set and bit clear which doesn't work for ports H - L on a Mega.

fat16lib:
bbbowden,

Are you using ChibiOS20130208.zip from Google Code Archive - Long-term storage for Google Code Project Hosting.?

Fat16lib - Yes, I downloaded the latest of all of those libraries. I'm going to try on a different computer in case I did something weird to the IDE...

OK, I got it to compile on a different computer. Unfortunately, I have no idea what I did to my first IDE that caused it to fail. Oh well, moving on...

fat16lib,

Got another question for you...

One of the functions (apps?) that I want to run on the RTOS is a web server. However, I think I read one of your posts that said the Ethernet lib isn't RTOS friendly. I can't find the post again but do I have that right?

Thanks

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.

pito,

I found my BMP085 and it seems to work with the Adafruit library by just changing Wire.h to TwiMaster.h.

I noticed this call in your post:

  bmp.begin(I2C_100KHZ);

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

I tested on an Uno and a 2560 Mega using the Adafruit example sketch. I don't have a 1284.

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"