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
Hi Der Flashspeicher ist zwar 32k-Byte gross, aber die Flashadressen sind Word-Adressen. Es gibt daher keine Adresse >$3FFF. MfG Spess
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.
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. :-)
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
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
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.
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
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.
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
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.
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
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
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.