时钟频率设置不会改变仿真速度



我正在尝试在simavr上运行以下AVR程序:

#include <avr/io.h>
#include <util/delay.h>
int main ()
{
    DDRB |= _BV(DDB5);
    for (;;)
    {
        PORTB ^= _BV(PB5);
        _delay_ms(2000);
    }
}

我已经用F_CPU=16000000编译了它。Simavr Runner如下:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "sim_avr.h"
#include "avr_ioport.h"
#include "sim_elf.h"
avr_t * avr = NULL;
static void* avr_run_thread(void * ignore)
{
    for (;;) {
        avr_run(avr);
    }
    return NULL;
}
void led_changed_hook(struct avr_irq_t* irq, uint32_t value, void* param)
{
    printf("led_changed_hook %d %dn", irq->irq, value);
}
int main(int argc, char *argv[])
{
    elf_firmware_t f;
    elf_read_firmware("image.elf", &f);
    f.frequency = 16e6;
    const char *mmcu = "atmega328p";
    avr = avr_make_mcu_by_name(mmcu);
    if (!avr) {
        fprintf(stderr, "%s: AVR '%s' not knownn", argv[0], mmcu);
        exit(1);
    }
    avr_init(avr);
    avr_load_firmware(avr, &f);
    avr_irq_register_notify(
        avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 5),
        led_changed_hook,
        NULL);
    pthread_t run;
    pthread_create(&run, NULL, avr_run_thread, NULL);
    for (;;) {}
}

问题在于,我从led_changed_hook的输出中可以看到它以〜4倍速度运行。此外,更改f.frequency似乎对模拟速度没有任何影响。

如何确保Simavr以正确的实时速度运行模拟?

事实证明,simavr不支持opcodes的计时 - 准确模拟,因此将_delay_ms繁忙等待完成的模拟时间完全无关与

  • 真正的MCU需要多长时间
  • 模拟MCU的时钟频率

正确的解决方案是使用计时器中断,然后在MCU上睡觉。模拟器将正确模拟计时器计数器,睡眠将暂停模拟直到计时器启动。

#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
int main ()
{
    DDRB |= _BV(DDB5);
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;
    TIMSK1 |= (1 << OCIE1A);
    sei();
    /* Set TIMER1 to 0.5 Hz */
    TCCR1B |= (1 << WGM12);
    OCR1A   = 31248;
    TCCR1B |= ((1 << CS12) | (1 << CS10));
    set_sleep_mode(SLEEP_MODE_IDLE);
    sleep_enable();
    for (;;)
    {
        sleep_mode();
    }
}
ISR(TIMER1_COMPA_vect){
    PORTB ^= _BV(PB5);
}

最新更新