Если просто прыгнуть по нулевому адресу, то все переменные будут в неопределенном состоянии, что может быть чревато. Лучше перезагрузиться по watchdog, вот так:
#include <avr/wdt.h>
void cmd_reset()
{
// пишем прощальное письмо
return_status(CMD_RESET, ERR_NO);
// и совершаем самоубийство
// для этого заводим часовую бомбу
wdt_enable(WDTO_15MS);
// и ждем реинкарнации
while(1);
}
Но на многих процессорах таймер будет продолжать работать и после перезагрузки, и если не принять мер, то через 15 мс он опять все сбросит, и так бесконечно. Для этого затыкаем его до входа в main() вот так:
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
void wdt_init(void)
{
MCUSR = 0;
wdt_disable();
return;
}
Это все написано в WinAVR-20090313/doc/avr-libc/avr-libc-user-manual/FAQ.html
Но, как говорится, если ничего не получается, прочти инструкцию. Мне пришлось некоторое время потрахаться, пока не нашел решение. Может кому пригодится.