Hi!
Ich habe einen ATMega16 der auf die 512 Byte internes EEPROM zugreifen
soll. Zumindest das Schreiben funktioniert im Moment noch nicht (nicht
sicher weshalb) aber das schlimmste ist das Problem mit dem Lesen.
Der 16er hat ja 512 Byte EEPROM - ich sollte also theoretisch bis zur
Adresse 0x1FF hoch lesen können. Ein BASCOM-Programm was vorher auf dem
Atmel lief (nicht von mir) konnte diese Speicherbereiche auch korrekt
adressieren.
Mein C-Variante stürzt jedoch NUR bei Adresse 0x1F0 ab, in der Form, das
der Mikrocontroller direkt neu startet.
Was stimmt da nicht? Habe ich in meinem Code ein "Problemchen" eingebaut
oder liegt es am EEPROM?
Code (Includes usw raus gelöscht):
Noch was neues zum aktuellen Fall:
Ich habe jetzt eine Testroutine aufgebaut, der ich per USART
Speicherposition und Daten senden kann, die Routine schreibt die Daten
an der gewünschten Stelle ins EEPROM und versucht sie danach wieder
auszulesen.
Folgender Fehler tritt dabei auf: Der Absturz des Atmels wird durch das
auslesen des EEPROMs verursacht und zwar NUR DANN, wenn im Byte welches
im EEPROM abgelegt ist, das 0x08 Bit gesetzt ist.
Dazu fällt mir jetzt garnichts mehr ein..
Ich hoffe es kommen vielleicht noch Vorschläge.
Was noch an Code?
Hier erstmal die main(), die den Testaufruf enthält. Die UART-Funktionen
habe ich nicht dabei, die sind aber von vorne bis hinten getestet und es
gab nie Probleme damit.
Kurze Erklärung dazu:
1
voidinit_uart(void);
Schnittstelle auf 9600,8,N,1 (Asynchron); Interrupts einrichten.
1
unsignedcharrx_chars(void);
Abrufen wie viele Zeichen im Empfangspuffer sind (Ring-Puffer)
1
unsignedcharuart_puts(unsignedchar*s);
String (bis \0) in den Sendepuffer schreiben (Ring-Puffer)
1
unsignedcharuart_getc(void);
Zeichen abrufen und aus dem Empfangspuffer löschen.
1
unsignedcharuart_putc(unsignedcharzeichen);
Zeichen in den Sendepuffer schreiben.
Gibt noch ein Paar mehr aber die benutze ich nicht..
Oh, und das Wichtigste natürlich.. Die gesendeten Daten und die Antwort:
[pre]
Gesendet: 0x00 0x01 0x05
Antwort: "Writing & Reading: Adr0001=ABCDE05(" + 0x05 + ")"
Gesendet: 0x00 0x01 0xF7
Antwort: "Writing & Reading: Adr0001=ABCDEF7(" + 0xF7 + ")"
Gesendet: 0x00 0xFF 0x05
Antwort: "Writing & Reading: Adr00FF=ABCDE05(" + 0x05 + ")"
Gesendet: 0x00 0x01 0x08
Antwort: "Writing & Reading: Adr0001=ABFAULT"
Gesendet: 0x00 0x08 0x16
Antwort: "Writing & Reading: Adr0008=ABCDE16(" + 0x16 + ")"
Gesendet: 0x00 0x01 0xFF
Antwort: "Writing & Reading: Adr0001=ABFAULT"
Immer wenn das 0x08er-Bit gesetzt ist (bzw 3er bei 0-Zählweise) startet
er nachdem er die Adresse gesetzt hat (danach kommt der "B"-Status) ab
und sendet den "FAULT"-String der in der main() ganz am Anfang geschickt
wird..
Hast du denn einmal mal einen anderen Mega probiert? Man kann ja nicht
ausschliessen das deiner einfach kaputt ist. (Hab mir den Code jetzt
nicht angeschaut)
Nein, habe ich nicht. Ich bin leider in der dummen Lage das die Hardware
nicht von mir ist. Ich hab das HEX-File allerdings an den Kollegen
geschickt der die Platte entwickelt - der soll bei sich mal gucken ob da
was ähnliches raus kommt. Kann sich nur noch um Stunden handeln ;)
Ich vermute auch das am EEPROM was hinüber ist; das Problem ist eben das
es bis gestern noch einwandfrei lief (dann aber über BASCOM
angesprochen)..
Das Problem ist hier:
> 1500: 80 93 3c 00 sts 0x003C, r24
Der ATmega16 (und noch diverse andere) hat einen Hardware-Bug, der einen
EEPROM-Interrupt auslösen kann, wenn das EECR-Register per STS
beschrieben wird.
Schalte die Optimierungen ein. Das sollte nicht nur den Code deutlich
kürzer machen, sondern auch das Problem beheben.
Nur mal so auf den ersten Blick:
Es werden Register versaut, die nicht gerettet wurden.
Der Global-Interupt wird mehrfach abgeschaltet (CLI), aber nicht mehr
eingeschaltet (kein SEI). Oder hat das im Gesamtkontext seinen Sinn?
Jochen Müller
Jochen Müller wrote:
> Es werden Register versaut, die nicht gerettet wurden.
Und? Das sind die "call-clobbered" Register.
> Der Global-Interupt wird mehrfach abgeschaltet (CLI), aber nicht mehr> eingeschaltet (kein SEI).
Enabled werden die Interrupts dann wieder durch das Zurückschreiben des
gesicherten SREGs, sofern sie auch vorher enabled waren. So schützt man
einen Bereich vor Interrupts, wenn nicht feststeht, ob die Interrupts zu
diesem Zeitpunkt enabled sind, oder nicht.
>>Und? Das sind die "call-clobbered" Register.>>...
Ok, registriert. Ich programmiere auf Controllern nicht in C, kenne
daher das ganze Trara des Compilers nicht.
Wenn ich allerdings sehe, was für einen gigantischen Zirkus der Compiler
für das simple Lesen eines Bytes aus dem EEprom veranstaltet, dann weiss
ich echt nicht ob ich lachen oder weinen soll. Das ist doch wohl ein
Witz, oder?
Sowas benötigt in ASM eine Hand voll Befehle und 2-3 Lichtjahre weniger
Performance.
Interessehalber: Bringt da die o.g. Codeoptimierung einen wirklichen
Durchbruch? Warum muss die erst zugeschaltet werden?
Jochen Müller
Jochen Müller wrote:
> Interessehalber: Bringt da die o.g. Codeoptimierung einen wirklichen> Durchbruch?
Ja. Mit Optimierung sieht der Code so aus:
1
unsigned char ee_readByte(unsigned short address) {
2
5e: e1 99 sbic 0x1c, 1 ; 28
3
60: fe cf rjmp .-4 ; 0x5e <ee_readByte>
4
while (!EEPROM_READY) { }
5
EEPROM_ADDRESS(address);
6
62: 9f bb out 0x1f, r25 ; 31
7
64: 8e bb out 0x1e, r24 ; 30
8
EEPROM_READ;
9
66: e0 9a sbi 0x1c, 0 ; 28
10
while (!EEPROM_READ_READY) { }
11
68: e0 99 sbic 0x1c, 0 ; 28
12
6a: fe cf rjmp .-4 ; 0x68 <ee_readByte+0xa>
13
return EEPROM_GET_DATA;
14
6c: 8d b3 in r24, 0x1d ; 29
15
}
16
6e: 08 95 ret
Das bekommst du auch in Assembler nicht kürzer hin.
> Warum muss die erst zugeschaltet werden?
Weil es unterschiedliche Level der Optimierung gibt und weil Optimierung
nicht immer erwünscht ist.
Zumindest war das das Problem :) Vorsichtshalber werde ich auch den
EEPROM-Interrupt noch definieren und aber leer lassen. Falls da "nochmal
jemand hinspringt" ;)
Danke für die Hilfe!
- Tobi
Ok, trotzdem das eigentliche Problem nun wohl gelöst ist,
möchte ich das doch noch mal kurz aufgreifen.
1) Die optimierte Fassung liegt wirklich sehr nahe an dem, was Assembler
schaffen kann. Vielleicht 1-2 Opcodes könnte ich da noch sparen. Aber
so, wie es ist, ist es ok.
Aber Ihr müsst zugeben, dass die un-optimierte Fassung ein
himmelschreiendes Elend war, für das es überhaupt keinen Grund gibt.
Auch eine abgeschaltete Optimierung kann SO EINEN SCHEISS-CODE nicht
rechtfertigen.
Oder wird der unoptimierte Code absichtlich so dermassen krank
generiert, damit irgendwelche Optimizer dann in besserem Licht stehen?
Oder anders gefragt:
WIESO muss der Compiler erst auf Optimierung geschaltet werden, damit er
so einen Scheiss unterlässt. Es kann doch wohl erwartet werden, dass er
das auch ohne Optimierung ETWAS BESSER hinbekommt.
2) Aus welchem Grund kann eine Optimierung NICHT erwünscht sein?
3) Und das ist mir am wichtigsten:
Habe ich das jetzt richtig verstanden, dass OHNE Codeoptimierung ein
Code erzeugt wird, der nicht lauffähig ist. Mit Optimierung funktioniert
der Code bei sonst gleichen Umgebungsbedingungen dann?
Was für eine hinterhältige Falle ist DAS DENN BITTE?
Jochen Müller
Jochen Müller wrote:
> 1) Die optimierte Fassung liegt wirklich sehr nahe an dem, was Assembler> schaffen kann. Vielleicht 1-2 Opcodes könnte ich da noch sparen.
Nein, kannst du nicht. Jedenfalls nicht bei gleicher Funktionalität.
> 3) Und das ist mir am wichtigsten:> Habe ich das jetzt richtig verstanden, dass OHNE Codeoptimierung ein> Code erzeugt wird, der nicht lauffähig ist. Mit Optimierung funktioniert> der Code bei sonst gleichen Umgebungsbedingungen dann?> Was für eine hinterhältige Falle ist DAS DENN BITTE?
Du lastest den Hardware-Bug dem Compiler an?
Du kannst übrigens aufhören herumzuschreien, ich habe längst kapiert,
dass du keinen blassen Schimmer davon hast, wie Compiler arbeiten, und
dass du eine vorgefasste Meinung dazu hast. Auch die Tatsache, dass du
dich für einen ober-coolen Assemblerprogrammierer hältst, der für die
C-Weicheier nur ein müdes Lächeln übrig hat, kommt sehr deutlich raus.
Du musst das nicht näher ausführen.
Jochen Müller wrote:
> Aber Ihr müsst zugeben, dass die un-optimierte Fassung ein> himmelschreiendes Elend war, für das es überhaupt keinen Grund gibt.> Auch eine abgeschaltete Optimierung kann SO EINEN SCHEISS-CODE nicht> rechtfertigen.> Oder wird der unoptimierte Code absichtlich so dermassen krank> generiert, damit irgendwelche Optimizer dann in besserem Licht stehen?
(Vorsicht, stark vereinfachte Erklärung)
Das ist einfach eine Folge dessen wie Compiler heutzutage arbeiten. Die
C-Anweisung wird parsed und dann in einen Metacode übersetzt, der
versucht das ganze auf den kleinsten gemeinsamen Nenner runterzubrechen.
Der Optimizer fasst diesen Metacode dann zusammen und wirft Redundanzen
raus, etc.
Der Vorteil des Metacodes ist einfach das man möglichst lange ohne
Architekturspezifische Sachen arbeiten kann. Ausserdem hat die jeweilige
Optimierungsstufe dann auch wirklich Freiraum in jede Richtung.
Optimizer laufen normalerweise besser wenn sie Code vorgeworfen bekommen
an dem sie sich austoben können.
Und die meisten Leute die mit gcc arbeiten wissen eigentlich das sie
Optimierung aktivieren sollten. -Os ist im µC/embedded bereich ja sehr
verbreitet, -O2 auf "normalen" Systemen. (Wobei -Os auf modernen kleinen
CPU wie VIA C7 etc. auch oft mehr Sinn macht, da der Cache dort eher
begrenzt ist)
>>Du kannst übrigens aufhören herumzuschreien, ich habe längst kapiert,>>dass du keinen blassen Schimmer davon hast, wie Compiler arbeiten, und>>dass du eine vorgefasste Meinung dazu hast. Auch die Tatsache, dass du>>dich für einen ober-coolen Assemblerprogrammierer hältst, der für die>>C-Weicheier nur ein müdes Lächeln übrig hat, kommt sehr deutlich raus.>>Du musst das nicht näher ausführen.
Du schreibst Unsinn.
Ich habe konkret nach einigen Punkten gefragt, die absolut begründet
sind.
Wenn das alles Quatsch ist, was ich schreibe, müsste das ja SEHR LEICHT
zu widerlegen sein, also antworte einfach sachbezogen.
Übrigens kann ich Dir SEHR GENAU erklären wie Compiler arbeiten, danke.
GENAU DESHALB darf ich auch mal nachfragen, wenn es offensichtlich ist,
das DIESER Compiler Mist baut oder überaus ineffizient ist.
Ich halte C-Leute auch nicht für Weicheier, das ist Quatsch.
Weicheier sind UNKRITISCHE DEPPEN wie Du, die auch angesichts konkreter
Probleme oder begründeter Zweifel keine Rückfrage zulassen, weil sonst
jemand vielleicht ihr faschistisch verehrtes Heiligtum vom Sockel
stürzen könnten.
Bisher konntest Du keine einzige der o.g. begründeten Fragen
beantworten.
Darüber solltest Du nachdenken, über nichts anderes.
Jochen Müller
@ Jochen Müller (taschenbuch)
>Wenn das alles Quatsch ist, was ich schreibe, müsste das ja SEHR LEICHT>zu widerlegen sein, also antworte einfach sachbezogen.>Aber Ihr müsst zugeben, dass die un-optimierte Fassung ein>himmelschreiendes Elend war, für das es überhaupt keinen Grund gibt.
Doch, aber das kann ich auch nciht wirklich erklären. Ohne Optimierung
wird der Code "hirnlos-formal" übersetzt. Das ist gängige Praxis.
Wahrscheinlich um Plausiilitätscheks etc. zu machen.
>so einen Scheiss unterlässt. Es kann doch wohl erwartet werden, dass er>das auch ohne Optimierung ETWAS BESSER hinbekommt.
Nicht notwendigerweise. Kann ich aber nciht wirklich erklären.
>2) Aus welchem Grund kann eine Optimierung NICHT erwünscht sein?
Um linearen Ablauf der Sourcecodes zu erreichen. Optimierung kann die
Reihenfolge verdrehen, solange das Ergebnis gleich bleibt.
>Übrigens kann ich Dir SEHR GENAU erklären wie Compiler arbeiten, danke.
Naja . . .
>das DIESER Compiler Mist baut oder überaus ineffizient ist.
Du lehnst dich WEIT aus dem Fenster . . .
>Habe ich das jetzt richtig verstanden, dass OHNE Codeoptimierung ein>Code erzeugt wird, der nicht lauffähig ist.
Ja.
> Mit Optimierung funktioniert>der Code bei sonst gleichen Umgebungsbedingungen dann?>Was für eine hinterhältige Falle ist DAS DENN BITTE
Keine Falle, sondern ein Hardwarefehler EINESEINZELNENAVR-Typens.
Der Compiler ist OK.
MfG
Falk
Jochen Müller wrote:
> Wenn das alles Quatsch ist, was ich schreibe, müsste das ja SEHR LEICHT> zu widerlegen sein, also antworte einfach sachbezogen.
Da du ganz offensichtlich eine vorgefasste Meinung hast, wäre jede
detaillierte Ausführung einfach nur Zeitverschwendung.
Und wer Posts schreibt, in denen kaum ein Satz ohne GROßGESCHRIEBENE
Worte ist, hat eh nur die Absicht rumzustänkern. Die Wortwahl
unterstreicht das noch. Also wieder: jedes detaillierte Eingehen darauf
wäre reine Zeitverschwendung.
> Übrigens kann ich Dir SEHR GENAU erklären wie Compiler arbeiten, danke.> GENAU DESHALB darf ich auch mal nachfragen, wenn es offensichtlich ist,> das DIESER Compiler Mist baut oder überaus ineffizient ist.
Genau, deshalb wusstest du auch so genau, was "call-clobbered" Register
sind.
> Weicheier sind UNKRITISCHE DEPPEN wie Du, die auch angesichts konkreter> Probleme oder begründeter Zweifel keine Rückfrage zulassen, weil sonst> jemand vielleicht ihr faschistisch verehrtes Heiligtum vom Sockel> stürzen könnten.
Es besteht ein himmelweiter Unterschied zwischen "begründeter Zweifel"
und "Rückfrage" auf der einen Seite, und rausgeschrienen Geschimpfe à la
"SCHEISS-CODE" auf der anderen.
> Bisher konntest Du keine einzige der o.g. begründeten Fragen> beantworten.
Wie bereits geschrieben, an dir wären diese Antworten schlicht
verschwendet.
@Stefan Ernst (sternst)
Also, was ist los mit Dir, was soll der Unsinn?
Für mich waren das schon sehr begründete und berechtigte Fragen, die
taschenbuch da stellte.
Wenn ein Code den ein Compiler auswirft Mist ist, muss man das auch so
sagen dürfen. Alles andere ist willfähriges und unkritisches Gejubel.
Und der Code, den ich da oben sah, ist eben Scheisse, da gibt es nichts
zu beschönigen. Warum willst Du den unbedingt so verherrlichen?
Und mit dem Begriff HEUTZUTAGE zu kommen ist, das wirklich lustig.
Damit rechtfertigt man dann jeden Mist. Dann sind eben HEUTZUTAGE die
Compiler schlecht, mehr kann man daraus nicht schliessen.
Mir sind jedenfalls Leute, die Schwachstellen mal hinterfragen sehr viel
lieber, als Jubelheinis, die alles schlucken aus ideologischen Gründen.
So entsteht Rückschritt und kein Fortschritt, das solltest Du Jüngelchen
Dir mal merken. Mir scheint eher, dass DU hier der Faschist und Ideologe
bist.
Sachlich hast Du jedenfalls nichts beigetragen, das steht ausser
Zweifel.
Übrigens hatte tb in seinem Posting doch den optimierten Code als gut
und brauchbar anerkannt, das Lesen fällt Dir auch schwer?
Nichts für ungut, aber sowas unkritisches konnte ich nicht stehen
lassen.
Udo
Jochen Müller wrote:
> Ok, trotzdem das eigentliche Problem nun wohl gelöst ist,> möchte ich das doch noch mal kurz aufgreifen.>> 1) Die optimierte Fassung liegt wirklich sehr nahe an dem, was Assembler> schaffen kann. Vielleicht 1-2 Opcodes könnte ich da noch sparen. Aber> so, wie es ist, ist es ok.> Aber Ihr müsst zugeben, dass die un-optimierte Fassung ein> himmelschreiendes Elend war, für das es überhaupt keinen Grund gibt.> Auch eine abgeschaltete Optimierung kann SO EINEN SCHEISS-CODE nicht> rechtfertigen.> Oder wird der unoptimierte Code absichtlich so dermassen krank> generiert, damit irgendwelche Optimizer dann in besserem Licht stehen?>> Oder anders gefragt:> WIESO muss der Compiler erst auf Optimierung geschaltet werden, damit er> so einen Scheiss unterlässt. Es kann doch wohl erwartet werden, dass er> das auch ohne Optimierung ETWAS BESSER hinbekommt.
Nein. Das eigentliche Problem ist nicht in avr-gcc, sondern in der
avr-libc. In der 3er Version von avr-gcc (die mit einer anderen avr-libc
Version zusammenarbeitete) gabs diesen Horror-Code noch nicht, aber die
avr-libc-Leute haben sich für eine "bequeme" Implementierung der
EE-Routinen über indirecte Calls entschieden. Und wenn der Compiler
nicht optimiert, wird das sau teuer.
Beitrag "Re: avr-gcc: 3.4.6 contra 4.3.0"
Ausserdem ist der EERE-Fehler bekannt und in den Errata der betroffenen
AVR ganz klar beschrieben. Gleichwohl wird der Fehler von der Toolchain
nicht umschifft (in anderen Toolchains ist es üblich, auch die
Errata-Sheets eines µC zu lesen und Silicon-Bus, falls möglich, in
Compiler, Assembler oder Libs zu umschiffen).
> 2) Aus welchem Grund kann eine Optimierung NICHT erwünscht sein?
Optimierung erschwert Debugging. Bei manchen Compilern schliesst sich
Debugging und Optimierung sogar aus. Bei gcc jedoch nicht, aber die
Debug-Info wird zunehmend übel, zB ist eine asm-Instruktion nicht mehr
unbedingt einer bestimmten Quellezeile zuzuordnen oder eine Quellzeile
kann mehrfach in asm umgesetzt sein.
> 3) Und das ist mir am wichtigsten:> Habe ich das jetzt richtig verstanden, dass OHNE Codeoptimierung ein> Code erzeugt wird, der nicht lauffähig ist. Mit Optimierung funktioniert> der Code bei sonst gleichen Umgebungsbedingungen dann?> Was für eine hinterhältige Falle ist DAS DENN BITTE?
Wie gesagt, ein nicht beachtetes, gleichwohl bekanntes, klar in den
Sheets beschriebens Erratum, das in der avr-libc nicht umschifft wird.
Also, ein Bugreport schreiben. Ein Workaround kann ohne vertretbaren
Aufwand nicht in avr-gcc geschehen. In der avr-libc wäre ein Workaround
möglich, und mit der EE-Implementierung wie in der 3er Toolchain wäre
dieser Silicon-Bug nie zum Tragen gekommen.
Immerhin hast Du noch Glück, wenn man sich die Odyssee anderer
AVR-Benutzer anschaut... Originalton
Beitrag "Riesige Änderungen zwischen WinAVR 030913 und der aktuellen Version?"> Auf EECR darf nicht mittels ST oder STS zugegriffen werden,> (wahrscheinlich auch nicht über STD), sondern es muss via IN/OUT> zugegriffen werden.> Mit dem leeren EE_READY sollte das Problem erst mal aus der Welt sein,> bis der nächste drüber stolpert und sich den Wolf sucht...
Johann
Also ich nutze beides, C-Compiler und auch Assembler. Je nach Anwendung.
Das ist ja nun wie bei Religionen, da scheiden sich die Geister.
Aber Stefan E. überzieht da absolut. Auf eine berechtigte Frage reagiert
man nicht mit dem Vorwurf das der Frager sich für besser hält, das kann
ich aus dessen Text auch nicht absolut herauslesen. Sowas ist pubertär
und kindisch.
Aber nachzuhaken, wenn ein (unberechtigt) göttlich verehrtes Produkt mal
hakt, wie der Compiler in obigem Fall, das muss erlaubt sein. Stefan
scheint eine falsche Ideologie über das Ergebnis zu stellen und das ist
m.E. verwerflich.
Also -im Sinne der Religion ASM und C-
Friede sei mit Euch.
Grüsse von Frank
Stefan Ernst wrote:
>> Du lastest den Hardware-Bug dem Compiler an?>
Ich sag mal so: Es gibt Controller (etwa der, der unter der Haube nicht
weniger PKWs in diesem Lande sitzt (BMW, VW, Daimler, ...) die Du ohne
Berücksichtigung der Silicon-Bugs im Compiler/Toolchain direkt in die
Tonne treten kannst. Übrigens nicht der Controller für's CD-Laufwerk.
Die Errata-Sheets dieses µC sind nicht wie bei AVR auf einer
DIN-A4-Seiten abgehandelt, sondern haben einen Umfang von weit mehr als
1/3 des Handbuchs!
...soviel zu dem Thema...
CCUser wrote:
> Sachlich hast Du jedenfalls nichts beigetragen, das steht ausser> Zweifel.
Richtig, ich habe ja nur dem OP geholfen, sein Problem zu beseitigen, so
was Nebensächliches aber auch. :-D