我正在尝试在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跑步者如下:
#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 %d\n", 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 known\n", 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以正确的实时速度运行模拟?
答案 0 :(得分:0)
It turns out SimAVR doesn't support timing-accurate simulation of opcodes因此,_delay_ms
完成忙碌等待的模拟时间与
正确的解决方案是使用定时器中断,然后在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);
}