ChibiOS/RTand FreeRTOS for Teensy 3.0

Status
Not open for further replies.

Bill Greiman

Well-known member
I have posted a first beta of two Real Time Operating System kernels for Teensy 3.0 as Teensy3-RTOSbeta20121116.zip http://code.google.com/p/beta-lib/downloads/list.

These systems are packaged as Arduino libraries so they can be used with other Arduino software. Since these are preemptive kernels, careful design is required to avoid problems with normally single-threaded Arduino software.

These RTOSs must be used with the beta8 version of the Teensy 3.0 software.

ChibiOS/RT is version 2.4.2 http://www.chibios.org/dokuwiki/doku.php?.

FreeRTOS is version 7.3.0 http://www.freertos.org/.

Warning: If this is your first use of a RTOS, you will likely experience the pain of my bugs and problems that are inherent to preemptive RTOSs. Please read the warnings in the included html documentation.

Four examples are included with each system. These example are described in the html included with the libraries.
 
Eventually I believe there will be 3 options. I've been communicating with the Arduino developers are cooperatively scheduled approaches. They've published a cooperative scheduler library (developed by google as part of the ADK), and work is underway to make it integrate better with Arduino libraries. I'm also planning something similar to Bill Roy's "Run" library, but based on those new APIs. This stuff is all under development now, but hopefully in a few weeks there will be more options.
 
Both ChibOS and FreeRTOS can be run in cooperative mode.

With ChibiOS you edit chconf.h and set CH_TIME_QUANTUM to zero. Setting this value to zero disables the preemption for threads with equal priority and the round robin becomes cooperative. Note that higher priority threads can still preempt, the kernel is always preemptive.

For FreeRTOS, the configUSE_PREEMPTION flag prevents the system tick from performing a task context switch. Therefore, Tasks have to explicitly yield. When you call any of the queue functionality, semaphores, or task delay or specifically taskYIELD(), then your task will yield and the scheduler can select the next task.

These modes simplify things in terms of threadsafe/reentrancy issues.

As far as a choice between ChibiOS and FreeRTOS, they are both first class systems so you need to look at the examples, read the documentation, and try them then decide.
 
Bill - Just curious ...

ChFastLogger fails SD

I ran the ReadWriteSDFat test with SPI chip select 10 at SPI_Half_Speed.
This test passes.

On the chFastlogger there is no place to select SPI_half_Speed and the chip select.
So I did this

const int chipSelect = 10;

