2

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?

lch361
  • 21
  • 1

1 Answers1

1

The documentation of qemu-system-avr says:

[...] ATmega controller, which model is limited to USART & 16-bit timer devices, enough to run FreeRTOS based applications [...]

It means the emulator does not support the 8-bit timer 0, which is used by the Arduino timing functions like millis().

the busybee
  • 2,408
  • 9
  • 18