Pages: [1]   Go Down
Author Topic: Digital port programming, interrupt disable why?  (Read 626 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 196
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I was hacking through the core libraries and found the pinMode declaration:

Quote
void pinMode(uint8_t pin, uint8_t mode)
{
   uint8_t bit = digitalPinToBitMask(pin);
   uint8_t port = digitalPinToPort(pin);
   volatile uint8_t *reg;

   if (port == NOT_A_PIN) return;

   // JWS: can I let the optimizer do this?
   reg = portModeRegister(port);

   if (mode == INPUT) {
      uint8_t oldSREG = SREG;
                cli();
      *reg &= ~bit;
      SREG = oldSREG;
   } else {
      uint8_t oldSREG = SREG;
                cli();
      *reg |= bit;
      SREG = oldSREG;
   }
}

I don´t understand why is the cli() used?
Why do you need to save SREG and disconnect interrupts to change de port mode?

Best regards
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26485
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Because the operation may not be atomic, i.e. an interrupt could cause a change to the value of the register between reading, and writing back the new value
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there an automatic sei() added in the compile? Well, it seems to me there must be something.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
God Member
*****
Karma: 19
Posts: 785
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

SREG = oldSREG;

This turns the interrupts back on.
Logged

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

SREG = oldSREG;

This turns the interrupts back on.

If they were turned on to begin with.

...
Why do you need to save SREG...

An sei() at the end of the function would turn on the interrupts whether they were initially enabled or not.  This would result in a pinMode call enabling interrupts even if initially disabled.  SREG contains a Global Interrupt Enable bit(cli() and sei() clear and set this bit)  By saving the value of SREG and restoring it at the end of the function you only enable the interrupts if they were enabled to begin with.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So it's probably much better to save SREG before cli() and restore SREG later than to just throw cli() and sei() in as needed?

3 steps instead of 2, for better code.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void setup() {
  Serial.println("This is my favorite sketch");
}

void loop() {
  Serial.println("I'm entering a time-sensitive part of the program!");
  noInterrupts();
  digitalWrite(4, HIGH);
  delayMicroseconds(1000);
  Interrupts();
}

Good thing digitalWrite doesn't enable interrupts, or this wouldn't work*

*assuming it did anything
Logged

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 70
Posts: 2738
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So it's probably much better to save SREG before cli() and restore SREG later than to just throw cli() and sei() in as needed?

3 steps instead of 2, for better code.



You sarcasm isn't helpful.

You are not understanding that interrupts are not always enabled and so you can't simply blindly mask
them and blindly turn them on.
If you were to do that then interrupts would be turned on when they were disabled before this function were
called.

ISR routines are allowed to call functions like pinMode() and digitalWrite().
Libraries like the servo library, and IRremote call these functions from their ISR.

The issue is that given the way the core code is currently implemented, it uses a |= operation using non compile
time constants, which means it has to mask interrupts to protect the updates that an ISR may do to a port bit
from the foreground port bit updates.
It also has to save and restore the interrupt mask in the status register to ensure that it
doesn't accidentally re-enable interrupts when they are disabled.

Given the way the core code is implemented, there is no way around this.

--- bill
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So it's probably much better to save SREG before cli() and restore SREG later than to just throw cli() and sei() in as needed?

3 steps instead of 2, for better code.



You sarcasm isn't helpful.

There's absolutely Zero Sarcasm there. That last line is what I believe to be a statement of fact.

Fact is that 3 steps to do the right thing is better than 2 steps that leave a hole for error.

 
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 70
Posts: 2738
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So it's probably much better to save SREG before cli() and restore SREG later than to just throw cli() and sei() in as needed?

3 steps instead of 2, for better code.



You sarcasm isn't helpful.

There's absolutely Zero Sarcasm there. That last line is what I believe to be a statement of fact.

Fact is that 3 steps to do the right thing is better than 2 steps that leave a hole for error.

 

Ok, apology offered. Sorry about that.
I totally misinterpreted the comment.

--- bill
Logged

Pages: [1]   Go Up
Jump to: