Hallo, ich habe kürzlich diesen Akkulader (für 4 Zellen, Strom- u Spannungsanzeige, umfangreiche Einstellmöglichkeiten mit geregelter und vorbestimmbarer Stomabgabe, RS232-Anschluß) mit ATMega16 nachgebaut und mich an dessen Funktion erfreut. http://www.avr-asm-tutorial.net/akkuload/de/ Die originalen Programm-Dateien findet man hier: http://www.avr-asm-tutorial.net/akkuload/de/akkuload.zip Beim Assemblieren fiel mir auf, daß die Programm-Datei noch in einen ATMega8535 passen müßte. Deshalb kam ich auf die Idee, den Quelltext mal eben so für den ATMega8535 anzupassen. Die Fehlermeldungen beim assemblieren rührten alle von den verwendeten Befehlen call und jmp her, die der ATMega8535 nicht kennt. Die Sprungweiten sind größer als 2 K -Worte, so daß es keine direkte Lösung gibt.Als Lösung erschien mir die Möglichkeit sinnvoll, die Sprünge auf jeweils zwei kürzere Sprünge für jeden einzelnen Aufruf umzuschreiben. Nun erhalte ich ein fehlerfrei assembliertes Programm, das aber kurz nach der ersten Ausgabe aufs LCD und aufs UART stehen bleibt und keine Befehle vom Terminal annnimmt. Also klemmt wieder irgendein Sprung oder Unterprogramm-Aufruf. Hat jemand eine Idee, wie man das richtig macht? In den Anhang habe ich mal die von mir geänderten Dateien hochgeladen. mit freundlichem Gruß _________ Alle Labels geändert, die einen call-Befehl hatten. Sie bekamen ein Tr vor den Namen. call nach rcall geändert. Jmp-Befehl zum Sprung auf Programmanfang auch geändert, allerdings in Sprung zu main über die Treppe. rjmp Trmain. ;Binde die selbstgemachte Treppe für Sprünge > 2K-Worte ein ; TrEpRead: rcall EpRead ret TrEpWrite: rcall EpWrite ret TrEpStore: rcall EpStore ret TrClearCap: rcall ClearCap ret TrIdSetPar: rcall IdSetPar ret TrUartInit: rcall UartInit ret TrUartSendOpenText: rcall UartSendOpenText ret TrUartSendCursor: rcall UartSendCursor ret Trmain: rjmp main TrUartRxLine: rjmp UartRxLine
Hi
>Hat jemand eine Idee, wie man das richtig macht?
Deine NOPs nach den rjmp/reti in der Interruptvektortabelle am
Programmanfang sind falsch und müssen raus.
MfG Spess
Hallo, danke für die Hilfe!!! Ja, also das Programm läuft nun tatsächlich ohne diese nops im m8535. Und die Interrupttabelle habe ich zwar betrachtet, aber natürlich mir nichts dabei gedacht oder auch nicht oben drüber die Schrift gelesen: ; Reset- und Interrupt-Vektoren ; (Vektoren beim ATmega16 sind Doppelworte!) Mal wieder eine Unachtsamkeit. Analyse: Ich habe noch nie mit dem Mega16 zu tun gehabt und deshalb auch nichts von dessen doppelt breiten Interruptvektoren gewußt. Vielen Dank fürs Drüber schauen! ....es läuft und läuft... Im Anhang die korrigierte Datei, falls es jemand nachbauen will. mit freundlichem Gruß
Christian S. schrieb: > Analyse: Ich habe noch nie mit dem Mega16 > zu tun gehabt und deshalb auch nichts von dessen doppelt breiten > Interruptvektoren gewußt. Wenn man die vordefinierten Adressen nutzt kann man sich den ganzen quatsch mit nops etc. übrigens wunderbar sparen...
Hallo, hmm, welche meinst Du genau? Welche gibt es da vordefiniert? Die Interrupttabelle aus dem Datasheet des 8535? Stehen die irgendwo geschrieben? Das Programm war im Bauvorschlag bereis fertig angeboten. Da habe ich mir weiter keine Gedanken gemacht, irgendwelche Bestandteile zu ändern. mfG
Schau mal in die m8535def.inc da sollten Namen für alle Interuptvektoren drin stehen mit den Daten aus dem Datenblatt.
Hi >Wenn man die vordefinierten Adressen nutzt kann man sich den ganzen >quatsch mit nops etc. übrigens wunderbar sparen... NOPs braucht man eh nicht, wenn man die passenden Sprungbefehle nutzt. Mir ist eine vollst. Interruptvektortabelle wesentlich sympatischer als dieses .org-Gedödel. MfG Spess
Hallo, ja, klar, diese inc-Dateien sind generell sehr aufschlußreich, wenn es um die Existenz oder die genauen Namen der verschiedenen Register geht. Ganz am Ende der Datei erkennt man, daß beim m8535 alle Interruptvektoren auf geraden und ungeraden Adressen liegen, während beim Mega 16 die Interruptvektoren NUR auf geraden Adressen liegen. Auszug aus m8535def.inc: ; ***** INTERRUPT VECTORS ************************************************ .equ INT0addr = 0x0001 ; External Interrupt 0 .equ INT1addr = 0x0002 ; External Interrupt 1 .equ OC2addr = 0x0003 ; Timer/Counter2 Compare Match .equ OVF2addr = 0x0004 ; Timer/Counter2 Overflow .equ ICP1addr = 0x0005 ; Timer/Counter1 Capture Event .equ OC1Aaddr = 0x0006 ; Timer/Counter1 Compare Match A .equ OC1Baddr = 0x0007 ; Timer/Counter1 Compare Match B .equ OVF1addr = 0x0008 ; Timer/Counter1 Overflow .equ OVF0addr = 0x0009 ; Timer/Counter0 Overflow .equ SPIaddr = 0x000a ; SPI Serial Transfer Complete .equ URXCaddr = 0x000b ; USART, RX Complete .equ UDREaddr = 0x000c ; USART Data Register Empty .equ UTXCaddr = 0x000d ; USART, TX Complete .equ ADCCaddr = 0x000e ; ADC Conversion Complete .equ ERDYaddr = 0x000f ; EEPROM Ready .equ ACIaddr = 0x0010 ; Analog Comparator .equ TWIaddr = 0x0011 ; Two-wire Serial Interface .equ INT2addr = 0x0012 ; External Interrupt Request 2 .equ OC0addr = 0x0013 ; TimerCounter0 Compare Match .equ SPMRaddr = 0x0014 ; Store Program Memory Read Auszug aus m16def.inc: ; ***** INTERRUPT VECTORS ************************************************ .equ INT0addr = 0x0002 ; External Interrupt Request 0 .equ INT1addr = 0x0004 ; External Interrupt Request 1 .equ OC2addr = 0x0006 ; Timer/Counter2 Compare Match .equ OVF2addr = 0x0008 ; Timer/Counter2 Overflow .equ ICP1addr = 0x000a ; Timer/Counter1 Capture Event .equ OC1Aaddr = 0x000c ; Timer/Counter1 Compare Match A .equ OC1Baddr = 0x000e ; Timer/Counter1 Compare Match B .equ OVF1addr = 0x0010 ; Timer/Counter1 Overflow .equ OVF0addr = 0x0012 ; Timer/Counter0 Overflow .equ SPIaddr = 0x0014 ; Serial Transfer Complete .equ URXCaddr = 0x0016 ; USART, Rx Complete .equ UDREaddr = 0x0018 ; USART Data Register Empty .equ UTXCaddr = 0x001a ; USART, Tx Complete .equ ADCCaddr = 0x001c ; ADC Conversion Complete .equ ERDYaddr = 0x001e ; EEPROM Ready .equ ACIaddr = 0x0020 ; Analog Comparator .equ TWIaddr = 0x0022 ; 2-wire Serial Interface .equ INT2addr = 0x0024 ; External Interrupt Request 2 .equ OC0addr = 0x0026 ; Timer/Counter0 Compare Match .equ SPMRaddr = 0x0028 ; Store Program Memory Ready mfG
Christian S. schrieb: > Die Sprungweiten sind größer als 2 K > -Worte, so daß es keine direkte Lösung gibt. Doch, er springt einfach rückwärts. Dazu mußt Du nur das M8535-Include einbinden. Es ist also jede Adresse durch rjmp/rcall erreichbar und deshalb gibt es kein jmp/call.
spess53 schrieb: > Mir ist eine vollst. Interruptvektortabelle wesentlich > sympatischer als dieses .org-Gedödel. Das mag ja sein, trotzdem ist das weder lesbar noch gut wartbar, wie man in diesem Beispiel sieht. Und wie oft braucht man denn wirklich alle Interrupts?
Hier mal ein Grundgerüst für AVR-Assembler Programme:
1 | .include "m8535def.inc" |
2 | ; |
3 | .macro INTERRUPT |
4 | .set current_pc = PC |
5 | .org @0 ; vector address |
6 | .if FLASHEND > 0x0fff |
7 | jmp current_pc |
8 | .else |
9 | rjmp current_pc ; jump to handler |
10 | .endif |
11 | .org current_pc ; restore PC |
12 | .endmacro |
13 | ;--------------------------------------------------------------- |
14 | rjmp init |
15 | .org INT_VECTORS_SIZE ; behind vector table |
16 | init: |
17 | nop ; insert init stuff here |
18 | main: |
19 | nop ; insert main stuff here |
20 | rjmp main |
21 | ;--------------------------------------------------------------- |
22 | INTERRUPT OVF0addr |
23 | nop ; insert handler here |
24 | reti |
25 | ;--------------------------------------------------------------- |
26 | INTERRUPT INT0addr |
27 | nop ; insert handler here |
28 | reti |
29 | ;--------------------------------------------------------------- |
Hallo. Für meine Lösung, RJMPs und NOPs zu verwenden, spricht, dass JMP drei, RJMP aber nur zwei Takte braucht. Also warum Takte verschwenden, wenn es nur "unschön" aussieht, was auch immer für ein Schönheitsbegriff da dahinter stecken mag. Das mit dem Gerödel mit ORG-Orgien teile ich, das ist ziemlich krank und nur scheinbar unproblematisch. Beim Umstellen auf einen anderen Chip ist das Allererste sich zu versichern, dass alle nötige Hardware drin ist und die Interrupts exakt so funktionieren wie im alten Chip. Aufgrund der langen Entwicklungsgeschichte haben die Vektoren alles andere als eine systematische Struktur und Reihenfolge. mfg gerd
Hallo, nochmals habe ich mich mit dieser Portierung des Programms befasst, um die "perfekte" Lösung nun zu haben: (...es läuft und läuft...) was war zu tun: -in akkuload.asm und in akkuuart.asm alle jmp Befehle in rjmp umbenannt und alle call-Befehle in rcall umbenannt. -in akkuload.asm alle nop-Befehle aus der Interrupttabelle auskommentiert -in akkuload.asm die include-Datei geändert: .INCLUDE "m8535def.inc" Das macht mit Übung ca 20 Minuten Aufwand, wenn man weiß was zu tun ist. Anbei die beiden Dateien, die geändert wurden, falls es irgendwann mal jemand nachbauen möchte. Vielen Dank für die hilfreichen Zuschriften. Das Grundgerüst probiere ich bei Gelegenheit mal aus. mit freundlichem Gruß AVRASM: AVR macro assembler 2.1.42 (build 1796 Sep 15 2009 10:48:36) ATmega8535 memory use summary [bytes]: Segment Begin End Code Data Used Size Use% --------------------------------------------------------------- [.cseg] 0x000000 0x001e86 5402 2412 7814 8192 95.4% [.dseg] 0x000060 0x000060 0 0 0 512 0.0% [.eseg] 0x000000 0x0000c0 0 192 192 512 37.5% Assembly complete, 0 errors. 0 warnings
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.