EmbDev.net

Forum: µC & Digital Electronics AVR bootloader reset specialties


von booti (Guest)


Rate this post
useful
not useful
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

von logarithmus (Guest)


Rate this post
useful
not useful
booti wrote:
> I can add details later (e.g. the bootloader), but don't want to get it

 No need  4 that.
 Just don't use it any more.

 Or change ur Bootloader code from MEGA8 to M328 and it should be fine.

von booti (Guest)


Rate this post
useful
not useful
logarithmus wrote:
> Just don't use it any more.

Brilliant, also could've jumped from the roof to fix even more problems 
;)


For the folks that's interested:
It's fixed now. The hardware reset will run through the bootloader, 
before continuing with the firmware. Any register modification done by 
the bootloader will survive, if starting the actual firmware is realized 
by a jump to address 0x0 initated by the bootloader. Watchdog timer 
reset does not seem to be an option in this scenario, but 
re-initialising the bootloader touched registers did the job :)

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.