Go Down

Topic: DuinOS: small and simple rtos (Read 51 times) previous topic - next topic


Jul 18, 2010, 11:35 pm Last Edit: Jul 19, 2010, 01:53 am by LAVco Reason: 1
Hello everyone,

Wow great to see an RTOS port for the arduino!  I've used uC/OS-II but haven't toyed much with FreeRTOS.

Anyhow I've downloaded the 0.2 Alpha version have the samples working (FYI - the main.cxx wasn't included and I had to use 0.1 Alpha version - not certain if there were any changes though but it works).  However there may be a potential bug with Serial or Print.

Board: Duemilanove Atmel ATmega328
ArduinoL IDE 0017

Code: [Select]

float myFloat = 23.23;
int myInt = 43;
Serial.print("Hello World..");  // works
Serial.println("Hello World Again..");  // works
Serial.println(myFloat); // prints the first digit and hangs "print" does the same
Serial.println(myInt); // prints the first digit and hangs "print" does the same

After comparing Print.cpp and Print.h files from Arduino core to DuinOS there were differences.  Once I copied the Arduino core Print.cpp and Print.h files over it DuinOS was able to print ints via serial port but floats are failing e.g. one char prints and hangs the system.

Also, is there a way to check which environment the project is compiled from using a ifdef check?  I wouldn't mind porting some libraries for DuinOS but wanted to know if they can be transparent between platforms.

code sample for clarification
Code: [Select]

#if ___DuinOS___ //
     #define LONG_PULSE delay(100)
       #define LONG_PULSE delayMicroseconds(1)


Downloaded Arduino IDE 0018.

Tried the same cases (includes replacing files) and neither int or float are able to print using Serial.print.

Sketch file...

Code: [Select]

DuinOS MoreComplexBlinkingSoundSerial

Blinks two LEDs and play sound.

The circuit:
* 1 LED connected from digital pin 14 (8)
* 2 LED connected from digital pin 15 (9)
* Speaker connected from digital pin 16 (10)

Created 2010.06.30 (yyyy.mm.dd)
by Michael Grigorev aka CHERTS


#include <Streaming.h>         // Include the Streaming library

#define ledPinRed 2
#define ledPinGreen 3
#define SoundPin 6
#define greenDelay 200
#define redDelay 400
#define outDelay 5000


 Serial << "Hello" << endl;  // yippy Streaming library works...provided a float or int isn't concatenated
 Serial.print("Val: ");
 //Serial.print(23.33);   // *** hangs here if un-commented
 //Serial.print(" ");
 //Serial.print(23);      // *** hangs here is un-commented
 Serial.println(" something...");

 digitalWrite(ledPinRed, HIGH);
 digitalWrite(ledPinRed, LOW);

 digitalWrite(ledPinGreen, HIGH);
 digitalWrite(ledPinGreen, LOW);

 tone(SoundPin, 1245, 480);
 tone(SoundPin, 932, 240);
 tone(SoundPin, 1245, 960);
 tone(SoundPin, 831, 240);
 tone(SoundPin, 932, 480);
 tone(SoundPin, 622, 720);
 tone(SoundPin, 784, 120);
 tone(SoundPin, 932, 120);
 tone(SoundPin, 1245, 240);
 tone(SoundPin, 932, 240);
 tone(SoundPin, 1397, 240);
 tone(SoundPin, 1245, 960);
 tone(SoundPin, 1109, 360);
 tone(SoundPin, 1047, 120);
 tone(SoundPin, 932, 120);
 tone(SoundPin, 831, 360);
 tone(SoundPin, 932, 960);

// The setup() method runs once, when the sketch starts
void setup()  
 // Initialize the digital pins as outputs:
 pinMode(ledPinRed, OUTPUT);
 pinMode(ledPinGreen, OUTPUT);
 createTaskLoop(OutputSHT, LOW_PRIORITY);
 createTaskLoop(redLED, NORMAL_PRIORITY);
 createTaskLoop(greenLED, NORMAL_PRIORITY);
 createTaskLoop(PlaySound, NORMAL_PRIORITY);

 //This initializes the main loop's with a different priority (default is LOW_PRIORITY):

// This is the main loop() method, wich runs over and over again,
// as long as the Arduino has power. Is a LOW_PRIORITY taskLoop:
void loop()                    
 // Stop the task of redLED in 10 seconds
 // Start the task of redLED in 10 seconds
 resumeTask(PlaySound);  // play Micheal's funky intro again


