Hi,
my (for here stripped down, but probably not minimalist) program
executes a pin change interrupt handler after hitting a button. Its
handler does toggle an LED and also starts a timer. The timer finally
overflows to toggle the LED back. Pretty easy. Unbounced, but hey, just
demoing.
Additionally, there is some UART output in the beginning (just to have
it there for debugging purpose later on), and that's basically it. The
program, when flashed to an ATmega 328p works as expected. See the issue
below the code section.
The format will most probably be terrible, but here it is:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "uart.h" //fleury's
#include "main.h"
#define UART_BAUD_RATE 38400
#define RELAIS_TIME_MS 500
volatile uint16_t cnt_switch_ms;
char uart_getc_wait();
void io_init(void);
unsigned int c;
int main(void)
{
cli();
uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));
io_init();
sei();
uart_puts( "Basic UART node1\r\n" );
while(1)
{
}
}
void io_init()
{
cli();
//PD4 as input and triggers pin change ISR
DDRD &= ~(1 << PIND4); // PD4 as input
PCICR |= (1 << PCIE2); // enable interrupt
PCMSK2 |= (1 << PCINT20); // set to trigger an interrupt on state
change
// PB7 as output (red LED)
DDRB |= (1 << PIND7); // PB7 as output
// timer1 config
// Set the Timer1 Mode to CTC
TCCR1B |= (1 << WGM12);
//OCRn = [ (clock_speed / Prescaler_value) *
Desired_time_in_Seconds ] - 1
//OCR1 = [ (8000000 / 64 ) * 0.001] - 1 = 125-1
= 0x7c (timer IRQ each 1ms)
OCR1A = 0x007c;
TIMSK1 |= (1 << OCIE1A); //Set the ISR COMPA vect
sei();
}
//PD4 pin change interrupt handler
ISR(PCINT2_vect) // remark: higher prio than timer1 ISR
{
cli();
PORTB ^= (1 << PINB7); //switch relais
TCCR1B |= ((1 << CS11) | (1 << CS10)); //start timer1
sei();
} // end PCINT2_vect
// timer1 overflow interrupt handler
ISR (TIMER1_COMPA_vect)
{
//executed every 1ms
cnt_switch_ms += 1;
//do stuff when timer is over
if (cnt_switch_ms >= RELAIS_TIME_MS ) {
PORTB ^= (1 << PINB7); // toggle the LED back
TCCR1B &= ~((1 << CS11) | (1 << CS10)); // stop the timer
cnt_switch_ms = 0; // reset its counters
TCNT1 = 0;
uart_puts( "t" ); // even notify via UART for checking the
ISR was exec'd
}
} // end TIMER1_COMPA_vect
1 When flashed to the AVR via ISP programmer, this is all working as
expected (LED flashes on triggering the pin, LED is toggled back after
timer is overflowed, "t" is printed on the serial console).
2 AVR was reset via hardware (button on reset pin): still works as in 1.
3 When this program was not ISP-programmer flashed, but by a bootloader
(CAN here): still works as expected.
4 When flashed via this bootloader, and the mentioned reset button was
used at least once - the LED will still change its status by toggling
the button connected to PD4 (i.e. pin change ISR is working fine).
However, the timer ISR is not working at all it seems (toggling the LED
back is missing as well as the uart's "t" on console).
5 Same behavior as in 3 for powering down, short circuiting and
re-powering the board.
--> any obvious pitfalls here one can think of? In the case of using the
bootloader, at least some ISR's are suffering from not being ..
executed?!
Of course, after getting the code running with the bootloader, and
having it disfunctional after resetting the AVR, one can still re-flash
it via the bootloader and it will run without problems. Until the next
reset/powerdown.
Is there something very obvious coming to your minds, what could be the
problem here? Something, an unexperienced hobbyist like me could have
easily overlooked? Standard issues not tackled, because not known?
I can add details later (e.g. the bootloader), but don't want to get it
too long in the opening thread.
Regards
Christian