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
(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
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.