I am really surprised that with the latest version of RTX that Keil has changed the functionality of the millisecond parameter to delay functions.
See
http://www.keil.com/support/docs/3766.htm
It sees that now the delay parameter is having 1 added to it in the latest version of RTX.
This is a significant functional change that I would have thought would not have been implemented without reaching out to the community of users. This change breaks a ton of existing code that relies on polling intervals of the tick frequency.
I regularly have threads that implement a 1 ms polling of hardware devices. This is implemented as a simple delay of 1 ms. Granted the first call to this delay function may return in less than 1 ms, but after that it is consistently 1 ms in duration. With the changes I don't believe that I will be able to poll at the tick frequency of 1 ms, it would be 2 ms. It seems to me that minimum polling time has been decreased to 2 times the tick frequency with the latest version.
I would strongly encourage KEIL to put back the original functionality, but I was wondering if others had the same concern.
I agree that the API shouldn't try to hide the user from the sample point synchronization by an obligatory add of 1 to the requested delay value.
It should be up to the individual developers to add that extra tick.
Right now, you changed the behavior to "always" give a too long delay. It is quite strange that existing software should need to add a -1 just to get around a design change, when it's the users with lacking experience that should really learn about sampling theory.
Changing the behavior of an existing API really is a no-no! Especially when the new design always produces a delay that is off-by-one. A "busy-loop" with delay 10ms will no longer manage 100 iterations in a second, since each delay will average 11ms. So 91 iterations instead of 100.
You introduced medicine with worse side effects than the sickness you wanted to cure.
I agree with you 100%
At the very least if they wanted to make this change they should have made it a modifiable parameter with the default being the original implementation.
Rule number 1 is to never break existing code.
What baffles me is that previously there was a simple work-around (add 1 to the delay), but now there is no work-around for those that need the original implementation.
I really hope that Keil reconsiders this ill conceived change.
So this is the official Keil response to my request to make the change configurable.
>>> I've spoken to several people, and the conclusion was that our developers >>> will not entertain any request to restore the old functionality. >>> We do supply the full source of the CMSIS RTOS, so you can recompile the >>> library with any changes you want.
I would love to know if others feel this is a poorly thought out change. Thankfully Keil is correct, I can make my own changes with the source, but I would really prefer not to have to do this.
After much consideration of this, my stance is that the change itself does not seem unreasonable. So many times I've see code that assumes (for example) a 1ms delay can be derived from a timer having 1ms granularity, just to find that delays based on it often end up being less. The change made basically just changes the situation that would occur with a software based delay; ie, assume it is a 'wait for a minimum amount of time'.
With regards changing an API: that is always undesirable, but at least Keil have documented it as a change. I would not like to count the number of times I've witnessed a change made to an API where there has been no notification. With the detail given, it should be a relatively simple task to update the application to use the new API detail.
But that is just it, it isn't a simple task.
To make my application work with the new RTOS I would either need to change my SYSTICK period to 0.5 ms so that I ensure my state machine polling states poll every 1 ms. Or I need to change many states to a new polling period of 2 ms.
Neither is desirable. Changing the SYSTICK period would mean that I now have twice as many timer interrupts causing a reduction in available bandwidth. Changing the polling period though possible, means that my syncronization period is now twice what it used to be with possible ramifications due to the real-time nature of my application. Also this change would impact many threads
In addition the code is now more confusing since either way the code will say a delay of 1 timer tick period but the actual delay between polling iterations will be a period of 2 timer ticks, how is this helpful.
It seems to me that as far as making the behavior easier to understand we have reduced the readability and understandably of the code, since an osDelay(1) in a loop will actually introduce a delay of 2ms, that doesn't make sense to me.
Hi Andrew,
we have documented that change in the Revision History of CMSIS-RTOS RTX. www.keil.com/.../rtx_revision_history.html Now a delay or timeout value of '1; ensures that it is at least 1 millisecond (actually between 1..2). Before the modification a delay or timeout value of '1' was actually between 0..1 milliseconds and this caused complains form other users.
The real issue is that the behaviour is not specified precisely. Also a osDelay function cannot be used to implement interval timers (use osTimer functions instead for that).
Currently we have a discussion in team. We consider to revert back to the previous behaviour where a delay or timeout value was effectively up to 1 millisecond less then than specified value.
Can we get some opinions from other users.
Thanks
Almost all delay functions in existence are implemented in a way where the user must understand the concept of timer granularity and that the initial period may be shorter because the delay might be called a random time into that first time quantum. If they aren't implemented that way, then they normally manage by internally operating on a much faster time base than the delay parameter - so if 1ms is requested, they might be based on a 1us timer meaning you get a shortetst delay of 999us.
Sometimes, people are lucky enough to reserve a single timer for their task, allowing them to run the timer at a high enough frequency that the length of the first tick doesn't matter. One such example are the multimedia timers in Windows.
In this case, Keil is doing something that is deviating from the normal practice, and for the single reason that they want to protect beginners from making a mistake. Should Keil protect beginners from stupid assumptions, by instead forcing their experienced users to suffer?
The scary scenario here would be that it is a junior developer at Keil that recently suffered from the specific assumption that the first tick will be a full time period - and so made the decision that the delay should always add +1 instead of letting the individual developers decide if they need a guaranteed minimum time, or if it is more important that multiple delays in sequence accumulates correctly. Or if they want to run a timer at 10 times the speed of the granularity to make sure that first tick can never be shorter than 0.9 times the nominal time.
I don't like this change even though the user can re-compile the source code to get his own compatible version. I agree osTimer is better than osDelay to implement interval timers. But this doesn't help preventing previous code from breaking.
I am really surprised to see that Keil would make such a change that will impact their customer's existing code so drastically! As Andrew mentioned, it now is impossible to get timing from the RTOS in 1ms granularity. This really messes up my existing code and will require quite a large change to be compatible. I would strongly urge Keil to reverse this change.
Thanks!
Am I misunderstanding something? The Keil change just adds one on entry to the function. The reason for doing so seems sound to me. What's difficult about changing existing code to subtract one for use with that change? For the meticulous, that addition could be a macro with a value based on the RTX version.
Yes you are missing the fact that you can't subtract 1 from 1. That leaves 0 which doesn't cause any delay.
The point is that there is lots of existing code that relies on being able to create repeating timing delays of single increments of the rtos timer interval which typically is 1ms. This change causes this code to break because now the minimum timing delay is 2ms.
An example is in my state machine code implemented as a thread that jumps to a function depending on a state variable.
In one state function I might wait on a mail message, in another I might wait on a signal and in another I might poll on a hardware signal. That polling currently is implemented as an osDelay(1), which effectively will poll the hardware once every ms. There also may be other side effects that is dependent on that delay having a 1 ms period.
I realize that the first time that this state runs that the delay may be less than 1ms, but after the first iteration the delay is very accurately 1 ms.
Now with the change my polling frequency is reduced with other potential side effects and there is no work around to get it to poll at 1ms without reducing the SYSTICK period to 0.5 ms, which reduces the processor bandwidth due to the increased number of timer interrupts it needs to process. This is all then notwithstanding the confusion from a readability perspective, where an osDelay(1) now really means a 2 ms delay.
Nope. Can't see the problem.
Reading: http://www.keil.com/support/docs/3766.htm
Looking at os_dly_wait (since I use RL-ARM RTX):
os_dly_wait(1 /* rest of current tick */ + 1) ; /* in KEIL RL-ARM RTX */
The library code now adds one on entry. I change my code to passing one less and hey-presto, the library uses the same value as it did before.
You are missing that I am using a delay of '1'. Subtracting 1 from 1 leaves 0. Looking at the RTX source you will find that when you pass 0 to the delay function it will not block, there will be no delay, I can't use your workaround in my case.
Please don't take offence, your code may have worked but it could be argued that it was not safe in the first instance.
If this is the only complaint of the Keil change, I would personally accept it. At least the operation is now fully defined.
No offence taken, but without looking at my code I don't know why you would think it wasn't safe? Do you mean because the initial delay was anywhere between 0 and 1 second instead of between 1-2 seconds? In either case there is a variable timing that needs to be accounted for.
I am curious however in the following code what would you expect to happen?
osDelay(1); osDelay(1); osDelay(1); osDelay(1); osDelay(1);
Regardless of whether anyone would do this or not, it seems that based on a simplistic reading of the code that it should cause a delay of approximately 5ms. With the new RTX however the delay will be between 9 and 10ms, this is not at all obvious and doesn't make sense to me.