Ik probeer al een tijdje een ATMEGA328 te resetten / rebooten via software/code maar krijg het niet voor elkaar.

Ik heb deze geprobeerd maar die werkt niet echt betrouwbaar, hij reset wel, maar er lijkt iets mis met de interrupts, de delay() routines werken niet meer na deze reset, dat zelfde effect kreeg ik door cli() te gebruiken, interrupts blokkeren :

void(* resetFunc) (void) = 0; //declare reset function @ address 0

Toen deze, reset via de watchdog.
In de setup() zet ik als eerste : wdt_disable();

Code loopt en doet zn ding, dan wil ik een reset / reboot via :

wdt_enable(WDTO_4S); 
while (true) {}         // wait for reset

Dit lijkt de processor zodanig op te hangen dat zelfs een harde reset (reset lijn laag trekken) niet werkt. Alleen de spanning er af- en op krijgt het weer aan de praat. Tijdens die "hang" status kan ik wel de flash programmeren (niet via een bootloader, direct met een MKII) , maar ook na het flashen komt de processor niet uit de "Hang" status, ook dan pas na power-off/on

Iemand een idee ?

Op dit moment los ik het op door de processor in een loop te laten hangen en dan de reset button te gebruiken maar meteen via software was mooier geweest.

Die jump naar 0x0000 'doet' op zich wel een reset in de zin van 'dat is doorgaans het start adres'. Echter, alle 'defaults' voor registers worden niet gezet (de hardware weet van niks). Dus als je ergens een timer interrupt actief hebt (ik noem maar wat), dan blijft die dat. Ik denk niet dat de gemiddelde compiler alle config registers zo gaat zetten als die na een reset zijn.

Dat watchdog verhaal is een ander paar mouwen. Dat is raar. Het was mijn eerste insteek. Als dat betekent dat de controller compleet hangt... dan heb je ook niks aan die watchdog. Conclusie: je hebt een rot exemplaar te pakken (is het wel een originele???). Of je doet iets verkeerd (duh...).
Er staat me heeeeeel vaag uit het verleden iets van bij dat je de watchdog eerst moet resetten voor je die enabled. Ik heb er geen context meer bij en ik *denk* dat dat op een AVR sloeg (teveel verschillende merken en types onder handen gehad inmiddels om het nog allemaal uit elkaar te kunnen houden). RTFD.
Verder weet ik niet wat het gedrag wordt als je de watchdog in software 'aan' zit, maar in de fuses is die 'disabled'. Het zou netjes zijn als de 'externe' reset dan wel gewoon zou blijven werken...

Als de watchdog volgens de fuse disabled is, dan kun je er toch nog wat mee, maar dan software geconfigureerd.
Dat is ff spitten om daar uit te komen.

1.
Dat een processor niet door een keiharde hardware reset komt is op zich wel heel vreemd. Dit klikt als een bug in de CPU dat niet alle peripherals intern gereset worden na een hardware reset.
Vaak staat zoiets wel in het datasheet wat na reset UNDEFINED is.
Dus hier nakijken welke periferie je gebruikt en dan 1 voor een elimineren welke het is die de boel opknoopt. Zie ook punt 2.

2.
Dat een watchdog of jump(0) het niet doet komt vaak voor en is een probleem in de initialisatie code die je zelf gemaakt hebt.
Heel vaak zie ik in code dat er vanuit gegaan wordt dat registers de default waarde bevatten. Daar moet je dus niet vanuit gaan en alle peripherals clean initialiseren zodat er geen spontane interrupts kunnen ontstaan en andere ongein.
Kortom datasheet opzoeken en alle belangrijke bits in de juiste volgorde aan/uit-zetten, vectoren en variable van IRQs eerst definieren voordat je de IRQ EN doet. Dat lost in 99% van alle gevallen de problemen op.

Als je de harde reset gefixed hebt (punt 1) zal dit probleem waarschijnlijk ook opgelost zijn.

