ChibiOS/RT 2.4.1 RTOS update

I have updated the ChibiOS/RT library to version 2.4.1.

This library is a simple way to use the ChibiOS/RT RTOS on 328 and Mega Arduinos.

The download is ChibiOS20120529.zip at Google Code Archive - Long-term storage for Google Code Project Hosting..

ChibiOS 2.4.1 is a maintenance release fixing all known bugs. More details are available in the release note at the ChibiOS website.

I have made minor changes to examples and included a new version of the SdFat library.

Nice, new version. Thanx.

Do you know if its possible to let the OS do cooperative multitasking?
I remember reading that somewhere, but I can't find it again.

I don't think ChibiOS is the best choice but you can arrange for cooperative multitasking.

#define CH_TIME_QUANTUM 20

Round robin interval.

This constant is the number of system ticks allowed for the threads before preemption occurs. 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.

Note:
Disabling the round robin preemption makes the kernel more compact and generally faster.

Definition at line 70 of file chconf.h.

Referenced by _scheduler_init(), chSchDoReschedule(), chSchGoSleepS(), and chSchWakeupS().

HI folks, there is a nice subproject starting at Giovanni - Nil Rtos.
It is a very small and simple variant of chibios, intended for small mcus, where CM0 is considered a high end.
Maybe useful for avr as well.

http://forum.chibios.org/phpbb/viewforum.php?f=12&sid=7e0b515caae252657af6351384d1419a

Preliminary results (95% complete code, now it compiles).
Total image size: 1284 bytes
Divided as:
Appl.Main: 76 bytes
Vectors: 192 bytes
NVIC code: 156 byes <- To be removed from the code
CRT0: 188 bytes
CM0 Port: 140 bytes
Kernel: 492 bytes
Talking about a real, usable, kernel with threads, semaphores, timeouts, delays, system time, without even start optimizing.

p.

Nil Rtos examples look interesting. Many Arduino projects need two or three threads and this should work well with Nil Rtos.

Looks like all development is with ARM CM0 but it should not be too hard to port to AVR and make an Arduino library.

There are many tiny systems like this but Giovanni Di Sirio is a real expert in embedded systems so I expect this will be a very good OS.

Designing a good general RTOS takes a lot of experience and talent and Giovanni has both. I worked on some the largest embedded systems in physics research for 40 years. The last system I did design work for was the LHC Atlas experiment at CERN which may have discovered the Higgs Boson.

I think ChibiOS is one of the best free systems available so it will be worth trying Nil Rtos on Arduino.

About the ChibiOS port...Have you had any trouble with the serial port behavior using arduino HardwareSerial? It seems Fat16Lib has been using them successfully in the demos. However, I have issues when using them in my own code. Here is an example on Mega1280:

#include <ChibiOS.h>
#include <util/atomic.h>

static WORKING_AREA(waSerialHandler,256);
static msg_t SerialHandler(void *arg)
{
  Serial.begin(9600);
  String inputStr = "";
  inputStr.reserve(200);
  volatile uint8_t count = 0;
  char inChar = 0;
  while (true)
  {
    if (!Serial.available()) chThdYeild();
    else
    {
      do
      {
        inChar = (char)Serial.read();
        if(inChar=='c') 
        {
          Serial.println("Count:  "+count);
          Serial.println("Output string:  " + inputStr);
        }
        inputStr.concat((String)inChar);
        count++;
      }while (Serial.available());
    }
    if (count >= 10)
    {
    Serial.println(inputStr);
    Serial.flush();
    count=0;
    inputStr = "";
    }
//    chThdSleep(1);
  }
}
void setup() {
  // put your setup code here, to run once:
  cli();
  halInit();
  chSysInit();

  Serial3.begin(9600);
  
  chThdCreateStatic(waSerialHandler,sizeof(waSerialHandler),NORMALPRIO +100, SerialHandler, NULL);

}

void loop() {
  // put your main code here, to run repeatedly: 
  chThdSleep(10);
  
}

This code doesn't do anything other than wait for 10 characters to arrive on the serial port, then print them. My intention is to use a thread to parse data coming in on one, check for conditions, the use another thread to drive another port to send modified data. Trouble is, if I type a string like "1234567890-" into the terminal, I usually only get two characters printed.

Is this a problem in the port? Should I be modifying the chibiOS uart drivers to support Uart2 and Uart3(only 0 and 1 are currently included in the driver file)?

The problem appears to be the Arduino String class.

