[ ATMega328p ] Implementing ISR breaks / freezes program

Hi,

i'm trying to program an ATMega328P using avrdude on a breadboard.

When i implement an ISR for timer-0-overflow the program crashes and won't start anymore. It seems like just implementing an ISR breaks the whole program.

I'm trying the following:

#include <avr/io.h>
#include <avr/interrupt.h>

// T = 0.5s with 16 MHz Frequency
constexpr uint16_t ovf_max_count = 31250;

volatile uint16_t ovf_count = 0;

int main()
{
    // Configure Pin 5 of Port-D to Output
    // Set Pin 5 of Port-D to high
    DDRD |= (1 << PD5);
    PORTD |= (1 << PD5);

    // Enabling Timer 0 without prescaler
    // Enable Timer 0 OVF-Interrupt
    // Setting Timer 0 Count to 0

    TIMSK0 |= (1 << TOIE0);
    TCCR0B |= (1 << CS00);

    TCNT0 = 0;

    // Enable interrupts
    sei();

    for(;;)
    {
    }
}

// Implementing this breaks the program and the LED on pin 5 doesn't light up.
// When not implemented the LED is on and it seems to work. When testing
// with delay in the main loop it works. When trying to use it this way with
// interrupts it breaks the whole program.

ISR(TIMER0_OVF_vect)
{
    if(++ovf_count >= ovf_max_count)
    {
         PORTD ^= (1 << PD5);
         ovf_count = 0;
    }
}

It doesn't depend on this interrupt in special. Every ISR i'm implementing breaks the program. The TIMER0_OVF_vect as well as any other like PCINT0 etc. I don't have any idea left which could cause this problem.

I'm using an ATMega328P-PU with an 16 MHz Crystal oscillator on a breadboard. Capacitor-Values are 22 pF.

Thanks for your answers or advices!

Cheers,

Smokehead

Wiring uses that ISR

so that we can have a millis function.

I bet the compiler is not very pleased with having two references to the interrupt.

Multiple ISRs for the same vector should prevent compile from succeeding, so it's weird that it even builds....

I'm not using anything from the Arduino-API. I'm not even using the arduino boards anymore. So i don't think it does have to do anything with any Arduino APIs anymore. I switched to programming via ISP on a breadboard with the testing setup. Programs without ISRs work as intended but as soon as i add an ISR it doesn't do anything. Not even the LED is on.

I'm using avr-gcc 8.2 on ArchLinux 4.19.8 with avrdude using an pavolu avr programmer v2.1.

Cheers,

Smokehead

That is some bleeding edge stuff, not even Microchip is using it that fresh. You are going to have to figure out how to fix your own problems if you want to play the game at that level. The 8.x updates do look interesting, but I think I will wait for Debian and/or Microchip before I start working with it.

I'm playing around with Templatemetaprogramming using Templatestructures for Hardwareabstruction without producing the same overhead like classic C++ classes. There i need a lot of constexpr and stuff like this. Older compilers aren't capable of these things. I need to have a new one for using the C++ 17 features.

For sinple I/O and Pin toggling or even configuring some Regusters it works fine. But when i start using simple things like this it breaks everything. Then i've tried a simple.program.like this one above and couldn't get it running.

But thanks for the hint! I'll try using an older compiler for testing the ISR code to see if this coukd be the problem.

If i'd post the disassembler binary, could any one help me find an possible error?

Cheers,

Smokehead

Update:

It seems like the microcontroller is running into the following ISR. After implementing this it seems to do exactly this. It puts on the LED connected to pin PC0. I'm slightly confused. I don't have any other interrupt enabled nor do i have called sei() (just for testing purposes).

ISR(BADISR_vect)
{
    PORTC |= (1 << PC0);
}

I don't know whats happening there. Do Fuses maybe have any influence to interrupt handling? The external crystal oscillator at 16MHz seems to run without any issues. When using the _delay_ms(500) with 500 ms as parameter it toggles the LED 2 times a second which would be correct. I do not have any idea what could cause this behaviour.

