Hallo,
wollte gerade ein bisschen programmieren. Bei
ldi r16, 0b00001111
out DDRB, r16
bringt er beim assemblieren folgenden Fehler:
error: Overlap in .cseg: addr=0x9 conflicts with 0x9:0xa
dabei ist im register nichts.
was mache ich dabei falsch?
Die Meldung bezieht sich auch nicht auf das Register, sondern auf den
Programmspeicher. Wenn Du allerdings nur eine Codezeile zeigst, kann man
nur raten, dass Du irgendwo eine .org-Direktive drin hast, deren Adresse
mit dem Rest des Programms kollidiert.
Hast du irgendwelche Interrupthandler eingebunden?
Welcher Controller?
Versuch mal, vor die erste Anweisung deines Programmes folgendes zu
setzen:
.org $002a
Kleiner Tip: es macht fast immer Sinn, die komplette
Interrupt-Vektortabelle einzubauen und in die nicht verwendeten
Interrupt-Vektoren ein reti (oder nop reti bei AVRs mit mehr als 8 KiB
Flash) reinzuschreiben oder ein (r)jmp zu einer
Fehlerbehandlungsroutine. Nur wenn man überhaupt keine Interrupts
verwendet, macht es viel Sinn, die Tabelle wegzulassen und direkt im
Reset-Vektor mit dem Programm anzufangen.
wie baue ich die ein?
Wenn ich die vom tutorial reinschreibe, bringt er nur fehler!
eigentlich brauch ich nur den interrupt vom timer0 und vom timer2 beim
mega8!
Christoph S. wrote:
> wie baue ich die ein?> Wenn ich die vom tutorial reinschreibe, bringt er nur fehler!
Welche Fehler?
> eigentlich brauch ich nur den interrupt vom timer0 und vom timer2 beim> mega8!
Hab nochmal im Tutorial nachgesehen:
Klar bringt der dort Fehler.
Wenn da steht
RJMP SPI_STC
und es gibt kein Label SPI_STC im Code, dann ist das ein Fehler.
Drum steht aber auch nach dem Code der Satz:
Bei unbenutzten Interrupts ist es üblich, statt des Sprungbefehls
einfach den Befehl reti reinzuschreiben.
Aber im Prinzip hast du recht. Das müsste man mal im Tutorial
überarbeiten und eine schöne Interrupttabelle mit .org
Anweisungen aufbauen.
undefined symbol: EXT_INT0
und bei allen anderen vektoren auch.
Im Datenblatt hab ich auch keine Tabelle gefunden.
bräucht eigentlich nur ein .org OVF0addr für den timer2!!!
.org OVF2addr geht nicht, da kommt die Fehlermeldung mit den registern!
MFG
reti ; USART Receive Complete Interrupt Vector Address
27
.org UDREaddr
28
reti ; USART Data Register Empty Interrupt Vector Address
29
.org UTXCaddr
30
reti ; USART Transmit Complete Interrupt Vector Address
31
.org ADCCaddr
32
reti ; ADC Interrupt Vector Address
33
.org ERDYaddr
34
reti ; EEPROM Interrupt Vector Address
35
.org ACIaddr
36
reti ; Analog Comparator Interrupt Vector Address
37
.org TWIaddr
38
reti ; Irq. vector address for Two-Wire Interface
39
.org SPMaddr
40
reti ; SPM complete Interrupt Vector Address
41
.org SPMRaddr
42
reti ; SPM complete Interrupt Vector Address
43
44
main:
45
... dein Code hier
Du möchtest einen Handler für den Overflow Interrupt vom Timer 2
installieren, also tauscht du in der betreffenden Zeile den reti
gegen einen Sprung zu deiner Behandlungsroutine.
.org INT_VECTORS_SIZE ; ist generell in den includes passend gesetzt
13
main:
14
... dein Code hier
Generell reti bei unbenutzten Vektoren hat den Nachteil, daß sich
bestimmte Programmfehler verstecken können. Ein falscher freigegeber IRQ
wird sauber mit reti beendet, das eigentlich gewünschte Routine macht
aber scheinbar nichts.
Ganz gut wäre sicher ein Error-Handler, der bei allen ungenutzten IRQs
aufgerufen wird und mault, dazu bin ich aber auch meist zu bequem...
Gruß aus Berlin
Michael
Karl heinz Buchegger wrote:
> So sieht eine saubere Interrupt Tabelle aus:
Ja, man kann es so umständlich machen mit viel Schreibarbeit.
Und wenn Du nen anderen AVR nimmst, ist die ganze Tabelle vorn Arsch.
Man kann es sich aber auch einfach machen mit einem Macro:
1
.include "m8535def.inc"
2
;
3
.macro INTERRUPT
4
.set current_pc = PC
5
.org @0 ; Vektor-Adresse
6
.if FLASHEND > 0x0fff
7
jmp current_pc
8
.else
9
rjmp current_pc ; Sprung zum Handler
10
.endif
11
.org current_pc ; restore Programmcounter
12
.endmacro
13
;
14
rjmp main
15
.org INT_VECTORS_SIZE ; hinter allen Interruptvektoren
16
main:
17
nop
18
rjmp pc
19
;
20
INTERRUPT OVF0addr
21
nop ; hier interrupthandler einfügen
22
reti
23
;
24
INTERRUPT INT0addr
25
nop
26
reti
Und wenn man dann z.B. den ATMega8535 durch nen ATmega32 ersetzen will,
einfach nur das Include ändern, mehr nicht.
Peter
Peter Dannegger wrote:
> Karl heinz Buchegger wrote:>> So sieht eine saubere Interrupt Tabelle aus:>> Ja, man kann es so umständlich machen mit viel Schreibarbeit.>> Und wenn Du nen anderen AVR nimmst, ist die ganze Tabelle vorn Arsch.
Eben nicht, die Vektoren sind doch alle einzeln mit .org adressiert.
Ich habe diese Version jetzt mal ins Tutorial aufgenommen.
Der MACRO-Trick ist natürlich auch nicht schlecht.
Peter Dannegger wrote:
> Karl heinz Buchegger wrote:>> So sieht eine saubere Interrupt Tabelle aus:>> Ja, man kann es so umständlich machen mit viel Schreibarbeit.>> Und wenn Du nen anderen AVR nimmst, ist die ganze Tabelle vorn Arsch.>>> Man kann es sich aber auch einfach machen mit einem Macro:
Und du denkst ein Neuling versteht was da abgeht :-)
Ansonsten: nettes Makro. Das ist das Schöne: da lernen
die alten Hasen auch noch dazu :-)
wenn man .org ..... und reti in eine Zeile schreibt, ist diese nur noch
halb so lang. Und man sieht gleich, welcher Befehl zu welchem Interrupt
gehört, ohne 2 Zeilen lesen zu müssen. (ist es die vorherige oder
nachfolgende, könnte doch von Anfängern auch mißverstanden werden).
mfg
Eine eigene Frage?
Dieser Thread ist über 19 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.