AW: [En-Nut-Discussion] Register overwriting in interrupted code

Oliver Schulz olischulz at web.de
Sat Jul 24 18:41:13 CEST 2004


Hi Gordian,

>
> In in the serial port implementation uartavr.c we encountered
> a strange
> problem: in "int UartAvrInput(NUTDEVICE * dev)" there is a
> NutEventWait() function; when the event is set, dev (r21:r20) and
> another variable, which both have been stored in a register pair each,
> are overwritten with 0.
> It seems that the eventing code (interrupt driven) somewhere
> uses those
> registers and does not restore them to their original values.
> Shouldn't
> the interrupt code take care of the registers it uses?

please tell me first which compiler you use and the Nut/OS release number.

For avr-gcc I can say, that the registers r18 to r27 are so called
'called-used' registers. Means, that any called subfunction can modify them
freely.
If the caller needs the values after calling the subfunction, the _caller_
is responsible to save (i.e. push to stack) the registers before calling the
subfunction.

BTW, in the current cvs HEAD and using avr-gcc, the parameter 'dev' of the
function UartAvrInput is stored in r25:r24, and r21:r20 hold the lower 16
bits of dcb->dcb_rtimeout.

>
> How can that work? Or rather: does it make sense to enter a critical
> section (disabling interrupts) and then wait for interrupt
> driven events
> (I know that this usually works, but how)?
>
Using NutEnterCritical() and NutExitCritical() here has one special purpose.
The function uses some variables (ifs->if_rx_idx) which can be altered by an
interrupt handler. Because the access to those variables is usually not
atomic (for 16 bit or greater sized variables on avr core), the interrupts
are disabled, so the value is not modified _while_ reading the variable.
(But a look at device.h reveals, that ifs->if_rx_idx and ifs->if_rd_idx are
8 bit integers, so there is no need to use NutEnterCritical() here...)

By calling NutEventWait, the context is switched to the next waiting thread,
which in turns (normally) enables the interrupts again. So disabling the
interrupts prior to NutEventWait() will not block the "reception" of the
event.

Cheers,
Oliver.




More information about the En-Nut-Discussion mailing list