@EricP : Klopt volgens mij dat er wat met de watchdog aan de hand is. Er hangt me ook wat van bij dat je de WDT als eerste moet disablen/resetten in de reset handler of zo. Dus ook hier in het datasheet kijken hoe dat ook alweer zat.

Is het niet eenvoudiger als een IO pin de reset pin naar gnd trekt?

Dat werkt niet betrouwbaar, je krijgt dan meestal een te korte reset puls omdat je niet weet wanneer de output pin in tristate gezet wordt.
Kost ook een extra pin + weerstand extra.

Verder heb je nog steeds het probleem wat Bram beschrijft: dat een harde reset het dan niet altijd doet.

En het is, naar mijn mening, een "ransige" oplossing omdat het een lapmiddel is voor een software probleem.

komt vaak voor en is een probleem in de initialisatie code die je zelf gemaakt hebt

Ik ben dat niet helemaal met je eens. Maar goed... met goede init code kun je wel heel veel afvangen. Alleen... die wordt in deze dus wel door een compiler voor je verzonnen...

Even wachten op Bram met hoe de fuses staan. Ik kan me ook zomaar voorstellen dat het C-sausje over de assembly het nodige voor je oplost. Dat zal de compiler documentatie duidelijk moeten maken - en anders de source van die functie.

Op maandag 9 maart 2026 16:24:14 schreef henri62:
Dat werkt niet betrouwbaar, je krijgt dan meestal een te korte reset puls omdat je niet weet wanneer de output pin in tristate gezet wordt.
Kost ook een extra pin + weerstand extra.

Verder heb je nog steeds het probleem wat Bram beschrijft: dat een harde reset het dan niet altijd doet.

En het is, naar mijn mening, een "ransige" oplossing omdat het een lapmiddel is voor een software probleem.

Als het goed is zit er al een 10k van Reset naar VCC.

Is een reset in software dan niet ranzig? Dit doen is een ander probleem maskeren. Maar lost dat probleem niet op. Een WDT die overloopt is er om onbedoeld hangen te voorkomen. Maar waarom zou je die zelf uitlokken? Het probleem aanpakken is een stuk doeltreffender.

Mocht het een normaal gebruikte techniek zijn, dan was daar ongetwijfeld code voor te vinden en was er meer dan waarschijnlijk wel een standaard routine voor. Niet dus.

Als het goed is zit er al een 10k van Reset naar VCC

Daar wordt die puls niet langer van hoor...

Is een reset in software dan niet ranzig?

Wat is daar ranzig aan?

Dit doen is een ander probleem maskeren.

Welk probleem doel je op?

Het probleem aanpakken is een stuk doeltreffender.

Nog een keer: welk probleem dan??

Overigens... ik heb - over 'ranzig' gesproken - op die manier ooit een 'bootloader' constructie met een 8051 gemaakt.
Het ding boot vanuit ROM. Dan kan het vanuit flash z'n firmware ophalen en die wordt naar RAM gecopieerd. Dan zet het een paar trucen in de adressering op scherp en reboot zichzelf - en draait dan uit RAM (maar wel 'program memory' natuurlijk). De ellende zat ingegoten, dit was de manier om het van firmware te voorzien. Tegenwoordig is dat allemaal wat makkelijker geregeld, maar toen was dat er gewoon niet.
Ranzig? Ja, best wel. Werkte het? Ja, het draait nog steeds (tot mijn eigen verbazing).

[Bericht gewijzigd door EricP op (46%)]

Op maandag 9 maart 2026 17:00:15 schreef buckfast_beekeeper:
Mocht het een normaal gebruikte techniek zijn, dan was daar ongetwijfeld code voor te vinden en was er meer dan waarschijnlijk wel een standaard routine voor. Niet dus.

Die is er wel hoor, en is ook gedocumenteerd 20 jaar geleden door Atmel:
https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/Applica…

Nu zou je het aan AI kunnen vragen:
https://claude.ai/share/3378e4fd-3043-4bd0-8d1e-0ab90fb5cf77

Maar wat TS kan hebben is dat ie per ongeluk de watchdog in interrupt mode heeft aangezet, en de interrupt halfhartig gebeurt door oude (arduino?) code.

Dat ophangen doet hij alleen als ik die watchdog-code uitvoer / watchdog aanzet, dus misschien moet ik inderdaad eerst nog wat anders initialiseren.

Gebruik ik die 2 regels watchdog niet kan ik m altijd prima met een drukknopje op de reset lijn resetten.

Ik kan me voorstellen (maar nu speculeer ik) dat die pin op dat moment niet als reset geschakeld staat (hij kan ook als PIO gebruikt worden).
Wel apart dat zolang hij "hangt" ik m wel kan flashen.

Mocht het een normaal gebruikte techniek zijn, dan was daar ongetwijfeld code voor te vinden en was er meer dan waarschijnlijk wel een standaard routine voor. Niet dus.

De Watchdog truuk (tijd zetten, enable, en while(){} , ) komt veelvuldig voor als "oplossing" in de diverse fora.

@Ericp , zo staan mijn fuses.

Dus als je ergens een timer interrupt actief hebt (ik noem maar wat), dan blijft die dat. Ik denk niet dat de gemiddelde compiler alle config registers zo gaat zetten als die na een reset zijn.

Dat had ik gemerkt, die begint meteen weer te lopen (timer interrupt).

Maar wat TS kan hebben is dat ie per ongeluk de watchdog in interrupt mode heeft aangezet, en de interrupt halfhartig gebeurt door oude (arduino?) code.

Dat "hangen" is ook maar zoals het op mij overkomt, ik kan nl wel flashen, en misschien is hij wel iets van code aan t uitvoeren, ik kan er niet in kijken. Hij doet in ieder geval niet wat hij moet doen.

Overigens heb ik meerdere processors geprobeerd (Farnell) , doen allemaal t zelfde.

[Bericht gewijzigd door bprosman op (17%)]

Gebruik je interrupts in je programmma?

Zo ja:
Stap 1: zet dat allemaal eens uit/disable dat even, stop in je main() een stukje code wat een pinnetje togggled (zonder delays en functie rommel). Meet met de scoop of dat loopt zoals het hoort.

Stap 2: Activeer de hardware watchdog voordat je het toggle routinetje in gaat.
Als de watchdog de processor reset zul je toch eerst een burst zien op dat I/O pinnetje voordat de watchdog ingrijpt (orde grootte honderden ms tot sec net hoelang de WD ingesteld staat).

Stap 3: Na reset door de watchdog moet je elke reset loop effe een toggle burst zien, zo nee (waar ik niet niet geloof) is er iets grondig mis met je CPU.

Als dit wel werkt naar behoren dan 1 voor een je stukjes code toevoegen (voor de toggle loop) die iets met periferie in de chip doet, tot de boel zich opknoopt.

Dan heb je de "schuldige" gevonden.

Blijft de µC niet ergens hangen in de Startup / Init (compiler) routine na de WD-reset?

Dat denk ik dus ook, door systematische eliminatie kom je daar vrij snel achter.

Op maandag 9 maart 2026 17:20:05 schreef EricP:
[...]Daar wordt die puls niet langer van hoor...[...]Wat is daar ranzig aan?[...]Welk probleem doel je op?[...]Nog een keer: welk probleem dan??

