| Author |
Message |
|
|
Posted: Aug 12, 2010 - 05:51 AM |
|


Joined: Jul 19, 2010
Posts: 19
|
|
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 |
|
|
| |
|
|
|
|
|
Posted: Aug 12, 2010 - 06:22 AM |
|

Joined: Nov 17, 2004
Posts: 13847
Location: Vancouver, BC
|
|
| 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.
|
| |
|
|
|
|
|
Posted: Aug 12, 2010 - 06:46 AM |
|

Joined: Aug 21, 2002
Posts: 895
Location: Austria
|
|
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
Code:
asm("mov r30, 0");
asm("mov r31, 0");
asm("ijmp");
But why don't you use
Code:
asm("jmp 0");
And why assembly at all?
Code:
typedef void (*fptr_t) (void);
fptr_t reset = (fptr_t) 0;
reset ();
|
_________________ /Martin.
|
| |
|
|
|
|
|
Posted: Aug 12, 2010 - 10:24 AM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
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) |
_________________
|
| |
|
|
|
|
|
Posted: Aug 13, 2010 - 01:17 AM |
|


Joined: Jun 06, 2010
Posts: 5
|
|
Was already discussed here.
void force_sw_reset(void)
{
cli();
CCP = (uint8_t)CCP_IOREG_gc;
RST.CTRL = (uint8_t)RST_SWRST_bm;
} |
_________________ MediaCodeSpeedEdit
|
| |
|
|
|
|
|
Posted: Dec 20, 2012 - 08:00 PM |
|

Joined: Dec 20, 2012
Posts: 1
|
|
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:
Code:
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)
}
|
|
|
| |
|
|
|
|
|
Posted: Dec 20, 2012 - 08:13 PM |
|


Joined: Jul 18, 2005
Posts: 62324
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| You should consider submitting this to AVR-libC perhaps. |
_________________
|
| |
|
|
|
|
|
Posted: Dec 20, 2012 - 09:51 PM |
|


Joined: Dec 21, 2006
Posts: 1483
Location: Saar-Lor-Lux
|
|
| You can avoid all the magic numbers:
Code:
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();
}
|
_________________ avr-gcc News • ABI • Options • 4.8-Windows • Inline Asm
|
| |
|
|
|
|
|