Common sense is not so common...


Hi Julián,

this is a great project you're working on.


I have the same problem with DuinOS, migit.
Code: [Select]
Wire.beginTransmission(0x52);// transmit to device 0x52
  Wire.send(0x00);// sends one byte
  Wire.endTransmission();// stop transmitting

Anyone has solved this?



Sep 09, 2010, 12:40 pm Last Edit: Sep 09, 2010, 12:46 pm by SimonJ5 Reason: 1
Hi. The problem with the Serial.println() is to do with the lack of stack space allocated for the task. See this reply http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256745982/95#95 (number 95 page 7) of this thread for details of how to change the amount of stack allocated when a task is created.

Compatiliby with Arduino-0018 is available in the version 0.2 alpha as explained in reply http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256745982/144#144 (144 page 10) of this thread.

I am using DuinOS in a control system (Arduino Mega board) that uses I2C to communicate with another Arduino that is running 'plain' Arduino code and it all works pretty well. I have 5 concurrent tasks some of which are accessing the I2C bus so I'm using mutexs to control that.

Don't be fooled by the '0.2' nomenclature of DuinOS - it's pretty sound (based in FreeRTOS) and it's impressive what it allows you to do on an 8-bit processor. Yes it has some rough edges and the documentation can be a bit sparse at times but...

An updated version of DuinOS that includes the stack and mutex changes would be great. Any news on the next version?

I also notice that Aruino-0019 was released recently but I haven't tried DuinOS with it yet.



The link to alpha 2 is http://novell.chel.ru/get.php?file=DuinOS_v0.2_Alpha but I wasn't allowed to post this link in my first post!



My arduino0018+DuinOS0.2 freezes when:
Code: [Select]

Any ideas?


Sep 09, 2010, 02:00 pm Last Edit: Sep 09, 2010, 05:03 pm by SimonJ5 Reason: 1
I had a number of problems that seemed to go away when I put in 4K7 pull up resistors on the SDA and SCL lines. Otherwise, and as long as there's no contention between multiple tasks both trying to use the I2C bus, it just worked.

Does your sketch work without DuinOS? A possiblilty is that the Wire library expects 7 bit addresses since I2C uses bit 0 as a read/write indicator and shifts the supplied address left. In otherwords if trying to talk to a device with an ID of 0x52 you probably want to do something like:-

Code: [Select]
Wire.beginTransmission(0x52 >> 1);



Using Make and the DuinOS

I've made a makefile (based on a makefile from a post in another thread) that builds DuinOS and your sketch.   This makefile builds the sketch that was posted in the very beginning of the thread.  The makefile assumes that the sketch is DuinOSTest.pde.  Note, this is from a MAC, but it should be easy to modify for linux or even windows

TARGET = $(notdir $(CURDIR))
#INSTALL_DIR = $(HOME)/arduino-0018

# This is the location on the MAC
INSTALL_DIR = /Applications/Arduino.app/Contents/Resources/Java
# Serial port which I always connect my MEGA to
PORT = /dev/tty.usbserial-A900ceXD
#MCU = atmega168
# Processor for the Arduino Mega
MCU = atmega1280
F_CPU = 16000000

# Below here nothing should be changed...

# Location of the boards file
ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino.DuinOS
AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin
#AVR_TOOLS_PATH = /usr/local/CrossPack-AVR-20100115/bin
#AVR_TOOLS_PATH = /usr/bin
#AVRDUDE_PATH = $(INSTALL_DIR)/hardware/tools
AVRDUDE_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin
#These are all the C language files for Arduino and the DuinOS
$(ARDUINO)/wiring_pulse.c \
$(ARDUINO)/wiring_analog.c \
$(ARDUINO)/pins_arduino.c \
$(ARDUINO)/wiring.c \
$(ARDUINO)/wiring_digital.c \
$(ARDUINO)/WInterrupts.c \
$(ARDUINO)/wiring_shift.c \
$(ARDUINO)/DuinOS/croutine.c  \
$(ARDUINO)/DuinOS/heap_1.c  \
$(ARDUINO)/DuinOS/heap_2.c  \
$(ARDUINO)/DuinOS/heap_3.c  \
$(ARDUINO)/DuinOS/list.c  \
$(ARDUINO)/DuinOS/port.c  \
$(ARDUINO)/DuinOS/queue.c  \
$(ARDUINO)/DuinOS/tasks.c  \
# end of C_MODULES