Cheers,

Smokehead

Are the interrupt vectors properly defined in your tools? AFAIK ISR with misspelled name still compiles and you get only warning, the ISR is not attached to any interrupt and probably is not included to the binary at all. If you don't have the interrupt names defined (or the names are slightly different) it would explain what you see.

I now have a completely different behaviour.

I've looked at the disassembled code for some time and wrote another simple program. It seems like the first one (created with CMake) did something different than the one with a simple Makefile.

The one i've build using a Makefile i've wrote included all interrupt vectors pointing to __bad_interrupt except the one i've defined. The one built with cmake didn't include this one but had some other sections in it. It seems like i'm going to use Makefiles instead of CMake for future MCU-projects.. CMake does some strange things.. I think it did something to the compiler options.

Now i've got the ISRs running but it seems that i've broken something on my programmer or board itself.

When i'm flashing the chip it's much slower than before and i get the following output:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.07s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "app.elf"
avrdude: writing flash (244 bytes):

Writing |                                                    | 0% 0.00savrdude: stk500v2_ReceiveMessage(): timeout
Writing | #########################                          | 50% 3.02savrdude: stk500v2_ReceiveMessage(): timeout
Writing | ################################################## | 100% 6.04s

avrdude: 244 bytes of flash written
avrdude: verifying flash memory against app.elf:
avrdude: load data flash data from input file app.elf:
avrdude: input file app.elf contains 244 bytes
avrdude: reading on-chip flash data:

Reading |                                                    | 0% 0.00savrdude: stk500v2_ReceiveMessage(): timeout
Reading | ################################################## | 100% 5.95s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x80 != 0x0c
avrdude: verification error; content mismatch

avrdude: safemode: Fuses OK (E:FF, H:D9, L:D6)

avrdude done.  Thank you.

I don't know what happened there. I did not change anything on the board itself nor on the programmer nor on the wiring.

Just reading from the flash using avrdude doesn't work either. I've tried that on three ATMega328P chips. The programs run as intended but it needs longer to upload and throws errors. Does anyone have an idea? Should i open another thread for this one?

For the basic-questions:

Yes, i'm using a pullup-resistor (10 k) on the reset pin as well as a 100nF capacitor between VCC and GND.

Like i said, the programs are working but i get these verification errors.

Thanks!

Cheers,

Smokehead

I have seen a verification error because I was doing something wrong but I don't recall what it was.

For reference, I have some Makefiles that load with an Arduino Uno using the example ISP sketch (avrdude -c stk500v1).

with the optiboot loader (avrdude -c arduino)

and again with xboot loader (avrdude -c avr109)

As far as i know i do not need a bootloader because im flashing the program with an ISP. I'm using a Polulu AVR Programmer v2.1 which as far as i know emulates the stk500v2.

That's how i start flashing:

avrdude -v -c stk500 -p atmega328p -P /dev/ttyACM0 -U flash:w:app.hex:i

I'm curious what caused the problem because i'm working with this command and it worked. Something happened today which broke my setup. Should i upload my schematic? Maybe there are some capacities or mistakes i'm not aware of.

Cheers,

Smokehead

Here it is.. Maybe it will show you my setup and leads to a solution.

Cheers,
Smokehead

The AVCC needs power, and I use a bypass for AVCC, VCC, and AREF (one on VCC works, but ... well it is probably my OCD).

with avrdude version 6.3 on Ubuntu 18.04, the programmer options I see are

  stk500           = Atmel STK500
  stk500hvsp       = Atmel STK500 V2 in high-voltage serial programming mode
  stk500pp         = Atmel STK500 V2 in parallel programming mode
  stk500v1         = Atmel STK500 Version 1.x firmware
  stk500v2         = Atmel STK500 Version 2.x firmware

I have no clue if the Polulu programmer would be using the original stk500 or one of the newer v1 and v2.

