Watchdog issue - Assembler code

Hi guys

I am looking to assembly code a watchdog timer with interrupt to save energy.
I do manage to set the :

  • Vector table
  • Timer prescale in register (WDTCR) 32ms
  • Enable the time out interrupt in register (WDTCR)
  • Watchdog Reset Flag in register (MCUSR)
  • Sleep mode in register (MCUCR)
  • Set global interrupt and put in sleep mode ..

But after, I am not able to get it out of the sleep mode ( in fact yes but after 2 098,94 ms )
I have spend a lot of hours read the AVR doc without being able to find the issue by myself.
Would someone would be kind enought to help me.

Please post the code, using code tags.

This excellent tutorial has a section on the AVR WDT: https://gammon.com.au/power

; Author : Online67
;



; REGISTER USAGE
;               | sbr/cbr            | sbrs/sbrc       | Comment
; R16    (0x80) |                    |                 |Variable Temporary Register file 
; R17    (0x80) |                    |                 |Variable Incrementation Watchdog 
; R22[6] (0x40) |                    |                 |
; R22[5] (0x20) |                    |                 |
; R22[4] (0x10) |                    |                 |
; R22[3] (0x08) |                    |                 |
; R22[2] (0x04) |                    |                 |
; R22[1] (0x02) |                    |                 |
; R22[0] (0x01) | MILLISEC           | _millisec       | End of mS - 1 indicates end of mS

.org 0

rjmp setup                     ; Reset - Address 0
reti                          ; INT0 (address 01)
reti                          ; Pin Change Interrupt Request 0        
reti                          ; Timer/Counter1 Compare Match A
reti                          ; Timer/Counter1 Overflow
reti                          ; Timer/Counter0 Overflow
reti                          ; EEPROM Ready
reti                          ; Analog Comparator
reti                          ; ADC Conversion Complete
reti                          ; Timer/Counter1 Compare Match B
reti				          ; Timer/Counter0 Compare Match A
reti                          ; Timer/Counter0 Compare Match B
rjmp Compteurwatchdog         ; Watchdog Time-out
reti                          ; USI START
reti                          ; USI Overflow


Compteurwatchdog:
cp R17,R18						; Compare registers R30 and R0
breq Full_pulse_1				; si compare = vrai jump to signal court 
rjmp Watchdog_routine			; jump a signal court 

;===================================================================================================================================================================================================
Setup:
; Define directions for port pins
ldi r16,(1<<PB0)|(1<<PB1)|(1<<PB2)|(0<<PB3)|(1<<PB4)|(0<<PB5) ; ports set to output   0001 0111 (Pas besoin de port3 et port5 en outpout (non utilisé))
out DDRB,R16   ; Set OUTput ports.
;===================================================================================================================================================================================================
main:
ldi R17,0x13			; Valeur du nombre de relative JUMP dans R17 (13 hexa = 19 decimal * 32ms = 0.608ms de watchdog)
ldi r18,0x00
;===================================================================================================================================================================================================
Watchdog_routine:
cli							; Turn off global interruptcli
ldi R16,(1<<WDCE)|(1<<WDE)  ; Autorisation Changement setting Watchdog (obligatoirement 1 dans WDCE et WDE dans la emme commande)
out WDTCR,R16				; set Watch Dog Timer Controler Register avec valeur de R16