I never use the String class or anything that uses malloc/free in my sketches.

Most coding standards for critical embedded systems forbid use of dynamic memory after system start-up and my background was with this type system. My libraries do not use dynamic memory.

If you want to use String it appears that you will need to enable the ChibiOS wrapper for dynamic memory and modify the Arduinos String class to be multithreaded.

Note that Serial is the Arduino HardwareSerial driver, not the ChibiOS driver.

This sketch which uses char arrays seems to work.

#include <ChibiOS.h>
#include <util/atomic.h>

static WORKING_AREA(waSerialHandler,256);
static msg_t SerialHandler(void *arg)
{
  Serial.begin(9600);
  char str[20];
//  String inputStr = "";
//  inputStr.reserve(200);
  volatile uint8_t count = 0;
  char inChar = 0;
  while (true)
  {
    if (!Serial.available()) chThdYield();
    else
    {
      do
      {
        inChar = (char)Serial.read();
        if(inChar=='c') 
        {
          str[count] = 0;
          Serial.print("Count:  ");
          Serial.println(count);
          Serial.print("Output string:  ");
          Serial.println(str);
        }
        str[count] = inChar;
  //      inputStr.concat((String)inChar);
        count++;
      }while (Serial.available());
    }
    if (count >= 10)
    {
      str[count] = 0;
      Serial.println(str);
  //  Serial.println(inputStr);
    Serial.flush();
    count=0;
//    inputStr = "";
    }
//    chThdSleep(1);
  }
}
void setup() {
  // put your setup code here, to run once:
  cli();
  halInit();
  chSysInit();

  Serial3.begin(9600);
  
  chThdCreateStatic(waSerialHandler,sizeof(waSerialHandler),NORMALPRIO +100, SerialHandler, NULL);

}

void loop() {
  // put your main code here, to run repeatedly: 
  chThdSleep(10);
  
}

Thank, Bill! I appreciate all the work that you have done and shared with the masses.

I see also that you have an improved serial port implementation on your beta-lib google code page. Do you continue to use this?

Also, have you used the ChibiOS serial port driver? Even though the problem is in the string or stream implementation, I'm wondering if one would be better off to use an alternative to the standard arduino implementation.

I looked at the problem again and found that dynamic memory in avr-libc will not work with ChibiOS. Avr-libc assumes there is one stack and the heap is above the stack. In ChibiOS the workspace for a thread is above the heap so malloc/realloc fails.

To use dynamic memory with ChibiOS you would need to enable the ChibiOS heap manager.

I have not used the ChibiOS driver for AVR, just ARM. The serial driver is very basic in terms of functionality but is multithread friendly.

If a thread reads and there is no data or writes and the queue is full, it uses qwait so lower priority threads can run. This makes programing simple in the thread.

Using chThdYield in your program with Arduino Serial will use round robin scheduling to allow equal priority threads to run if you are waiting for input and will block lower priority threads. Only higher priority threads will run if you block on output using Arduino Serial.

You would need to add ports three and four to serial_lld.c.

There is probably a way to force the linker to move things around, but I don't think its worth the effort. After testing the performance of your SerialPort library vs default arduino HardwareSerial, I think I'll see if it plays nice with ChibiOS first. If not, I work on ChibiOS drivers.

BTW, SerialPort is roughly seven times faster in serial read/write echo when compared to HardwareSerial. Thanks again.

I remembered how to fix malloc. Here is the documentation avr-libc: Memory Areas and Using malloc().

If you add this at the beginning of setup(), String will work in your program. It may fail if malloc is called in separate threads since I suspect malloc is not thread safe.

  char stkVar;
  extern char* __malloc_heap_end;
  // allow 256 locations for loop() stack
  __malloc_heap_end = &stkVar - 256;

No need to fix the linker script.

After working with this a bit and looking at your examples, I have another question. In the chFastLogger and chMegaLogger examples, you have a "while(1);" at the end of the loop function. It is not present in other examples.

Is this line consequential? Do I understand correctly that any thing that ends up in main() after chSysInit() is now the idle task? If so, I would assume that it would be preempted whenever necessary by Thread1. But, wouldn't it still get stuck in while(1), preventing loop() from looping?

I don't have quick access to an SD card right now, so the loggers both fail in setup(). Can someone explain the expected behavior, and what would happen if I did have the SD card?

Thanks

The programs stop on the while(1) when they are done.

If you have an SD, analog data will be logged from when you enter the first character until you enter the second character.