Overigens... ik heb - over 'ranzig' gesproken - op die manier ooit een 'bootloader' constructie met een 8051 gemaakt.
Het ding boot vanuit ROM. Dan kan het vanuit flash z'n firmware ophalen en die wordt naar RAM gecopieerd. Dan zet het een paar trucen in de adressering op scherp en reboot zichzelf - en draait dan uit RAM (maar wel 'program memory' natuurlijk). De ellende zat ingegoten, dit was de manier om het van firmware te voorzien. Tegenwoordig is dat allemaal wat makkelijker geregeld, maar toen was dat er gewoon niet.
Ranzig? Ja, best wel. Werkte het? Ja, het draait nog steeds (tot mijn eigen verbazing).

Waarom ga je beslissen nu wil ik wel eens een software reset uitvoeren. Daar moet je toch een reden voor hebben. WDT bij een onvoorziene fout kan je nog plaatsen. Maar waarom zou je dat doen bij een µC die zijn programma deftig uitvoert. Dat er even geen input is op een ingang, is geen reden. Dat moet je opvangen. Ik zie echt geen reden waarom je een reset zou in programmeren. Kom maar eens met plausibele situaties waar je dat wel zou doen omdat je het niet op een andere manier kan opvangen.

De H fuses staan op 0xD1. Dus de processor gebruikt de bootloader vector tabel na een hardware reset. Dus een hardware reset gaat hier naar address 0x7800, niet naar 0x0000.

Het gebruik van een boootloader heeft een aantal consequenties. De bootloader doet meestal hardware initialisatie voordat de bootloader besluit om naar de app code te springen. Normaal doet de app zijn eigen hardware-initialisatie maar het kan zomaar gebeuren dat je een paar dingen vergeet omdat die normaal al in de bootloader zijn gedaan. Maar bij een jump(0) gebeurt dat niet.

En voordat je een Jump(0) doet moet je ook eerst de interrupts uitzetten, want anders heb je kans dat de interrupt al afgaat als je nog bezig bent met hardware initialisatie en stack pointer goedzetten.

En bij een normale hardware reset staan veel I/O registers in een gedefinieerde reset toestand. Als de init-code dan alleen die bits zet die anders moeten, dan kan het wel eens goed misgaan na een jump(0), omdat je mogelijk met een heel andere beginwaarde start.

Laatste 2 alineaas: Juist, precies wat ik bedoel.

En dan ook niet vergeten de WDT uit te zetten als jij net je jump-naar-start doet om te voorkomen dat die er ook nog ff tussendoor komt (alhoewel dat zo op het eerste gezicht geen kwaad kan...).

