buserror / simavr

simavr is a lean, mean and hackable AVR simulator for linux & OSX
GNU General Public License v3.0
1.56k stars 365 forks source link

timer overflow issue depending on prescaler value #368

Open jmfriedt opened 4 years ago

jmfriedt commented 4 years ago

As I was struggling with input capture and reading the timer value, I slowly removed all unnecessary code to reach the following example of what I believe to be improper behavior of the timer overflow interrupt. If I

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>  // _delay_ms

// simulator variables: trace file + CPU type (not used in the firmware)
#include "avr_mcu_section.h"
AVR_MCU(F_CPU, "atmega32u4");

ISR(TIMER3_OVF_vect) {PORTE^=1<<PORTE6;}

void myicp_setup() // initialisation timer3
{TCCR3A = 1<<WGM31 | 1<<WGM30;
 TCCR3B = 1<<ICES3 | 1<<WGM33 | 1<<CS30;
 OCR3A  = 32000;
 TIMSK3 = (1<<TOIE1);
 TIFR3  = 1<<ICF3;
}

int main(void)
{MCUCR &=~(1<<PUD);
 DDRE |=1<<PORTE6;      // blinking LED

 myicp_setup();
 sei();

 while(1) { }
}

then no timer overflow occurs, as indicated by the lack of message hinting at PE6 toggling. However replacing TCCR3B = 1<<ICES3 | 1<<WGM33 | 1<<CS30; with TCCR3B = 1<<ICES3 | 1<<WGM33 | 1<<CS31; will generate multiple GPIO toggling messages, although I am supposed to only have divided the clock rate by 8. I do not believe this is the proper behavior of the timer. I am unable to track the issue in the simavr source code though.

jmfriedt commented 4 years ago

The issue seems to be restricted to the fast PWM mode. Keeping the normal mode (WGM3i=0 \forall i) seems to work properly, both input capture and overflow interrupt.

buserror commented 4 years ago

Is this one "fixed"? You mentioned you had it working...

jmfriedt commented 4 years ago

Indeed I should have updated the issue request after identifying the cause. Timer modes 8 to 11 are not implemented for the Atmega32U4 (and other Atmega cores I believe) as shown in https://github.com/buserror/simavr/blob/master/simavr/cores/sim_mega32u4.c#L302 and https://github.com/buserror/simavr/blob/master/simavr/cores/sim_mega32u4.c#L367 where modes 8 to 11 are not implemented. Using mode 0 (normal) did work fine and I stuck to that. As I understand not implementing the timer means that the associated TCNT is just not incremented and hence nothing occurs on ICP or OVF, which makes sense once I understand the issue. So basically just stay away of these modes if their functionality is not needed.