I wrote a small application using Keil RTX for smartfusion device and probed RTX overhead using Cortex-M3 systick timer (in Digital CRO). I have changed the OS_TICK macro to 50 micro sec. (Even though as per manual its suggested to set it >= 1msec). Using RTX as per our design we wanted to run the foreground processing frame every 100 micro sec. When probing the wave pattern in CRO i see RTX overhead time of ~= 34 micro sec (This changes with OS_TICK value). Am i doing something wrong or this is how it is suppose to behave ? (We won't be able to achive time resolution in micro sec using RTX os)
In task phaseA i set os_itv_set (2). The periodic wakeup interval is 2 sys ticks (i.e 100 micro sec). i switch on and off LED_A.
When i probe the via in eval board for LED_A (D1). I see every 134.2 micro sec the On operation is performed.
File: RTC_Conf_CM.c // </h> // <h>SysTick Timer Configuration // ============================= // <o>Timer clock value [Hz] <1-1000000000> // Set the timer clock value for selected timer. // Default: 100000000 (100MHz) #ifndef OS_CLOCK #define OS_CLOCK 100000000 #endif // <o>Timer tick value [us] <1-1000000> // Set the timer tick value for selected timer. // Default: 10000 (10ms) #ifndef OS_TICK #define OS_TICK 50 #endif
File: main.c #include <RTL.h> #include "a2fxxxm3.h" /* A2FxxxM3x definitions */ OS_TID t_phaseA; /* assigned task id of task: phase_a */ #define LED_A 0x01 #define LED_On(led) GPIO->GPIO_OUT &= ~led #define LED_Off(led) GPIO->GPIO_OUT |= led __task void phaseA (void) { os_evt_wait_and (0x0001, 0xffff); /* wait for an event flag 0x0001 */ os_itv_set (2); for (;;) { os_itv_wait (); LED_On (LED_A); LED_Off(LED_A); } } __task void init (void) { GPIO->GPIO_0_CFG = 5; /* Configure GPIO for LEDs */ GPIO->GPIO_1_CFG = 5; GPIO->GPIO_2_CFG = 5; GPIO->GPIO_3_CFG = 5; GPIO->GPIO_4_CFG = 5; GPIO->GPIO_5_CFG = 5; GPIO->GPIO_6_CFG = 5; GPIO->GPIO_7_CFG = 5; GPIO->GPIO_OUT |= 0xFF; t_phaseA = os_tsk_create (phaseA, 0); /* start task phaseA */ os_evt_set (0x0001, t_phaseA); /* send signal event to task phaseA */ os_tsk_delete_self (); } int main (void) { WATCHDOG->WDOGENABLE = 0x4C6E55FA; /* Disable the watchdog */ os_sys_init (init); /* Initialize RTX and start init */ }
The intent of code is simple. I guess u understood it.Can you share something using RTX kernel which does the job in micro sec delay (With precision) ?
Using the same above example even if i am setting OS_TICK to 10milli sec, My Digital CRO waveform is actually showing 13.4 milli sec. Now this is not good for a RTOS to behave.
There is, of course, an alternative - that your code isn't as correct as you think it is.
Not a huge fan of RTX, but if this what you measured I can assure you 100% that it's your code that is at fault.
This link gives the performance for RTX: www.keil.com/.../rlarm_ar_timing_spec.htm
see RTX overhead time of ~= 34 micro sec
I think you can find RTX performance metrices on this website. Either way, a context switch within 34 microseconds is not bad at all! What is your processor speed? If you internal flash MAM enabled? Either way as already mentioned, you are trying to solve your problem with the wrong method.
Per,
I was too lazy to search for that link :-)
Thanks tamir for replying. Finally i found someone else other than "Per" in keil forum.
My only question at this time, even if i set the interval wait time to 10 millisec why i am seeing a periodic wakeup of 13.4 millisec. I can understand my resolution of 100 microsec is actully turing out to 134 microsec. Where am i going wrong? Did you ever faced anything like this before in lab ?
http://www.keil.com/support/docs/3464.htm
RL-ARM: WRONG TIMING WITH OS_ITV_SET()
SYMPTOM Periodic wake-up time interval specified by os_itv_set() changes unexpectedly.
CAUSE The task that should wake up periodically also uses one of the following delay functions: os_dly_wait() os_mut_wait() os_evt_wait_and() os_evt_wait_or() os_mbx_wait()
-- I have learnt a lot from Per Westermark. I like Per's presence and technical capabilities.
But i am not using any wait calls as mentioned in tech support. The only place i use it is before setting periodic time interval in same task. I also tried commenting out "os_evt_wait_and (0x0001, 0xffff);" but no difference. I know with actel smartfusion running at 100Mhz +RTX its difficult to get microsec periodic wakeup interval. I can definitely go baremetal. But the design implementation requires RTOS at some point of time. Mixing ISR timer with RTX is what i am worried of. While servicing ISR routine RTX won't be able to snach CPU cycle if required. Even if its deterministic time taken to service timer ISR routine in 50 usec interval not sure how things will be when i am running around 80+ task in RTX.
Now comming back to "Per" involment, I don't have any problem. But he needs to learn some forum basic manners. I don't like his tone in his replies, Kinda rude.
What will happen if you do get your timing right and the system's load will increase due to some future requirement? In other words - programs that require this sort of timing are much better of running of their own sub-processor doing minimal other work.
Let me say this again: in the original post you complained about a 34% drift, but you did mention that your task should run each 100 microsecond. We now know that this is the order of magnitude of a RTX context switch (that quite good, actually). If you need timing of this sort you are solving your problem with the wrong tool - I doubt very much if you can find an RTOS with a much lower context switch overhead.
I am (still) not _very_ familiar with Cortex-Mx chips, but they do have an inherent nested interrupts handling ability. Can't you manage this using interrupt priorities?
Can't you manage this using interrupt priorities?
No, you probably cannot.
int main (void) { WATCHDOG->WDOGENABLE = 0x4C6E55FA; /* Disable the watchdog */ os_sys_init (init); /* Initialize RTX and start init */ while (1); }
Hi sanjoy saha,
(I am not good at this.)
If you are still interested in even if i set the interval wait time to 10 millisec why i am seeing a periodic wakeup of 13.4 millisec. I guess you should start with either of the following example code: http://www.keil.com/support/man/docs/rlarm/rlarm_ar_preemt.htm http://www.keil.com/support/man/docs/rlarm/rlarm_ar_rrobmt.htm http://www.keil.com/support/man/docs/rlarm/rlarm_ar_coopmt.htm And make sure you always have two tasks running, switching to each other properly.
There are some hidden assumptions, we have to follow with. (like the mentioned http://www.keil.com/support/docs/3464.htm)
os_itv_set (2);
2 is very small, maybe try 20 or 50 for accuracy.
Tamir, Thanks for you reply. Appreciate your time and effort.
The drift of 34% is cumilatively adding up that what worries me. Not sure where i am going wrong. Let say for periodic interval of 20 usec i get 36 usec [difference of 16 usec for context switch and other overheads], Now for 10 millisec periodic interval i get 13.4 millisec [difference of 3.4 millisec]. Just wanted to drill through why there is so much difference [theoretically i should get 10 millisec + 16 usec].
i know the system overhead is going high with 100 usec. Discussed with my customer and he is fine with it. I suggested to use FPGA module to get life easier, But he wants to stick with soft implementation.
What is your suggestion if i intermix timer ISR with RTX to get my job done ? Timer ISR will give me precision of usec and it will take fixed interval for servicing. While ISR is being serviced RTX doesn't stand a chance to intervene. The timer ISR will perform scheduling of task [using isr_set_evt]. Well there definitely is a chance of frame overrun. But this situation can happen with 100msec RTX priodic timer (if drift was deterministic).
Thanks John, Appreciate your time and effort.
I will definitely give a shot.I tried with 20/50 for getting some accuracy, but there is always a non-deterministic drift. I will check once again with examples you pointed out. I just wanted to get a deterministic drift value.
What surprise me the most, Am i the only one who is facing issue with RTX (Periodic interval timer drift).