Overigens zou je ook die registers goed kunnen zetten na het disablen van de interrupts (en ook nog in de juiste volgorde; eerst een counter 'uit' zetten, dan op 0 zetten!) voor je die jump doet. Enige 'nadeel' daarvan is dat je de 'hard reset' default heb bij een power-on en je eigen 'default' als je zelf reboot. Je loopt het risico dat, hoe goed je je best ook doet, die niet helemaal hetzelfde zijn. :(

Maar al met al... het blijft raar dat het ding niet gewoon gereset wordt door de WDT. Als die goed staat ingesteld, dan zou je verwachten dat dat gewoon werkt. Anders is die WDT tenslotte vrij zinloos...
[offtopic]Ik kwam neuzend op internet nog een vieze tegen: met een I/O pin de voeding onderuit trekken (bedoeld, ingrijpen op de feedback) en zorgen dat de BOD een reset forceert. Zodra die reset actief wordt, wordt de pin Hi Z en komt de voeding weer op. Het schijnt te werken... Maar wel erg vies.

[Bericht gewijzigd door EricP op (23%)]

Op maandag 9 maart 2026 20:06:56 schreef buckfast_beekeeper:
Ik zie echt geen reden waarom je een reset zou in programmeren. Kom maar eens met plausibele situaties waar je dat wel zou doen omdat je het niet op een andere manier kan opvangen.

Omdat je een update van je firmware geinstalleerd hebt en die wilt activeren.

En ja, dat kan in een Atmega328p. Daar heb ik ooit betaald voor gekregen, dus daar is behoefte aan.

Op maandag 9 maart 2026 20:28:12 schreef deKees:
De H fuses staan op 0xD1. Dus de processor gebruikt de bootloader vector tabel na een hardware reset. Dus een hardware reset gaat hier naar address 0x7800, niet naar 0x0000.

@deKees
De fuse is een "1" , ofwel niet geprogrammeerd. (Ben ik de enige die gek word van die omgekeerde logica?),
Bit 0 (BOOTRST): Boot Reset vector Enabled (Default 1, unprogrammed - starts at 0x0000)

@Buckfast_beekeeper

Waarom ga je beslissen nu wil ik wel eens een software reset uitvoeren. Daar moet je toch een reden voor hebben. WDT bij een onvoorziene fout kan je nog plaatsen.

Je hebt hier wel een punt. Dit gebeurt nadat er nieuwe waarden naar de EEProm zijn geschreven. Soort van , "Pas een config file aan -> Reboot" , maar ik moet daar inderdaad wel iets eleganters voor kunnen bedenken.
@Henri62, ik ga eens stuk voor stuk uitvissen waarom die WDT niet werkt alleen denk ik dat ik t programma ook wel kan aanpassen dat ik het niet nodig heb. Lost natuurlijk het "probleem" niet op.

Dat EEPROM gebeuren... het hangt er vanaf hoe ingrijpend dat in de software is. En ja, dat kun je vast wel anders oplossen. Maar op zich - als de toepassing zich er voor leent - kan een reboot best wel eens een elegante oplossing zijn (bijvoorbeeld als er op basis van die EEPROM allerlei registers worden ingesteld... Zeker als het 3rd party software is, dan is het best een uitdaging om dat allemaal uit te vlooien).

Je zou eens moeten uitzoeken wat er met dat watchdog gebeuren vanuit de compiler nou eigenlijk gedaan wordt.

Ik kan met die fuses ook nooit zoveel. Het is altijd pielen :) Ik houd het altijd op positive logic en pas op het moment dat het bitje daadwerkelijk gedaan moet worden draai ik het om - daar kom ik aardig mee weg. Gelukkig zijn er ook wel de nodige programming tools die het gewoon inzichtelijk maken.

Ik ben (moet ik bekennen) te lui geweest om te kijken of je watchdog enable aan staat (ok, die moet dus aan, dus een 1 in positive logic. En nou moeten we naar de fuse en die moet dan dus een 0 zijn).
Ok, die zou (als ik het goed gelezen heb) in de high byte moeten zitten. Die heb jij op 0xD1 staan. Het is de laatste bit van er eerste nibble. 0x0D is iets van 13, zijnde 1101.
Als bovenstaande klopt, dan lijkt het erop dat de watchdog niet enabled is.
Dan is de response afhankelijk van de WDE en WDIE bits in WDTCSR. WDE komt weer indirect uit MCUSR. Dat is een wat ingewikkelder stuk.
Conslusie: regel het met de fuses en je probleem is (wederom: als ik hierboven goed geredeneerd heb) waarschijnlijk opgelost.

Het verklaart niet waarom een 'harde' reset niet werkt. Dat is en blijft raar.

[Bericht gewijzigd door EricP op (15%)]

ik vind een bewuste reset van je micro,na een reset defaults of iets dergelijks niks smerigs aan. Je brengt zo alles weer in een gedefinieerde staat. Je kan 10000 truken en usecases gaan maken om alles zo perfect af te vangen, maar als je voor een specifieke actie die niet regelmatig voorkomt ze allemaal met een deftige reset kan vervangen niks mis mee.

door dit met de watchdog te doen is hoe hij het ook altijd deden en nee niet in hobby projectjes.
Je moet alleen even goed kijken hoe je het watchdog register schrijft.
Je moet eerst in het watchdog register schrijven dat je de watchdog config wil wijzigen met de WDCE bit en dan moet je binnen 4 clockcycles de change schrijven meen ik.


