Asssembleprogramm für Mega16 auf Mega8535 anpassen, Sprungweite "call" und "jmp"

OP #3114599
Lesenswert?

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
Angehängte Dateien:
OP #3114628
Lesenswert?

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ß
Angehängte Dateien:
Gast #3114698
Lesenswert?

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
OP #3114704
Lesenswert?

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
#3114760
Lesenswert?

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
;---------------------------------------------------------------
Gast #3118625
Lesenswert?

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
OP #3118711
Lesenswert?

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
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren