Avr-gcc: Timer/counter interrupts conflicting with UART?
Please consider the following example (tried on Arduino IDE 0022, Ubuntu 11.04, Arduino AtMEGA 2560), where I'm trying to start a timer/counter interrupt and use the Arduino Serial
class at the same time:
volatile uint8_t sreg;
// Timer 0 interrupt routine
ISR(TIMER0_COMPA_vect, ISR_NAKED)
{
sreg = SREG; /* Save global interrupt flag */
cli(); /* Disable interrupts */
digitalWrite(34, not((bool)digitalRead(34)));
SREG = sreg; /* Restore global interrupt flag */
reti(); // must for ISR: return and enable interrupt
}
void setup() {
pinMode(13, OUTPUT);
pinMode(34, OUTP开发者_如何转开发UT);
Serial.begin(115200);
Serial.println("Hello from setup");
delay(200);
}
void loop() {
digitalWrite(13, HIGH);
Serial.println("Hello from loop: A");
digitalWrite(13, LOW);
delay(200);
digitalWrite(13, HIGH);
#if 1 // register update part
cli(); // disable interrupts
GTCCR = 0b10000011; // halt timers
// set up Timer/Counter 0
TCCR0A = 0b00000010; // CTC; normal mode (don't use output pin)
TCCR0B = 0b00000101; // no force output; CTC; ... and clock select: prescale 1024
TCNT0 = 0; // init the actual counter variable
TIMSK0 = 0b00000010; // enable (only) Compare Match A Interrupt
OCR0A = 125; //the top value, to which the running counter is compared to
GTCCR = 0b00000000;
sei(); // Enable interrupts once registers have been updated
digitalWrite(13, LOW);
delay(200);
#endif
digitalWrite(13, HIGH);
Serial.println("Hello from loop: B");
digitalWrite(13, LOW);
delay(200);
}
As the example is, the printout via serial will be:
Hello from setup
Hello from loop: A
Hello from loop: B
Hello from loop: A
Hello from loop: B
... and then all processing will stop (indicated by lack of action on both LED pin 13 and 34); I guess, this is what you would call a BSOD in the chip world :) Superficially, the halt happens as soon as the ISR routine kicks in for the first time.
If you take out the "register update part", then the serial printout runs forever, as expected - and also (as expected), there is no ISR running. However, if the "register update part" is left, and the two "Serial.println(...
" lines are commented instead - then the program prints only "Hello from setup" - but the interrupt does run (as evidenced by pulses on pin 34).
Which seems to tell me, that you cannot run a timer ISR and the UART on the ATMega2560 at the same time - which is silly, given that I had previously used, with success, the same kind of approach on an ATMega328.
So, I'm wandering whether what I want to do (have both serial printout and pins pulsing) is fundamentally impossible with this architecture - or am I just missing something in the setup?
Thanks in advance for any answers, Cheers!
(Just wanted to note that this Serial class actually operates on a class definition in HardwareSerial.cpp in the Arduino IDE package; and this class defines the reception USART interrupt routines; thought this may be the problem - but again, I used the same approach in ATMega328, where I had seen it work.. )
EDIT: Repost on Avr-gcc: Timer/counter interrupts conflicting with UART? - Arduino Forum
Ok, I just re-ran the same code on ATMega168 and ATMega328 - and it works as expected (both main loop with Serial.write
, and ISR routine, are running); so it must be an ATMEGA2560 specific problem - and not a problem with programming in general ...
EDIT: The short answer is - use a different timer, because Timer0 is already in use by the Arduino API.
(for more, see the repost on Arduino forum).
Cheers!
精彩评论