Who I am, where I am in AVR world.
I’m an Arduino enthusiast : it made some of my week ends 🙂
This way I learned about AVR 8bit architecture.
Soon I guessed Arduino IDE was way too limitative. then, I seeked a way to break free from the IDE. Then, I found out that Atmel toolchain was based on GCC, AVR flavoured ; so could theorically compile any ASM, C or C++ project using avr-gcc.
By that time, in Arduino IDE, it was hard to use two different lib in one single sketche. But using GCC and Make, I could wipe out those limitations, restoring a clean tree for project sources, and mainly reusable libs — Thanks to : Arduino Makefile (on github).
Note that Arduino-Makefile is able to compile pure avr-libc projects ! Nowadays, I use it to make && make upload any of my projects, either using Arduino lib parts, or not… (I’m used to link against Serial class for debugging purpose, even if i know some ways to work without, like coding some putc() enabling printf(), but… I’m lazy on this topic).
After some toy-projects with Aduino libs, I had a dive into the Atmel datasheet. I gave born to my first serious theorical appraoch of AVR:
could we even schedule threads on Arduinos ?
Once… upon a time, I was attending a conference about Linux Xenomai (for short it deals with hard real-time constraints). Stories about real-time systems often involve Big Bad Watchdogs. and Daemonic Timers… Timers are used to preempt some task and switch to another. Then, I was day dreaming… : “An AVR like atmega328 on an Arduino has timers and linked interrupts ; why the f*** does it not have threads implemented ?”
I tried to write out an implementation : it attempt to copy CPU state and the stack into a know location, and then smash the stack and CPU state with previous saved (or manually cooked — for initialization) data. The trick can make think of the buffer overflow attack, since we’re replacing return address in the stack. But here the address of return pointer changes with new task’s stack size ! Here, hopefully, and despite buffer overflow attack, we are are free to set SP register to point updated return address.
Sadly, it does not work : it manages to switch 3 times two simple tasks :
- one is a thread function, other being the main loop ; writing to an I/O port, in this source version, a special port used as stdout with the simulavr emulator),
- the other being the “main” loop.
…but the last (I)RET drive any simulator I tried crazy (then, I never tried on hardware). I guess that, somewhen, I smash the stack (or a stored copy later restored).
I did not go further in debug because i don’t believe anymore in task/thread scheduling on AVR… at least following this way.
Maybe, it could be used, with caution :
- in a purely pedagogic context, or,
- very conscientiously, with a low switch context frequency and low growing stacks per thread.
My first conclusion was… AVR is not for threads…
… As I implemented it :
- the first problem is memory amount ; switch context imply to copy the Stack. Dedicated memory to thread stacks decrease available memory to the application ;
- the second is about CPU consumption : not only there is a contant overhead, implied by saving/restoring a constant number of state registers, but, futhermore, we have to save and restore the stack, which size is variable by nature.
- urgent events are to be hold and processed by ISR sub-routines. Not by a thread context with (potentially very high) latency.
In conclusion, this implies that 8bit AVR threads (as I am implementing them) remains a kind of “hi-jacking” of the chip architecture which is clearly not dedicated to thread context switching.
A typical “Arduino” application using such a library to interlace applicative threads execution is not likely to work properly : GCC is used to compile C/C++ with extensive use of the stack… It is true, at least, on a genuine « Arduino Uno R3 » and it’s atmega328, with 2K SRAM embeded only.
A new Hope…
In a galaxy far far away…
I was hopeless about task scheduling (not using co-routines, they are great, but no real “tasks”) when I heard about FreeRTOS, which implements on real task concept.
If I need task scheduling for any reason, that jusify ISR are not enough, I would use FreeRTOS.
Other initiative …