monitor void EnableWatchdog(void) {
	UINT8 wdtcr= WDTCR |  WDE;
	__watchdog_reset();
	//enable watchdog change
	WDTCR = (WDCE | WDE);
	// enable
	WDTCR = wdtcr;
}

by default staan je fuses goed, daar hoef je niks aan te veranderen volgens mij, dat regel je gewoon lekker in je firmware zelf

by default staan je fuses goed, daar hoef je niks aan te veranderen volgens mij, dat regel je gewoon lekker in je firmware zelf

Volgens mij dus net niet (daar staat me wat van bij, meestal is dat omdat ik er een keer mee bezig ben geweest)... Maar goed, dat is niet heel spannend om uit te zoeken.
[edit]Een screendump wil hier ff niet (geen editor opgetuigd op deze machine), in de datasheet staat voor WDTON als default '1' (unprogrammed). Dus ik vrees dat die 'uit' staat...
Bij de tabel voor de watchdogtimer wordt vermeld dat die '0' moet zijn en in de footnote dat dat 'programmed' moet zijn. Op basis daarvan denk ik dat ik gelijk heb... (maar, net als Bram ben ik een enkele keer ook wel eens het bos in gegaan met die 'negative logic'.[/edit]

En voor die 4 cycles: daar staat ook wat van in de datasheet meen ik. Vandaar dat men meestal de interrupts ff uit zet - staat niet in de code van Stijnos.

Ik kan me niet herinneren dat we ooit de fuse eerst goed moesten hebben staan om een watchdog werkend te hebben. Maar goed

Wat ik vergeten te vermelden is dat mijn functie een monitor functie is en dus niet door interrupts onderbroken wordt. Goed punt EricP, dat zag je zo niet terug idd

Ik kan me niet herinneren dat we ooit de fuse eerst goed moesten hebben staan om een watchdog werkend te hebben. Maar goed

Ik weet ook niet of het bij alle AVRs zo is. Bij de wat oudere 2313 bijvoorbeeld past de datasheet beter bij jouw beschrijving (firmware control). Bij de 328 heeft men functionaliteit toegevoegd (of dat handig is, is een andere discussie, maar goed...) en kun je dus als het ding niet 'forced on' staat bepalen wat de response moet zijn. Dat moet dan wel 'goed' staan om het verwachte resultaat te krijgen... 'Default' lukt dat misschien ook nog. En nou is er ergens iemand zo handig geweest om code te baseren op een ander model waar dit bits niet in zitten en niet netjes een read-modify-write te doen op de byte en zelf een waarde in elkaar klust (immers... die bits worden daar toch niet gebruikt!). En dan ga je met diezelfde code (die daar prima werkt) op dit ding dus nat.

Persoonlijk denk ik dat je het simpel moet houden - en dat het zou moeten werken zoals Stijnos het beschrijft. Maar iemand heeft het anders verzonnen...

Wat ik vergeten te vermelden is dat mijn functie een monitor functie is en dus niet door interrupts onderbroken wordt. Goed punt EricP, dat zag je zo niet terug idd

'De compiler' (of eigenlijk: de runtime lib) zal het wel 'netjes' doen. Maar als er 'gez**k' is, dan is het wel altijd een aardige om te controleren - het zal niet de eerste keer zijn dat ik in die hoek over een rotje struikel. Als je geen interrupts gebruikt, dan speelt het hele verhaal natuurlijk niet (en kun je de shortcut nemen).

Voorlopig heeft Bram wat huiswerk :)

@deKees
De fuse is een "1" , ofwel niet geprogrammeerd. (Ben ik de enige die gek word van die omgekeerde logica?),
Bit 0 (BOOTRST): Boot Reset vector Enabled (Default 1, unprogrammed - starts at 0x0000)

Dat klopt, Dat had ik dus even verkeerd gezien.
En dat is inderdaad verwarrend. Het blijft opletten. 8)7