// initialize SD card
if (!sd.init(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

it fails with
Type any character to start
Can't access SD card. Do not reformat.
No card, wrong chip select pin, or SPI problem?
SD errorCode: 0X1,0XFF

Question:

1. what spi chip select are you using for ChFastLogger?

2. what SD electronics vendor (Adafruit/sparkfun/pjrc) are you using for ChFastLogger?

3. what do you consider a "quality" micro SD card?

BTW ... great RTOS port !!!!
 
The best way to use an SD card on Teensy 3.0 is to directly connect the card to these pins with very short wires.

CS - pin 10 (short white wire)
MOSI - pin 11 (violet wire)
MISO - pin 12 (orange wire)
SCK - pin 13 (long white wire)

red and black are vcc and gnd.

I use breakouts like these:

https://www.sparkfun.com/products/544

https://www.sparkfun.com/products/11403

Here is the actual setup with a cheap ebay breakout:
SdSetup.jpg
Note: the light made some areas shine like solder, pins are not shorted.

The version of SdFat included with the library is highly optimized for Teensy and uses a clock rate of 24 MHz at full speed.

You can test this version of SdFat independently of the RTOS by running examples in the SdFat/examples folder.

Try SdInfo.ino and QuickStart.ino. I don't think speed is the problem since SdFat slows the clock for initialization and your card fails on the first SD command.

You could try changing the SPI mode slightly by editing Sd2Card.cpp at line 81 and select 8-bit SPI frames. This introduces a slight delay between bytes.
Code:
// use 16-bit frame if SPI_USE_8BIT_FRAME is zero
#define SPI_USE_8BIT_FRAME 1

You don't need a super card. I use mostly SanDisk class 4 or better cards for this test. The card should not cause a problem in initialization. I had an old class 2 card suffer one data overrun due to one long write latency. It just took too long on one write, more than 200 msec. The SD spec allows a card to take up to 250 msec and some older class 2 cards do massive erases of flash occasionally.

For very high speed writes I use industrial SD cards like these http://www.newegg.com/Product/Product.aspx?Item=9SIA12K0CT6829. They use SLC flash which works better than consumer MLC/TLC flash for large fast writes.
 
Last edited:
t3andy,

Here is one more thing you can try to get your SD to work. You can edit SdFatConfig.h and use Paul's SPI that simulates AVR.

Change line 52 of SdFatConfig.h from
Code:
#define USE_NATIVE_MK20DX128 1
To:
Code:
#define USE_NATIVE_MK20DX128 0
 
Ok Bill
Using the Adafruit micro SD (NOT full size SD) breakout board
Under sdFat library examples (only at SPI half speed @ SS 10) <-------<<<<<<<
The following examples passed
SDinfo works <----------- OK
ReadWriteSdFat works OK <-------- OK
QuickStart works OK <------------ OK
PrintBenchmark <------------ OK

I "assumed" that both RTOS fast logger examples would default to SPI full speed?
Since the above examples only worked at SPI half speed with my micro SD then
what I did was to insert into the function sd.init(CHIP_SELECT, SPI_FULL_SPEED) which made both fast loggers fail.
Both fast loggers must already default to chip select 10 and SPI half speed because running them without any changes whatsoever they both work.
How to you alter the fastloggers chip select and SPI speed for the SD?
 
Last edited:
t3andy,

Sorry, I didn't catch the problem earlier. Here's what happened. I started with an old sketch from the AVR version of ChibiOS that used sd.init() instead of sd.begin(). The difference between the two is that the parameters are swapped. Here are the definitions of the two:

Code:
bool begin(uint8_t chipSelectPin = SD_CHIP_SELECT_PIN, uint8_t sckRateID = SPI_FULL_SPEED);

bool init(uint8_t sckRateID = SPI_FULL_SPEED, uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);

init() was the original call to initialize the system, then the Arduino company used SdFat as the base for their SD.h library and introduced begin(chipSelect) so I added begin().

Guess I should retire init() to prevent this type of confusion.

At a minimum, I will fix these examples.
 
Last edited:
I ve been looking into the chibi source code, and this is a bunch of things, a real OS :)
cool. Well same for freeRTOS.

on the other end this makes the choice difficult, because if you go that route , you need to invest time to deep dive and get the whole benefit of it.
looking at the vast arduino library landscape, I feel that preemptive capability is not for the everyone hobbyst due to non-re-entering stuff;
I m more voting for the cooperative approach, which chibi and freertos does support as well of course.

But then, I went trough the google world and didnt find too much of good and light library for the simple multitasking or event purpose !
also Paul, I ve read the thread in the arduino dev forum about the "yield" and I think thats going to be the future simple way of doing things. right?

then I d like just to share with you guys, that I m impressed by the library writen by "komisar" in the arduino forum, called ados.h ados.cpp here : http://arduino.cc/forum/index.php/topic,38030.0.html
look at it and its very light and does the job. not fully very self explaining for a noob, but if we make it simpler and if we package it with the right object classes, it could be a killer;
Paul, Bill and other, your opinion welcome, as I havent make a choice myself for the panSTamps and for my upcoming teensy3.0
cheers
 
Hi,
Bill,
I ve been playing with ChibiOS and I feel like there is a missing push R3 in the port_switch.
in some case I was not able to get the "this" pointer when coming back into the task.
seems R3 holds the this ptr at the entry of a method;

on my side, I ve made strong progress on a Cooperative scheduler, leveraging the Java Thread libraries and it seems to work pretty well on Teensy 3 and Teensy 2 !
I ll post soon a lib and a subject in the forum :)

Paul, I think your dream for a light library looking like the Java Thread/timer and using the famous yield() is almost ready, stay tuned;
 
Last edited:
http://mazsola.iit.uni-miskolc.hu/DATA/segedletek/arm/cmsis/CMSIS/Documentation/RTOS/html/index.htmlOn a context switch with ChibiOS, the registers R0–R3, R12 should be saved and restored by the NVIC. The SVC interrupt is used. Do you have an example where R3 is clobbered?

I am beginning to think that the multitude of schedulers and RTOSs for Arduino is a mistake. I keep reading of yet another effort in the forums. It's too easy to throw together another multithread solution.

One idea that I bumped into recently was an approach by ARM to make it easier to handle all the Cortex RTOSs.

The idea is to have a basic API that can provide functionality needed by libraries. This is a very thin layer that provides a common API for third party RTOSs.

This would allow libraries to be more multithread friendly in a standard way. It would require agreement on this API, probably not likely.

Since almost all RTOSs have a Cooperative scheduler mode they would both would have the simplest API functions.

