Forum: Mikrocontroller und Digitale Elektronik Problem Codesegment


von Karsten S. (scottyrebel)


Lesenswert?

Hallo,
ich glaube ich habe ein Verständnisproblem. Ich habe einen ATMega32, 
Dieser sollte 32Kb Programmspeicher haben. Soweit mirbekannt beginnt die 
Anwendung direkt hinter der Interrupttabelle.
So jetz mein Problem. Ich habe 2 Tabellen a 256 Bytes die ich ins 
Codesegment laden möchte. Um nicht in das Programm zu schreiben, dachte 
ichmir ich lege die Tabellen an das Ende des Codesegments. Das wären 
dann die Adressen 0x7E00 und 0x7F00. 32768 Bytes ergibt 0x8000 Bytes 
minus 512 Bytes sind 0x7E00 und minus 256 Bytes ergibt 0x7F00. Das 
funktioniert nur nicht, wenn ich die .Org-Direktiven dort setze, ich 
bekomme eine Over Warnung. Erst wenn ich die Direktiven auf 0x3E00 und 
0x3F00 setze ist die Warnung weg, jedoch werden dann auch falsche 
Werte(0xFF) gelesen. Erst wenn ich die die Direktiven wie folgt setze, 
arbeitet die Anwendung fehlerfrei:
.Org 0x400
CRC16_Table_Low:
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
  .DB 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

.Org 0x500
CRC16_Table_High:
  .DB 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2
  .DB 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04
  .DB 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E
  .DB 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8
  .DB 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A
  .DB 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC
  .DB 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6
  .DB 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10
  .DB 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32
  .DB 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4
  .DB 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE
  .DB 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38
  .DB 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA
  .DB 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C
  .DB 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26
  .DB 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0
  .DB 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62
  .DB 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4
  .DB 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE
  .DB 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68
  .DB 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA
  .DB 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C
  .DB 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76
  .DB 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0
  .DB 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92
  .DB 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54
  .DB 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E
  .DB 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98
  .DB 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A
  .DB 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C
  .DB 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86
  .DB 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40

Ich habe keine Ahnung warum, vielleicht könnte mich ja mal jemand 
aufklären.

Danke für jede Hilfe.
--
Gruß Scotty

von spess53 (Gast)


Lesenswert?

Hi

Der Flashspeicher ist zwar 32k-Byte gross, aber die Flashadressen sind 
Word-Adressen. Es gibt daher keine Adresse >$3FFF.

MfG Spess

von Grrrr (Gast)


Lesenswert?

Immer kompletten, assemblierbaren Code posten, der soweit reduziert ist, 
dass der Fehler noch auftritt. Lies: 
http://www.mikrocontroller.net/articles/Netiquette

Deine Rechnung mit 32768=0x8000 stimmt zwar, aber die Adressen im AVR 
zählen Wortweise, wobei ein Wort 2 Byte hat. Deswegen meckert der 
Assembler auch nicht mehr, wenn Du 0x3E00 bzw. 0x3F00 verwendest. Da 
hat er noch Flash-Speicher.

Warum es mit 0x3E00 bzw. 0x3F00 nicht geht, können wir mangels Code 
nicht wissen.

Lies mal das Datenblatt, insbesondere den Abschnitt über die Memory-Map.

von Floh (Gast)


Lesenswert?

Lass das .org weg, du pfuscht nur dem Assembler beim Verteilen des Codes 
rein.
Was, wenn dein Programm noch etwas größer wird? Dann musst du die 
Tabellen verschieben, damits keine Überschneidungen gibt.

Der Assembler weiß die Startadresse der Tabellen über die Label bereits.
:-)

von Karsten S. (scottyrebel)


Lesenswert?

Ok, das mit den Wortadressen wusste ich nicht. Der vollständighalber die 
verarbeitende Routine

\\\
CRC16:
  ;CRC-Berechnung mit Tabelle
  ;Polynom 0xA001


  PUSH YL
  PUSH YH

  SBRC  State, CRC_Init
  RJMP  CalcCRC16
  LDI    CRC_Low, 0xFF
  LDI    CRC_High, 0xFF
  SBR    State, 1<<CRC_Init
CalcCRC16:
  ;Index berechnen
  MOV    TempLow, CRC_Low
  EOR    TempLow, Received
  ;High-Byte ins Low-Byte schieben
  MOV    CRC_Low, CRC_High
  LDI    CRC_High, 0x00

  LDI    ZH, HIGH(CRC16_Table_Low)
  MOV    ZL, TempLow
  LPM
  EOR    CRC_Low, R0

  LDI    ZH, HIGH(CRC16_Table_High)
  MOV    ZL, TempLow
  LPM
  EOR    CRC_High, R0

  POP  YH
  POP  YL
RET
///
Wie man hoffentlich sehen kann muss ich den Speicher ausrichten, da 
sonst die Berechnung des Low-Bytes für den Z-Pointer nicht richtig ist. 
Dieser steht dann im TempLow und unfasst einen Wertebereich von 0...255.

Vielleicht noch anzumerken ist, das ich die Anwendung im AVR-Studio 
debugge, vielleicht liegt ja hier das Problem(Bei PWM versagt der 
Simulator ja auch).
--
Gruß Scotty

von spess53 (Gast)


Lesenswert?

Hi

>HLass das .org weg, du pfuscht nur dem Assembler beim Verteilen des Codes
>rein.
>Was, wenn dein Programm noch etwas größer wird? Dann musst du die
>Tabellen verschieben, damits keine Überschneidungen gibt.