Actually i've connected them to the supply voltage but i didn't put them in the schematic. Well, i've messed up the in/output labels as well. Had to be quick, you know...

I'll try different settings. Thanks fir the hint!

Cheers,
Smokehead

It sounds like you could be getting the wrong startup code, with vectors in the wrong place.
What EXACTLY does your build command end up looking like (the gcc command that make or cmake produces)? And what version of avr-libc do you have? (and/or post the disassembly of your test program...)

EDIT: AVR-LIBC Version is 2.0.0-3

The exact call is like the following:

avr-g++ -c -std=gnu++17 -Os -Wall -Wextra -Wpedantic -Iinc -mmcu=atmega328p src/main.cc -o src/main.o
avr-g++ -Os -mmcu=atmega328p src/main.o -o build/app.elf
avr-objcopy -O ihex -j .bss -j .data -j .text build/app.elf build/app.hex
avrdude -v -e -c stk500 -p atmega328p -P /dev/ttyACM0 -U flash:w:build/app.hex:a

That's what is called when flashing the program. I noticed sometimes it seems like the flashing progress changes the fuses.. I doesn't happen everytime but when it does it shows the following message:

...
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: safemode: hfuse reads as 58
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: safemode: efuse reads as 50
avrdude: safemode: lfuse changed! Was d6, and is now 50
Would you like this fuse to be changed back? [y/n] 
avrdude: safemode: hfuse changed! Was df, and is now 58
Would you like this fuse to be changed back? [y/n] 
avrdude: safemode: efuse changed! Was ff, and is now 50
Would you like this fuse to be changed back? [y/n] 
avrdude: safemode: Fuses OK (E:FF, H:DF, L:D6)

The disassembled code looks like this:

app.elf:     file format elf32-avr


Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
   8:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
   c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  10:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  14:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  18:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  1c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  20:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  24:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  28:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  2c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  30:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  34:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  38:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  3c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  40:	0c 94 48 00 	jmp	0x90	; 0x90 <__vector_16>
  44:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  48:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  4c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  50:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  54:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  58:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  5c:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  60:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>
  64:	0c 94 46 00 	jmp	0x8c	; 0x8c <__bad_interrupt>

00000068 <__ctors_end>:
  68:	11 24       	eor	r1, r1
  6a:	1f be       	out	0x3f, r1	; 63
  6c:	cf ef       	ldi	r28, 0xFF	; 255
  6e:	d8 e0       	ldi	r29, 0x08	; 8
  70:	de bf       	out	0x3e, r29	; 62
  72:	cd bf       	out	0x3d, r28	; 61

00000074 <__do_clear_bss>:
  74:	21 e0       	ldi	r18, 0x01	; 1
  76:	a0 e0       	ldi	r26, 0x00	; 0
  78:	b1 e0       	ldi	r27, 0x01	; 1
  7a:	01 c0       	rjmp	.+2      	; 0x7e <.do_clear_bss_start>

0000007c <.do_clear_bss_loop>:
  7c:	1d 92       	st	X+, r1

0000007e <.do_clear_bss_start>:
  7e:	a2 30       	cpi	r26, 0x02	; 2
  80:	b2 07       	cpc	r27, r18
  82:	e1 f7       	brne	.-8      	; 0x7c <.do_clear_bss_loop>
  84:	0e 94 6c 00 	call	0xd8	; 0xd8 <main>
  88:	0c 94 7a 00 	jmp	0xf4	; 0xf4 <_exit>

0000008c <__bad_interrupt>:
  8c:	0c 94 6a 00 	jmp	0xd4	; 0xd4 <__vector_default>