The standard is CMSIS V3.0 RTOS API. Several RTOS vendors are providing this API already. Here is a bit from the announcement:
ARM today announced the availability of Version 3.0 of the ARM® Cortex™ Microcontroller Software Interface Standard (CMSIS). CMSIS 3.0 is expanded with a standardized API for Real-Time Operating System (RTOS) kernels and support for System View Description (SVD) XML files.

The RTOS API is designed to expand existing RTOS kernels with a standardized function set that supports multiple threads, resource control, time management, and data exchange. The RTOS API allows programmers to rely on standard RTOS features that are required in source code templates, middleware libraries, and other software components.

You can still access unique functionality for a third party RTOS but common things have a standard API.

Details are in the CMSIS Version 3.0 http://www.onarm.com/cmsis/download/21/version-3-0-of-the-cortex-microcontroller-software-interface-standard-cmsis/

Edit: here it is on the web http://mazsola.iit.uni-miskolc.hu/DATA/segedletek/arm/cmsis/CMSIS/Documentation/RTOS/html/index.html
 
Last edited:
Any updated info / guides?

Hey Guys,

First post here, was wondering if you have any more information on getting started with ChibiOS on teensy 3.0?

I downloaded the latest chibios version but can't find anything related to teensy.

Help much appreciated.

-Ben
 
I've got the FreeRTOS port running on the Teensy 3. Not too hard, starting with the user contributed library.
I've used FreeRTOS on other processors, so I know its concepts.
 
Can anyone post a simple recipe to get this going on a teensy 3.0? I am not savvy enough to figure this out, but want to see if it may be a solution for a simple/small ethernet connected device. If not chibi, then some sort of an OS...

KeithG
 
Because I've used FreeRTOS in the past due to it's proliferation, I chose to use it, and easily adapted from the example posted here by the OP. That adaptation uses the T3's libraries whereas often, FreeRTOS runs as a bare metal OS.

I can send what I'm using - via a post or somehow send a zip file.
 
I can build frBlink inside the arduino IDE. I can build a simple arduino blink from a makefile. But I can't seem to build frBlink from a makefile. It builds if I insert a main, but it doesn't run. What's puzzling is that I would expect behavior to be more similar since my makefile can build and run an arduino based blink.

mk20dx128.c contains the same call to main no matter how it's compiled, but I'm not sure where this phantom main gets supplied when building frBlink via the IDE.
 
I didn't disable the 1KHz systick interrupt. FreeRTOS for Teensy, as I recall, used it for the scheduler. As I recall, the only hardware-ish thing in the FreeRTOS port to teensyduino was the software interrupt (trap), used to do a context switch.
The FreeRTOS delay / wait function is used as is, from the user program tasks.
 
The recipe I followed replaced entries 11, 14 and 15 in the vector table.
Below is a snippet of mk20dx128.c where some of my defines are shown...

Code:
	fault_isr,					//  9 --
	fault_isr,					// 10 --
#ifdef TEENSY_USE_FREERTOS
	vPortSVCHandler,			// 11 ARM: Supervisor call (SVCall)
#else
	svcall_isr,					// 11 ARM: Supervisor call (SVCall)
#endif
	debugmonitor_isr,				// 12 ARM: Debug Monitor
	fault_isr,					// 13 --
#ifdef TEENSY_USE_FREERTOS
	xPortPendSVHandler,				// 14 ARM: Pendable req serv(PendableSrvReq)
#else
	pendablesrvreq_isr,				// 14 ARM: Pendable req serv(PendableSrvReq)
#endif
#ifdef TEENSY_USE_FREERTOS
	xPortSysTickHandler,			// 15 ARM: System tick timer (SysTick)
#else
	systick_isr,					// 15 ARM: System tick timer (SysTick)
#endif
#if defined(__MK20DX128__)
	dma_ch0_isr,					// 16 DMA channel 0 transfer complete
	dma_ch1_isr,					// 17 DMA channel 1 transfer complete
 
Hi milhead,

I tried the "recipe" on the other blog and didn't work for me. Somehow the changes in the vector table give me these errors:

Arduino: 1.0.5-r2 (Windows 7), Board: "Teensy 3.0"
C:\Program Files (x86)\Arduino\hardware\teensy\cores\teensy3\mk20dx128.c:182:2: error: 'vPortSVCHandler' undeclared here (not in a function)
C:\Program Files (x86)\Arduino\hardware\teensy\cores\teensy3\mk20dx128.c:185:2: error: 'xPortPendSVHandler' undeclared here (not in a function)
C:\Program Files (x86)\Arduino\hardware\teensy\cores\teensy3\mk20dx128.c:186:2: error: 'xPortSysTickHandler' undeclared here (not in a function)

