DigitalWrite during interrupts

Can anyone explain in detail how the digitalWrite works. ie. how long does it take, how indirect it is in comparison to port writes and most importantly will /can it leave a port or port pin or DDR in an unknown state if interrupted. My data stream, all generated in timer interrupt seems to be affected by digitalWrites in main Loop. Doing port writes seems ok.
Any thought appreciated…

using 0017

digtialWrite does a “non-atomic” read-modify-write operation on the IO port containing the pin that you’re writing:

    read port
    set or clear appropriate bit
    write port

It’s certainly POSSIBLE that an interrupt could occur after the port has been read but before it has been written, causing pin changes done within the interrupt routine to be “lost”, though I wouldn’t expect it to be terribly LIKELY (depending on how often you call digitalWrite in loop().)

While digitalWrite is perhaps 20 to 50 times slower than the fastest possible direct write, the latter is a single instruction, so digitalWrite isn’t really THAT slow. You could just wrap the loop code in “turn off interrupt” instructions. It’s not possible to maintain the ability of digitalWrite to use variables for pin number and value and still be atomic or very fast; if everything is constant, you could use direct writes in the loop() code.

I think DDR should be OK unless you’re explicitly changing it back and forth in ISR and/or loop code.

My data stream, all generated in timer interrupt seems to be affected by digitalWrites in main Loop.

If westfw’s post above doesn’t point you to an answer you need to explain this. Where is the data stream coming from and going and how does it relate to the pins you’re writing in Loop?

digtialWrite does a “non-atomic” read-modify-write operation on the IO port containing the pin that you’re writing:

It’s certainly POSSIBLE that an interrupt could occur after the port has been read but before it has been written, causing pin changes done within the interrupt routine to be “lost”, though I wouldn’t expect it to be terribly LIKELY (depending on how often you call digitalWrite in loop().)

That’s genuinely interesting.

That’s genuinely interesting.

Yeah. Concurrency in general is a REAL PROBLEM, fully capable of attracting many PHD candidates and generating many papers. If you think it’s an issue with interrupts on an arduino, consider those 1000-core supercomputers, where each CPU has multiple interrupt levels and multi-tasking operating systems. (or even the quad-core desktops that you’d really like to run apps faster than a single-core system.)

Wow; thanks for all the rapid responses.
Reduced to a minimum here’s what works and what does not.
Using digitalWrite to a DIFFERENT PORT pin does not cause any problem.
So it looks like DigitalWrites outside should not be used in ISRs as well. Doing port writes don’t seem to cause any problems.

// V0.1B Data streaming
// Platform; Arduino Mini 16Mhz
// IDE Arduino 0017
// V0.1A 27 Jan 2010 Set up 250usec interrupt and toogle pin 13
// V0.1B 28 Jan 2010 Biphase data streaming on pin 12; sync pulses on pin 13
//------------------------------------------------------------------------------
// #define dataPin 12
#define led 13
volatile byte temp1;
volatile byte toggle;
volatile byte data[9];
//#define led 13
#define dataPin 12
volatile byte i=0;
volatile byte j=0;
volatile byte buffer;
volatile byte mask;
volatile boolean dataBit=0;
//-------------------------------- set up ---------------------------------------
void setup(){
//set up timer 2 cotrol registers here
TCCR2A = B00000000; //select Normal Mode,freerunning counter, no connection to hardware pins
TCCR2B = B00000011; //normale, prescaler equals clock/32. With 16Mhz clock this give 2uSec clock to the TCNT2
OCR2A = 125; //initialise compare register for first interrupt
TIMSK2 = B00000010; //generate interrupt on output compare match A
pinMode(led,OUTPUT); // set DDR
pinMode(dataPin,OUTPUT);
pinMode(11,OUTPUT);
pinMode(7,OUTPUT);

data[1]=B00000000; // dummy data
data[0]=B00011001; // dummy data
buffer=data[0];
mask=B00000001;

}
//-------------------------------- interrupt service routine ---------------------
ISR (TIMER2_COMPA_vect){
OCR2A += 125; //add 250uSec increment to timer2
toggle = !toggle;
//digitalWrite(led,toggle); // nice stable 2Khz square wave here just for initial testing
digitalWrite(led,1); // start pulse for synching 'scope

digitalWrite(dataPin,dataBit); //write nice stable biphase data to output

if (i!=1) { // shift data only every second interrupt
i=1;
dataBit=!dataBit; // data bit must be toggledat every data read
temp1 =buffer & mask; //put zero or non zero depending on the state of the bit under the mask

mask=mask<<1; // shift the mask left 1 bit
if (mask==0) {
mask=B00000001; // reset the mask bit
j=j+1; // increment data pointer
if (j>1) {
j=0;
}
buffer=data[j]; // get the next data byte
}
}
else{
i=0;
if (temp1!=0) { // if bit to be sent is a 1 then toggle dataBit again on the next interrupt
dataBit=!dataBit;
}
}
digitalWrite(led,0); //end sync pulse. THe pulse length indicates the fraction used of the time available
// So far this code uses about 10uSec out of the 250uSec period. There is still
// space for a fair bit of code.

}
//--------------------------------------- main loop ------------------------------
// this does notcause any problems with waveform made in ISR
void loop(){
digitalWrite(7,HIGH);
digitalWrite(7,LOW);

//this affects ISR
//digitalWrite(11,HIGH);
//digitalWrite(11,LOW);

}

Ahh.

This is one of thise threads i add to my Firefox bookmark folder called “Troubleshooting bizare Arduino problems”

As far as I can tell the digitalWrite provided with the Teensy libraries is (mostly) atomic. The code in digitalWrite that turns off PWM is not atomic in either library.