PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Tick-Händler für Zeitaufträge



Ruffy
30.01.2012, 21:11
; 2012
;#;###############################################





.def LEDS = r16
.def SWITCH = r17
.def SECONDS = r18
.def TEMP = r19
.def TEMP2 = r20



.def LEDS = r17


.cseg
.org 0




; all 17 ATMega8515 interrupt vectors
;------------------------------------------------
; nr. Source Interrupt Definition
;----------------------------------------------------
rjmp RESET ;(1) RESET External Pin, Power-on Reset,
; Brown-out Reset and Watchdog Reset
rjmp RESET ;(2) INT0 External Interrupt Request 0
rjmp RESET ;(3) INT1 External Interrupt Request 1
rjmp RESET ;(4) TIMER1 CAPT Timer/Counter1 Capt Event
rjmp start_new ;(5) TIMER1 COMPA Timer/Counter1 Comp Match A
rjmp RESET ;(6) TIMER1 COMPB Timer/Counter1 Comp Match B
rjmp RESET ;(7) TIMER1 OVF Timer/Counter1 Overflow

rjmp RESET ;(8) TIMER0 OVF Timer/Counter0 Overflow
rjmp RESET ;(9) SPI,STC Serial Transfer Complete
rjmp RESET ;(10) USART, RXC USART, Rx Complete
rjmp RESET ;(11) USART, UDRE USART Data Register Empty
rjmp RESET ;(12) USART, TXC USART, Tx Complete
rjmp RESET ;(13) ANA_COMP Analog Comparator
rjmp RESET ;(14) INT2 External Interrupt Request 2
rjmp RESET ;(15) TIMER0 COMP Timer/Counter0 Compare Match
rjmp RESET ;(16) EE_RDY EEPROM Ready
rjmp RESET ;(17) SPM_RDY Store Program memory Ready







RESET:

ldi TEMP, $FF ;configure PORTB (output)
out DDRB, TEMP

;----- here we start new or each time the LED-blinking
; comes to its end:

start_new:
;initialize SW stack (since we do not use RETI we have
; to clean up the stack this way
ldi TEMP, low(RAMEND)
out SPL, TEMP
ldi TEMP, high(RAMEND)
out SPH, TEMP

ldi LEDS, $FF ;all LEDS on PORTB off (initial state)
out PORTB, LEDS



;----- now start te timer:

;------------------------------------------------------------------------------
; set timer depending on which switch was pressed (timer code in reg SWITCH):
; switch 0 ~ 1 sec
; switch 1 ~ 2 sec
; ...
; switch 7 ~ 8 sec
; 1 sec ~ 3600*1/(clk/1024)=3600*277.78ns, 3600=$e10
;
; TIMSK: TOIE1 (OCIE1A) OCIE1B ###### TICIE1 ###### TOIE0 OCIE0
; TCCR1A: COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
; TCCR1B: ICNC1 ICES1 – WGM13 WGM12 (CS12 CS11 CS10) -> clock set!
; TIFR: TOV1 (OCF1A) OCF1B – ICF1 – TOV0 OCF0
;
; CS12 CS11 CS10 Description
; 0 0 0 No clock source (Timer/counter stopped).
; 0 0 1 clk I/O/1 (No prescaling)
; 0 1 0 clk I/O/8 (From prescaler)
; 0 1 1 clk I/O/64 (From prescaler)
; 1 0 0 clk I/O/256 (From prescaler)
; 1 0 1 clk I/O/1024 (From prescaler)
; 1 1 0 External clock source on T1 pin. Clock on falling edge.
; 1 1 1 External clock source on T1 pin. Clock on rising edge.
;------------------------------------------------------------------------------


start_timer1:
ldi TEMP, 64 ;enable Timer1 Output CompareA Match Interrupt
;-> set Bit6 (OCIE1A) in TIMSK
out TIMSK, TEMP

ldi TEMP, 0
out TCCR1A, TEMP ;init of TCCR1A -> normal port operation

ldi TEMP, 1 ; Prescaler 1!!
out TCCR1B, TEMP ;select clk/1 as time base TCCR1B=0000 0001

ldi TEMP, $4E
out OCR1AH, TEMP ;set counter target value 20,001=$4e21
;in OCR1AH $Xe is provided in register $4E
ldi TEMP, $21 ;
out OCR1AL, TEMP ;OCR1AL = $21 ($4E und $21 ergibt 20000)

ldi TEMP, 0b01000000 ;RESET OCF1A flag by writing 1 in TIFR bit 6
out TIFR, TEMP

sei ;enable all interrupts

ldi TEMP, 0
out TCNT1H, TEMP ;start timer with initial value 0 and flash
;the LEDs until timer reaches the
out TCNT1L, TEMP ;compareA match value in OCR1AH/L

;------------------------------------------------------------------------------



task_0: ;set led0

in r20, PORTB
ldi r20, 0b11111110
out PORTB, r20

reti


Atmel 8515, Taktfrequenz 4Mhz, alle 20.000 clock-zyklen ein IRQ


Der Timer funktioniert mittlerweile, alle 5ms wird ein Interrupt request generiert. Nun soll durch den Interrupt alles 5ms ein Tick-Handler aufgerufen werden der in SRAM gespeicherte Zeitaufträge von verschiedenen kleinen Tasks (Anzahl 5, aber erstmal unerheblich) durchläuft und denjenigen kleine Task aufruft dessen Zeit abgelaufen ist. Die Zeit der Tasks ist frei wählbar, vielfache von 5ms. Die Liste der Zeitaufträge soll als Array der Länge 10 in SRAM implementiert werden. Je nachdem von welchem Task die Wartezeit abgelaufen ist, wird der ein Unterprogrammaufruf (icall) zu dem jeweiligen Task gemacht.

Ich bin Anfänger in der Assembler-Programmierung und wühle mich seit Tagen durch diverse Tutorials und ich habe keine Ahnung wie ich die Liste der Zeitaufträge erstellen soll und wie ich den Tickhandler der in diese Liste( in SRAM) durchlaufen soll umsetzen kann.
Vielleicht kann mir ja jemand helfen?

Ruffy
02.02.2012, 08:51
Kann geclosed werden, es läuft. Die Hilfsbereitschaft hielt sich ja stark in Grenzen ;)

PicNick
02.02.2012, 10:18
Keep cool, so schnell geht das nicht.
Ich mach das so (sprachunabhängig erstma)

Eine Table von n Entries
Jeder Table-Entry beinhaltet:
Byte Flag 0 = inaktiv 1=aktiv 3=call
Word Counter wieviel Ticks kann auch eine byte sein, wenn das reicht
Word Vector Icall-Label
(addit. parameter) die müssen aber nicht sein

Einen Entry zu erstellen/aktivieren:
durch die Entries durchsteppen
wenn flag = 0, dann:
Counter anzahl Ticks setzen
Vector Sprungadresse setzen
Flag auf 1

Tick-ISR:
durch die Entries durchsteppen
wenn flag = 1, dann:
Counter - 1
Wenn Counter == 0 , Flag = 3 (callable)
next entry

Hauptschleife, jedesmal (kann man optimieren) durch die Entries durchsteppen
Wenn Flag = 3 :
Flag = 0 (deaktivieren)
ICALL Vector
next Entry

Die Trennung ISR / Hauptschleife, damit die aufgerufene Funktion nicht in der ISR läuft.

Im Detail noch u.a. davon abhängig, ob "erledigte" Entries automatsch reaktiviert werden sollen