Sketch load point?

Hi,

I want to implement a control-C handler that will abort long running commands, by using an interrupt handler of the UART.

I can use the RESET vector.. but that invokes the boot loader code so the arduino doesn't talk to me for a while afterwards..
Which is unfriendly and quite bad if it left motors running :(.

So the sketch startup seems the right point to aim for :slight_smile:

Can I invoke the sketch startup code from inside my sketch?

Dave

that will abort long running commands

What kind of "long running commands" are you trying to abort?

the ones I reset the board for now generates various diagnostic logs down the uart...
it just runs in a tight loop etc...

eventually the mainline should be implementing the positioning algorithm for the motors -
I am not sure exactly how at the moment: maybe a PID or a Kalman filter sort of thing...

part of the idea of the RESET approach is that it should bring the code back to power-on state. in case something has gone astray.

Dave

Bitlash uses setjmp()/longjmp() to handle fatal errors and ^C by restoring to a stable point. It might work for you.

More on the avr-gcc library page for setjmp():

http://www.gnu.org/savannah-checkouts/non-gnu/avr-libc/user-manual/group__setjmp.html

Best,

-br

http://entropymouse.com

I had a look in the bootloader code /hardware/arduino/bootloaders/atmega8/ATmegaBOOT.c and found

void (*app_start)(void) = 0x0000;

// timeing and other logic...
app_start() ;

Looks nice and simple - I will test in the morning and let you know how I go.

Dave

It seems to work...

The sketch :-
Blinks leds attached to digital pins 7, 8 and 9.
And counts of how often loop() is called.
And counts how often it is asked to 'a'dd.

You can ask it to 'p'rint - it will show the current values of the counts.
You can ask it to 'r'eset - when it starts over again by invoking app_start() ie 0x000

Send it a string of a's followed by a 'p' and see it count them ..
then send it an 'r'
and use 'p' to see the counters have been reset.
and you can not see a gap in the blinking leds :).

I can not think of a better way to test it.
Dave

// restart with varibles as per compiler; i hope, this is what the sketch is testing...
void (*app_start)(void) = 0x0000;

// define some leds to let me see it running
#define GREEN_LED 7
#define RED_LED 8
#define YELLOW_LED 9

void setup()
{
  Serial.begin(115200) ; // so print()s get done fast
  pinMode(GREEN_LED, OUTPUT) ;
  pinMode(RED_LED, OUTPUT) ;
  pinMode(YELLOW_LED, OUTPUT) ;
}

static int static_variable = 0 ;
union uu 
{
  long l ;
  char c[4] ;
} ;

static union uu u = {0L} ;

void loop()
{
  u.l++ ;

 // flash leds slow/fast enuf to see
  if (u.c[0] == 0 && (u.c[1]&0x1f)==0) // every 256*32 or 8k thru the loop
  {
    digitalWrite(GREEN_LED, (u.c[1] & 0x20) == 0) ; // togle green
    if (u.c[1]&0x20) // every 16k times
    {
      digitalWrite(RED_LED, (u.c[1] & 0x40)!=0) ; // toggle red
      if (u.c[1]&0x40) // every 32k times
        digitalWrite(YELLOW_LED, (u.c[2] & 0x1)!=0) ; // toggle yellow
    }
  }
  
  if(Serial.available()) // a character is waiting
  {
    switch(Serial.read())
    {
      case 'r': // reset
        (*app_start)() ; // call the start of myself:)
        break ; // dosnt get here

      case 'a':
        static_variable ++ ;
        break ;

      case 'p':
        Serial.print("static_variable = ") ; 
        Serial.println(static_variable) ; 
        Serial.print("loop counter.l = ") ; 
        Serial.println(u.l) ; 
        Serial.print("loop counter.c[0] = ") ;
        Serial.println(u.c[0]+0) ;
        Serial.print("loop counter.c[1] = ") ;
        Serial.println(u.c[1]+0) ;
        Serial.print(loop "counter.c[2] = ") ;
        Serial.println(u.c[2]+0) ;
        Serial.print("loop counter.c[3] = ") ;
        Serial.println(u.c[3]+0) ;
        break ;
    }
  }
}