
Hi All,
Well, here we are again, a Timer API discussion :)
All things considered, I don't think the Linux approach is right for U-Boot - It is designed to cater for way more use-cases than U-Boot will ever need to deal with (time queues and call-backs in particular)
To summarise, in a nutshell, what _I_ think U-Boot need from a Timer API
1. A reliable udelay() available as early as possible that is OK to delay longer than requested, but not shorter - Accuracy is not implied or assumed 2. A method of obtaining a number of 'time intervals' which have elapsed since some random epoch (more info below) 3. A nice way of making A->B time checks simple within the code
OK, some details:
1. I'm starting to thing this should be a function pointer or a flag in gd. Why oh why would you do such a thing I hear you ask... udelay() is needed _EARLY_ - It may well be needed for SDRAM or other hardware initialisation prior to any reliable timer sub-system being available. But early udelay() is often inaccurate and when the timer sub-system gets fully initialised, it can be used for an accurate udelay(). x86 used to have an global data flag that got set when the timer-subsystem got initialised. If the flag was not set, udelay() would use one implementation, but if it was set, udelay() would use a more accurate implementation. In the case of the eNET board, it had an FPGA implementation of a microsecond timer which was even more accurate that the CPU, so it had it's own implementation that should have duplicated the 'if (gd->flags & TIMER_INIT)' but never did (this was OK because udelay() was never needed before then)
I think a function pointer in gd would be a much neater way of handling the fact that more accurate (and efficient) implementations of udelay() may present themselves throughout the boot process
An other option would be to have the gd flag and make udelay() a lib function which performs the test - If the arch timer has better than 1us resolution it can set the flag and udelay() will use the timer API
2a (random epoch) - The timer sub-system should not rely on a particular epoch (1970, 1901, 0, 1, since boot, since timer init, etc...) - By using the full range of an unsigned variable, the epoch does not matter
2b (time interval) - We need to pick a base resolution for the timer API - Linux uses nano-seconds and I believe this is a good choice. Big Fat Note: The underlying hardware DOES NOT need to have nano-second resolution. The only issue with nano-seconds is that it mandates a 64-bit timer - A few people are against this idea - lets discuss. A 32-bit microsecond timer provides ~4300 seconds (~1.2 hours) which _might_ be long enough, but stand-alone applications doing burn-in tests may need longer. Going milli-seconds means we cannot piggy-back udelay() on the timer API.
My preference is a 64-bit nano-second timer with udelay() piggy-backed on the timer API (unless, like NIOS, the timer sub-system cannot provide micro-second resolution, in which case the gd flag or function pointer does not get set to use the timer API for udelay())
I really want to get the Timer API sorted this time around
Regards,
Graeme

Hi Graeme,
On Fri, Sep 16, 2011 at 4:53 AM, Graeme Russ graeme.russ@gmail.com wrote:
Hi All,
Well, here we are again, a Timer API discussion :)
All things considered, I don't think the Linux approach is right for U-Boot
- It is designed to cater for way more use-cases than U-Boot will ever need
to deal with (time queues and call-backs in particular)
Yes it is extremely complex.
To summarise, in a nutshell, what _I_ think U-Boot need from a Timer API
1. A reliable udelay() available as early as possible that is OK to delay longer than requested, but not shorter - Accuracy is not implied or assumed
Yes. Can you be specific about 'early'? Do you mean in start.S, before board_init_f(), or before arch_cpu_init() or something else?
My feeling is that callers prior to, say, the first few init functions called by board_init_f() could probably call their own implementation directly if needed.
2. A method of obtaining a number of 'time intervals' which have elapsed since some random epoch (more info below) 3. A nice way of making A->B time checks simple within the code
OK, some details:
- I'm starting to thing this should be a function pointer or a flag in gd.
Why oh why would you do such a thing I hear you ask... udelay() is needed _EARLY_ - It may well be needed for SDRAM or other hardware initialisation prior to any reliable timer sub-system being available. But early udelay() is often inaccurate and when the timer sub-system gets fully initialised, it can be used for an accurate udelay(). x86 used to have an global data flag that got set when the timer-subsystem got initialised. If the flag was not set, udelay() would use one implementation, but if it was set, udelay() would use a more accurate implementation. In the case of the eNET board, it had an FPGA implementation of a microsecond timer which was even more accurate that the CPU, so it had it's own implementation that should have duplicated the 'if (gd->flags & TIMER_INIT)' but never did (this was OK because udelay() was never needed before then)
I think a function pointer in gd would be a much neater way of handling the fact that more accurate (and efficient) implementations of udelay() may present themselves throughout the boot process
An other option would be to have the gd flag and make udelay() a lib function which performs the test - If the arch timer has better than 1us resolution it can set the flag and udelay() will use the timer API
Is this a general need or something architecture specific? Perhaps we should allow boards to override the raw timer function and deal with this feature that way? Am I right in saying that most boards will not need this feature?
2a (random epoch) - The timer sub-system should not rely on a particular epoch (1970, 1901, 0, 1, since boot, since timer init, etc...) - By using the full range of an unsigned variable, the epoch does not matter
Yes, the way I see it this is monotonic timer of no fixed base. The base could well be the time reset was removed from the board...
2b (time interval) - We need to pick a base resolution for the timer API - Linux uses nano-seconds and I believe this is a good choice. Big Fat Note: The underlying hardware DOES NOT need to have nano-second resolution. The only issue with nano-seconds is that it mandates a 64-bit timer - A few people are against this idea - lets discuss. A 32-bit microsecond timer provides ~4300 seconds (~1.2 hours) which _might_ be long enough, but stand-alone applications doing burn-in tests may need longer. Going milli-seconds means we cannot piggy-back udelay() on the timer API.
Re burn-in tests this sounds like an unusual case, and anyway it is unlikely to matter that the timer wraps. The tests can be written to deal with this quite easily, right?
My preference is a 64-bit nano-second timer with udelay() piggy-backed on the timer API (unless, like NIOS, the timer sub-system cannot provide micro-second resolution, in which case the gd flag or function pointer does not get set to use the timer API for udelay())
Well clearly nanoseconds fits better with the kernel, but it does mandate a 64-bit counter. No comments on this so far from anyone else. My feeling is that microsecond is enough for most purposes. Perhaps to placate the efficiency / code size people we could split the API into a mandatory nanosecond 64-bit value and an optional microsecond value which is 32-bit only. The default udelay() and get_timer_us (or whatever it is called) can rely on the 64-bit ns counter divided by 1000, but archs are free to provide their own implementation which is 32-bits. I suppose the main thing is to get the API clear and consistent even if implementations differ.
While I can see a ns in our future I also feel that CPU speeds have hit a limit of a few GHz and most things that U-Boot cares about re measured in us.
I really want to get the Timer API sorted this time around
Yes. I'm looking forward to getting my microsecond timer!
Regards, Simon
Regards,
Graeme _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (2)
-
Graeme Russ
-
Simon Glass