I tried with the FreeRTOS 8.0.1 source code and a FreeRTOSConfig.h from another port I had (somehow this file is nowhere to be found and no explanation in the blog on its provenance). I have included the "FreeRTOS.h" and "task.h" in the "mk20dx128.c" but somehow the linker or inclusion scheme can't find the "port.c" object at compile time, which makes me hate arduino even more... grrrrrrr

I'm curious also if you disabled the systick ini in the ResetHandler and how is it really done later, as stated in the blog. Also, seems the file "portable.h" is used to point on a "portmacro.h" but I would like to know if you added defines for that because it hasn't been defined for the teensy. I tried many other self proclaimed working examples (like this thread: http://forum.pjrc.com/threads/9481-New-version-of-FreeRTOS-for-Teensy-3-0-Due-and-AVR-boards) and other ports with no success. PLEASE HELP!! :)

Mevon
 
somehow adding these lines :

extern void xPortPendSVHandler( void ) __attribute__ (( naked ));
extern void xPortSysTickHandler( void );
extern void vPortSVCHandler( void ) __attribute__ (( naked ));

made compiling possible but nothing is happening.. must be that elusive delay() at the end of the ResetHandler that I don't seem to find that is sausing this.. :( more grrrrr

Mevon
 
Hi Mevon,

Two commands to the reset handler to enable and light a LED, I used the onboard Teensy LED
as you resolve issues just move it down. I just moved the LED-ON as my debugging tool until I got into my tasks. There is a call to the delay() function at the end of the reset code that will definatly block until you do something to implement delay() without using the counter in the systick() handler.

The default delay() function was a hard spin delay that would run until the millisecond timer (incremented
by the default systick() function) incremented past the required milliseconds.

I've (I'll probably get blasted here) replaced it with the following function

Code:
// Uber-cheesy Brute Force ms delay...  Requires 96MHz clock
// should probably put a bomb here in case it's run at a lower speed
// not terribly accurate but within a percent or so..
//
void spinDelayMs(uint32_t ms)
{
    volatile double x;
    int i;
    int j;
    for( j=0; j<ms; j++)
        for(i=0; i<77; i++)
        {
            x = sqrt(2000);
            x = sqrt(x);
        }
}
I've since Changed the default delay function to call this one the libraries I've tried work again. I realize that they are not designed to be threadsafe, lets not have that discussion here.

In my last effort I was trying to get another timer on the Teensy to fire the 1Khz sysTick function, I haven't looked where else the libraries rely in the millisecond count value generated by the default delay function.

There is a 1KHz clock always running in the Freescale part as part of the low-power stuff but I haven't yet figured out (or if it's possible) how to route it to an interrupt. I hate to burn a timer and will probably keep looking for another way to do it.

Good Luck!

Miller
 
awesome

Hi milhead,

I guess we are the last one standing (like in the movie Highlander, let's not chop each others head off :p) I think there's a delay called in the init usb function inside the usb_dev.cpp but not sure, let me check for that. Also, I am really interested in NOT hijacking the systick function and maybe have work nicely togheter with the all the other functions or com stacks used by arduino. Do you have any inputs on that?

I found that one could make some defines inside the freertos header to hook up on existing code like so:

Code:
#define xPortPendSVHandler    svcall_isr
#define xPortSysTickHandler   pendablesrvreq_isr
#define vPortSVCHandler       systick_isr

But I can seem to find the link to that now, think it was for some other platform on the FreeRTOS wiki/doc maybe in some readme. I think it's just sad to cripple the teensy to add some functionality that is maybe not needed after all. What is also sad is that the info on ChibiOS on arduino is rare. I have worked with Chibi and liked it very much. I had it running on the teensy 2 and on some sanguino clone but the code I had is lost or hard to find, since it was on my old laptop and reformated since. I don't know if I backed it up and have no time to look for that now.

And looking at this problem maybe we are trying to solve it in a wrong way. Maybe we could hook up the systick for the rtos directly on a "user created" timer interrupt (as I recall I think that's how it was done with chibi). Or maybe we could make a call in the existing systick function to call that other rtos systick function so both would be executed. My point is we don't know the repercussion of unhooking the original systick on others libraries that could be using it like maybe Time/Date libs with the RTC batt on, or maybe even just com libs or audio lib.

Anyways, I'll keep reporting here, thanks for reading.
Mevon

EDIT: no delay in usb_init(), but I think there is one other somewhere. I'll keep checking and post here..
 
Last edited:
Status
Not open for further replies.
Back
Top