00000090 <__vector_16>:
  90:	1f 92       	push	r1
  92:	1f b6       	in	r1, 0x3f	; 63
  94:	1f 92       	push	r1
  96:	11 24       	eor	r1, r1
  98:	2f 93       	push	r18
  9a:	8f 93       	push	r24
  9c:	9f 93       	push	r25
  9e:	80 91 00 01 	lds	r24, 0x0100	; 0x800100 <_edata>
  a2:	90 91 01 01 	lds	r25, 0x0101	; 0x800101 <_edata+0x1>
  a6:	01 96       	adiw	r24, 0x01	; 1
  a8:	90 93 01 01 	sts	0x0101, r25	; 0x800101 <_edata+0x1>
  ac:	80 93 00 01 	sts	0x0100, r24	; 0x800100 <_edata>
  b0:	81 3a       	cpi	r24, 0xA1	; 161
  b2:	97 40       	sbci	r25, 0x07	; 7
  b4:	40 f0       	brcs	.+16     	; 0xc6 <__vector_16+0x36>
  b6:	8b b1       	in	r24, 0x0b	; 11
  b8:	90 e2       	ldi	r25, 0x20	; 32
  ba:	89 27       	eor	r24, r25
  bc:	8b b9       	out	0x0b, r24	; 11
  be:	10 92 01 01 	sts	0x0101, r1	; 0x800101 <_edata+0x1>
  c2:	10 92 00 01 	sts	0x0100, r1	; 0x800100 <_edata>
  c6:	9f 91       	pop	r25
  c8:	8f 91       	pop	r24
  ca:	2f 91       	pop	r18
  cc:	1f 90       	pop	r1
  ce:	1f be       	out	0x3f, r1	; 63
  d0:	1f 90       	pop	r1
  d2:	18 95       	reti

000000d4 <__vector_default>:
  d4:	40 9a       	sbi	0x08, 0	; 8
  d6:	ff cf       	rjmp	.-2      	; 0xd6 <__vector_default+0x2>

000000d8 <main>:
  d8:	55 9a       	sbi	0x0a, 5	; 10
  da:	38 9a       	sbi	0x07, 0	; 7
  dc:	5d 9a       	sbi	0x0b, 5	; 11
  de:	80 91 6e 00 	lds	r24, 0x006E	; 0x80006e <__TEXT_REGION_LENGTH__+0x7e006e>
  e2:	81 60       	ori	r24, 0x01	; 1
  e4:	80 93 6e 00 	sts	0x006E, r24	; 0x80006e <__TEXT_REGION_LENGTH__+0x7e006e>
  e8:	16 bc       	out	0x26, r1	; 38
  ea:	85 b5       	in	r24, 0x25	; 37
  ec:	81 60       	ori	r24, 0x01	; 1
  ee:	85 bd       	out	0x25, r24	; 37
  f0:	78 94       	sei
  f2:	ff cf       	rjmp	.-2      	; 0xf2 <main+0x1a>

000000f4 <_exit>:
  f4:	f8 94       	cli

000000f6 <__stop_program>:
  f6:	ff cf       	rjmp	.-2      	; 0xf6 <__stop_program>

Thanks for your help.

Cheers,
Smokehead

SOLVED:

It seems like i accidentally changed some settings on the programmer which lead to an invalid ISP-frequency. After resetting this to 114 kHz it works again. Thank you for your help!

The main topic has been solved and this one has been solved too! Thank you guys!

Cheers,
Smokehead

It looks like,it should be ok to me.
The only other idea I have is to disassemble the .hex file (instead of the .elf), to make sure everything needed was actually copied.

You could make separate isrs for all the bad interrupt case, then at least you’d know which one was sending you into never-never land...

The issue with the ISRs is solved. I've seen that whatever CMake did pass to the compiler or which compiler it chose it didn't compile any interrupt vectors. After a manual call to the avr-gcc the code worked! It seems like CMake did something which shouldn't happen.

Now and for future projects i'll use simple Makefiles. CMake is good for other projects but i don't think it's worth the hassle for MCUs. You have to "hack" your way through it to make it running and compile without errors (regarding to the -rdynamic bug it has with avr-gcc).

Makefiles seem much more clear to me by now.

Thanks for your effort put into the answers.

Cheers,
Smokehead