DuinOS: small and simple rtos

Hi I changed the DuinOS.h file section '/* Scheduler include files. */'

from
#include "DuinOS\FreeRTOS.h"
#include "DuinOS\task.h"

to
#include "DuinOS/FreeRTOS.h"
#include "DuinOS/task.h"

To make it work on Mac OSX

Then it compiled and uploaded, now playing with it thanks Julian

Very Cool that you used FreeRTOS been meaning to play with it for some time, this is a perfect excuse..

Thanks for your words!!
I already made that modification in the current zip file.
Regards,
Julián

In my own opinion I feel the declareTaskLoop macro is ill-conceived. Writing
declareTaskLoop(greenLed) looks like you are calling a function to declare it and/or initialize it. I know it is simply a macro that is replaced with
extern xTaskHandle greenLed which I agree looks too complicated for a typical Arduino programmer but when you are reading through code what declareTaskLoop is doing is not at all obvious and seems counter-intuitive. I would rather see a typedef/define so that the code would then be:

taskLoopType greenLed

which to me makes it easier to understand what that line represents and perhaps less confusing even for beginning Arduino users.

Hi, thanks.

Are you suggesting to replace the macro with something like the following?

#define taskLoopType extern xTaskHandle

It works too (I have compiled it, changing the example too).

The macro is only for forward declarations when needed, I expect that most sketches will never use it, but right now I'm not sure which is more easy to understand. I like both!

Good question to decide as a community...

Regards,
Julián

Yes, I was suggesting using that macro. The current way looks like a method call and not a variable definition.

Have you done any testing on memory usage with tasks? Specifically, do you know how much base memory the creation of a task uses?

Hi Chumbud,

Regarding the macro, I think the change may be done in the next version. I agree with you about the sintax and that the function-call look isn't the best.

About the memory, now every task uses a space for it's CTB and for it's stack. The current default stack is defined with the configMINIMAL_STACK_SIZE in the FreeRTOS.h file.
Now it takes 85 bytes, but can be reduced very easy.

About the CTB this is the struct, from the task.c file:

typedef struct tskTaskControlBlock
{
      volatile portSTACK_TYPE      *pxTopOfStack;            /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
      xListItem                        xGenericListItem;      /*< List item used to place the TCB in ready and blocked queues. */
      xListItem                        xEventListItem;            /*< List item used to place the TCB in event lists. */
      unsigned portBASE_TYPE      uxPriority;                  /*< The priority of the task where 0 is the lowest priority. */
      portSTACK_TYPE                  *pxStack;                  /*< Points to the start of the stack. */
      signed portCHAR                  pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */

      #if ( portSTACK_GROWTH > 0 )
            portSTACK_TYPE *pxEndOfStack;                  /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
      #endif

      #if ( portCRITICAL_NESTING_IN_TCB == 1 )
            unsigned portBASE_TYPE uxCriticalNesting;
      #endif

      #if ( configUSE_TRACE_FACILITY == 1 )
            unsigned portBASE_TYPE      uxTCBNumber;      /*< This is used for tracing the scheduler and making debugging easier only. */
      #endif

      #if ( configUSE_MUTEXES == 1 )
            unsigned portBASE_TYPE uxBasePriority;      /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
      #endif

      #if ( configUSE_APPLICATION_TASK_TAG == 1 )
            pdTASK_HOOK_CODE pxTaskTag;
      #endif

      #if ( configGENERATE_RUN_TIME_STATS == 1 )
            unsigned portLONG ulRunTimeCounter                   /*< Used for calculating how much CPU time each task is utilising. */
      #endif

} tskTCB;

I know all this is too much memory for the small m168, but works well in the 328. We will try to fine tune and optimize all these things to fit better even in the 168.

As always, any comment is welcome.

Regards,
Julián

I think it is not worth trying to accommodate the atmega168 too much since the 328 has pretty much replaced the 168 as far as the arduino community. I think all the 168 arduino boards for sale have been replaced with 328 chips.

How much alteration did you have to do compared to the "standard" FreeRTOS to get it to work on the 8 bit avr's? What I see is these files needed to be altered:

portmacro./h
port.c
FreeRTOSConfig.h

and macro definitions that aren't necessary in: DuinOS.h

Does that cover it?

I think it will just take some time for the general Arduino community to catch on to the significance of the FreeRTOS port your group has done.

Hi, the m168 is not our main target, but the OS is already running on it (yes, but with some constraints). About the files, those you mentioned cover it. The initial work migrating the OS to most modern AVRs (than the 323) was made by the people at www.micropendous.org.

The macros at DuinOS.h are optional, but we think this is a more "Arduino-like" sintax. Of course you can always work with handles instead of names, and use the standard FreeRTOS API.

Regarding the evolution of the system, we are trying to do some optimizations and running more tests, in order to have the rtos working better with our robots. We think once we have more examples and better documentation (perhaps some videos too), this small os may be useful for many applications. In our specific case, the people who uses NXC, NQC, or small embedded versions of Java for robotics can use multitasking, and they really use it. So we want the same functiontality for Arduino and Arduino-compabible robots.

