This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Floating Point Register saves




Nick Garnett wrote:

David Brennan <eCos@brennanhome.com> writes:



Nick Garnett wrote:



David Brennan <eCos@brennanhome.com> writes:




According to the documentation in the i386 hal cdl documentation, it
states that by default eCos will "save and restore FPU state on every
thread switch, interrupt and exception." It states this in the option
for turning off lazy FPU switching. Our application uses floating
point registers in the DSR context. With Lazy FPU on, we get an
SIGFPE. (Which I guess is not surprising). So we have turned off lazy
FPU switching. With lazy FPU off, is it safe to use floating points in
DSR (or ISR) context? (We got burned by this earlier under VxWorks.)



In theory using the FPU in ISRs and DSRs is allowed, there is code to
save and restore the FPU state in both lazy and non-lazy
configurations. Of course this has not been exercised very much and
may contain bugs. You may have to some debugging.

However, I would also question the need to do FP operations in ISRs
and DSRs. These routines are meant to be fast and small. It is often
better to offload any complex computations to a thread. Note that even
if the DSR only does a small amount of FP computation, the cost of
saving and restoring the FP state to let it do so is very high.





Ok, I doubt that we can use floating points in a ISR context with lazy
FPU switching, since lazy FPU switching actually relies on an
exception being caught. (But interrupts will be disabled.)



It should still work. The interrupt disable only blocks external
interrupts, the FPU unavailable exception is not blocked by this.


We found that the compiler was doing something funky with our virtual tables. We changed our compile options and removed the -fvtable-gc and that problem has gone away. However, now we get an occasional SIGILL after running for a while with Lazy FPU on. (Program stops at pc $000000008 and the backtrace cannot show how it got there.) With Lazy FPU off, we have no problems.



So for now
we turned off lazy FPU switching. We only install one interrupt
driver, and it runs at a nominally slow 40 Hz (on a 1Ghz
Celeron).



That doesn't sound right at all. Even with the large extra cost of
saving and restoring the FPU state, I would expect better performance
than that. There must be something else getting in the way.


What I meant was that "our" only interrupt occurs at a very slow rate (about every 25mS in final production. For testing we have it running at about 3.8mS) So with only about 40Hz interrupt on a 1Ghz processor, we should be able to handle the extra overhead of the FPU state save.



However, in discussion with the team, we realized that this
will also affect the Ethernet driver which probably did not need
it. So we may be going back to some other method. Which brings up the
point, is there something like HAL_FPU_SAVE which is standard for
needing to do an FPU save/restore? And can would this "register" with
the FPU to prevent the Floating Point Exception?



There is no user-visible support for FPU save and restore. It was intended that this all be handled invisibly by the architecture HAL without the user needing to intervene.

Your best bet is to write this code yourself. A few inline
instructions, or a little asm routine should do the trick.

However, lazy FPU switching is intended to work in ISRs, all the code
is in place. I suspect that there is a fairly simple reason for it not
working at present. That SIGFPE you see should be cought by the FP
switch handler and not get passed back the RedBoot. It is probably
still simpler to find out why that is not working.


We probably will not pursue this. However, if we decide to dig in, where exactly would this be happening.



As for using floating points in DSR context, we have a rich C++
wrapper around the operating system so our application rarely (if
ever) needs to make OS calls. This wrapper uses floating point
timers. (Actually internally they are done in ticks, but the external
access is in seconds.) Therefore, if I need to access a timer (even to
check its value, or see if it has timed out, we end up using floating
points.)



While that may have been a good decision when running on top of a big
OS like Windows or *nix, it is not very portable to embedded systems
where the CPU frequently does not have FP hardware, or where there are
restrictions on FP use in interrupt routines. I would always favour a
"fixed point" representation, such as seconds+nanoseconds, which could
be manipulated using integer arithmetic.


Actually this code has only ever been used in embedded real-time operating systems. The original code was for pSOS, that was ported to QNX, that was ported to VxWorks, now we have ported it to eCos. We want the application developers to concentrate on making the application work without worrying about fixed point conversion factors. We do all process control in engineering units including seconds. For some projects the risk of an application error is too great. For instance here is a code snippet from net/bsd_tcpip/current/src/ecos/timeout.c:
// the following triggers if the "next" timeout has not just
// passed, but passed by 1000 ticks - which with the normal
// 1 tick = 10ms means 10 seconds - a long time.
CYG_ASSERT( last_set_time + e->delta + 1000 > now,
"Recorded alarm not in the future! Starved network thread?" );
There is a fundamental assumption with this code that a tick is 10mS. In our application it is not (we use 1mS tick rate).


We can afford to throw money at FPU hardware for the sake of making sure the software is easy to read/review/debug. But it does place some requirements on the OS, like doing FPU state saves on context switches. So if we can ensure that, we should be well on our way to finishing this port.

David Brennan




-- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]