Sketch_Restart()

The code is better or at least more elaborate..

Lots more comments as I have read more detail about how the USART works in the 328 and the 168.

Clears registers :).

The corruption on the serial port is reduced a bit.

if you send 'ccccccccccccccccccccccccpr' as one string then the last character of the printed data is not properly
flushed through the usart when the reset happens, and the next time i send a 'p' a garbage character is printed in place of the newline.

I think the change that I made with most effect was to comment out UDR0 = 0 ; when I realised that it was a bi-directional register.

I have still not worked out how to drain the transmit path.. i almost think it mioght not be possible

But, it is getting closer I think, and I know some more, and having fun.

Now I have registers cleared, and most of the USART code right (i think) next is to review the other devices.

Regards,
Dave

#define GREEN_LED 7    // flickers fast
#define RED_LED 8      // slow flicker
#define YELLOW_LED 9   // more of a flash

void setup()
{
  Serial.begin(115200) ;
  pinMode(GREEN_LED, OUTPUT) ;
  pinMode(RED_LED, OUTPUT) ;
  pinMode(YELLOW_LED, OUTPUT) ;
  digitalWrite(GREEN_LED, 1) ;
  digitalWrite(RED_LED, 1) ;
  digitalWrite(YELLOW_LED, 1) ;
}
#ifdef simple_reset
void (*sketchRestaRt)(void) = 0x0000;
#else
#include <avr/io.h>
void sketchRestart(void)
{
  noInterrupts() ; // no interrupts while adjusting register values.
  
  // SET ALL DOCUMENTED REGISTERS TO THEIR POWER ON VALUES.
  
  MCUSR = 0  ; // no reset source
  WDTCSR = 0 ; // no watch dog resets
  EICRA = 0 ; // no external interrupts
  EIMSK = 0 ; // external interrupt mask cleared
  EIFR = 0 ; // external interrupt flag register - no pending interrupts
  PCICR = 0 ; // pin change interrupt control register
  PCIFR = 0 ; // pin change interrupt flag register
  PCMSK2 = 0 ; // pin change mask register 2
  PCMSK1 = 0 ; // pin change mask register 1
  PCMSK0 = 0 ; // pin change mask register 0
  
  // port B
  DDRB = 0 ;
  PORTB = 0 ;
  // PINB not defined.
  
  // port C
  DDRC = 0 ;
  PORTC = 0 ;
  // PINC not defined
  
  // port D
  DDRD = 0 ;
  PORTD = 0 ;
  // PIND not defined
  
  // timer prescalers (timer 0 and 1)
  GTCCR = 0 ;
  
  // Timer - 0
  TCCR0A = 0 ;
  TCCR0B = 0 ;
  TCNT0 = 0 ;
  OCR0A = 0 ;
  OCR0B = 0 ;
  TIFR0 = 0 ;
  TIMSK0 = 0 ;
  
  // Timer - 1
  TCCR1A = 0 ;
  TCCR1B = 0 ;
  TCCR1C = 0 ;
  TCNT1 = 0 ; // 16 bit
  OCR1A = 0 ; // 16 bit
  OCR1B = 0 ; // 16 bit
  ICR1 = 0 ; // 16 bit
  TIFR1 = 0 ;
  TIMSK1 = 0 ;
  
  // Timer - 2
  TCCR2A = 0 ;
  TCCR2B = 0 ;
  TCNT2 = 0 ;
  OCR2A = 0 ;
  OCR2B = 0 ;
  TIFR2 = 0 ;
  TIMSK2 = 0 ;
  
  // Assynchronous Status Register (timer 2 stuff)
  ASSR = 0 ;
  
  // SPI
  SPCR = 0 ;
  SPSR = 0 ;
  // SPDR undefined on restart
  
  // usart0
  if ( UCSR0B & (1<<RXEN0)) // if recieve enabled, drain the input buffers
  {
    unsigned char dummy;
    while ( UCSR0A & (1<<RXC0) ) dummy = UDR0; // while data present read from receive queue
  }
  
  if (UCSR0B & (1<<TXEN0)) // if transmit enabled
  {
// Try to to drain the transmit fifo; sometimes we do not succeed, we leave the data
// in the shift register and change the settings, leading to garbage on the line.
// This code is not sure to work, as it is not possible to reliably tell if
//   there is data in the trasmit shift register.
// The bit TXC0 is cleared after a transmit interrupt is sent, and can be cleared by code.
// If the TXC0 bit is clear, it could mean that there is data waiting to be sent or that there isn't.
// If the TXC0 bit is set, there is no data to send.
// The only reliable signal that there is more data to send is the UDRE0 bit which indicates that one and
// a part characters are waiting to be sent.
    if ((UCSR0A & (1<<UDRE0)) == 0) // there is a byte in the transmit fifo
    {
      while ((UCSR0A & (1<<UDRE0)) == 0) // while transmit queue is not empty
        ; // drain the transmit buffer
      while ((UCSR0A & (1<<TXC0)) == 0) // transmit of last character not yet complete
        ; // and wait for the transmit shift buffer to empty
    }
  }
    
// the UDR0 register supplys the data for both input and output side of UART comms..
// UDR0 = 0 ; // would be transmitting a null :( - leads to corruption because we are about to set the speed to 1M Bit/second.
// if I put this back the garbage is much more :)

  UCSR0A = 0 ; // RXC0 bit is clear due to read queue draining above
               // TXC0 bit is cleared by assinment to 0.
               // UDRE0 bit is read only, and 1 according the restart normal logic
               // UDRE0 bit should be 1 if transmit was enabled because of the transmit fifo draining above.
               // FE0 (frame error) is cleared by draining the read queue
               // DOR0 (data over run) is cleared by draining read queue
               // UPE0 (usart parity error) is cleared by draining the read queue
               // U2X0 (double baud rate) is set to zero by assignment of 0
               // MPCM0 (multi-processor communication mode) cleared by to zero by assignment of 0
               
  UCSR0B = 0 ; // no recieve interrupt, no TX complete interrupt, no UDR empty interrupt, reciever disabled, transmitter disabled,
               // ! 9bit chars, 9th bit in =0, 9th bit out=0
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00) ; // reset values are these bits; // 8 bit characters
                // UMSEL01, UMSEL00 - bits are 0, indiactes Asynchronous USART
                // UPM01, UPM00 - bits are 0, partity disabled.
                // USBS = 0, one stop bit
                // UCSZ01, UCSZ02 - bits are 1, implies 8 bits per character.
                // UCPOL0, bit is 0, asynchronous mode.
                
  UBRR0L = 0 ;  // baud rate is clock divided by 16
  UBRR0H = 0 ;  // 
  
  // two wire interface - more to check
  TWBR = 0 ;
  TWCR = 0 ;
  TWSR = 0 ;
  
  TWDR = 0xff ; // this write might not suceed. Is only writeable when TWI is not shifting a byte.
                // maybe should disable twi as early as possible, so more chance this instruction works.
                
  TWAR = ~(_BV(TWGCE)) ; // all bits except TWGCE set.
  TWAMR = 0 ;
  
  // analog comparator
  ADCSRB = 0 ;
  ACSR = 0 ;
  DIDR1 = 0 ;
  
  // ADC
  ADMUX = 0 ;
  ADCSRA = 0 ;
  ADCSRB = 0 ;
  DIDR0 = 0 ;
  
 // ADCL = 0 ;  // read only
 // ADCH = 0 ;  // read only
 
  // debugWire - not accessible outside debugWire
  // DWDR = 0 ;  // might be prohibited from setting this.
  
  
  // flash access control
  SPMCSR = 0 ;
  

  asm volatile ("clr r0") ;
  asm volatile ("clr r1") ;
  asm volatile ("movw r2, r0") ;
  asm volatile ("movw r4, r0") ;
  asm volatile ("movw r6, r0") ;
  asm volatile ("movw r8, r0") ;
  asm volatile ("movw r10, r0") ;
  asm volatile ("movw r12, r0") ;
  asm volatile ("movw r14, r0") ;
  asm volatile ("movw r16, r0") ;
  asm volatile ("movw r18, r0") ;
  asm volatile ("movw r20, r0") ;
  asm volatile ("movw r22, r0") ;
  asm volatile ("movw r24, r0") ;
  asm volatile ("movw r26, r0") ;
  asm volatile ("movw r28, r0") ;
  asm volatile ("movw r30, r0") ;
  interrupts() ;
  asm volatile ("jmp 0") ;
}
#endif

static int static_variable = 0 ;
static unsigned long counter = 0 ;

void loop()
{
  counter++ ;

  if ((counter % (16u*1024LU)) == 0UL) // every 16k thru the loop
  {
    digitalWrite(GREEN_LED, (counter % (32u*1024UL)) == 0UL) ; // togle green
    if ((counter % (32u*1024UL)) == 0UL) // every 32k times
    {
      digitalWrite(RED_LED, (counter % (64u*1024UL)) == 0UL) ; // toggle red
      if ((counter % (64u*1024UL)) == 0UL) // every 64k times
        digitalWrite(YELLOW_LED, (counter % (128u*1024UL)) == 0UL) ; // toggle yellow
    }
  }
  
  
  if(Serial.available()) // a character is waiting
  {
    switch(Serial.read())
    {
      case 'r':
        sketchRestart() ; // call the start of myself:)
        break ; // dosnt get here
        
      case 'c':
        static_variable ++ ; // count my 'c's
        break ;
        
      case 'p':
        Serial.print("static_variable = ") ; 
        Serial.println(static_variable) ; 
        Serial.print("loop counter = ") ; 
        Serial.println(counter) ; 
        break ;
    }
  }
}