ldi R16,(1<<WDP0)|(0<<WDP1)|(0<<WDP2)|(0<<WDP3)|(1<<WDIE)  ; Remettre le WDE a 0 pour interrupte (a cause de la sequense de securite contre le changement de valeur du Watchdog  
															; clock counter prescaler setting en  Clk/4. 4kHz. soit 32ms a 5V Vcc
out WDTCR,R16												; set Watch Dog Timer Controler Register avec valeur de R16

ldi R16,(0<<WDRF)|(0<<PORF)								; Enable Watchdog Reset Flag
out MCUSR,R16											; in register MCUSR

ldi R16,(1<<SE)								; Enable sleep mode in MCUCR
out MCUCR,R16	

sei					; set Global Interrupt Enable in register I

wdr					;reset watchdog timer

sleep ; tout en veille 

;===================================================================================================================================================================================================

Any particular reason for wanting to use assembler ?

Yea .. I need to process in assembler to be fast enough when running the main action ..
I have to be precise at usec in the timing.

You don't need assembler language to program the watchdog, and that cannot possibly be a critically timed part of the project. Get the watchdog part running with a higher level language, if you can't do it with the assembler.

In any case, the code you posted is not complete.

here you are touching the point ..
After I have my main action prog but nothing more related to watchdog.
CAn you indicate me what is missing to create the interrupt ?

This makes no sense at all:

Compteurwatchdog:
cp R17,R18						; Compare registers R30 and R0
breq Full_pulse_1				; si compare = vrai jump to signal court 
rjmp Watchdog_routine			; jump a signal court 

If all you need to do with the watchdog is to wake or reset the processor, "reti" is the only instruction required. You don't even need an interrupt routine.

I understand your comments "this make no sense at all". :slight_smile:
The interrupt routine would be used to decrease a counter that I can adjust the watchdog time precisely by step of 0.32ms and running for example 20 times the watchdog ..

The interrupt routine Have not been worked properly yet but would more be something like

Compteurwatchdog:
dec R17	                        ; decremente 1 a R17
cp R17,R18						; Compare registers R17 and R18
breq Full_pulse_1				; si compare = vrai jump to signal court 
rjmp Watchdog_routine			; jump a signal court 

And now the code with the missing info.. I do not share the main part as it as no effect to the watchdog

; Author : Online
;


; Replace with your application code
; REGISTER USAGE
;               | sbr/cbr            | sbrs/sbrc       | Comment
; R16    (0x80) |                    |                 |Variable Temporary Register file 
; R17    (0x80) |                    |                 |Variable Incrementation Watchdog 
; R22[6] (0x40) |                    |                 |
; R22[5] (0x20) |                    |                 |
; R22[4] (0x10) |                    |                 |
; R22[3] (0x08) |                    |                 |
; R22[2] (0x04) |                    |                 |
; R22[1] (0x02) |                    |                 |
; R22[0] (0x01) | MILLISEC           | _millisec       | End of mS - 1 indicates end of mS

.org 0

rjmp setup                     ; Reset - Address 0
reti                          ; INT0 (address 01)
reti                          ; Pin Change Interrupt Request 0        
reti                          ; Timer/Counter1 Compare Match A
reti                          ; Timer/Counter1 Overflow
reti                          ; Timer/Counter0 Overflow
reti                          ; EEPROM Ready
reti                          ; Analog Comparator
reti                          ; ADC Conversion Complete
reti                          ; Timer/Counter1 Compare Match B
reti				          ; Timer/Counter0 Compare Match A
reti                          ; Timer/Counter0 Compare Match B
rjmp Compteurwatchdog         ; Watchdog Time-out
reti                          ; USI START
reti                          ; USI Overflow


Compteurwatchdog:
dec R17							; decremente 1 a R30
cp R17,R18						; Compare registers R30 and R0
breq Full_pulse_1				; si compare = vrai jump to signal court 
rjmp Watchdog_routine			; jump a signal court 

;===================================================================================================================================================================================================
Setup:
; Define directions for port pins
ldi r16,(1<<PB0)|(1<<PB1)|(1<<PB2)|(0<<PB3)|(1<<PB4)|(0<<PB5) ; ports set to output   0001 0111 (Pas besoin de port3 et port5 en outpout (non utilisé))
out DDRB,R16   ; Set OUTput ports.
;===================================================================================================================================================================================================
main:
ldi R17,0x13			; Valeur du nombre de relative JUMP dans R17 (13 hexa = 19 decimal * 32ms = 0.608ms de watchdog)
ldi r18,0x00
;===================================================================================================================================================================================================
Watchdog_routine:
cli							; Turn off global interruptcli
ldi R16,(1<<WDCE)|(1<<WDE)  ; Autorisation Changement setting Watchdog (obligatoirement 1 dans WDCE et WDE dans la emme commande)
out WDTCR,R16				; set Watch Dog Timer Controler Register avec valeur de R16


ldi R16,(1<<WDP0)|(0<<WDP1)|(0<<WDP2)|(0<<WDP3)|(1<<WDIE)  ; Remettre le WDE a 0 pour interrupte (a cause de la sequense de securite contre le changement de valeur du Watchdog  
															; clock counter prescaler setting en  Clk/4. 4kHz. soit 32ms a 5V Vcc
out WDTCR,R16												; set Watch Dog Timer Controler Register avec valeur de R16

ldi R16,(0<<WDRF)|(0<<PORF)								; Enable Watchdog Reset Flag
out MCUSR,R16											; in register MCUSR

ldi R16,(1<<SE)								; Enable sleep mode in MCUCR
out MCUCR,R16	

sei					; set Global Interrupt Enable in register I

wdr					;reset watchdog timer

sleep ; tout en veille 

;===================================================================================================================================================================================================


Full_pulse_1:

--- Here is my main code ----

rcall main			; recall function main

Good luck with your project.

you flatter the watchdog timer, it has very low accuracy

Dear ua6em

my timing have to be precise at usec in the main code when i am processing the action, that's why i need assembler code.
the watchdog waitting time periode can be precise with steps of 0.2ms so the 0.16ms watchdog flag combine with a loop and a counter is the perferct tool for me to save energy during this waitting time .. So let me ask the question differently..
does someone is having a working assembler code for a watchdog timer getting awake with an interrupt flag ?

If you are using a cpu with more than 8k of flash, your vector table is wrong because there are 4bytes per vector, and you have 3byte instructions there.

Set your goal first by clear statement what you want to do. After that you implement it using Arduino UNO Platform and then replace the high/Arduino level codes using inline assembly codes wherever possible.

1. You want to put the MCU into sleep -- which sleep mode of the following?
Idle, ADC Noise Reduction, Power-down, Power-save, Standby, and Extended Standby

2. For how long the MCU will remain in sleeping?
3. If you want to use WDT Timer to wake up the MCU, then the lowest sleep period is 16 ms (Fig-1).


Figure-1:

What does the above mean? Please explain with example.

Hi Mostafa

This have been define .. as following i

[quote="GolamMostafa, post:15, topic:1099083"]
1. Power-down mode ( SM1=1 & SM0=0 in register MCUCR)

2. Will use the WDP 4K (32ms) watchdog timer prescale

  • each time I have an interrupt, the vector table should start the interrupt routine that is decreasing the R17 value . than i compare the R17 value (count down that can be adjust) with a R18 value (0). the target is to create a loop counting the watchdog to be able to adjust the pause watchdog time.

I am using the ATTINY25-20PU .. that should be a 8k of flash .
Maybe you can confirm ..

How much is the expected sleep time of your MCU?

between 500ms and 650ms (have to be adjustable with the number of loops and countdown) by step or of 32 or 64ms .

The range of sleeping time could be 480 ms to 640 ms at 32 ms step. Every wakeup will augment the next sleeping time by 32 ms -- is it like this? Are you in a position to implement it using UNO-based high level codes?

The range of sleeping time could be 480 ms to 640 ms at 32 ms step. Every wakeup will augment the next sleeping time by 32 ms -- is it like this? Exactly
Are you in a position to implement it using UNO-based high level codes? Not sure what is uno-based high lvl codes but If i googled correctly seems to be a web simulator for arduino. so if the code is issue from that, i am sure i will be in position to understand my mistake and correct my code in assembler. My issue is that i am using microchip studio and home made PCB with attiny chip .. Meaning I have to transfert the full code in assembler.