#These are all the CPP language files for Arduino and the DuinOS
$(ARDUINO)/Tone.cpp \
$(ARDUINO)/main.cpp \
$(ARDUINO)/WMath.cpp \
$(ARDUINO)/Print.cpp \
$(ARDUINO)/HardwareSerial.cpp \
# end of CXX_MODULES

# Variable for where my sketches are kept

#Vpath simplifies MAKE finding source files

VPATH = ../libraries/SdFat:../libraries/SoftI2cMaster:../libraries/TwiMaster:../libraries/TinyGPS:$(ARDUINO):$(ARDUINO)/DuinOS

CXX_APP = applet/$(TARGET).cpp
# Additional CPP files - library files would be specified here

FORMAT = ihex

# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile

# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
#DEBUG = stabs

OPT = s

# Place -D or -U options here

# Place -I options here
# Local includes for the project


# Compiler flag to set the C Standard level.
# c89   - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99   - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
#CSTANDARD = -std=gnu99
#CWARN = -Wall -Wstrict-prototypes
#CWARN = -Wall   # show all warnings
CWARN = -w      # suppress all warnings
####CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CTUNING = -ffunction-sections -fdata-sections
CXXTUNING = -fno-exceptions -ffunction-sections -fdata-sections
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)

#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS = -O$(OPT) -lm -Wl,--gc-sections

# Programming support using avrdude. Settings and variables.
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex

#AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf \

AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf \

# Program settings
CC = $(AVR_TOOLS_PATH)/avr-gcc
CXX = $(AVR_TOOLS_PATH)/avr-g++
LD = $(AVR_TOOLS_PATH)/avr-gcc
OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy
OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump
AR  = $(AVR_TOOLS_PATH)/avr-ar
SIZE = $(AVR_TOOLS_PATH)/avr-size
NM = $(AVR_TOOLS_PATH)/avr-nm
REMOVE = rm -f
MV = mv -f

# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) $(CXXFILES:.cpp=.o)
OBJ_MODULES = $(C_MODULES:.c=.o) $(CXX_MODULES:.cpp=.o) $(CXXFILES:.cpp=.o)

# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)

# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_ASFLAGS = -x assembler-with-cpp $(ASFLAGS) -mmcu=$(MCU)

# Default target.
all: applet_files build sizeafter

build: elf hex

#applet_files: $(TARGET).pde
applet/$(TARGET).cpp: $(TARGET).pde
     # Here is the "preprocessing".
     # It creates a .cpp file based with the same name as the .pde file.
     # On top of the new .cpp file comes the WProgram.h header.
     # and prototypes for setup() and Loop()
     # Then the .cpp file will be compiled. Errors during compile will
     # refer to this new, automatically generated, file.
     # Not the original .pde file you actually edit...
     test -d applet || mkdir applet
     echo '#include "WProgram.h"' > applet/$(TARGET).cpp
     echo 'void setup();' >> applet/$(TARGET).cpp
     echo 'void loop();' >> applet/$(TARGET).cpp
     cat $(TARGET).pde >> applet/$(TARGET).cpp

elf: applet/$(TARGET).elf
hex: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym

     echo $(LST)

# Program the device.  
upload: applet/$(TARGET).hex

     # Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex
ELFSIZE = $(SIZE)  applet/$(TARGET).elf
     @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi

     @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi

# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000

coff: applet/$(TARGET).elf
     $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof

extcoff: $(TARGET).elf
     $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof

.SUFFIXES: .elf .hex .eep .lss .sym

     $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@

     $(OBJCOPY) -O $(FORMAT) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
     --no-change-warnings \
     --change-section-lma .eeprom=0 $< $@

# Create extended listing file from ELF output file.
     $(OBJDUMP) -h -S $< > $@

# Create a symbol table from ELF output file.
     $(NM) -n $< > $@

     # Link: create ELF output file from library.
#applet/$(TARGET).elf: $(TARGET).pde applet/core.a
applet/$(TARGET).elf: applet/$(TARGET).o applet/core.a
     $(LD) $(ALL_LDFLAGS) -o $@ applet/$(TARGET).o applet/core.a