Regards,
Julián

I think it is not worth trying to accommodate the atmega168 too much since the 328 has pretty much replaced the 168 as far as the arduino community. I think all the 168 arduino boards for sale have been replaced with 328 chips.

:-[Well not really. Its still hard to get Atmega328 here in india(Well looks the arduino guys here are the only ones to use Atmega168 and that is available only directly from ATMEL dealers and they don't have stock of 328 unless we place a order)

Putting it simply, All efforts to accommodate 168 would be appreciated and this would reach more people than making it possible only on 328.

Can someone come out with a simpler example(than the more complex led blink ;)) perhaps a scan input and give output at the same time will help.

cheers,
pracas

Hi julian,

Wow, Really cool, just the tool I have been looking for.. I have a modified version(added serial print lines to each routine so I didnt have to wire up leds) of the example working on one of my adafruit 328p chips right now and I am writing an app to demo it more extensively later today.

However my main project is moving to a sanguino within 24 to 48hours.. any chances of getting my grubby hands on the 644 port of DuinOS?

again many thanx for giving this back to the community .. it really rocks

gwen
ps the arduino community has mostly moved to the 328 and more capable chips the 168 prolly is just too small for rtos AND the arduino cruft combined(with regards to the above poster).

Hi gwen,

Many thanks for your comments.
The 644 and 1284 ports are already there, the only thing you must do is to add something like this to the /hardware/boards.txt file (just be carefull with the type of bootloader/protocol you are using, and with the build.f_cpu param -crystal freq-):

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

Multiplo_Brain_M644_DuinOS.name=Multiplo.Brain.M644 + DuinOS
Multiplo_Brain_M644_DuinOS.upload.protocol=usbasp
Multiplo_Brain_M644_DuinOS.upload.maximum_size=65536
Multiplo_Brain_M644_DuinOS.upload.speed=19200
Multiplo_Brain_M644_DuinOS.upload.verbose=true

Multiplo_Brain_M644_DuinOS.bootloader.low_fuses=0xFF
Multiplo_Brain_M644_DuinOS.bootloader.high_fuses=0xDC
Multiplo_Brain_M644_DuinOS.bootloader.extended_fuses=0xFD
Multiplo_Brain_M644_DuinOS.bootloader.path=ADABootloader
Multiplo_Brain_M644_DuinOS.bootloader.file=ADABoot_644p.hex
Multiplo_Brain_M644_DuinOS.bootloader.unlock_bits=0x3F
Multiplo_Brain_M644_DuinOS.bootloader.lock_bits=0x0F

Multiplo_Brain_M644_DuinOS.build.mcu=atmega644p
Multiplo_Brain_M644_DuinOS.build.f_cpu=16000000L
Multiplo_Brain_M644_DuinOS.build.core=arduino.DuinOS
Multiplo_Brain_M644_DuinOS.build.verbose=true

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

Multiplo_Brain_M1284_DuinOS.name=Multiplo.Brain.M1284 + DuinOS
Multiplo_Brain_M1284_DuinOS.upload.protocol=stk500v2
Multiplo_Brain_M1284_DuinOS.upload.maximum_size=131072
Multiplo_Brain_M1284_DuinOS.upload.speed=19200
Multiplo_Brain_M1284_DuinOS.upload.verbose=true

Multiplo_Brain_M1284_DuinOS.bootloader.low_fuses=0xFF
Multiplo_Brain_M1284_DuinOS.bootloader.high_fuses=0xDC
Multiplo_Brain_M1284_DuinOS.bootloader.extended_fuses=0xFD
Multiplo_Brain_M1284_DuinOS.bootloader.path=ADABootloader
Multiplo_Brain_M1284_DuinOS.bootloader.file=ADABoot_1284p.hex
Multiplo_Brain_M1284_DuinOS.bootloader.unlock_bits=0x3F
Multiplo_Brain_M1284_DuinOS.bootloader.lock_bits=0x0F

Multiplo_Brain_M1284_DuinOS.build.mcu=atmega1284p
Multiplo_Brain_M1284_DuinOS.build.f_cpu=16000000L
Multiplo_Brain_M1284_DuinOS.build.core=arduino.DuinOS
Multiplo_Brain_M1284_DuinOS.verbose=true

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

We have tested it on the 644 and looks that is working, however, please remember that this is the v0.1-Aplha, so you may find bugs.
Please let me know any issue.

Regards,
Julián

Hi Julian,
really cool I will attempt to add that stanza to the boards.txt and modify appropriately for the sanguino and test and get back to you.
and of course my app uses pulsein to measure PWM from a CO2 meter(but can move to I2C) and a RCtime routine to read an HS1101 humidity sensor(and soon a MG811 Co2 sensor). so all will have to be refactored/re-engineered I suspect.
sigh
gwen
ps changes for sangunio follow

Sanguino_DuinOS.name=Sanguino.M644 + DuinOS
Sanguino_DuinOS.upload.protocol=stk500
Sanguino_DuinOS.upload.maximum_size=63488
Sanguino_DuinOS.upload.speed=38400
Sanguino_DuinOS.upload.verbose=true

Sanguino_DuinOS.bootloader.low_fuses=0xFF
Sanguino_DuinOS.bootloader.high_fuses=0xDC
Sanguino_DuinOS.bootloader.extended_fuses=0xFD
Sanguino_DuinOS.bootloader.path=atmega644p
Sanguino_DuinOS.bootloader.file=ATmegaBOOT_644P.hex
Sanguino_DuinOS.bootloader.unlock_bits=0x3F
Sanguino_DuinOS.bootloader.lock_bits=0x0F

Sanguino_DuinOS.build.mcu=atmega644p
Sanguino_DuinOS.build.f_cpu=16000000L
Sanguino_DuinOS.build.core=arduino.DuinOS
Sanguino_DuinOS.build.verbose=true

Looks like the ebook on FreeRtos is starting to look like a reasonable investment :slight_smile:

gwen
ps I will be using Duinos for automating the measurement, control and supervisory tasks of running a hydroponic growing chamber.(now if only I could figure out a mostly software approach to measuring PPM of nutrients :)(that is just using the hardware that comes on an arduino.)

OUCH.. using core=arduino.duinos instead of sanguino on the 644 chip results in the onewire routines NOT working and hanging up the RTOS instead.

Any thoughts greatly welcome will post some sample code shortly after I I make a clean example(app too buggy right now :slight_smile:

gwen
using 1wire to read temp sensors

this routine works properly when sanguino core used and gets no devices found when arduino.DuinOS selected as the code instead

#include <OneWire.h>

//init the one wire interface on pin 10
OneWire ow(12);

void setup(void) {
Serial.begin(115200);
lookUpSensors();
}

void lookUpSensors(){
byte address[8];
int i=0;
byte ok = 0, tmp = 0;
//start the search
Serial.println("--Search started--");
while (ow.search(address)){
tmp = 0;
//0x10 = DS18S20
if (address[0] == 0x10){
Serial.print("Device is a DS18S20 : ");
tmp = 1;
} else {
//0x28 = DS18B20
if (address[0] == 0x28){
Serial.print("Device is a DS18B20 : ");
tmp = 1;
}
}
//display the address, if tmp is ok
if (tmp == 1){
if (OneWire::crc8(address, 7) != address[7]){
Serial.println("but it doesn't have a valid CRC!");
} else {
//all is ok, display it
for (i=0;i<8;i++){
if (address < 9){

  • Serial.print("0");*
  • }*
    _ Serial.print(address*,HEX);_
    _
    if (i<7){_
    _
    Serial.print("-");_
    _
    }_
    _
    }_
    _
    Serial.println("");_
    _
    ok = 1;_
    _
    }_
    _
    }//end if tmp*_
    * }//end while*
    * if (ok == 0){*
    * Serial.println("No devices were found");*
    * }*
    * Serial.println("--Search ended--");*
    }

void loop(void) {
* //do nothing :)*
}

I can try looking at this Saturday. I have those same sensors but haven't used OneWire with FreeRTOS yet. You have to remember almost none of the current libraries are going to be FreeRTOS/DuinOS friendly. Even the ones that work unaltered are probably using delay calls which is not needed nor efficient in FreeRTOS.

Thats why I am working through all I use and trying to find out what is working/vs nonworking.. the onewire does a LOT of temp reading function for me however.. and havent checked to see if this is a 328P vs 644P issue yet. I will in a moment.

gwen

Hi All,
the above example that malfunctions, breaks on merely selecting the arduino.Duinos instead of the sanguino core.

It is not even attempting to include or use DuinOS functionality.

Il does illustrate that onewire is completely broken in the arduino.DuinOS(at least the lib I used)

gwen
ps who is aware of the temp control lib(thanx to those who told me of same).(and I will now try the temp control lib also).

and the other temp control lib wont work as ArduinOS.h redefines delay in terms of vtaskDelay in a preprocessor define which iincluding in the tester example in the examples directory gets the following errors on compile when duionos core is selected.
/var/folders/4Y/4YGLW5ffGDSpthzV2FcqT++++Zg/-Tmp-/build3092707008643651543.tmp/DallasTemperature/DallasTemperature.cpp.o: In function `DallasTemperature::requestTemperatures()':

/Applications/Arduino.app/Contents/Resources/Java/hardware/libraries/DallasTemperature/DallasTemperature.cpp:257: undefined reference to `delay'

/var/folders/4Y/4YGLW5ffGDSpthzV2FcqT++++Zg/-Tmp-/build3092707008643651543.tmp/DallasTemperature/DallasTemperature.cpp.o: In function `DallasTemperature::writeScratchPad(unsigned char*, unsigned char const*)':

/Applications/Arduino.app/Contents/Resources/Java/hardware/libraries/DallasTemperature/DallasTemperature.cpp:162: undefined reference to `delay'

I've looked into this and besides the delay issue there appears to be a more fundamental problem with even getting serial output using DuinOS, at least in my simple test.
The following locks up the micro (which is in setup):

Serial.begin(9600);
Serial.println("D2");

The begin method returns but the println never returns. Any ideas Julián?