Эмуляция Arduino Uno с помощью QEMU: прерывания не работают

Итак, я написал этот код для Arduino Uno:

// file qemu.ino
void setup() {
    Serial.begin(9600);
}

void loop() {
    Serial.println(millis());
}

А затем скомпилировал и загрузил его в настоящий микроконтроллер. Все работает как надо, печать миллисекунд прошла. Значение millis() обновляется регулярно.

Затем я попытался выполнить тот же код в QEMU, используя эти команды:

arduino-cli compile -b arduino:avr:uno -e .
qemu-system-avr -M uno -nographic -bios build/arduino.avr.uno/qemu.ino.with_bootloader.bin

Последовательная печать работает, но millis() все время остается на 0. Так что печатается просто куча нулей.

Дальнейшее исследование исходного кода Arduino выявило проблему: millis() считывает переменную timer0_millis, которая обновляется в ISR(TIMER0_OVF_vect), то есть в 16-м векторе прерывания. Функция init() также обеспечивает включение этого прерывания.

Кроме того, поскольку millis() никогда не обновляется, delay() и Serial.read() зависают навсегда.

Итак, вывод такой: прерывания работают на реальном устройстве, но по какой-то причине не работают на QEMU. Может быть я что-то упускаю?

, 👍1


1 ответ


1

В документации qemu-system-avr говорится:

[...] Контроллер ATmega, модель которого ограничена устройствами USART и 16-битного таймера, достаточными для запуска приложений на базе FreeRTOS [...]

Это означает, что эмулятор не поддерживает 8-битный таймер 0, который используется функциями синхронизации Arduino, такими как millis().

,