Thanks!
No, didn't renamed all the functions. Just the ones we think are more usefull here, in an Arduino Env. But, the other are available with their oiriginal names. And we added the macro taskLoop, whose code is the following:
We also rewrote the delay(), wich is quite simple as well:
#define delay(ticks) vTaskDelay(ticks)
Regarding the heap, we are using model 1, because, to cut the RAM and Flash usage we don't allow tasks deletes. If you enable this functionality (easy, just a #define), you must use model 2, but we didn't test it yet. Model 3 does not make sense here, I think.
About the execution time, in our initial tests it seems to be quiet acceptable. By now, I can tell you that we compiled a few "standard" arduino examples (Comms, etc.) but with this kernel (so the main loop is a task), and they seems to be running without problems. But have to make more tests with a digital osciloscope about the timming.
That's what we are going to do this weekend!
Wonderful idea - i relaly love that already now :0)
What's the maximum number of tasks that can run properly semi-simultanously?
Could this be used to call in one task a TWI device and in the other do some data - output?
Hi, thanks for your kindly comments!
The maximun tasks that can be running simultanously depends on what they are doing. We are testing these kind of things now, but I think in a few days will be uploaded the full IDE so you could run your own tests, and tell us (thanks in advance! :)). By now, I can tell you that the system interrupt tick is at 1 KHz.
In addition, as it's based on FreeRTOS, in the bigger CPUs (like the 644, 1280, etc.), you can enable the mutexes, semaphores, and even the lighter coroutines. We didn't encapsulate these, because think that in the more advanced applications that will use them, perhaps the programmer will prefer to access the FreeRTOS API directly.
Hi Julián, I wonder how much time a typical context switch takes. If it is many microseconds than the 1 ms interrupts could affect the servo library. Have you tested with that library?
its not just servos that may be affected by a context switch. pulseIn readings may also be affected. I would be interested to know how long the context switch takes.
I was looking the servo and pulsein, although I could not make tests today. The servo library will have a conflict with the kernel, but I just added to the list of things to modify (as done with the delay() function). The problem is not a big problem: the current library uses the timer 1.
Regarding the pulseIn, I have two comments:
The kernel has CRITICAL_SECTIONS, so computation-intensive routines could be used. I don't think this aproach is the better, when using a preemptive kernel for many reasons, but it is still out there.
We plan in our group to continue improving this, and one of the main things to do is to get a better integration with the Arduino environment as a whole. This will imply to modify or even rewrite some things. There are examples, of small boards with nice libraries which can manage servos, pwms, pulses and has multitasking. One of them has more than 10 years old an runs on a 1 MIPS old HC11 (@4 MHz in some versions). It's the HandyBoard, wich has multitasking running over a virtual stack machine (IC). So we think this is possible in a near 16 MIPS AVR, but will surely demand some work.
Downloaded DuinOS and can't use it out of the box without modifying the DuinOS.h file. The path specified in there is a Windows path so you'll get a compile error on any unix variant OS.
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.
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!
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.
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.