avr: rewrote timer code (split into timer and basetimer).
Only basetimer depends on hardware and clock speed. Works onj AtTiny 84 at 1 MHz and 8 MHz.
This commit is contained in:
12
avr/modules/basetimer/0BUILD
Normal file
12
avr/modules/basetimer/0BUILD
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<extradist>
|
||||
main.asm
|
||||
</extradist>
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
|
||||
188
avr/modules/basetimer/main.asm
Normal file
188
avr/modules/basetimer/main.asm
Normal file
@@ -0,0 +1,188 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2024 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
;
|
||||
; The base timer makes sure that "onSystemTimerTick" is called about every
|
||||
; 100ms.
|
||||
; The setup depends on hardware and clock.
|
||||
;
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
baseTimerModuleData:
|
||||
baseTimerModuleReloadValue: .byte 1
|
||||
baseTimerModuleTickCounter: .byte 1
|
||||
baseTimerTicksSinceLastRun: .byte 2
|
||||
baseTimerModuleData_end:
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
BASETIMER_BEGIN:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @rotuine BaseTimer_Init @global
|
||||
;
|
||||
; @clobbers r16, r17, x
|
||||
|
||||
BaseTimer_Init: ; setup timer for IRQ every 100ms
|
||||
; reset data in SDRAM
|
||||
ldi xh, HIGH(baseTimerModuleData)
|
||||
ldi xl, LOW(baseTimerModuleData)
|
||||
ldi r16, 0
|
||||
ldi r17, (baseTimerModuleData_end-baseTimerModuleData)
|
||||
rcall Utils_FillSram
|
||||
|
||||
ldi r16, (1<<CS02) | (1<<CS00) ; Prescaler 1024
|
||||
out TCCR0B, r16
|
||||
|
||||
ldi r16, (1<<WGM01) ; CTC mode
|
||||
out TCCR0A, r16
|
||||
|
||||
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
||||
out TIFR0, r16
|
||||
|
||||
ldi r16, (1<<OCIE0A)
|
||||
out TIMSK0, r16
|
||||
|
||||
;
|
||||
; Settings for clock 1Mhz (default)
|
||||
; use timer0 with OCR0A=98-1 (irq every 97.65625 millisecs), baseTimerModuleReloadValue 1
|
||||
;
|
||||
.if clock == 1000000
|
||||
; CMP-A interrupt about every 100ms
|
||||
ldi r16, 98-1 ; (1,000,000/1024)/10 = 97.65625
|
||||
out OCR0A, r16
|
||||
|
||||
ldi r16, 1
|
||||
sts baseTimerModuleReloadValue, r16
|
||||
.endif
|
||||
|
||||
;
|
||||
; Settings for clock 8Mhz
|
||||
; use timer0 with OCR0A=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
|
||||
;
|
||||
.if clock == 8000000
|
||||
; CMP-A interrupt about every 10ms
|
||||
ldi r16, 78-1
|
||||
out OCR0A, r16
|
||||
|
||||
ldi r16, 10
|
||||
sts baseTimerModuleReloadValue, r16
|
||||
.endif
|
||||
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine BaseTimer_Fini @global
|
||||
;
|
||||
|
||||
BaseTimer_Fini:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine BaseTimer_Run @global
|
||||
;
|
||||
; @return CFLAG set if something done, cleared otherwise
|
||||
; @clobbers all
|
||||
|
||||
BaseTimer_Run:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
lds r24, baseTimerTicksSinceLastRun
|
||||
lds r25, baseTimerTicksSinceLastRun+1
|
||||
clr r16 ; replace with 0 for next IRQ
|
||||
sts baseTimerTicksSinceLastRun, r16
|
||||
sts baseTimerTicksSinceLastRun+1, r16
|
||||
out SREG, r15 ; restore global IRQ flag
|
||||
pop r15
|
||||
sbiw r25:r24, 0
|
||||
clc ; flag "nothing done"
|
||||
breq BaseTimer_Run_End
|
||||
|
||||
BaseTimer_Run_loop: ; for every timer tick
|
||||
push r24
|
||||
push r25
|
||||
rcall onSystemTimerTick
|
||||
pop r25
|
||||
pop r24
|
||||
sbiw r25:r24, 1
|
||||
brne BaseTimer_Run_loop
|
||||
sec
|
||||
BaseTimer_Run_End:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine baseTimerIrqOC0A @isr
|
||||
;
|
||||
; OC0A interrupt handler
|
||||
;
|
||||
; Increments baseTimerModuleTickCounter, if it reaches 0 then baseTimerTicksSinceLastRun
|
||||
; is also incremented and the baseTimerModuleTickCounter reloaded.
|
||||
; The rest is done outside ISR baseTimerTicksSinceLastRun in BaseTimer_Run.
|
||||
|
||||
baseTimerIrqOC0A:
|
||||
push r15
|
||||
in r15, SREG
|
||||
|
||||
push r24
|
||||
push r25
|
||||
lds r24, baseTimerModuleTickCounter
|
||||
dec r24
|
||||
breq baseTimerIrqOC0A_timerElapsed
|
||||
sts baseTimerModuleTickCounter, r24
|
||||
rjmp baseTimerIrqOC0A_end
|
||||
|
||||
baseTimerIrqOC0A_timerElapsed:
|
||||
lds r24, baseTimerModuleReloadValue ; reload counter
|
||||
sts baseTimerModuleTickCounter, r24
|
||||
|
||||
lds r24, baseTimerTicksSinceLastRun
|
||||
lds r25, baseTimerTicksSinceLastRun+1
|
||||
adiw r25:r24, 1
|
||||
sts baseTimerTicksSinceLastRun, r24
|
||||
sts baseTimerTicksSinceLastRun+1, r25
|
||||
|
||||
baseTimerIrqOC0A_end:
|
||||
pop r25
|
||||
pop r24
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
BASETIMER_END:
|
||||
.equ MODULE_SIZE_BASETIMER = BASETIMER_END-BASETIMER_BEGIN
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user