ATmega328P ISR's

Hey there,
I was wondering if someone had any luck using ATmega328 interrupt vectors outside of src/main.c in PlatformIO projects? I’ve tried to write my interrupt routines in a separate file that I would keep in the lib/ folder but for a reason that I don’t grasp, interrupts never get called. Howewer, when written in main.c, it works perfectly. I did read something about library options in some json file but I’m new to this approach and didn’t quite understand. So I’m looking for some help here if people have had the same issue :slight_smile:
(by the way I program in plain C and I’m not using the Arduino framework)

I’ve had no problems using interrupts. In fact, I wrote a book about Arduino Interrupts.

One thing I noticed because I’m a fat fingered typist, if you spell the ISR name incorrectly, you won’t see a compiler warning or error, and your interrupts won’t fire!

If you are not using the Arduino framework, then global interrupts are disabled by default so unless you #include <avr/interrupt.h> and sei(); you also won’t get any interrupts!

The number of times I have debugged code that wasn’t working only to find I hadn’t enabled interrupts is “more than once”!

Failing these suggestions, do you have a minimal sketch that isn’t working you could post?

HTH

Cheers,
Norm.

Shot in the dark: Add

lib_archive = no

to the platformio.ini (docs) and retry. If that solves it, you need to create a library.json with that option. Linking interrupt code from lib/ has always been problematic.

Thanks for the tip, though I have already tried this trick and it doesn’t do much…

Hey Norman, thanks for your reply.

I am aware of this as I’m used to working with Atmel Studio usually. This is all mentioned in my code. I can show you the basic program I wrote but I’m not sure it’ll help…
I just set INT0 to be called on rising edges by configuring EIMSK and EICRA registers. The routine just turns the onboard LED on and off. Simple stuff.
Down below you’ll found my src/main.c, lib/isr/isr.c and platformio.ini files. I didn’t create a isr.h files as I’m pretty sure interrupt routines don’t need prototypes. Or do they in this case?

main.c

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

int main(void)
{	
	cli();
	DDRB = 0b00100000;
	EIMSK |= 1 << INT0;
	EICRA |= (1 << ISC01) | (1 << ISC00);
	sei();

    while (1);
}

isr.c

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

ISR(INT0_vect)
{
	PORTB ^= 1 << 5;
}

platformio.ini

[env:ATmega328P]
platform = atmelavr
board = ATmega328P

board_build.f_cpu = 16000000UL

upload_protocol = custom
upload_flags = -patmega328p
    -carduino
    -PCOM9

upload_command =  "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe" $UPLOAD_FLAGS -U flash:w:$SOURCE:i

lib_archive = no

So as I mentioned, INT0 never gets called using this method. However it does work when I write my interrupt routine below the main function, which makes sense.
I’m pretty surprised PlatformIO hasn’t tackled this issue or given a clear explanation about it as it seems pretty common to write ISR in a separate files. Maybe the solution is actually easy and I’m just missing something obvious.

Thanks for you help anyways!!

Do you know of any other way to link ISR code written outside of main.c?

So I just found a solution! I just moved the isr.c file in the src folder and it is now working! If anyone else has had trouble with this I guess that’s the way to go :slight_smile:

I’m puzzled to be honest. I’ve got a few self written interrupt based libraries that I use from, currently, a lib_extra_dir location and the test applications work fine.

I set up a test library (lib/interrupt) and placed your isr.c in there. It was never compiled—I used pio run -v to build it. Disassembling the elf file showed this:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 3e 00 	jmp	0x7c	; 0x7c <__bad_interrupt>  <<<<<<<<<< INT0

As you noticed, when you move the isr.c file into src/ it works fine and a verbose compilation shows that the file is being compiled. The disassembly shows this now:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 40 00 	jmp	0x80	; 0x80 <__vector_1>  <<<<<<<<<<<< INT0

However, if I add the following to platformio.ini:

lib_deps = interrupt

As my isr.c is in lib/interrupt, then it compiles the isr.c file just fine and a disassembly shows that the vector is being correctly setup:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__ctors_end>
   4:	0c 94 40 00 	jmp	0x80	; 0x80 <__vector_1>  <<<<<<<<<<<<<<<<<<< INT0

This would explain why my stuff has “just” worked! ;wink:

HTH

Cheers,
Norm.