applet/core.a: $(OBJ_MODULES)
     @for i in $(OBJ_MODULES); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done

# Compile: create object files from C++ source files.
     $(CXX) -c $(ALL_CXXFLAGS) $< -o $@

# Compile: create object files from C source files.
     $(CC) -c $(ALL_CFLAGS) $< -o $@

# Compile: create assembler files from C source files.
     $(CC) -S $(ALL_CFLAGS) $< -o $@

# Assemble: create object files from assembler source files.
     $(CC) -c $(ALL_ASFLAG


Oct 04, 2010, 01:44 am Last Edit: Oct 04, 2010, 02:03 am by ArduinoAndy Reason: 1
Juliandasilva have you ever given any thought to porting FreeRTOS to an Arduino compatible ARM processor like The Maple?
There are plenty of hardware resources available and The Maple has four timers. Plus, it has a SysTick peripheral that is associated millis() and delay() functions are another simple way to perform periodic or delayed events. This separate timer does not conflict with any other peripherals

             <Arduino ATMega328>       <THE Maple ARM STM32F103RB>

Board Cost    $28 NCC Amazon        $50 Leaflabs
Flash                  30KB                      108KB
Ram                    2KB                       17KB
EEPROM               1KB                       N/A          <No on chip EEPROM>
Clock                 16MHz                     72MHz       <~ 4.5 faster instruction execution than Arduino>
Voltage                5 VDC                     3.3 VDC
I2C               1 Hardware Port              2 Hardware Ports
SPI               1 Hardware Port              2 Hardware Ports
Serial            1 Hardware Port              3 Hardware Ports
I/O                      14                          39 <See notes>
PWM                    6 <8 Bit>                15 <16 Bit>     <Both subtracts from I/O count>  
Analog IN             6 <10 Bit>              16 <12 Bit>      <Both subtracts from I/O count>                                      
Ext. Interrupts             2                     15               Rising/Falling <All usable at the same time> <See Notes>
Arduino Inst. Comp.    N/A                       Yes              <Most instructions. See Maple's language link>

Notes: There are 18 5 VDC tollerant I/O pins and 20 which are not (3.3 VDC only).
      There are a total of 38 I/O pins which can have the external "attachinterrupt();" assigned to them.

"The Maple is the high performance Arduino"
8-) 8-) 8-)
"Never trust an Internet bully who insults and makes fun of your level of intelligence."


We are working on that at RG.Labs. Currently, we have a running FreeRTOS on an ARM, but not on an ST ARM yet. However, this is in our scheduler.

bullethole: Nice work! Thanks for the makefile!



I've really embraced using DuinOS for my project.   But I'm noticing some strange behaviors when using serial on an Arduino MEGA.  I have a few tasks, one which reads data from Serial2 which is a GPS device, another which handles reading various sensors (accelerometer, voltage (0-1v)) and processes a tachometer input (the input is handled by an interrupt, which increments a counter, ever 250ms, the handler task runs and converts it to RPM).   All of these tasks queue messages to a handler task which will output through Serial2 to a Arduino Pro Mini which will drive a LCD display.   In the QueueHandler function, if I only do a "Serial.print" of a string, everything works fine.  When I try and Serial.print data from the queued message things just hang.  Things also hang when I try and Serial2.write out to the Pro Mini.

Sometimes the led on Pin 13 blinks, sometimes it goes solid, but in most cases it just remains off.

Anyone have any ideas what may be the issue here.

I'd post the code, but its quite large.  I'm happy to send via email.  Note, I've tried playing with stack sizes on the tasks when they are created going as large as 4K.  No joy there.


There is a bug reported when printing numbers with the overloaded Serial.Print (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1256745982/160#160) and I'm not sure it's caused by a stack problem. Sadly we could not work on it yet.

May I suggest that you try with the v0.1 and the 0018 core? These bugs were not reported for that version, and there was a FreeRTOS kernel change between v0.1 and v0.2. If it works, we may roll-back something for the v0.3.




I actually seem to have fixed the problem when I went back and simplified some of the code.  Things seem to be working fine now.. I will roll back to 0.1 if I run into more problems.  

Mark G.


I'm getting back into some Arduino/DuinOS coding after some time off and was wondering if the latest DuinOS rev is compatible with the latest Arduino build (21).  



Hi, we did not test it yet but I think it's not.
The latest v0.2 is 0018-compatible.


Go Up