Er wollte die Tabellen ans Flashende legen. Grösser kann das Programm 
nicht werden.

Der Assembler weiß die Startadresse der Tabellen über die Label bereits.
:-)

Aber an bestimmten Adressen ist der Tabellenzugriff einfacher.

MfG Spess

von Grrrr (Gast)


Lesenswert?

Karsten Sosna schrieb:
> Ok, das mit den Wortadressen wusste ich nicht.

Das hört sich an, als wenn Du es jetzt wüsstest. Dennoch lädst Du ZH mit 
der dem High-Wort der Wortadresse der Tabelle. Korrigiere das. LPM 
erwartet Byte-Adressen.

von Karsten S. (scottyrebel)


Lesenswert?

Grrrr schrieb:
> Das hört sich an, als wenn Du es jetzt wüsstest. Dennoch lädst Du ZH mit
>
> der dem High-Wort der Wortadresse der Tabelle. Korrigiere das. LPM
>
> erwartet Byte-Adressen.


Und wie wenn ich fragen darf? Ich will meine Tabellen am Ende des 
Speichers haben, damit ich genug Platz für den Programmcode bekomme und 
keine Lücken enstehen. Wenn Du mir ein kleines Beispielgeben würdest(Und 
zwar so das ich es auch verstehen kann), wäre ich Dir dankbar.
--
Gruß Scotty

von Grrrr (Gast)


Lesenswert?

Karsten Sosna schrieb:
> Und wie wenn ich fragen darf?

Was ist denn das Problem?

Deine Tabelle sei bei 0x3F00. Das erste Byte hat also die Byte-Adresse 
0x3F00 * 2 = 0x7E00.

Also:

  LDI    ZH, HIGH(CRC16_Table_Low) * 2

Du wirst dies vermutlich als Widerspruch zu dem oben gesagten empfinden.
Aber:
Wenn Du .org schreibst, bestimmst Du Wortadressen.
Wenn Du das Label, das unmittelbar dem org folgt nimmst ist auch das 
eine Wortadresse. In der Regel sind diese Labels Sprungziele, die auch 
Wortweise adressiert werden. Also musst Du, um die Byte-Adresse zu 
erhalten mit Zwei multiplizieren. Aber Achtung: Dein Low-Byte hat schon 
Byte Auflösung. Das musst Du nicht mit zwei Multiplzieren.

von spess53 (Gast)


Lesenswert?

Hi

>LDI    ZH, HIGH(CRC16_Table_Low) * 2

Wenn schon, dann

LDI    ZH, HIGH(CRC16_Table_Low * 2)

oder

LDI    ZH, HIGH(CRC16_Table_Low<<1)

MfG Spess

von Grrrr (Gast)


Lesenswert?

Spess hat da recht.

Da die Tabellen 256 Byte gross sind, also 0x80 Worte wirst Du auf 
Wort-Adressen wie 0x3F00 und 0x3F80 kommen. Daher musst Du die gesamte 
Adresse mit Zwei multiplizieren, ehe Du das High-Byte nimmst.

von Karsten S. (scottyrebel)


Lesenswert?

Grrrr schrieb:
> Deine Tabelle sei bei 0x3F00. Das erste Byte hat also die Byte-Adresse
> 0x3F00 * 2 = 0x7E00.
> Also:
>   LDI    ZH, HIGH(CRC16_Table_Low) * 2
> Du wirst dies vermutlich als Widerspruch zu dem oben gesagten empfinden.
> Aber:
> Wenn Du .org schreibst, bestimmst Du Wortadressen.
> Wenn Du das Label, das unmittelbar dem org folgt nimmst ist auch das
> eine Wortadresse. In der Regel sind diese Labels Sprungziele, die auch
> Wortweise adressiert werden. Also musst Du, um die Byte-Adresse zu
> erhalten mit Zwei multiplizieren. Aber Achtung: Dein Low-Byte hat schon
> Byte Auflösung. Das musst Du nicht mit zwei Multiplzieren.

Ok, das habe ich fast verstanden, wundert tut es mich nur, das es bei 
mir meinem ersten Posting funktioniert. Ist auch egal, ich hatte den 
Code schon abgeändert, allerdings mit ShiftLeft, da hat es dann auch auf 
den hören Adressen funktioniert.
Ok, eine Frage noch: Sind alle Adressen Wortadressen? Sprich über die 
.Org-Direktive. Die kann ich ja auch im Daten- oder Extra-Segment 
festlegen.

An dieser Stelle erst mal Danke.
--
Gruß Scotty

von spess53 (Gast)


Lesenswert?

Hi

>Die kann ich ja auch im Daten- oder Extra-Segment festlegen.

Ein Extra-Segment gibt es bei AVRs nicht. Du meinst wahrscheinlich 
EEPROM-Segment.
Im 'dseg' und 'eseg' sind es Byte-Adressen.

MfG Spess

von Karsten S. (scottyrebel)


Lesenswert?

> Ein Extra-Segment gibt es bei AVRs nicht. Du meinst wahrscheinlich
> EEPROM-Segment.
Ja, das meinte. Ich .eseg steht für Extrasegment, so wie es bei anderen 
Prozessoren auch der Fall ist. Nun auch egal.

Nun rechtherzlichen Dank.
--
Gruß Scotty

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
Noch kein Account? Hier anmelden.