So I wrote this code for Arduino Uno:
// file qemu.ino
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(millis());
}
And then compiled and uploaded it to the real microcontoller. Everything works as it should, printing milliseconds elapsed. The millis()
value updates regularly.
Then, I tried to execute the same code in QEMU by using these commands:
arduino-cli compile -b arduino:avr:uno -e .
qemu-system-avr -M uno -nographic -bios build/arduino.avr.uno/qemu.ino.with_bootloader.bin
Serial prints work, but millis()
stays at 0 all the time. So just a bunch of 0s getting printed.
Further investigation of Arduino source code revealed the problem: millis()
reads the variable timer0_millis
, which gets updated in ISR(TIMER0_OVF_vect)
, that is, in the 16th interrupt vector. The init()
function also makes sure that this interrupt is enabled.
Also because millis()
never gets updated, delay()
and Serial.read()
hang forever.
So the conclusion is: interrupts work on a real device, but for some reason not on QEMU. Maybe I am missing something?
millis()
.