Programmatic reset

Last post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a more elegant if not shorter way of resetting an XMega device

asm("mov r30, 0");
asm("ijmp");

It seems to work but doesn't reset any outputs, states etc. C code or assembly code either way.... I am sure there would be cases where this wouldn't do exactly what is needed.

Simon

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That will not reset the chip, only restart the program. The easiest way of doing a full reset of the AVR by software only is by letting the watchdog timer time out, but this is by no means a "short" way of doing it.You could also have circuitry that holds the reset low for the required amount of time that can be triggered by software.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This topic is discussed here on regular intervalls, always recommending the use of the watchdog, like Steve suggested.

@Simon: ijmp jumps to location R31:R30 - if you can rely on your compiler, that R31 is 0, your code is o.k., otherwise you need to change it to

asm("mov r30, 0");
asm("mov r31, 0"); 
asm("ijmp");

But why don't you use

asm("jmp 0");

And why assembly at all?

typedef void (*fptr_t) (void); 
fptr_t reset = (fptr_t) 0;
reset ();

/Martin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to note that as far as I know the Xmega now has a control bit that can be used to force an immediate IO reset so the watchdog is not required like on tiny/mega.

EDIT: In the "A manual" see 9.4.6 and/or search the PDF for "SWRST"

(surprise, surprise this info was found in the Chapter 9 "Reset system" - never underestimate the power of actually reading the datasheet)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Was already discussed here.

void force_sw_reset(void)
{
cli();

CCP = (uint8_t)CCP_IOREG_gc;
RST.CTRL = (uint8_t)RST_SWRST_bm;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Forgive the thread necromancy, this may be useful to other googlers:

The avr-gcc code above requires -Os, otherwise the write to the SWRST bit in RST.CTRL is too slow (outside the 4 cycle limit after CCP is written) and the reset doesn't work.

The following alternative works regardless of compiler optimization setting:

void force_reset() {
  // ATXMEGA software reset routine:
  asm volatile("cli\n\t"          // disable interrupts
              "ldi r24, 0xD8\n\t" // value to write to CCP
              "ldi r25, 0x01\n\t" // value to write to SWRST
              "ldi r30, 0x78\n\t"  // base address of RST peripheral
              "ldi r31, 0\n\t"
              "out __CCP__, r24\n\t"
              "std Z+1, r25\n\t"  // +1 is the offset of RST.CTRL
              ::); // no clobber list because we don't return

  // (doesn't return)
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should consider submitting this to AVR-libC perhaps.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can avoid all the magic numbers:

static __inline__ __attribute__((always_inline,noreturn))
void force_reset (void)
{
    __asm volatile ("cli"                 "\n\t" 
                    "out __CCP__, %[ccp]" "\n\t" 
                    "st  %a[rst], %[swrst]"
        :
        : [ccp]   "r" ((uint8_t) CCP_IOREG_gc),
          [swrst] "r" ((uint8_t) RST_SWRST_bm),
          [rst]   "e" (&RST.CTRL)
        : "memory");
    __builtin_unreachable();
}

avrfreaks does not support Opera. Profile inactive.