Hello
I'm doing some experiments with RTX to investigate how quickly it switches between tasks and how much of the time I can make the processor (STM32F103 sleep.
Following the advice in this thread (http://www.keil.com/forum/18158/) I've implemented a function in my code with the signature:
void rt_post_taskswitch (U32 task_id)
As I understand it, RTX should call this after a task switch however this never happens (the break point I've set in the function is never hit). I had a quick poke around the RTX source and I can see where the function is weakly declared and where it's called. Everything looks fine except my implementation of the function never gets called.
I suspect this is because the project is linking against the RTX library and unless I recompile RTX along with my project it'll never know I've implemented the function.
What's the neatest way to go about making this work?
Many thanks in advance, Al
I rather doubt that. More likely, you put your function in a sourcefile of its own, and made no other reference to it. So the linker saw no need to actually keep in the build, so it's no longer visible at the point it goes looking for a potential definition of that function. In that case, the weak fall-back definition inside the library might win. If you need more details, I would expect there to be special switches to get the linker to document its every step, so you see what's going on.
I use this function in some of my projects that use RTX for diagnostics reasons (note: it will not monitor all task switches! If you can, use a scope instead). I only needed to add it to the project, with no other special provisions. What happens if you use RTX's source files?
Do you have any more information about the "it will not monitor all task switches"?
Did you just think about the time spent inside interrupt handlers or in what situations does the OS perform a task switch without calling this function?
Per,
There are certainly missing calls to this function (I have reported a similar issue to Keil about 2 years ago and they fixed it, but not entirely so it seems. I'm working mainly with FreeRTOS now, so I have less interest in this problem right now). I know this to be a 100% correct as we were making a performance profile for a client a while ago, and there were gaps seen in the resulting log - each entry had its RTC timestamp and we saw that, for example, task x was scheduled without task y (that ran before it) switching to it, either explicitly of implicitly. But most of the time, the data represented what the kernel did.
I have to assume that all round-robin scheduling does work as expected.
Was there some indication that it was threads that intentionally slept waiting for queues or similar that could happen to execute without this being called? Maybe when another task triggs the task switch or maybe when an interrupt sends the switch?
I assume that the kernel is working correctly and that the only problem is that the function is not called when required. I don't think we managed to understand why the gap was there - as far as I can recall, we did not even bothered to as the problem was not common and anyway we got what we needed from the log (I hope that's not considered sloppy, but Keil always require a test case before even starting to look into an issue - completely impossible in this case!) and we were abroad, with a serious time pressure. I am sorry, but I'm afraid I really cannot reconstruct the exact chain of events that led to this.
My log included interrupts - I did see our 1[ms] background ISR, but no task switch for about 40[ms]+ even though the controller seemed to have been functioning correctly. Or maybe the kernel did not switch tasks after all - but that was certainly not due to priority issues or it being disabled. I don't remember...
I have never tried this function.
The only profile I have done have been using LEDs in ISR and high-prio tasks.
So task A (with highest prio) lights LED A when it runs, and turns off the LED when it calls a wait function. LED A will then represent the total time spent with thread A running (including time spent for ISR processing).
Task B (next highest prio) lights LED A when it runs, and turns off the LED when it calls a wait function. LED B will represent the total time spent for ISR processing, task A and task B. B-A will represent time used by thread B.
Same thing for next lower task.
That have managed to cover the most important stuff. For less important tasks, I have read out a high-speed timer when an ISR or high-prio task sees something that needs to be done, and the low-prio task picks up the timer value again when having serviced the event. In this case, I haven't really bothered with CPU load, but only been interested in average and worst-case response times.
With a four-channel scope, quite a lot of information can be gathered from such a setup. A scope with configurable hold-off time for trigger can give even more interesting information while the system is up and running - and still with quite low additional CPU load and with a minimal need for any bandwidth on any peripherial. The only bandwidth needed would basically be to regularly dump avg + worst-case for event processing in full timer resolution (in my case 12MHz tick speed).
Many thanks for all the input.
I'm still having no luck making my rt_post_taskswitch work. This is probably my lack of knowledge with the linker.
I'm going to play around with different ways of doing this, probably just adding calls at entry and exit points of tasks.
Cheers, Al
"probably just adding calls at entry and exit points of tasks."
Note that depending on thread priorities, and if you have round-robin scheduling, you can get lots of task switches that will not result in any printout because the task that gets put to sleep was between two printouts, and the woken task was previously paused while between two printouts.
All you can manage is to print just before you call a wait-capable function, and directly after it returns. But that isn't enough.