This is just a question for learning only. It's from an observation, and just trying to understand what's happening in the wings.
I have a very short arduino program. And, in the setup area, I disable all interrupts with cli();
I then set a delay of 30 seconds .... with delay(30000);
Next, I have a Serial.print line that is meant to just print 'READY' on the serial monitor screen.
When I load the code into the arduino UNO, the characters 'RE' show up in serial monitor, which are the first 2 characters of 'READY'. The characters 'RE' appear pretty soon after firing up serial monitor, so there's no long 30 second delay or anything.
I have read that disabling interrupts affect timer0 and serial activity (that requires interrupts). And the delay function probably gets affected as well.
Does anyone know what causes the 'RE' to show up on the serial monitor like that (and with no delay noticed)? Is it because I disabled features that shouldn't be disabled if I want to use delay() etc? And why 'RE' gets through..... instead of say 'R' or 'REA' etc?
Here's my short code for an UNO running on serial monitor at 115200 bit per second :
#include <avr/io.h>
#include <stdint.h> // has to be added to use uint8_t
#include <avr/interrupt.h> // Needed to use interrupts
void setup()
{
cli(); //disable all interrupts
delay(30000); //30 second delay
Serial.begin(115200);
Serial.println("READY");
}
void loop()
{
}
With no interrupts, the Serial() function/class whatever it is has no way to know when a byte has been transferred out.
delay() also does not work as the 4uS time interrupt that makes the basis of delayMicroseconds() and delay() is turned off.
There's no reason to turn off interrupts unless you have something that needs to run really fast, like blasting out a string of bytes over SPI that need to be synced to some start pulse and the interrupt tick is upsetting the smoothness of that blast of bytes. And even then you need a protocol analyzer or an oscilloscope to be able to determine that.
Very curios behavior. I have found another wrinkle.
When I upload the sketch, RE appears on the Serial monitor and it is also retransmitted every time I press the reset button.
However, if I do a full power cycle of the Arduino (unplug power, and replug it back in), the characters are not transmitted. The Arduino is halted at the delay call just as expected.
Jiggy-Ninja:
However, if I do a full power cycle of the Arduino (unplug power, and replug it back in), the characters are not transmitted. The Arduino is halted at the delay call just as expected.
This is does not happen for me: when I unplug Arduino and reconnect it the RE does not appear. But it is not strange because by unplugging Arduino the Serial loose communication with any sketch on my computer. After reopening Serial "RE" appears as before.
Still "RE" should not be sent.
I tried to comment out the libraries you included, Arduino includes them on its own. Nothing changed.
Is there a way to get the compiled files (.lss) to look into it and try understand what is going on?
unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;
cli();
m = timer0_overflow_count;
#if defined(TCNT0)
t = TCNT0;
#elif defined(TCNT0L)
t = TCNT0L;
#else
#error TIMER 0 not defined
#endif
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
m++;
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
uint32_t start = micros();
while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
micros() check for Timer0 overflow flag and if it is set increments m (count of milliseconds). But does not clear the flag! Normally Timer0 overflow ISR clears the flag. But not when interrupts are disabled. So once Timer0 overflows (about 1 ms) every call of micros() adds one fake millisecond. So delay() expires very quickly, RE is written to USART but then disabled interrupts break the Serial somehow...
CrossRoads:
With no interrupts, the Serial() function/class whatever it is has no way to know when a byte has been transferred out.
delay() also does not work as the 4uS time interrupt that makes the basis of delayMicroseconds() and delay() is turned off.
There's no reason to turn off interrupts unless you have something that needs to run really fast, like blasting out a string of bytes over SPI that need to be synced to some start pulse and the interrupt tick is upsetting the smoothness of that blast of bytes. And even then you need a protocol analyzer or an oscilloscope to be able to determine that.
Thanks for your help CR!
Thanks jiggyN and smajd for adding observations and comments about that as well.
With no interrupts, the Serial() function/class whatever it is has no way to know when a byte has been transferred out.
The UART has a two byte output buffer (well, the shift register plus one other byte) in hardware, so the first two characters can be output without any interrupts. The UART code is essentially:
Normally, the UART ISR will come along when a character is 'finished' and move characters from the SW buffer to the HW buffer, but that won't happen if interrupts are off. (The actual interrupt cause is "HW buffer has room")
Thanks westfw! So....when the UNO code starts running, two bytes reach that hardware buffer (that can hold two bytes) you mentioned. And those particular operations don't involve (or require) any interrupt activity - otherwise those two characters wouldn't have made it, right? Thanks again. You guys and/or girls really know the ins and outs of these systems really well.
The thing to remember that serial is created BEFORE setup(). So check to see if serial's buffer is cleared/reset on a reset as opposed to a power on reset.
Serial can do output with interrupts disabled. I think the feature was added in 2013. When you try to send a byte, and the fifo buffer is full, and interrupts are disabled, the code loops waiting for the UART status register to indicate that the output register has room. It then simulates an interrupt (calls the ISR and clears the interrupt flag) to move a byte out of the fifo. It can then put your byte in the fifo and return. This slows the Serial.print() to the rate of the serial line.