DuinOS: small and simple rtos

Good news. keep the good work!

DuinOS v0.2 Alpha

What's new: (2010.06.30)

  • Arduino updated to version 0018
  • FreeRTOS updated to version 6.0.5
  • Add new example MoreComplexBlinkingAndSound (Blinks two LEDs and play sound)

Download: http://novell.chel.ru/get.php?file=DuinOS_v0.2_Alpha

MD5: e22213ca659872b64cad11a85ddd22d6 *DuinOS_v0.2_Alpha.rar

Julian,

Why don't you put up a complete tutorial on this? (perhaps i missed it?)

Cheers,
Pracas

A tutorial would be nice, I'm not sure how to use it, and I belive others also don't know so they dont toutch it. This have a lot of potencial, but if no one know how to work with it... :S

Sorry, the system did not notify me automatically about your posts, don't know why.

I will look the 0.2 Alpha, thanks CHERTS!

We lack documentation yet, I have taken note of the tutorial thing.

Julián

Thanks for version 0.2. The example compiles in Arduino 0018.

Does this new version support the "Wire" library? Whenever I have the duinOS enabled(on the boards section) the only value I get from my external device is the max value.

Like...Even if the program isnt using any duinOS features... but is set to compile for the duemilanove w/ an atmega328 +duinOS, it simply fails, but works perfectly without the "+duinOS".

Also, it seems to crash and burn if I put the code below in a critical section:
Wire.beginTransmission(0x52);// transmit to device 0x52
Wire.send(0x00);// sends one byte
Wire.endTransmission();// stop transmitting

I wish I realized it was duinOS's fault and not my code 6 hours ago...

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

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

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

Update:

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...

/*
 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

declareTaskLoop(OutputSHT);
declareTaskLoop(redLED);
declareTaskLoop(greenLED);
declareTaskLoop(PlaySound);

taskLoop(OutputSHT)
{
  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...");
  delay(outDelay);
}

taskLoop(redLED)
{
  digitalWrite(ledPinRed, HIGH);
  delay(redDelay);
  digitalWrite(ledPinRed, LOW);
  delay(redDelay);
}


taskLoop(greenLED)
{
  digitalWrite(ledPinGreen, HIGH);
  delay(greenDelay);
  digitalWrite(ledPinGreen, LOW);
  delay(greenDelay);
}

taskLoop(PlaySound)
{
  tone(SoundPin, 1245, 480);
  delay(480);
  tone(SoundPin, 932, 240);
  delay(240);
  tone(SoundPin, 1245, 960);
  delay(120);
  tone(SoundPin, 831, 240);
  delay(240);
  tone(SoundPin, 932, 480);
  delay(480);
  tone(SoundPin, 622, 720);
  delay(240);
  tone(SoundPin, 784, 120);
  delay(120);
  tone(SoundPin, 932, 120);
  delay(120);
  tone(SoundPin, 1245, 240);
  delay(240);
  tone(SoundPin, 932, 240);
  delay(240);
  tone(SoundPin, 1397, 240);
  delay(240);
  tone(SoundPin, 1245, 960);
  delay(120);
  tone(SoundPin, 1109, 360);
  delay(360);
  tone(SoundPin, 1047, 120);
  delay(120);
  tone(SoundPin, 932, 120);
  delay(120);
  tone(SoundPin, 831, 360);
  delay(360);
  tone(SoundPin, 932, 960);
  suspend();
}

// The setup() method runs once, when the sketch starts
void setup()   
{  
  //
  Serial.begin(9600);
  
  // 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):
  //initMainLoopPriority(NORMAL_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
  delay(10000);
  suspendTask(redLED);
  // Start the task of redLED in 10 seconds
  delay(10000);
  resumeTask(redLED);
  //
  delay(30000);
  resumeTask(PlaySound);  // play Micheal's funky intro again
}

Thanks

Eric

Hi Julián,

this is a great project you're working on.
+1

I have the same problem with DuinOS, migit.

Wire.beginTransmission(0x52);// transmit to device 0x52
   Wire.send(0x00);// sends one byte
   Wire.endTransmission();// stop transmitting

Anyone has solved this?

Thanks!

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.

SimonJ

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!

Simon

My arduino0018+DuinOS0.2 freezes when:

Wire.endTransmission();

Any ideas?
Thanks

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:-

Wire.beginTransmission(0x52 >> 1);
Wire.send(10);
Wire.endTransmission();

Simon

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
UPLOAD_RATE = 57600
AVRDUDE_PROGRAMMER = stk500v1
#MCU = atmega168

Processor for the Arduino Mega

MCU = atmega1280
F_CPU = 16000000

############################################################################

Below here nothing should be changed...

VERSION=18

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
C_MODULES =
$(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
CXX_MODULES =
$(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

SKETCHHOME=/Users/sbade1/Documents/Arduino

#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

CXXFILES =

MODULES = $(C_MODULES) $(CXX_MODULES) $(CXXFILES)
SRC = $(C_MODULES) $(CXXFILES)
CXXSRC = $(CXX_MODULES) $(CXX_APP) $(CXXFILES)
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
DEBUG =

OPT = s

Place -D or -U options here

CDEFS = -DF_CPU=$(F_CPU)L -DARDUINO=$(VERSION)
CXXDEFS = -DF_CPU=$(F_CPU)L -DARDUINO=$(VERSION)

Place -I options here

Local includes for the project

CINCSLOCAL = -I$(ARDUINO) -Ipwd -I$(ARDUINO) -I$(ARDUINO)/DuinOS

CINCS = -I$(ARDUINO) -Ipwd $(CINCSLOCAL)
CXXINCS = -I$(ARDUINO) -Ipwd $(CINCSLOCAL)

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
CDEBUG = -g$(DEBUG)
#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)

CFLAGS = $(CDEBUG) -O$(OPT) $(CWARN) $(CTUNING) $(CDEFS) $(CINCS) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEBUG) -O$(OPT) $(CWARN) $(CXXTUNING) $(CDEFS) $(CINCS)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS = -O$(OPT) -lm -Wl,--gc-sections

Programming support using avrdude. Settings and variables.

AVRDUDE_PORT = $(PORT)
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
-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
-b $(UPLOAD_RATE)

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
AVRDUDE = $(AVRDUDE_PATH)/avrdude
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_CFLAGS = $(CFLAGS) -mmcu=$(MCU)
ALL_CXXFLAGS = $(CXXFLAGS) -mmcu=$(MCU)
ALL_ASFLAGS = -x assembler-with-cpp $(ASFLAGS) -mmcu=$(MCU)
ALL_LDFLAGS = $(LDFLAGS) -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

foo:
echo $(LST)

Program the device.

upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)

Display size of file.

HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex
ELFSIZE = $(SIZE) applet/$(TARGET).elf
sizebefore:
@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi

sizeafter:
@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

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

.elf.eep:
$(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.

.elf.lss:
$(OBJDUMP) -h -S $< > $@

Create a symbol table from ELF output file.

.elf.sym:
$(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.

.cpp.o:
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@

Compile: create object files from C source files.

.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@

Compile: create assembler files from C source files.

.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@

Assemble: create object files from assembler source files.

.S.o:
$(CC) -c $(ALL_ASFLAG

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


Board Cost $28 NCC Amazon $50 Leaflabs
Flash 30KB 108KB
Ram 2KB 17KB
EEPROM 1KB N/A
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
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
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"

:sunglasses: :sunglasses: :sunglasses:

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!

Regards,
Julián

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.

Thanks!

Regards,
Julián

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.