Pages: [1]   Go Down
Author Topic: Interrupt handling question - optimised digitalWrite  (Read 375 times)
0 Members and 1 Guest are viewing this topic.
Kent
Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A question for the interrupt handling experts. 

I'm using the optimised digitalWrite library here: http://code.google.com/p/arduino/issues/detail?id=140#c10 to speed things up (see extract below), and I understand why it is necessary to disable interrupts (cli()) when updating registers above 32 or when using variables. 

However, what I don't understand is when the interrupts get re-enabled after the function call.  I don't see a call to sei() or similar, but without that then surely the main program will then be running with interrupts disabled.  But I know that can't be true because my program works and does things that need interrupts enabled.

Does the return re-enable interrupts?  Any help much appreciated (and as a by-the-way, why the "while(0)" loop, which will only ever execute once?).

----------------

#define digitalWrite_implementation(pin, value)\
do {\
   uint8_t oldSREG;\
   uint8_t bit = digitalPinToBitMask(pin);\
   uint8_t port = digitalPinToPort(pin);\
   volatile uint8_t *reg = portOutputRegister(port);\
\
   if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
      oldSREG = SREG;\
      cli();\
   }\
\
   if (value == LOW) {\
      *reg &= ~bit;\
   } else {\
      *reg |= bit;\
   }\
\
   if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
      SREG = oldSREG;\
   }\
} while(0)
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 207
Posts: 12912
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Does the return re-enable interrupts?

No.

The global interrupt enable state is determined by a bit in a register; specifically, the I (eye) bit in the Status Register (SREG).  If the I bit is set, interrupts are enabled.  If the I bit is clear, interrupts are disabled.

As you've discovered, the CLI instruction (aka cli()) disables interrupts.  It does that by clearing the I bit in the SREG register.

The "oldSREG = SREG;" assignment saves the current value of the SREG register, including the I bit, in a local variable named oldSREG.

The "SREG = oldSREG;" assignment restores the previously saved value of the SREG register, including the I bit.

So, the code does not re-enable interrupts.  It restores the interrupt state to what it was when digitalWrite was called.
Logged

Kent
Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, I'd missed that.  Thank you
Logged

Pages: [1]   Go Up
Jump to: