Hello,
I am porting the RTX Kernel to a Cortex-M3 device and ran into a difficulty.
I have set up 2 tasks to toggle 2 LEDs to see if my tasks are running as expected. As below.
/*---------------------------------------------------------------------------- * Task 4 'blink_P2': Blink LED P2 *---------------------------------------------------------------------------*/ __task void blink_P2 (void) { os_itv_set (40); for (;;) { os_itv_wait (); Toggle_P2(); } } /*---------------------------------------------------------------------------- * Task 5 'blink_P3': Blink LED P3 *---------------------------------------------------------------------------*/ __task void blink_P3 (void) { os_itv_set (40); for (;;) { os_itv_wait (); Toggle_P3(); } }
If the time delay is set the same for both tasks then there is no problem. Both tasks toggle each LED at 40mS. This works.
However if I change the time delay on one task,(for example the second task to 50mS) then both tasks now take several seconds to toggle the LEDs.
I have ported the RTX kernel previously to an ARM7 core without difficulty but cannot see the problem on the Cortex-M3 ?
Can someone advise please ?
thanks!
Are any other tasks running? What are the ask priorities? Can you show us the task create section of your code?
Note: the wait functions are in values of systick not miliseconds.
Did you properly configure your systick timer?
Note: to post code you can use < pre> and </ pre> (without the spaces).
M
Thanks for the reply Marc,
Yes only 2 tasks are setup. The init task sets up the 2 tasks as below and exits.
/*---------------------------------------------------------------------------- * Task 4 'init': Initialize *---------------------------------------------------------------------------*/ __task void init (void) { GPIO_INIT(); t_blink_P2 = os_tsk_create (blink_P2, 0); /* start task 'blink' */ t_blink_P3 = os_tsk_create (blink_P3, 1); /* start task 'blink' */ os_tsk_delete_self (); }
In the RTX_Conf_CM.c file it is as default except for :
// </h> // <h>SysTick Timer Configuration // ============================= // <o>Timer clock value [Hz] <1-1000000000> // Set the timer clock value for selected timer. // Default: 6000000 (6MHz) #ifndef OS_CLOCK #define OS_CLOCK 16000000 #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 1000 #endif
thanks Mike
Per is absolutely correct.
The only thing I would point out in addition is that because (at least in my experience) it can be difficult to force a tasks (a critical "real work" task) into it's "longest path" taking a look at the number of instructions can be of additional value.
Also as Per pointed out you can eliminate this issue by designing non-interruptable operations in tasks with high priorities.
Thanks for all the helps.
Sorry for that, I think I can not catch the key point.
Assuming that,
There are 4 tasks, task_A, task_B, task_C, task_D.
task_A for critical CAN receiving/processing/transmission, highest priority; needs 25ms. task_B for critical UART receiving/processing, high priority; needs 18ms. task_C for key input checking, low priority; needs 1ms. task_D for LCD displaying, lowest priority; needs 10ms.
If I set the Round-Robin time slice to 15ms. When there are no CAN and UART events, task_A and task_B are at wait_for_some_ticks() or wait_for_HW_event(). So task_A and task_B are not runnable. System is working on task_C and task_D.
When CAN event happens, soon or later, task_A wakes up from waiting_state, since task_A has the highest priority, task_A performs as long as it likes. The Round-Robin time slice does not matter.?
I know I must miss some very important pieces, but I just can not discover it.
I am no longer a KEIL/ARM user, but would like to know more about RTOS/scheduling.
I think you are correct. With 4 tasks all with different priorities the round-robin time slice doesn't really matter as you are designing a preemption based system.
task_A for critical CAN receiving/processing/transmission, high priority; needs 25ms. task_B for critical UART receiving/processing, high priority; needs 18ms. task_C for key input checking, low priority; needs 1ms. task_D for LCD displaying, low priority; needs 10ms.
If I set the Round-Robin time slice to 19ms, and the events happen in the following order, UART -1ms-> 1st-CAN -XXms-> UART -YYms-> 2nd-CAN, task_A will be blocked for (18-1)ms, then execute only 19ms, not able to finish its 1st-CAN, then be blocked for 18ms once again, when 2nd-CAN comes, there are two CAN events need to be handle.
But if I set the Round-Robin time slice to 26ms, it would be much better.
Note that in many situations, you can split a task into a real-time critical part and a less critical background task.
So the question here is that CAN thread really do need 25 ms, or if it can be optimized into a high-prio part that makes real-time-critical decisions, and a background task that may figure out new questions to ask or what to do with logs/statistics of received data.
Another thing is that the program would normally use interrupts to pick up received data and store in an input buffer, to make sure that the hw buffers do not overflow.
Both the 18ms for the UART and 25ms for the CAN tasks sounds like quite long times, indicating a hope that some of work can be splitted out from the real-time tasks.
Another thing here is that you just have to take into account the worst-case loss of CPU capacity when your interrupt handlers are running at peak, thereby stealing CPU cycles from your time slices. Will your program consume 1%, 10% or more of CPU capacity just for interrupt processing at peak load?
Now, my understanding is:
1. Pre-emptive scheduling 2. Round-Robin scheduling 3. Round-Robin Pre-emptive scheduling 4. Co-operative multi-tasking are quite different.
And the order of events, the interval of events are also important.
I checked the below pages, www.keil.com/.../rlarm_ar_technical_data.htm www.keil.com/.../rlarm_ar_timing_spec.htm
They talk about things like Interrupt lockout time/Interrupt latency, I assume that, this is for, when RTOS is doing something that needs to be atomic, RTOS quickly/temporarily disable/enable interrupts, so interrupts are locked out, we get some interrupt latency. Am I right?
The cycles of [Set event (switch task)] means the guaranteed response time of an event processing. Am I right?
2. Round-Robin scheduling 3. Round-Robin Pre-emptive scheduling 4. Co-operative multi-tasking
You normally only have preemptive (timer-based) and cooperative round-robin scheduling.
Cooperative is when the task calls a specific "pass" function, or call any of the wait functions. Sometimes, other OS functions may also generate a task switch in case the OS thinks enough time has passed.
Old 16-bit Windows did use cooperative scheduling which was the reason everything locked up if one program did something really time-consuming without calling one of the magic functions where Windows would be able to perform a task switch.
Cooperative scheduling is easier to implement and also have the advantage that you don't get into troubles by task switches happening at random locations in the code. So unless you interact with an interrupt routine, you don't need critical sections.
With preemptive scheduling, and when sharing variables between a task and an ISR, you almost always needs critical sections to avoid problems with concurrent updates. And these critical sections does affect your latencies. Both in relations to interrupts and in relation to switching to a higher-prioritized task after it has become runnable.
So the documentation for the RTOS can give worst-case information about the OS primitives. But depending on use of critical sections or similar, the application itself can add significant to the worst-case performance.
Hi Per,
Many thanks for your help.
With RTX I believe the most common scheduling option is pre-emptive round robin.
i.e. dedicated time slices for tasks with the same priority but the ability of high priority tasks to pre-empt lower priority tasks.
But note that preemptive isn't just the ability of high priority tasks to pre-empty lower priority tasks. Preemptive works even when all threads have the same priority. It's just that the scheduler can switch threads asynchronously anywhere. This compared to co-operative task switching where the scheduler can only perform a task switch when a task have called an OS function that explicitly supports task switching.
So RTX would use preemptive scheduling (break at any position in thread code, except inside critical sections). And RTX would use priority, i.e. the tasks are switched in a fixed sequence (round robin) when they have the same priority, but switched depending on arrival of events if the threads have different priorities.
I think this may be a semantics thing but I believe in the context of RTX terminology preemption when the tasks are of the same priority is referred to as "round-robin". While the term "preemption" is used (I believe) exclusively for priority preemption.
http://www.keil.com/support/man/docs/rlarm/rlarm_ar_schedopt.htm
Correct me if I'm wrong but this is how I've always understood their docs. (If I remember correctly this is not the terminology used by freertos)
Keil has always used a bit of creative freedom when naming functions.
That can, alas, create lots of confusion when there exists established naming conventions.
velOSity RTOS www.ghs.com/.../velosity.html
Unlike other real-time operating systems that disable interrupts in every kernel service call, velOSity's state-of-the-art architecture guarantees the absolute minimum interrupt latency by never disabling interrupts in any service call.
==========>
I am quite confused about that "never disabling interrupts". Does that mean, it does not disable interrupts in any critical sections?
www.padauk.com.tw/products.php
All series of PADAUK Proudcts are developed by FPPA technology. FPPA (Field Programmable Processor Array) is the technology to realize the truly parallel processing, multi-cores concept in one die. In FPPA architecture, all the processing cores can run its own program independently. Moreover, due to its supreme architecture, the power consumption will keep low.
One of the English Datasheets: www.padauk.com.tw/.../getfile.php
It seems that, some people prefer to use hardware power to solve the parallel processing problem. So they build an 8-core MCU (Field Programmable Processor Array), with such FPPA MCU, there is no latency for multi-tasking.
I don't think it means that. I think in kernel calls (eg. SVC calls) they have designed the OS to be re-entrant. (i.e. you can interrupt the kernel function with a hardware interrupt.
Just my guess, I know nothing about this OS.
View all questions in Keil forum