Hallo,
ich habe gerade das Problem, dass die UART-Ausgabe eines kleinen
Programms an einer Stelle hängt, wo ich mir einfach keine Ursache dafür
vorstellen kann. Es handelt sich um folgende Funktion, die innerhalb
einer ISR aufgerufen wird:
1
; Send 8-bit unsigned number as two hex digits.
2
; Parameter: wri0.
3
sendDbgHex:
4
push wri0
5
swap wri0
6
andi wri0, 0x0F
7
rcall sendDbgHexDigit
8
pop wri0
9
push wri0
10
andi wri0, 0x0F
11
rcall sendDbgHexDigit
12
pop wri0
13
ret
14
sendDbgHexDigit:
15
cpi wri0, 10
16
brlo sendDbgHexDigit0
17
subi wri0, -('A'-'9'-1)
18
sendDbgHexDigit0:
19
subi wri0, -'0'
20
rcall sendDbgByte
21
ret
Den vollständigen Code habe ich angehängt. Das Programm soll die
ISP-Schnittstelle eines ATtiny12 simulieren (zu Testzwecken meines
avrispv2-Programms). Nachdem diese Routine an anderen Stellen innerhalb
der ISR problemlos ausgeführt wird, bleibt sie nach dem Aufruf in Zeile
298 von 'main.asm' nach der Ausgabe der ersten Null hängen: PuTTY zeigt
"Write Program Memory, byte address 0", eigentlich müssten eine zweite
Null und weitere UART-Ausgaben folgen.
Ich sitze nun schon eine ganze Weile und gehe den Code durch, aber
konnte bisher nichts Verdächtiges finden. Sowas wie Stackoverflow sollte
ausgeschlossen sein, da die 8KB RAM für die paar wenigen rcall-Ebenen ja
dicke reichen sollten. Und Interrupts können auch nicht stören, da der
Aufruf ja bereits in einer ISR erfolgt und somit das I-Flag gelöscht
ist.
--Johannes
Niklas G. schrieb:> Johannes F. schrieb:>> rcall sendDbgByte>>>> ret>> Das kann man doch schon mal durch ein "rjmp" ersetzen 😄
Wieso? 'sendDbgByte' ist eine andere Routine, die ein Byte an USART0
ausgibt und auch von anderen Routinen aufgerufen wird.
1
; Parameter: wri0, the byte to be sent.
2
sendDbgByte:
3
push wri0
4
; Make sure the transmit data registers are empty:
S. L. schrieb:>> in einer ISR erfolgt und somit das I-Flag gelöscht ist>> Das kann man so bei den AVRxt nicht sagen ...
Ah, hat sich da wohl was geändert? Dann muss ich mich damit erstmal
beschäftigen, danke für den Tipp.
Johannes F. schrieb:> S. L. schrieb:>>> in einer ISR erfolgt und somit das I-Flag gelöscht ist>>>> Das kann man so bei den AVRxt nicht sagen ...>> Ah, hat sich da wohl was geändert? Dann muss ich mich damit erstmal> beschäftigen, danke für den Tipp.
Bei dieser neuen Serie(n) kann man pauschal sagen, dass die
Interruptflags nicht mehr automatisch gelöscht werden. Man muss sie
manuell löschen. Paar wenige Ausnahmen davon stehen im Manual. Man macht
jedoch nichts falsch, wenn man pauschal die Flags selbst löscht.
Da ich kein Assembler kann, folgende Frage. Da ist nicht zufällig ein
Interruptaufruf innerhalb einer ISR drin? Das darf nicht sein.
Johannes F. schrieb:> Habe jetzt 'cli' und 'sei' an Anfang bzw. Ende der ISRs eingefügt,> leider besteht das Problem aber weiterhin.
Das ist Unsinn. Innerhalb einer ISR den ISR sperren und freigeben.
Veit D. schrieb:> Da ich kein Assembler kann, folgende Frage. Da ist nicht zufällig ein> Interruptaufruf innerhalb einer ISR drin? Das darf nicht sein.
Was meinst du mit Interruptaufruf, einen Aufruf einer anderen ISR? Es
werden nur 'normale' Routinen innerhalb der ISR aufgerufen, keine
Interrupt-Routinen.
Johannes F. schrieb:> Was meinst du mit Interruptaufruf, einen Aufruf einer anderen ISR? Es> werden nur 'normale' Routinen innerhalb der ISR aufgerufen, keine> Interrupt-Routinen.
Ok, dann sehe ich damit kein Problem.
Veit D. schrieb:> Das ist Unsinn. Innerhalb einer ISR den ISR sperren und freigeben.
Hmm, wieso? Ist nicht genau das hardwaremäßig bei den älteren AVRs
passiert? Also Löschen des I-Bits beim Aufruf einer ISR und erneutes
Setzen durch 'reti'. Damit eben eine ISR nicht durch (andere) Interrupts
unterbrochen wird.
Hallo,
beim AVR wird in die ISR gesprungen, alles komplett ohne weitere
Unterbrechung abgearbeitet, zurück ins Hauptprogramm, und ggf. in die
nächste ISR gesprungen wenn notwendig usw. Eine Unterbrechung einer ISR
durch eine andere ISR gibt es beim AVR nicht. Deswegen ist das sperren
innerhalb einer ISR ohne Effekt bzw. negativen Effekt. Andererseits kann
innerhalb einer ISR nichts aufgerufen werden was selbst eine ISR
benötigt.
Veit D. schrieb:> beim AVR wird in die ISR gesprungen, alles komplett ohne weitere> Unterbrechung abgearbeitet, zurück ins Hauptprogramm, und ggf. in die> nächste ISR gesprungen wenn notwendig usw.
Im Instruction Set Manual steht (Note 1, p. 113):
"In the AVRe series of devices, the Global Interrupt Enable bit is
cleared by hardware once an interrupt occurs, and this bit is set when
RETI is executed.
In the AVRxm and AVRxt devices, RETI will not modify the Global
Interrupt Enable bit in SREG since it is not cleared by hardware while
entering ISR. This bit should be modified using SEI and CLI instructions
when needed."
Der letzte Satz klingt für mich danach, dass man eben die ISRs mit SEI
und CLI einklammern soll, falls ISRs nicht selbst unterbrochen werden
sollen.
Veit D. schrieb:> Johannes F. schrieb:>> S. L. schrieb:>>>> in einer ISR erfolgt und somit das I-Flag gelöscht ist>>>>>> Das kann man so bei den AVRxt nicht sagen ...>>>> Ah, hat sich da wohl was geändert? Dann muss ich mich damit erstmal>> beschäftigen, danke für den Tipp.>> Bei dieser neuen Serie(n) kann man pauschal sagen, dass die> Interruptflags nicht mehr automatisch gelöscht werden.
So wie ich das lese geht's um das I-Flag im SREG, und das wird doch nach
wie vor bei IRQ-Auslösung auf 0 gesetzt? (Und bei RETI wieder auf 1
gesetzt?)
Oder hab ich da was verschlafen?
Letzteres.
Die AVRxt haben zwei Interrupt-Prioritäten ...
PS:
> I-Flag im SREG, und das wird doch nach wie vor> bei IRQ-Auslösung auf 0 gesetzt?
Johannes F. hatte diesbezüglich bereits zitiert.
Dann bin ich wohl, wie es aussieht, nicht der einzige, dem dieses neue
"Feature" der Interruptauslösung nicht bewusst war – sondern befinde
mich in bester Gesellschaft. ;·)
Dennoch scheint dies nicht die Ursache des Problems zu sein, wie ich
bereits schrieb, denn das Klammern mit CLI/SEI brachte keine Abhilfe.
Ich bin weiterhin auf der Suche und auf Hinweise auf mögliche
Fehlerquellen gespannt.
> Ich bin weiterhin auf der Suche
Da sind wir zu zweit - oder besser: "waren", denn ich gebe jetzt auf,
mir fällt nichts mehr ein. Zumal das Programm ohne entsprechende
Umgebung schlecht zu testen ist.
S. L. schrieb:> Zumal das Programm ohne entsprechende> Umgebung schlecht zu testen ist.
Ja, das stimmt leider. Vielleicht sollte das hier für mich der Anlass
sein, mich in die Debugging-Möglichkeiten von UPDI und MPLAB-X-IDE
hineinzufuchsen.
Johann L. schrieb:> Veit D. schrieb:>> Johannes F. schrieb:>>> S. L. schrieb:>>>>> in einer ISR erfolgt und somit das I-Flag gelöscht ist>>>>>>>> Das kann man so bei den AVRxt nicht sagen ...>>>>>> Ah, hat sich da wohl was geändert? Dann muss ich mich damit erstmal>>> beschäftigen, danke für den Tipp.>>>> Bei dieser neuen Serie(n) kann man pauschal sagen, dass die>> Interruptflags nicht mehr automatisch gelöscht werden.>> So wie ich das lese geht's um das I-Flag im SREG, und das wird doch nach> wie vor bei IRQ-Auslösung auf 0 gesetzt? (Und bei RETI wieder auf 1> gesetzt?)>> Oder hab ich da was verschlafen?
Hallo,
ähm nein, passt schon. Das I-Flag im SREG muss man selbst nicht
behandeln. Deswegen ist das mit sei/cli innerhalb einer ISR sinnlos.
Manuell muss man nur das Interruptflag der auslösenden ISR löschen. Ganz
pauschal bis auf sehr wenige Ausnahmen.
Johannes F. schrieb:> In the AVRxm and AVRxt devices, RETI will not modify the Global> Interrupt Enable bit in SREG since it is not cleared by hardware while> entering ISR. This bit should be modified using SEI and CLI instructions> when needed.">> Der letzte Satz klingt für mich danach, dass man eben die ISRs mit SEI> und CLI einklammern soll, falls ISRs nicht selbst unterbrochen werden> sollen.
Das würde dann doch i.W. ein neues Function Attribute erfordern, damit
CLI die erste Instruktion in einer ISR ist und SEI die letzte?
Ansonsten, also wenn man das händisch macht, wird CLI erst nach dem
ISR-Prolog ausgeführt, und SEI bereits for dem ISR-Epilog.
Veit D. schrieb:> ähm nein, passt schon. Das I-Flag im SREG muss man selbst nicht> behandeln. Deswegen ist das mit sei/cli innerhalb einer ISR sinnlos.> Manuell muss man nur das Interruptflag der auslösenden ISR löschen. Ganz> pauschal bis auf sehr wenige Ausnahmen.
Sorry, aber du bist nicht mehr auf dem aktuellen Stand.
Siehe Datenblatt des AVR64DD32, S. 134; dort wird es in Satz 2 sehr
deutlich:
"15.3.2.4 Interrupt Priority AVR64DD32/28
CPUINT - CPU Interrupt Controller
All interrupt vectors are assigned to one of three possible priority
levels, as shown in the table below. An interrupt request from a
high-priority source will interrupt any ongoing interrupt handler from a
normal-priority source. When returning from the high-priority interrupt
handler, the execution of the normal-priority interrupt handler will
resume."
Johann L. schrieb:> Das würde dann doch i.W. ein neues Function Attribute erfordern, damit> CLI die erste Instruktion in einer ISR ist und SEI die letzte?>> Ansonsten, also wenn man das händisch macht, wird CLI erst nach dem> ISR-Prolog ausgeführt, und SEI bereits for dem ISR-Epilog.
In C, meinst du, oder? Wenn ich das in Assembler code, ist ja CLI dann
die erste Instruktion nach dem Sprung zur ISR.
Johannes F. schrieb:> Johann L. schrieb:>> Das würde dann doch i.W. ein neues Function Attribute erfordern, damit>> CLI die erste Instruktion in einer ISR ist und SEI die letzte?>>>> Ansonsten, also wenn man das händisch macht, wird CLI erst nach dem>> ISR-Prolog ausgeführt, und SEI bereits for dem ISR-Epilog.>> In C, meinst du, oder? Wenn ich das in Assembler code, ist ja CLI dann> die erste Instruktion nach dem Sprung zur ISR.
Ja, ich meine C/C++. Zum Beispiel wird
Ich denke, diese Nested Interrupts sind auch gar nicht sooo das Problem
– vorausgesetzt, man ist sich darüber im Klaren und rettet z.B. alle
Register (was ich ursprünglich nicht gemacht hatte, da ich eben dachte,
es wäre in meinem Fall nicht notwendig). Daher habe ich auch die CLI/SEI
wieder rausgenommen, nachdem ich die PUSHs/POPs ergänzt habe. Es muss an
irgendwas anderem liegen.
Hallo,
mit dem neuen Interrupt Controller haste recht, ist mir entgangen, weil
ich die Features noch nie verwendet habe. Habe nochmal nachgelesen. Nun
die Frage, hast du das Priority Feature eingeschalten? Ansonsten würde
er sich wie gewohnt normal verhalten. Ohne konkreten Grund würde ich das
nicht aktivieren.
Pardon, ich wollte keine unnötige Diskussion lostreten, wollte nur den
Satz, ganz am Anfang,
> in einer ISR erfolgt und somit das I-Flag gelöscht ist
nicht unkommentiert stehen lassen.
So wie es mir schwerfällt, das TCA-Fragment im Programm nicht
anzusprechen - führt alles beim eigentlichen Problem nicht weiter.
Guten Morgen,
Veit D. schrieb:> Nun> die Frage, hast du das Priority Feature eingeschalten? Ansonsten würde> er sich wie gewohnt normal verhalten.
Nein, am Interrupt Controller habe ich nichts verändert, es gelten alle
Default-Werte. Somit dürften also hier eigentlich auch keine Interrupts
unterbrochen werden, da alle die normale Priorität haben und nur
High-Priority-Interrupts andere unterbrechen können, wenn ich das
Datenblatt richtig verstanden habe.
S. L. schrieb:> Pardon, ich wollte keine unnötige Diskussion lostreten, wollte nur den> Satz, ganz am Anfang,>> in einer ISR erfolgt und somit das I-Flag gelöscht ist> nicht unkommentiert stehen lassen.
Kein Problem, im Gegenteil – danke für den Hinweis, denn dadurch habe
ich wieder etwas dazulernen dürfen.
S. L. schrieb:> das TCA-Fragment im Programm
Das soll später dazu dienen, eine verzögerte Speicherung der zu
schreibenden Bytes zu realisieren, damit ich das Verhalten des Data
Polling untersuchen kann. Das bisherige Grundgerüst dürfte ja erstmal
nicht stören, wenn ich nichts übersehen habe, da der Timer ja noch
nirgends aktiviert wird.
P.S.: Anbei noch der geänderte Code, und ich habe noch den aktuellen
Stand meines 'avrispv2' hinzugefügt – der ist aber noch sehr
experimentell, bisher nur schwach getestet und kann noch grobe Fehler
enthalten.
Johannes F. schrieb:> Guten Morgen,>> Veit D. schrieb:>> Nun>> die Frage, hast du das Priority Feature eingeschalten? Ansonsten würde>> er sich wie gewohnt normal verhalten.>> Nein, am Interrupt Controller habe ich nichts verändert, es gelten alle> Default-Werte. Somit dürften also hier eigentlich auch keine Interrupts> unterbrochen werden, da alle die normale Priorität haben und nur> High-Priority-Interrupts andere unterbrechen können, wenn ich das> Datenblatt richtig verstanden habe.
Hallo,
nein. Hier benötigt man Nerven.
Default ist, dass es keine gegenseitigen ISR Unterbrechungen gibt. Wenn
zeitgleich mehrere Interrupts anstehen, wird zuerst der ausgeführt mit
der höheren Priorität. Sie werden also nach Prio abgearbeitet. Dann gilt
"The lowest interrupt vector address has the highest priority." Siehe
ioavr64dd32.h ab Zeile 6105.
Das heißt auch, dass nach Beendigung irgendeiner ISR die nächste ISR mit
der aktuell höchsten Prio als Nächstes abgearbeitet wird. Es gibt keine
wilden Sprünge innerhalb einer ISR zur nächsten ISR und zurück. Das ist
Default.
Wo tritt in der aktuellen Version welcher Fehler auf?
Nur Frage am Rande: was ist der Grund dafür, das Blank einmal als
solches und direkt im Anschluss als '20' auszugeben?
S. L. schrieb:> Wo tritt in der aktuellen Version welcher Fehler auf?
Es ist noch derselbe Fehler; beim Versuch, einige Bytes in den
simulierten Flash zu übertragen, bekomme ich die Ausgabe
1
SSFE
2
SSFE
3
RSB 00
4
RSB 01
5
RSB 02
6
SSFE
7
SSFE
8
RSB 00
9
RSB 01
10
RSB 02
11
CE
12
SSFE
13
RPM 0004 00
14
RPM 0005 00
15
WPM 0
und nach der letzten '0' hängt das Programm.
S. L. schrieb:> Nur Frage am Rande: was ist der Grund dafür, das Blank einmal als> solches und direkt im Anschluss als '20' auszugeben?
Das war natürlich ein Fehler, danke für den Hinweis – habe es
korrigiert, ebenso wie noch mehrere Fehler im Programm 'avrispv2', die
sich im Zuge einer Umstrukturierung eingeschlichen hatten. Letzteres
funktioniert nun wieder, getestet an einem ATmega88A (Lesen/Schreiben
von Flash und EEPROM); habe es wieder mit in das ZIP-Archiv gepackt.
Ich habe nun einen AVR32DD28 mit Ihrem Programm an mein
Selbstbau-Programmiergerät angeschlossen, habe im Programm die Signatur
auf ATmega48PA geändert, und kann so 'schreiben', ohne Hänger; das
anschließende Verify geht schief, ist ja aber erstmal nachrangig:
S. L. schrieb:> Ich habe nun einen AVR32DD28 mit Ihrem Programm an mein> Selbstbau-Programmiergerät angeschlossen, habe im Programm die Signatur> auf ATmega48PA geändert, und kann so 'schreiben', ohne Hänger;
Hmm, ist ja seltsam. Vielleicht stimmt auch mit meinem 64DD32
irgendetwas nicht, evtl. zu heiß geworden beim Verlöten ... Einen
Moment, ich probiere es mal mit einem anderen.
15:23 Uhr: Habe das Programm jetzt auf einem anderen Exemplar laufen,
und bin zunächst nun auch über das scheiternde Programming Enable
gestolpert – ich hatte vergessen, das Echo des 0x53 beim dritten
SPI-Byte einzubauen. Seltsamerweise hat sich das auf dem ersten 64DD32
noch nicht ausgewirkt, dort lief es ja bis zum Write Program Memory.
Sehr seltsam ...
Also das Schreiben funktioniert ja ansatzweise, aber der Lesevorgang
muss grundlegend überdacht werden: der Master taktet (gnadenlos) nach
dem dritten Byte weiter, da muss schnellstmöglich das zu liefernde Byte
im SPI bereitgestellt werden; hier aber wird erstmal, wenn ich's richtig
vestehe,
1
...
2
rcall sendDbgMsg
3
...
4
rcall sendDbgHex
5
...
6
rcall sendDbgHex
7
...
8
; Load the addressed byte and move it into SPI transmit register:
Ja, das ist tatsächlich problematisch, ich hatte deshalb schon im
Master, also dem avrispv2-Programm, ein Delay zwischen den SPI-Bytes von
einigen Millisekunden eingefügt (gesteuert über die Konstante
SPI_INTERBYTE_DELAY_MS).
So, ich habe das Programm nun auf den ATmega328P übertragen und dort zum
Laufen gebracht. Zuvor habe ich noch einige Fehler gefunden, z.B. hatte
ich vor dem Schreiben bzw. Lesen vom/in den SRAM vergessen, den Beginn
des Arrays 'simFlash_sram' zum Z-Pointer zu addieren. Auf dem m328P
funktioniert es nun; jetzt gilt es noch, das auch auf dem AVR-DD zu
erreichen, dort hapert es noch an irgendetwas (momentan klappt das
Programming Enable nicht, das 0x53 wird nicht zurückgegeben).
Johannes F. schrieb:> Wieso? 'sendDbgByte' ist eine andere Routine, die ein Byte an USART0> ausgibt und auch von anderen Routinen aufgerufen wird.
Aha! Etwa auch aus main()? Vermutlich ja schon. Wenn das so ist, dann
ist der Fehler hier:
>
1
> sendDbgByte0:
2
> --------------------------------
3
> xin wri0, USART0_STATUS
4
> --------------------------------
5
> sbrs wri0, USART_DREIF_bp
6
> rjmp sendDbgByte0
7
> pop wri0
8
> xout USART0_TXDATAL, wri0
9
>
Dieser Teil des Codes ist eine "critical section", er darf nicht durch
durch den Interrupt unterbrochen werden. Den tatsächlich kritischen
Punkt habe ich mal durch Linien markiert. Wenn ausgerechnet während
dieses Taktes bei der Ausführung in main() der Interrupt erfolgt, hast
du eine klassische race condition.
Das ganze muss also "atomic" gemacht werden.
Das kostet ein zusätzliches Register, ich nenne es mal "scratch0". So
lange du nichts am Standardverhalten von AVR8-Interrupts änderst (also
in keiner ISR ein "sei" auftaucht und du auch die Features des
neuzeitlichen Interruptcontrollers nicht nutzt), dann kannst du dieses
Register global reservieren und in allen ISRs vollkommen frei nutzen,
ohne es jeweils sichern und wiederherstellen zu müssen. Du darfst aber
natürlich nicht davon ausgehen, dass es beim Eintritt in eine ISR
bereits einen definierten Inhalt hat. Das ist allerdings für die
Verwendung als "atomic"-Merker auch nicht nötig.
Der korrigierte Code würde also erst mal so aussehen:
>
1
> sendDbgByte0:
2
> in scratch0, CPU_SREG ;bzw. "SREG" für die klassischen AVR8
3
> cli
4
> sendDbgByte1:
5
> xin wri0, USART0_STATUS
6
> sbrs wri0, USART_DREIF_bp
7
> rjmp sendDbgByte1
8
> pop wri0
9
> xout USART0_TXDATAL, wri0
10
> out CPU_SREG, scratch0 ;bzw. "SREG" für die klassischen AVR8
11
>
Schwachsinnig bleibt der Code allerdings auch in dieser Form. Aber das
ist dann schon ein anderes Thema, was da heißt: "howto implement
buffered IO"...
Habe mir das Zip.file angesehen. Also mindestens 50% würde ich
rauswerfen.
Die ganzen ifs und endifs zum Beispiel.
Dieses Programm ist offensichtlich "allgemein" geschrieben.
Besser wäre es, dies ganz gezielt auf das tatsächlich verwendete Target
zu spezifizieren. Das ist ja - ganz nebenbei bemerkt - das Manko bei
ASM. Die Portierbarkeit wird erschwert, wenn nicht gar unmöglich.
Sonst wird das eigentliche Programm durch die Varietäteneventualitäten
unnötig aufgeblasen.
Ich stolpere bereits über die ersten Zeilen:
; Devices to be supported (in future):
.equ T3227 = 0
.equ A64DD32 = 1 ; not supported yet
.equ M88A = 2 ; not supported yet
und vor allem:
.nolist
.if MCU == T3227
.include "C:\Program
Files\Microchip\MPLABX\v6.20\packs\Microchip\ATtiny_DFP\3.1.260\avrasm\i
nc\tn3227def.inc"
.else
.error "Device not supported yet."
.endif
.include "stk500v2-isp.inc"
.include "..\macros.inc"
.list
Was soll der Quatsch.
Unnötig aufgeblasen. Dient eher dazu, hinterher den Wald vor lauter
Bäumen nicht mehr zu sehen
so sehen "meine" Programme aus: Etwas aufgeräumter möchte ich meinen
.nolist
.include "8535def.inc"
.list
.def temp = r16
.def temp1 = r17
.def zeit = r18
.def zeit1 = r19
.def zeit2 = r20
.def zeichen1 = r21
.equ daten = portb
.equ impuls = portb
.equ taste = pina
ciao
gustav
Nachdem nun Experten mit an Bord sind, darf ich mich getrost
verabschieden. Zumal ich vor der neuesten Version (von gestern abend)
etwas ratlos sitze:
> ... das 0x53 wird nicht zurückgegeben ...
Nun sehe ich aber den ganzen Block §spiTcIsr6...9, in welchem $53 an SPI
übergeben wird, auskommentiert; aber angeblich läuft es auf dem
ATmega328 - wie gesagt, ich verstehe es leider nicht mehr.
Aaarghh. wollte noch was ergänzen:
Schau mal hier:
Kannst Du auf SPI umschreiben.
Ist natürlich zum besseren pädagogischen Verständnis auch "aufgeblasen".
ciao
gustav
Ob S. schrieb:> Aha! Etwa auch aus main()? Vermutlich ja schon.
Nope. Es gibt keine 'main()', bzw. diese besteht nur aus einer leeren
Schleife:
1
loop:
2
rjmp loop
'sendDbgByte' wird nur von Subroutinen aufgerufen, die ihrerseits in
einer der beiden ISRs aufgerufen werden. Es kann also keine Race
Condition geben, da Interrupts ja somit immer blockiert sind, wenn diese
Routine ausgeführt wird (unter den genannten Voraussetzungen
hinsichtlich SEI und Interrupt Controller, die hier erfüllt sind).
Ob S. schrieb:> Schwachsinnig bleibt der Code allerdings auch in dieser Form. Aber das> ist dann schon ein anderes Thema, was da heißt: "howto implement> buffered IO"...
Mag sein, dass du es schwachsinnig findest; für mich sollte dieses
Programm nur eine "schnelle" Möglichkeit des Testens von bestimmtem
Verhalten meines avrispv2-Programms im Zusammenspiel mit avrdude sein.
Dass man IO puffern kann bzw. i.d.R. sollte, weiß ich auch; das war mir
aber für dieses Programm unangemessen aufwendig und unnötig.
Karl B. schrieb:> Also mindestens 50% würde ich> rauswerfen.> Die ganzen ifs und endifs zum Beispiel.> Dieses Programm ist offensichtlich "allgemein" geschrieben.> Besser wäre es, dies ganz gezielt auf das tatsächlich verwendete Target> zu spezifizieren.
Nö, das wäre meines Erachtens nach überhaupt nicht besser, weil ich dann
mehrere Dateien (für jedes Device) parallel pflegen und jede Änderung am
Ablauf überall vornehmen und synchron halten müsste. Das wäre viel
aufwendiger als die Assembler-Direktiven.
Karl B. schrieb:> Das ist ja - ganz nebenbei bemerkt - das Manko bei> ASM. Die Portierbarkeit wird erschwert, wenn nicht gar unmöglich.
Das ist Unsinn. Die meisten Unterschiede bestehen in den
Peripherie-Einheiten der verschiedenen AVR-Serien, und diese muss man in
C genauso unterschiedlich behandeln (z.B. Einrichten von UART, SPI, oder
ob ein ISR-Flag manuell gelöscht werden muss oder nicht).
Karl B. schrieb:> Was soll der Quatsch.> Unnötig aufgeblasen. Dient eher dazu, hinterher den Wald vor lauter> Bäumen nicht mehr zu sehen
Sorry, dass du es Quatsch findest. Mir dient es als Hilfe, für welche
MCUs ich vorhatte, das Programm zu ergänzen, und ich selbst finde es
auch nicht unübersichtlich.
S. L. schrieb:> Zumal ich vor der neuesten Version (von gestern abend)> etwas ratlos sitze:>>> ... das 0x53 wird nicht zurückgegeben ...> Nun sehe ich aber den ganzen Block §spiTcIsr6...9, in welchem $53 an SPI> übergeben wird, auskommentiert; aber angeblich läuft es auf dem> ATmega328 - wie gesagt, ich verstehe es leider nicht mehr.
Mir war bewusst geworden, dass das Echo von 0x53 im dritten Byte
automatisch passiert, da dieses einfach im SPI-DATA-Register verbleibt
und somit wieder rausgeshiftet wird. Der auskommentierte Block ist somit
überflüssig. Das Problem, welches mal beim Programming Enable vorhanden
war, musste wohl ein anderes sein.
Johannes F. schrieb:> 'sendDbgByte' wird nur von Subroutinen aufgerufen, die ihrerseits in> einer der beiden ISRs aufgerufen werden.
Dir ist schon bewußt, dass jede dieser beiden ISRs bei der gegebenen
Implementierung das Potential besitzt, die jeweils andere quasi "endlos"
zu blockieren?
Warum benutzt du nicht die Konstante SRAM_START aus 'tn4313def.inc'?
Viel besser lesbar und weniger fehleranfällig und besser portierbar.
Und warum benutzt du nicht .byte-Direktiven und lässt die Adressen damit
vom Assembler zuweisen? So wie es oben steht, hättest du das .dseg und
.org auch weglassen können.
Und das findest du übersichtlicher als meine paar .if- und .else-Zweige?
1
ldi temp, low(ramend) ; Stackpointer setzen
2
out spl, temp
3
ldi temp, high(ramend)
4
out sph, temp
Bei den alten AVRs sollten 16-bit-Registerpaare immer mit H zuerst
beschrieben werden (wobei es in diesem Fall egal ist, aber besser, man
macht es immer so).
Ob S. schrieb:> Dir ist schon bewußt, dass jede dieser beiden ISRs bei der gegebenen> Implementierung das Potential besitzt, die jeweils andere quasi "endlos"> zu blockieren?
Aber wie soll das denn passieren? Während die eine ISR ausgeführt wird,
sind Interrupts gesperrt – die andere kann also gar nicht
dazwischenfunken.
Johannes F. schrieb:> Es gibt keine 'main()', bzw. diese besteht nur aus einer leeren> Schleife:
Sollte da nicht besser ein Sleep rein um Energie zu sparen?
Johannes F. schrieb:> Der auskommentierte Block ist somit> überflüssig.
Also doch. Dinge die nicht nötig sind, einfach so copy- and paste-mäßig
übernommen. Ohne Sinn und Verstand.
Johannes F. schrieb:> Mir dient es als Hilfe, für welche> MCUs ich vorhatte, das Programm zu ergänzen, und ich selbst finde es> auch nicht unübersichtlich.
Es ist jedem selbst überlassen. Aber eine allgemein übliche Maxime
sollte doch lauten:
Möglichst sparsam mit Programmspeicherplatz umgehen.
Der Geiz mit Speicherplatz zeigt sich hinterher bestimmt nicht nur
sondern gelegentlich auch in der Performance.
(Für Pädagogikzwecke kann davon abgewichen werden.)
; ATtiny4313 memory use summary [bytes]:
; Segment Begin End Code Data Used Size Use%
;[.cseg] 0x000000 0x00080e 2026 36 2062 4096 50.3%
;[.dseg] 0x000060 0x00007b 0 27 27 256 10.5%
;[.eseg] 0x000000 0x000000 0 0 0 256 0.0%
;Assembly complete, 0 errors. 0 warnings
oder großzügiger mit der Targetauswahl umgehen.
; ATmega32U2 memory use summary [bytes]:
; Segment Begin End Code Data Used Size Use%
; [.cseg] 0x000000 0x0005f2 1430 36 1466 32768 4.5%
; [.dseg] 0x000100 0x000112 0 18 18 1024 1.8%
; [.eseg] 0x000000 0x000000 0 0 0 1024 0.0%
; Assembly complete, 0 errors. 8 warnings
Letzteres Programm ist nicht identisch mit dem für den Attiny.
Hier muss zwingend eine Anpassung nicht nur der Ansprache der Peripherie
vorgenommen werden.
Kannst Du ja selber probieren.
Insofern relativiert sich Deine Aussage oben etwas.
Johannes F. schrieb:> Das ist Unsinn. Die meisten Unterschiede bestehen in den> Peripherie-Einheiten der verschiedenen AVR-Serien, und diese muss man in> C genauso unterschiedlich behandeln
ciao
gustav
Niklas G. schrieb:> Sollte da nicht besser ein Sleep rein um Energie zu sparen?
Mit Energiesparmodi habe ich mich noch nicht befasst, da ich bisher
keinen Bedarf daran hatte. Hier sollte das auch keine Rolle spielen, da
es eh nur ein Testprogramm ist und ob der Controller nun ein paar
Stunden lang 12 mA zieht oder nicht ...
Karl B. schrieb:> Johannes F. schrieb:>> Der auskommentierte Block ist somit>> überflüssig.>> Also doch. Dinge die nicht nötig sind, einfach so copy- and paste-mäßig> übernommen. Ohne Sinn und Verstand.
Was für copy and paste? Das Programm habe ich selbst geschrieben, da
wurde nichts kopiert.
Karl B. schrieb:> Möglichst sparsam mit Programmspeicherplatz umgehen.> Der Geiz mit Speicherplatz zeigt sich hinterher bestimmt nicht nur> sondern gelegentlich auch in der Performance.
.if und .else und Co. sind Assembler-Anweisungen. Die entscheiden, ob
der Assembler das, was dazwischen steht, assembliert oder nicht. Auf den
Speicherplatz im Mikrocontroller hat das also überhaupt keine
Auswirkung, weil alles, was für die Ziel-MCU nicht relevant ist,
ignoriert wird.
Karl B. schrieb:> Letzteres Programm ist nicht identisch mit dem für den Attiny.> Hier muss zwingend eine Anpassung nicht nur der Ansprache der Peripherie> vorgenommen werden.> Kannst Du ja selber probieren.> Insofern relativiert sich Deine Aussage oben etwas.
Keine Ahnung, was genau du damit meinst. Ich schrieb: "die meisten
Unterschiede".
Johannes F. schrieb:> Mit Energiesparmodi habe ich mich noch nicht befasst, da ich bisher> keinen Bedarf daran hatte. Hier sollte das auch keine Rolle spielen, da> es eh nur ein Testprogramm ist
Hmm, warum schreibt man das dann in Assembler? Wenn Performance und
Energieverbrauch egal sind, kann man auch C++ nehmen. Wenn man schon
Assembler nutzt sollte man auch jeden letzten Takt rausquetschen, sonst
ist der Aufwand umsonst...
Niklas G. schrieb:> Hmm, warum schreibt man das dann in Assembler?
Weil es einem Spaß macht und man es lernen will.
Niklas G. schrieb:> Wenn Performance und> Energieverbrauch egal sind
Zumindest Performance ist mir nicht egal, da versuche ich schon immer zu
optimieren, soweit ich kann.
Ich freue mich auch immer über konstruktive Kritik. Voraussetzung ist
natürlich, dass der Kritiker auch wirklich Ahnung von Assembler hat und
nicht bloß an Dingen herummeckert, von denen er selbst nichts versteht
...
Johannes F. schrieb:> Ob S. schrieb:>> Dir ist schon bewußt, dass jede dieser beiden ISRs bei der gegebenen>> Implementierung das Potential besitzt, die jeweils andere quasi "endlos">> zu blockieren?>> Aber wie soll das denn passieren? Während die eine ISR ausgeführt wird,> sind Interrupts gesperrt – die andere kann also gar nicht> dazwischenfunken.
Eben!
Die aufgerufene Routine enthält eine Warteschleife. Solange die eine ISR
in dieser Schleife hängt, kann die andere garantiert niemals zum Zuge
kommen. Auch (und insbesondere dann) nicht, wenn sie eigentlich zeitnah
ein Ereignis behandeln müsste, was mit der Debugausgabe rein garnichts
zu schaffen hat.
Ob S. schrieb:> Die aufgerufene Routine enthält eine Warteschleife. Solange die eine ISR> in dieser Schleife hängt, kann die andere garantiert niemals zum Zuge> kommen. Auch (und insbesondere dann) nicht, wenn sie eigentlich zeitnah> ein Ereignis behandeln müsste, was mit der Debugausgabe rein garnichts> zu schaffen hat.
OK, ich werde das Programm nochmal mit deaktivierter Debugausgabe
assemblieren und schauen, ob das Problem dann immer noch besteht. Damit
müsste sich ja ggf. sagen lassen, ob es damit zusammenhängt.
Johannes F. schrieb:> Voraussetzung ist> natürlich, dass der Kritiker auch wirklich Ahnung von Assembler hat und> nicht bloß an Dingen herummeckert, von denen er selbst nichts versteht> ...
Damit war natürlich nicht der darüber zitierte Niklas G. gemeint – nur
um das klarzustellen.
*Nachtrag:* Habe gerade festgestellt, dass ich zuletzt bereits mit
DEBUG=0 auf dem AVR64DD32 getestet hatte, und da hat das Programm nicht
auf das Programming Enable reagiert (avrdude meldete dabei einen Fehler,
mein 'avrispv2' hat wohl STATUS_CMD_FAILED zurückgeliefert, was
bedeutet, dass kein 0x53 zurückkam).
Johannes F. schrieb:> .if und .else und Co. sind Assembler-Anweisungen. Die entscheiden, ob> der Assembler das, was dazwischen steht, assembliert oder nicht.
Jain. Die Funktion hast du schon richtig wiedergegeben, aber eben wegen
dieser Funktion handelt es sich nicht um "Assembler-Anweisungen",
sondern um "Assembler-Direktiven".
Der Unterschied ist einfach: Anweisungen sind die Dinger, die Code
erzeugen, Direktiven sind die Dinger, die das eben nicht tun.
Ob S. schrieb:> Jain. Die Funktion hast du schon richtig wiedergegeben, aber eben wegen> dieser Funktion handelt es sich nicht um "Assembler-Anweisungen",> sondern um "Assembler-Direktiven".
Ja OK, ich meinte es in dem Sinne "Anweisungen an den Assembler", aber
stimmt, "Direktiven" ist die passende Bezeichnung. Der Punkt, worauf ich
hinaus wollte, war ja, dass die Verwendung von .if .elif .else zur
Anpassung an verschiedene Ziel-MCUs eben nicht den Speicherbedarf des
Programms erhöht, wie es behauptet wurde.
Dass das von mir als Denkanstoß gedachte Programm in der Praxis gekürzt
und noch ausgefeilt werden kann, braucht nicht besonders betont zu
werden.
Hatte ja oben extra darauf aufmerksam gemacht, indem ich schrieb:
Karl B. schrieb:> Ist natürlich zum besseren pädagogischen Verständnis auch "aufgeblasen".
Ein guter Cxx-Compiler übernimmt die Aufgabe schon für Dich.
Nicht umsonst will sich kaum einer mehr sich das ASM-Programmieren
antun.
Niklas G. schrieb:> Hmm, warum schreibt man das dann in Assembler? Wenn Performance und> Energieverbrauch egal sind, kann man auch C++ nehmen. Wenn man schon> Assembler nutzt sollte man auch jeden letzten Takt rausquetschen, sonst> ist der Aufwand umsonst...
Weils Spaß macht?
Noch ein Tip: Debugger haben auch Macken. Nutze hier die Debug Funktion
im Build and Run-Menü. Bei Studio 4. Vielleicht reden wir hier
aneinander vorbei. Step for Step mit F10. Bis eine Meldung kommt.
Hat nur den Nachteil, die "Peripherie" muss physisch angeschlossen sein,
die Zeitschleifen müssen angepasst werden.
ciao
gustav
Johannes F. schrieb:> Ob S. schrieb:>> Jain. Die Funktion hast du schon richtig wiedergegeben, aber eben wegen>> dieser Funktion handelt es sich nicht um "Assembler-Anweisungen",>> sondern um "Assembler-Direktiven".>> Ja OK, ich meinte es in dem Sinne "Anweisungen an den Assembler", aber> stimmt, "Direktiven" ist die passende Bezeichnung. Der Punkt, worauf ich> hinaus wollte, war ja, dass die Verwendung von .if .elif .else zur> Anpassung an verschiedene Ziel-MCUs eben nicht den Speicherbedarf des> Programms erhöht, wie es behauptet wurde.
Wie schon gesagt: die Funktion der Sache hast du vollkommen korrekt
beschrieben, nur die Bezeichnung passte nicht.
Zum besseren Verständnis für die C-Only-Fraktion: .if .. .elif .. .endif
des Atmel-Assemblers entspricht weitgehend dem C-Präprozessor-Konstrukt
mit #if .. #elif .. #endif. Übrigens: tatsächlich kann man im
Atmel-Assembler auch den C-Präprozessor verwenden.
Allerdings ist der eingebaute des Assemblers mächtiger, denn er kann
Zwischenergebnisse für den zweiten Pass des Assemblers bereitstellen.
Allerdings ist diese Nutzung auch sehr fehlerträchtig. Wenn man damit
operiert, sollte man schon sehr genau wissen, was man tut.
Du benutzt diese erweiterten Fähigkeiten in deinem Programm aber nicht,
es ist also diesbezüglich völlig unkritisch und könnte tatsächlich 1:1
durch den C-Style ersetzt werden.
Karl B. schrieb:> Dass das von mir als Denkanstoß gedachte Programm in der Praxis gekürzt> und noch ausgefeilt werden kann, braucht nicht besonders betont zu> werden.
Naja, es hat halt keinen direkten Bezug zu dem Problem, um das es in
diesem Thread geht. Aber trotzdem danke.
Karl B. schrieb:> Ein guter Cxx-Compiler übernimmt die Aufgabe schon für Dich.> Nicht umsonst will sich kaum einer mehr sich das ASM-Programmieren> antun.
Ich habe allerdings auch des Öfteren schon von diversen Bugs der
AVR-Compiler gelesen. Für mich stellt sich dann die Frage, ob bei solch
vergleichsweise "trivialen" Programmen, mit denen ich bisher gespielt
habe (DCF77-Empfang, LCD-Ansteuerung, Infrarot-Kommunikation etc.) der
Aufwand, der mit einem Compiler verbunden ist (Einarbeitung in
MCU-spezifische Spracherweiterungen wie Interrupts etc., Kontrolle des
Assembler-Outputs im Hinblick auf Nachoptimierung und evtl.
Compiler-Bugs etc.) überhaupt in diesen Fällen sinnvoll die Vorteile der
Hochsprache aufwiegen würde. Dass das bei komplexeren Programmen sicher
der Fall ist, keine Frage.
Karl B. schrieb:> Weils Spaß macht?
Da stimme ich dir zu.
> Noch ein Tip: Debugger haben auch Macken. Nutze hier die Debug Funktion> im Build and Run-Menü. Bei Studio 4. Vielleicht reden wir hier> aneinander vorbei. Step for Step mit F10. Bis eine Meldung kommt.> Hat nur den Nachteil, die "Peripherie" muss physisch angeschlossen sein,> die Zeitschleifen müssen angepasst werden.
Ja, das mit dem IDE-gestützten Debugging habe ich mir mal vorgenommen.
Wäre ja jetzt ein guter Anlass dazu, da ich mit dem UART-Debugging
offensichtlich nicht weiterkomme.
Ob S. schrieb:> Du benutzt diese erweiterten Fähigkeiten in deinem Programm aber nicht,> es ist also diesbezüglich völlig unkritisch und könnte tatsächlich 1:1> durch den C-Style ersetzt werden.
Den C-Style (insb. #define) habe ich auch schon benutzt, weil dieser im
Gegensatz zu den Assembler-Direktiven auch Fließkommarechnung
unterstützt (war z.B. bei meinen Infrarot-Routinen vorteilhaft für die
Präprozessor-Berechnung der Zeitkonstanten).
Insgesamt muss ich übrigens sagen, dass ich den Atmel-Assembler avrasm2
sehr ausbaufähig finde. Wird ja auch nicht weiterentwickelt. Z.B. würde
ich mir lokale Sprungmarken und mehr mathematische Möglichkeiten des
Präprozessors wünschen. Für später habe ich mir vorgenommen, mal einen
eigenen Assembler mit solchen Features zu entwickeln, dafür muss ich
mich allerdings erstmal tiefer in die PC-Programmierung einarbeiten.
Johannes F. schrieb:> Insgesamt muss ich übrigens sagen, dass ich den Atmel-Assembler avrasm2> sehr ausbaufähig finde. Wird ja auch nicht weiterentwickelt. Z.B. würde> ich mir lokale Sprungmarken
Kann er. Innerhalb von Macros.
> und mehr mathematische Möglichkeiten des> Präprozessors wünschen
Naja, das wird halt dadurch erschlagen, das man auch den C-Präprozessor
benutzen kann.
> Für später habe ich mir vorgenommen, mal einen> eigenen Assembler mit solchen Features zu entwickeln
Verschenkte Lebenszeit. Höchstens zu autodidaktischen Zwecken nützlich.
Allerdings eher in Richtung "Compilerbau" als in Richtung
"Assemblerpropgrammierung".
Was für letzteres nötig ist, ist bereits vollständig verfügbar. Sogar
(leider) in etlichen Inkarnationen. Man braucht wahrlich nicht noch
einen (wieder zu allen anderen inkompatiblen).
Ob S. schrieb:>> lokale Sprungmarken> Kann er. Innerhalb von Macros.
Echt? Wo ist das denn dokumentiert? Im AVR Assembler Manual DS40001917A
finde ich nichts darüber.
Davon abgesehen fände ich es aber auch außerhalb von Macros sehr
wünschenswert, um z.B. sowas schreiben zu können:
1
tst reg0
2
{ breq skip
3
mov reg0, reg1
4
skip:}
5
ldi reg2, 42
Also lokale Marken z.B. durch Klammern in der Gültigkeit beschränkt, wie
lokale Variablen in C-Funktionen, damit man nicht immer einen
übergeordneten Bezeichner voranstellen und nummerieren muss etc. Würde
eine Menge Tipparbeit ersparen und auch die Lesbarkeit verbessern.
Ob S. schrieb:> Verschenkte Lebenszeit. Höchstens zu autodidaktischen Zwecken nützlich.> Allerdings eher in Richtung "Compilerbau" als in Richtung> "Assemblerpropgrammierung".
Naja, Compilerbau ist mir dann doch zu hoch, ich habe nicht Informatik
studiert und weiß nicht, ob ich mir die dafür nötigen Fähigkeiten jemals
autodidaktisch aneignen kann. Interessieren würde es mich aber schon ...
Johannes F. schrieb:> Davon abgesehen fände ich es aber auch außerhalb von Macros sehr> wünschenswert, um z.B. sowas schreiben zu können:>
1
> tst reg0
2
> { breq skip
3
> mov reg0, reg1
4
> skip:}
5
> ldi reg2, 42
6
>
Tja, sowas macht man dann halt einfach mit Makros.
1
.macro mveq
2
tst @0
3
breq skip
4
mov @0, @1
5
:skip
6
.endmacro
Aus deinem ursprünglichen Code würde dann werden:
1
mveq reg0, reg1
2
ldi reg2, 42
Übrigens gibt es bereits etliche solcher Macros fest eingebaut im
Assembler. Nicht zuletzt auch "tst". Das ist keine wirkliche Anweisung,
sondern nur ein Macro mit dem Body "or @0,@0".
Ob S. schrieb:> Ob S. schrieb:>>> :skip>> Mist, der Doppelpunkt gehört natürlich an's Ende.
Und nochmal krasser Mist: Das Macro müßte sinnvollerweise natürlich
"mvne" heißen. Das ist jetzt aber richtig peinlich...
S. L. schrieb:> Verlangt allerdings, sobald es über mehr als 2-3 Zeilen geht,> eine hohe Disziplin bei Programmänderungen.
Ja, und man müsste auch auf die Wortlänge der Instruktionen achten, denn
es gibt ja solche aus einem und aus zwei Worten (JMP z.B.). Das wäre mir
persönlich dann zu fehleranfällig.
Ob S. schrieb:> Tja, sowas macht man dann halt einfach mit Makros.
Dann muss ich aber für jeden solcher Fälle extra ein eigenes Makro
definieren. Das macht es dann ja leider wieder ziemlich umständlich.
Johannes F. schrieb:> Dann muss ich aber für jeden solcher Fälle extra ein eigenes Makro> definieren. Das macht es dann ja leider wieder ziemlich umständlich.
So what? Wenn du Assembler gewählt hast, hast du ganz bewußt auch die
"Umständlichkeit" gewählt. Willst du es einfacher haben, musst du eben
einen viel mächtigeren Makroassembler benutzen.
Sprich: Einen C-Compiler.
Ob S. schrieb:> Johannes F. schrieb:>>> Dann muss ich aber für jeden solcher Fälle extra ein eigenes Makro>> definieren. Das macht es dann ja leider wieder ziemlich umständlich.>> So what? Wenn du Assembler gewählt hast, hast du ganz bewußt auch die> "Umständlichkeit" gewählt.
Naja, man kann ja einen vernünftigen Mittelweg finden, um sich das Leben
nicht unnötig aufwendig zu machen. Dass andere Assemblersprachen solche
lokalen Sprungmarken auch außerhalb von Makros haben (z.B.
Intel-Assembler, mit einem vorangestellten Doppelpunkt, AFAIRC) deutet
ja daraufhin, dass dieser Gedanke vielleicht nicht völlig abwegig ist.
Und ich werde auch bei meinem Ziel bleiben, mir einen eigenen Assembler
nach meinen Vorstellungen (und für meinen eigenen Gebrauch, muss sich ja
sonst keiner davon stören lassen) zu implementieren, weil ich es eben
für sinnvoll und nebenbei auch eine gute Programmierübung halte.
Johannes F. schrieb:> Ich habe allerdings auch des Öfteren schon von diversen Bugs der> AVR-Compiler gelesen. Für mich stellt sich dann die Frage, ob bei solch> vergleichsweise "trivialen" Programmen, mit denen ich bisher gespielt> habe (DCF77-Empfang, LCD-Ansteuerung, Infrarot-Kommunikation etc.) der> Aufwand, der mit einem Compiler verbunden ist (Einarbeitung in> MCU-spezifische Spracherweiterungen wie Interrupts etc., Kontrolle des> Assembler-Outputs im Hinblick auf Nachoptimierung und evtl.> Compiler-Bugs etc.) überhaupt in diesen Fällen sinnvoll die Vorteile der> Hochsprache aufwiegen würde. Dass das bei komplexeren Programmen sicher> der Fall ist, keine Frage.
Nunja, das hängt sicher davon ab, wo man herkommt und natürlich von der
Architektur. So einfache Architekturen wie AVR8 sind auch in Asm noch
sehr gut beherrschbar (wenn man halt den Assembler als Sprache perfekt
beherrscht).
Ähnlich einfach sind Architekturen wie z.B. Z80, 6502, ARM-CortexM0.
Als Abgrenzung könnte man sagen: Je komplexer die im Programm zu
verwendende Mathematik ist, desto geneigter wird man sein, eine Sprache
zu verwenden oberhalb von Assembler.
Lustigerweise führt das aber im Umkehrschluss oft dazu: Wie weit kann
ich eigentlich die (sehr oft nur scheinbar) nötige komplexe Mathematik
für den konkreten Zweck vereinfachen...
Diese Überlegungen sind keinesfalls nutzlos, selbst wenn's am Ende doch
ein C-Programm wird, wird es von diesen Überlegungen profitieren...
Ob S. schrieb:> Ähnlich einfach sind Architekturen wie z.B. Z80, 6502, ARM-CortexM0.
Mich reizt tatsächlich auch die Herausforderung, mich in
Cortex-M0+-Assembler für den RP2040 einzuarbeiten. Mal sehen, ob ich in
absehbarer Zeit dazu komme.
Ob S. schrieb:> Als Abgrenzung könnte man sagen: Je komplexer die im Programm zu> verwendende Mathematik ist, desto geneigter wird man sein, eine Sprache> zu verwenden oberhalb von Assembler.
Oder man hat umgekehrt sogar Spaß daran, komplexere Rechenfunktionen für
einfache Architekturen in Assembler zu implementieren, um sie dort
überhaupt mit akzeptabler Effizienz nutzbar zu machen; dazu gibt es gute
Bücher von Manfred Schwabl-Schmidt über Fließkommaarithmetik etc. auf
AVR, die habe ich schon lange im Schrank stehen und bisher nur mal
durchgeblättert. Ist auch ein großes Ziel von mir, mich damit mal
eingehend zu befassen. Aber dass das nicht für jeden was ist, ist mir
natürlich klar.
Ob S. schrieb:> Diese Überlegungen sind keinesfalls nutzlos, selbst wenn's am Ende doch> ein C-Programm wird, wird es von diesen Überlegungen profitieren...
Ja bestimmt, und manchmal wird ja wohl auch bei effizienzkritischen
Programmteilen aus Assembler erzeugter Objektcode mit vom C-Compiler
erzeugtem zusammen gelinkt. Es muss also nicht entweder–oder sein. Und
wer sich mit Compilerbau beschäftigt, muss auch Assembler können, und
lernen tut man das wohl nur, indem man in Assembler programmiert. Somit
hat Assembler schon seine Berechtigung, auch vom reinen Spaß an der
Freude mal abgesehen.
Johannes F. schrieb:> Mich reizt tatsächlich auch die Herausforderung, mich in> Cortex-M0+-Assembler für den RP2040 einzuarbeiten.
Na dann: ARM-ASM-Tutorial. Bezieht sich allerdings auf den STM32F1,
welcher ein Cortex-M3 ist. Der ist aber in Assembler einfacher zu
programmieren als der M0, weil der Instruction Set des M0 ziemlich
limitiert ist und diverse Verrenkungen benötigt. Und nach etwas
Einarbeitung auch besser programmierbar als der AVR, weil man mit 32bit
einfach flüssiger arbeiten kann...
Johannes F. schrieb:> Ja bestimmt, und manchmal wird ja wohl auch bei effizienzkritischen> Programmteilen aus Assembler erzeugter Objektcode mit vom C-Compiler> erzeugtem zusammen gelinkt.
Der C-Compiler selber erzeugt bereits vielfach ein Konglomerat aus
Sachen, die er wirklich aus seiner Quellsprache übersetzt und Sachen,
die als Assemblermakros in seinem Bauch schlummern. Gerade auch im
Mathe-Bereich stößt man ständig auf solche Asm-Fragmente. Das beweist:
Den Compilerbauern selber ist absolut bewusst, wie suboptimal ihr
Compiler ist.
Nur die ausschließlich biblisch besattelte "C-only-Fraktion" glaubt
ernsthaft, dass es nicht so wäre und ihr Compiler schon von sich aus
immer alles optimal macht.
Richtig spannend sind allerdings die Leute, die wirklich versuchen, den
Compiler zu verbessern. Die lassen zwar einerseits öffentlich nix auf
C/C++ kommen, kennen aber aber andererseits wenigstens selber die
Schwächen und versuchen, sie zu verbessern (natürlich: auf dem einzig
möglichen Weg: neue/bessere Asm-Macros).
Interessant ist das weniger aus rein technischer Sicht, sondern vor
allem in Bezug auf deren Argumentation...
Einerseits müssen sie Asm verteufeln (denn damit könnte es ja jeder auch
ohne den Compiler) andererseits kommen sie aber nicht darum herum,
selber Asm zu benutzen, um den Compiler besser zu machen. Diese
Zwangslage führt wohl zu durchaus gepaltenen Persönlichkeiten, wie man
in einigen Einlassungen sehen kann.
Johannes F. schrieb:> Und ich werde auch bei meinem Ziel bleiben, mir einen eigenen Assembler> nach meinen Vorstellungen (und für meinen eigenen Gebrauch, muss sich ja> sonst keiner davon stören lassen) zu implementieren, weil ich es eben> für sinnvoll und nebenbei auch eine gute Programmierübung halte.
Ich kann nur vom Herzen empfehlen, sich gar nicht von irgendwelchen
Maulhelden von diesem Weg und Ziel abbringen zu lassen, denn der
8-Bit-AVR-Assembler ist eine sehr gute Übung, von der man später bei der
C-Programmierung sehr viel profitieren kann, sofern man unterm Strich
wirklich eine gewisse Anzahl an Monaten intensiven, realen Schreibens
damit verbracht hat. AVR mit 8-Bit ist die perfekte Umgebung dafür, denn
das gewonnene Wissen und die entstandene Erfahrung wird man für sich auf
jeden Fall auch bestens nutzen können – später wird man z.B. unter
anderem auch sofort beurteilen können, was der Compiler für einen
geschrieben hat und wie man das in C eventuell auch beeinflussen kann.
Die Maulhelden dieser Welt haben oft selbst nie richtig Assembler
geschrieben, sie haben oft auch nie eine richtige Leiterplatte entworfen
und herstellen lassen, sie haben oft nie ein richtiges Projekt
durchgezogen und zum Leben erweckt, insofern haben sie – die Maulhelden
irgendwelcher Foren – nicht das Recht, andere, die es wirklich tun, zu
kritisieren oder zu sagen, dass man es lieber lassen sollte. Sie
„wissen” natürlich immer sofort, wie man dies und jenes „besser” machen
sollte, die Maulhelden. Vom STM32-Assembler kann ich in diesem
Zusammenhang nur abraten, denn hier gibt es böse Fallen und so leicht
wie mit dem AVR-8-Bit-Assembler wird es leider nicht gehen.
Ob S. schrieb:> natürlich: auf dem einzig möglichen Weg: neue/bessere Asm-Macros
Die Codegenerierung ist nur ein kleiner Teil des Compilers. Vorher muss
der C/C++ Code analysiert werden, um überhaupt festzustellen welche
Daten wann wohin fließen und auch um die Stellen zu finden, wo solche
Snippets hin kommen können, und das ist der eigentliche Aufwand. Viele
Ineffizienzen der Compiler beruhen darin, dass sie manche unnötige
Instruktionen einfügen, weil sie nicht erkennen, dass sie überflüssig
sind - aber nicht, dass dem Compiler zu wenige Assemblertricks bekannt
wären. Ein Compiler macht eben viel mehr als nur Snippets zusammen zu
stückeln.
Ob S. schrieb:> Einerseits müssen sie Asm verteufeln (denn damit könnte es ja jeder auch> ohne den Compiler)
Warum? Die Logik musst du mal erklären.
Gregor J. schrieb:> Vom STM32-Assembler kann ich in diesem Zusammenhang nur abraten, denn> hier gibt es böse Fallen
Einen eigenen ARM-Assembler zu implementieren ist in der Tat
kompliziert, aber mit einem solchen Assembler zu arbeiten ist recht
komfortabel.
Gregor J. schrieb:> Vom STM32-Assembler kann ich in diesem> Zusammenhang nur abraten, denn hier gibt es böse Fallen und so leicht> wie mit dem AVR-8-Bit-Assembler wird es leider nicht gehen.
Es gibt keinen "STM32-Assembler". STM benutzt zwar ARM-Kerne, hat die
aber nicht erfunden. Es gibt eine riesige Vielfalt von konkurrierenden
Anbietern, die zwar allesamt ebenfalls nicht den ARM erfunden haben,
aber gleichermaßen benutzen.
Wenn, dann gibt es einen "ARM-Assembler". Tatsächlich gibt es deutlich
mehr als einen. Das macht die Sache zunächst scheinbar etwas
kompliziert. Wenn man sich aber auf CortexM0(+) beschränkt, wird es
plötzlich wieder recht einfach. Ähnlich einfach wie beim AVR8. Natürlich
durchaus anders (ist schließlich auch eine andere Architektur), aber
prinzipiell ist es dieselbe Soße in grün. Ist eher sogar einfacher, weil
es nur einen Adressraum gibt, was viel von der Komplexität der AVR8 raus
nimmt. Nunja, es gibt andererseits natürlich auch Eigenschaften, die
Komplexität an anderer Stelle einführen, wie etwa die sehr begrenzten
Immediate-Fähigkeiten. Ist aber beherrschbar, so wie auch die AVR8
beherrschbar sind.
Johannes F. schrieb:> Mich reizt tatsächlich auch die Herausforderung, mich in> Cortex-M0+-Assembler für den RP2040 einzuarbeiten. Mal sehen, ob ich in> absehbarer Zeit dazu komme.
Da empfehle ich:
1
ARM and Thumb-2 Instruction Set
2
ARM_GNU_assembler_ref
3
ARM ThumbRefCard
4
ARM v6-M Architecture Reference Manual
5
Cortex-M0+ Technical Reference Manual
Da hast du im Grunde genommen alles, was es braucht um den RP2040 zu
programmieren.
Für den RP23xx dann noch:
Johannes F. schrieb:> ich habe gerade das Problem, dass die UART-Ausgabe eines kleinen> Programms an einer Stelle hängt, wo ich mir einfach keine Ursache dafür> vorstellen kann.
Bevor ich hier anfange unnötig zu schreiben, vielleicht eine Frage
vorab: funktioniert das nach Deinen Korrekturen mit der
UART-Schnittstelle jetzt schon wie gewünscht oder besteht dieses
ursprüngliche Problem weiterhin?
Gregor J. schrieb:> funktioniert das nach Deinen Korrekturen mit der> UART-Schnittstelle jetzt schon wie gewünscht oder besteht dieses> ursprüngliche Problem weiterhin?
Wenn ich das Programm 'tn12-isp-simulator' für den AVR64DD32 assembliere
und flashe, funktioniert es nicht (ist aber inzwischen ein anderer
Fehler, denn schon beim Programming-Enable-ISP-Befehl scheitert es
dort); die angepasste Version für den ATmega328P funktioniert auf diesem
hingegen einwandfrei.
Ich muss jetzt erstmal los, mache dann heute Abend weiter.
Bis dahin viele Grüße & einen schönen Tag an alle
Johannes F. schrieb:> Für später habe ich mir vorgenommen, mal einen> eigenen Assembler mit solchen Features zu entwickeln
Dann würde ich die Zeit doch besser dazu nutzen, sich in C
einzuarbeiten. Das beschleunigt das Programmieren um Größenordnungen.
Nebenbei erhöht das auch die Lesbarkeit, Wartbarkeit und Erweiterbarkeit
drastisch.
Johannes F. schrieb:> Ich habe allerdings auch des Öfteren schon von diversen Bugs der> AVR-Compiler gelesen.
Ich kann mich nicht erinnern, daß ich mit sowas nennenswert Debugzeit
verplempern mußte. Die Hauptfehlerquelle beim Programmieren sitzt immer
vor dem Bildschirm.
Die Compiler sind inzwischen recht ausgereift. Viele benutzen sogar noch
den alten WINAVR 2010.
Peter D. schrieb:> Die Compiler sind inzwischen recht ausgereift. Viele benutzen sogar noch> den alten WINAVR 2010.
Borland ist doch so ein Stichwort.
ciao
gustav
Peter D. schrieb:> Dann würde ich die Zeit doch besser dazu nutzen, sich in C> einzuarbeiten. Das beschleunigt das Programmieren um Größenordnungen.> Nebenbei erhöht das auch die Lesbarkeit, Wartbarkeit und Erweiterbarkeit> drastisch.
Nunja, wie oben schon geschrieben, macht mir das Programmieren in
Assembler für solch eine vergleichsweise sehr einfache Architektur wie
AVR eben einfach mehr Spaß. Ich finde es toll genau zu wissen, wie die
CPU mit welchen Registern arbeitet und was wo genau im Speicher liegt.
Ich verdiene auch kein Geld mit der Programmiererei, daher steht die
Effizienz des Prozesses nicht an erster Stelle, sondern es geht mehr um
den Spaß an der Freude. Natürlich ist es dabei dennoch von Bedeutung,
dass auch messbare Erfolge entstehen, aber die Art und Weise, wie ich
diese erreiche, wähle ich eben gern selbst.
Nebenbei bemerkt habe ich auch schon in C programmiert; das war die
erste Sprache, mir der ich mich so ca. als Siebtklässler beschäftigt
habe, ist also schon eine Weile her, aber Grundkenntnisse sind
vorhanden.
Johannes F. schrieb:> Wenn ich das Programm 'tn12-isp-simulator' für den AVR64DD32 assembliere> und flashe, funktioniert es nicht (ist aber inzwischen ein anderer> Fehler, denn schon beim Programming-Enable-ISP-Befehl scheitert es> dort); die angepasste Version für den ATmega328P funktioniert auf diesem> hingegen einwandfrei.> Ich muss jetzt erstmal los, mache dann heute Abend weiter.
– Programme immer nur in kleinen Zwischenschritten testen, korrigieren
und zum Laufen bringen; einfach alles runterschreiben und erst danach
nach Fehlern suchen, verursacht in der Regel mehr Arbeit, denn meistens
enthält so ein runtergeschriebener Block mehrere Flüchtigkeitsfehler,
oft auch Denkfehler, die die Funktionsweise des Programmablaufs
betreffen; diese Vorgehensweise der kleinen Schritte gilt inbesondere
dann, wenn Assembler geschrieben werden möchte, aber auch in C hilft
diese sukzessive Inbetriebnahme ungemein
– wenn Peripherieteile im Projekt verwendet werden sollen, sollte man
diese vorher so lange üben, bis man es geschafft hat, sie zum Laufen zu
bringen, d.h.
– erstmal nur UART (ohne alles andere) richtig zum Laufen bringen, man
kann dazu ein neues Projekt anlegen, um es dort bis zum Erfolg zu
exerzieren
– kann man mit UART ein Byte senden, dann im nächsten Schritt das
Absenden von mehreren Bytes üben und real testen - das Reinschreiben in
den Sendebuffer darf immer nur mit der Flagüberprüfung erfolgen, d.h. am
Ende des Prozesses sollte man auch in der Lage sein, auch längere
Bytearrays per UART fehlerfrei abzuschicken
– ist auch der UART-Empfang im Projekt relevant, dann danach mit den
Empfangtests beginnen und erst dann weitermachen, wenn auch das mit dem
Empfang klappt
– auch alles vorher immer auf Plausibilität prüfen: CPU-Takt auf CLKOUT
ausgeben und die Frequenz mit einem Oszilloskop nachmessen, genauso die
UART-Baudrate z.B. anhand eines Sendebits mit dem Oszilloskop
nachmessen, sobald man mit UART ein Byte senden kann; hier auch mit dem
Oszilloskop schauen, ob komplette Frames versendet werden (für solche
Testzwecke verwende ich oft Testzahlen wie 170 oder 85, also
01010101-Muster)
– der CCP-Mechanismus ist zeitkritisch, macht/schreibt man es falsch,
wird der Befehl von der CPU regulär abgearbeitet, intern jedoch
ignoriert – was man umschalten wollte, bleibt unverändert; möchte man
eine Umschaltung unter CCP als Subroutine zur Laufzeit nutzen, muss man
für die kritische Zeit auch die Interrupts sperren
– das UART-Senden aus der Interruptroutine heraus ist generell keine
gute Sache, vor allem dann, wenn man mehrere Bytes absenden möchte und
z.B. zwischendurch warten muss; es sei denn, man kann programmtechnisch
sicherstellen, dass der Sendebuffer in dem Moment nicht voll ist, man
dort in der ISR also etwas ohne Warterei schicken (in den Buffer
schreiben) und anschließend ohne große Verzögerung aus der ISR wieder
verschwinden kann
Gregor J. schrieb:> erstmal nur UART (ohne alles andere) richtig zum Laufen bringen, man> kann dazu ein neues Projekt anlegen, um es dort bis zum Erfolg zu> exerzieren
Erstmal danke für deine Tipps. Also die UART-Ausgabe hatte ja zunächst
prinzipiell auch auf dem AVR-DD funktioniert (Strings und Zahlen wurden
korrekt gesendet), ist nur an einer für mich unerklärlichen Stelle
hängen geblieben.
Zuletzt hatte ich aber die UART-Ausgabe komplett deaktiviert (DEBUG=0
gesetzt), somit ist nun nur noch SPI aktiv, am UART kann es nicht mehr
liegen.
Der allerwichtigste Tip zur Fehlersuche ist natürlich: Debugger
(JTAG/SWD/debugWIRE) verwenden. Damit kann man sehr schnell und einfach
eine große Zahl an Fehlern finden. Insbesondere so etwas wie "Programm
bleibt stehen" - einfach im Debugger unterbrechen wenn dies passiert ist
und schauen, in welchem Zustand sich das Programm befindet. Damit wäre
möglicherweise dieser ganze Thread unnötig und das Problem in Minuten
gelöst.
Gregor J. schrieb:> einfach alles runterschreiben und erst danach nach Fehlern suchen,> verursacht in der Regel mehr Arbeit
Finde ich nicht unbedingt. Man kann durchaus große Programmteile "runter
schreiben" und dann per Debugger die Fehler finden. Man muss natürlich
noch einen Überblick über den Code haben und etwas Routine im Umgang mit
den Debuggingtools.
Johannes F. schrieb:> Erstmal danke für deine Tipps. Also die UART-Ausgabe hatte ja zunächst> prinzipiell auch auf dem AVR-DD funktioniert (Strings und Zahlen wurden> korrekt gesendet), ist nur an einer für mich unerklärlichen Stelle> hängen geblieben.
Solche liegengebliebenen ungeklärten Leichen sind nie gut für das eigene
Verständnis und Vorankommen, denn irgendwann mal später wird man wieder
genau an dieser unerklärlichen Stelle landen und wieder nicht
weiterkommen. Da UART hier jetzt aber nicht relevant ist, ist es für
diese Betrachtung erstmal egal.
> Zuletzt hatte ich aber die UART-Ausgabe komplett deaktiviert (DEBUG=0> gesetzt), somit ist nun nur noch SPI aktiv, am UART kann es nicht mehr> liegen.
Mit der SPI-Schnittstelle sollte man prinzipiell genauso wie mit UART
vorgehen – bevor irgendetwas davon in einem Projekt verwendet wird, so
lange in einem Nebenprojekt exerzieren, bis es sitzt und zu 100%
funktioniert. Je nach Geschwindigkeit ist auch der Gebrauch des
SPI-Sendens in einer ISR als kritisch einzustufen, wenn zwischendurch
gewartet werden muss.
> hatte ich vor dem Schreiben bzw. Lesen vom/in den> SRAM vergessen, den Beginn des Arrays 'simFlash_sram'> zum Z-Pointer zu addieren
Schon, aber das darf natürlich (in §spiTcIsr10 bzw. §spiTcIsr3) erst
nach
1
; Convert the received word address to byte address:
2
lsl ZL
3
rol ZH
erfolgen.
PS:
Beim ATmega328 hebt sich der Fehler heraus (in gewissen Grenzen), aber
beim AVR64DD32 (mit seiner hohen SRAM-Startadresse) nicht.
S. L. schrieb:> :> Beim ATmega328 hebt sich der Fehler heraus (in gewissen Grenzen), aber> beim AVR64DD32 (mit seiner hohen SRAM-Startadresse) nicht
Ah OK, vielen Dank für den Hinweis, das werde ich heute Nachmittag
gleich korrigieren. Und mal das Debuggen über UPDI ausprobieren.
Johannes F. schrieb:> Und mal das Debuggen über UPDI ausprobieren.
Hast Du es noch kein einziges mal ausprobiert? Dafür ist ja die neue
1-Pin-Schnittstelle unter anderen auch gedacht worden – ich habe das
auch relativ zeitnah bei der Einarbeitung in den AVR128DB ausprobiert,
allerdings unter Atmel Studio 7.
Gregor J. schrieb:> Hast Du es noch kein einziges mal ausprobiert?
Tatsächlich noch nicht - ich benutze auch sonst die Mplab X IDE
lediglich zum Setzen von Fuses, ansonsten arbeite ich mit Notepad++ und
der Kommandozeile bzw. Batchdateien.
Johannes F. schrieb:> ich benutze auch sonst die Mplab X IDE lediglich zum Setzen von Fuses
Ich musste diese IDE zwangsläufig auch mehrere male installieren und
benutzen, um meine Snaps mit der richtigen Firmware zu flaschen – diese
IDE ist mit Hintergrundthreads so überladen, dass sie schlimmer als die
STM32CubeIDE lahmt und damit für meine Wahrnehmung für normales, flottes
Arbeiten problematisch ist; mit einem nicht besonders schnellen PC ist
das extrem nervig und quasi nicht zu gebrauchen, was die Leute sich da
wieder ausgedacht haben.
Gregor J. schrieb:> diese IDE ist mit Hintergrundthreads so überladen,
Ja, aus diesen Gründen habe ich es bisher vermieden, damit zu arbeiten.
Aber fürs Debugging muss es wohl sein. Leider wird das von der
Performance her wesentlich bessere Studio ja nicht mehr weiterentwickelt
bzw. ist nicht mehr auf dem aktuellen Stand, was neuere Devices und
Tools betrifft.
Johannes F. schrieb:> Leider wird das von der Performance her wesentlich bessere Studio ja nicht> mehr weiterentwickelt bzw. ist nicht mehr auf dem aktuellen Stand, was> neuere Devices und Tools betrifft.
Die ganzen neuen AVRs sind in der Finalversion des Atmel-Studios schon
drin und den Snap braucht man nur mit der entsprchenden Firmware mittels
MPLAB-X-IDE flaschen – da das Atmel Studio 7 keine Updates mehr erfährt,
ist es in diesem Fall für viele Jahre sogar vorteilhaft, wenn sich da
nichts ändert, sonst müsste man den Snap irgendwann mal wieder mit einer
neueren Firmware nachflaschen. Auch was der Compiler generiert, ist dann
nach einem neuen Build immer identisch, was für mich auch vorteilhaft
ist, weil ich immer den generierten Assembler-Code auch überprüfe und
ggfs. über entsprechende C-Anweisungen oder -schreibweise indirekt so
modifiziere. Wenn man die Optimierungsstufe des Projekts beibehält,
bleibt es dann auch so – wie ich es haben wollte – erhalten. Ich habe am
Anfang über viele Jahre hinweg alles selbst in Assembler für die AVR
geschrieben – aus Komfort- und Zeitgründen mache ich das nicht mehr, ich
weiß aber zu jedem Zeitpunkt, was der Compiler da für eine Akrobatik
macht, ich weiß ebenfalls, was die Leute oft für eine komische und
völlig unnötige Akrobatik in ihren präsentierten Assemblercodes machen.
Nachtrag: Screenshot angehängt – Dein AVR ist da natürlich auch drin und
ein Assemblerprojekt müsste dementsprechend auch gehen
Johannes F. schrieb:> Niklas G. schrieb:>> Sollte da nicht besser ein Sleep rein um Energie zu sparen?>> Mit Energiesparmodi habe ich mich noch nicht befasst, da ich bisher> keinen Bedarf daran hatte. Hier sollte das auch keine Rolle spielen, da> es eh nur ein Testprogramm ist und ob der Controller nun ein paar> Stunden lang 12 mA zieht oder nicht ...
12 mA? Also mein AVR32DD28 begnügt sich mit 2.6 mA bei 5.0 V und 20 MHz
(korrekt konfiguriert).
"Energie sparen" bei diesem Vorhaben? Merkwürdige Idee, unter den
gegebenen Umständen ein paar mW sparen zu wollen - als Preis dafür aber
eine zum Teil deutliche Verlängerung der Reaktionszeit in Kauf zu
nehmen:
1
; Interruptverzoegerung:
2
; active : 9 T mit 2.6 mA @ 5.0 V
3
; idle : 16 T mit 1.7 mA @ 5.0 V
4
; standby: 45 T mit 0.6 mA @ 5.0 V
Und da ich gerade beim Thema bin:
1
.org PORTA_PORT_vect
2
jmp spiSsIsr ; SPI Slave Select ISR
3
.org TCA0_OVF_vect
4
jmp tcaOvfIsr
5
.org SPI0_INT_vect
6
jmp spiTcIsr ; SPI Transfer Complete ISR
"Zu kurz gesprungen" kann man hier wahrhaft nicht behaupten ...
S. L. schrieb:> 12 mA? Also mein AVR32DD28 begnügt sich mit 2.6 mA bei 5.0 V und 20 MHz> (korrekt konfiguriert).
Die 12 mA hatte ich dem Datenblatt des ATmega328P entnommen, auf diesen
bezog sich daher die Angabe.
S. L. schrieb:> "Zu kurz gesprungen" kann man hier wahrhaft nicht behaupten ...
Vorher hatte ich hier auch RJMPs, aber im Datenbuch stehen dort
natürlich JMPs (bei allen Devices mit mehr als 8KB Flash), daher hatte
ich das geändert. Eigentlich ist mir zwar bewusst, dass RJMPs bei der
von mir gewählten Art der Notation mit den einzelnen .ORG-Direktiven
dort ebenso funktionieren müssten, aber ich wollte sichergehen.
Johannes F. schrieb:> aber im Datenbuch stehen dort> natürlich JMPs (bei allen Devices mit mehr als 8KB Flash)
Aber RJMP funktioniert auch bei denen und in beide Richtungen. Nur wenn
die Sprungdistanz für RJMP zu groß wird, gibt es eine Fehlermeldung und
kein Hex-File wird erzeugt.
Assemblercode >8kB zu erstellen, ist schon ne Menge und dürfte Jahre
dauern.
> Sprungdistanz für RJMP zu groß wird, gibt es eine Fehlermeldung
Eben, und dann ist immer noch Zeit, den Einzelfall zu korrigieren (oder
zu überlegen, ob man nicht etwas umordnet).
Nun gut, es wurden wieder RJMPs draus.
Ich habe wieder den jetzigen Stand angehängt, und versuche mich gerade
am Debuggen in der MPLAB X IDE. Bisher habe ich es noch nicht geschafft,
an irgendwelche nützlichen Informationen zu gelangen. Ich habe mal einen
Breakpoint in Zeile 190 gesetzt, aber scheinbar wird diese überhaupt
nicht erreicht. Seltsamerweise scheint die ISR gar nicht angesprungen zu
werden. Keine Ahnung, woran das liegen könnte. I-Flag ist gesetzt,
SPI-IE ebenso ...
Die spiSsIsr wird dagegen ausgeführt, das "SSFE" wird zweimal
nacheinander gesendet, so wie es sein sollte.
Gregor J. schrieb:> – das UART-Senden aus der Interruptroutine heraus ist generell keine> gute Sache, vor allem dann, wenn man mehrere Bytes absenden möchte und> z.B. zwischendurch warten muss; es sei denn, man kann programmtechnisch> sicherstellen, dass der Sendebuffer in dem Moment nicht voll ist, man> dort in der ISR also etwas ohne Warterei schicken (in den Buffer> schreiben) und anschließend ohne große Verzögerung aus der ISR wieder> verschwinden kann
Wenn man einen Ringbuffer hat und eine Statemaschine, dann schreibt und
liest in/aus dem Buffer wie man lustig ist. Dann kann bspw. der "Data
Register Empty Interrupt" dafür sorgen, dass das nächste Byte aus dem
Ringbuffer automatisch ins Senderegister geschoben wird. Dank Interrupt
passiert das alles im "Hintergrund" ohne künstliche Wartezeiten. Es muss
lauten. Man muss sicherstellen das man den Ringbuffer unter Kontrolle
hat. Dann funktioniert auch der Rest.
> Läuft doch - also ich kann ...
Und wenn ich '.equ DEBUG = 0' setze (nachdem ich nach §loop '.if DEBUG
... .endif ; DEBUG' ergänzte), wird das Ganze sogar relativ flott:
Johannes F. schrieb:> Vorher hatte ich hier auch RJMPs, aber im Datenbuch stehen dort> natürlich JMPs (bei allen Devices mit mehr als 8KB Flash), daher hatte> ich das geändert. Eigentlich ist mir zwar bewusst, dass RJMPs bei der> von mir gewählten Art der Notation mit den einzelnen .ORG-Direktiven> dort ebenso funktionieren müssten, aber ich wollte sichergehen.
Wenn man mit '.org' oder NOPs auf den richtigen Offset achtet, ist es
quasi egal, ob man relative oder absolute Sprünge nimmt, man könnte
vermutlich auch eine Kombination aus NOP+RJMP oder CLI+RJMP nehmen, denn
bei den AVRs handelt es sich nicht um eine echte Vektortabelle, wie man
sie z.B. von dem 68000 oder der STM32 kennt, sondern nur um eine
Pseudo-Vektortabelle, wo einfach der Programmcode ausgeführt wird und
die normalen Befehle für das Laden des Programmcounters missbraucht
werden – diese Art der Sprünge hat damals vermutlich einfach etwas Platz
auf Siliziumebene gespart und man behielt es dann so bis heute bei den
auch neueren Entwicklungen bei. Wenn man überhaupt keine Interrupts
verwendet, kann man den eigentlichen Programmcode gleich ab Adresse 0
anfangen zu schreiben – man kann die Vektortabelle auch in eine andere
Region verlegen und hat diese Möglichkeit, ab 0 direkt mit dem Programm
zu beginnen, dann auch zur Verfügung.
Umgekehrt geht es aber nicht, also wo explizit RJMP verlangt wird,
einfach JMP zu platzieren, allein aufgrund der doppelten Befehlsbreite
ist es nicht möglich – es geht aber auch schon rein physikalisch vom
Code her nicht, denn bei den AVRs mit diesem kleinen Flashspeicher
fehlen (angeblich) auch die absoluten Sprungbefehle im Befehlssatz. Ob
sie wirklich im Silizium nicht abgebildet worden sind, könnte man
bestimmt mit einigen Tests herausfinden – ist aber nur etwas für
irgendwelche Freaks, die sich gerne mit eher unnötigen oder weniger
wichtigen Dingen befassen.
Die Verkleinerung der Latenz der Interruptannahme um den einen Takt ist
im Normalfall eher nicht der Rede wert, wenn man weiß, dass da sowieso
gleich viele PUSHs folgen werden, weil man die Register incl.
Statusregister auf dem Stack retten muss. Bei ganz speziellen
Anwendungen könnte diese Möglichkeit der Takteinsparung oder des
CLI-Befehl-Einschubs doch wieder interessant sein – oft ist es aber
sinnvoller, dann bei solchen zeitkritischen Anwendungen zu einem
anderen, deutlich schnelleren µC zu greifen, wo die CPU mit z.B. 170
oder 550 MHz laufen kann und einige Register in diesem schnellen Takt
auch schon selbständig auf dem Stapel ablegen tut. Wenn auch das nicht
reicht, kann man Dinge auch rein kombinatorisch mit z.B. einer in einem
FPGA abgebildeten Gatter-Logik realisieren und so mit der Antwort auf
ein Ereignis auf die Nanosekundenebene runtergehen, sofern man dazu
befähigt ist.
S. L. schrieb:> Läuft doch - also ich kann (mit meinem Selbstbauprogrammiergerät)> schreiben und lesen.
Hmm, das ist ja seltsam. Ich werde es später noch einmal mit einem
anderen AVR64DD32 versuchen, vielleicht liegt es doch an der Hardware
...
Nachtrag: Habe dasselbe Hex gerade auf einen anderen 64DD32 geflasht und
bekomme beim Programming Enable das Output "AC 53 00 00 ". Dafür wird
aber die fallende Flanke an ¬SS nicht signalisiert. Sehr seltsam. Kann
es vielleicht wirklich sein, dass die Hitzeeinwirkung beim
Heißluftverlöten zu hoch war, sodass manche Teilfunktionen beschädigt
wurden? Oder betrifft sowas immer den ganzen Chip, sodass gar nichts
mehr funktionieren würde?
Gerade fällt mir noch ein, dass diese billigen Dupontkabelchen, die ich
hier auch für sämtliche Verbindungen verwende, ja wohl auch teils
Wackelkontakte verursachen sollen. Vielleicht liegt's auch daran. Werde
heute Nachmittag noch einen Versuch mit besseren starten.
Nachtrag: Eine Platine mit 64dd28 im DIP habe ich auch noch liegen,
darauf werde ich das Programm auch mal laufen lassen. Damit müsste sich
ja ausschließen bzw. bestätigen lassen, dass es an den 64dd32-Exemplaren
liegt.
Haben Sie keine anderen? Es ist ja eine große Familie.
Mit entsprechender CLKCTRL-Anpassung läuft es auch auf einem
AVR32EA28, legt man das TCA-Fragment still auch auf einem AVR16EB28; von
den DA und DB ganz zu schweigen. Und sicher klappt es auch mit einem der
neueren ATtinies.
Allerdings halte ich ein Problem mit den Verbindungen oder der
Stromversorgung für wahrscheinlicher.
Johannes F. schrieb:> Nachtrag: Habe dasselbe Hex gerade auf einen anderen 64DD32 geflasht und> bekomme beim Programming Enable das Output "AC 53 00 00 ". Dafür wird> aber die fallende Flanke an ¬SS nicht signalisiert. Sehr seltsam. Kann> es vielleicht wirklich sein, dass die Hitzeeinwirkung beim> Heißluftverlöten zu hoch war, sodass manche Teilfunktionen beschädigt> wurden? Oder betrifft sowas immer den ganzen Chip, sodass gar nichts> mehr funktionieren würde?
Wie ich bereits schrieb, man muss den/die Fehler in kleinen Schritten
suchen – das geht auch mit einem bereits vollständig geschriebenen
Programm prinzipiell genauso wie mit einem, das man in Schritten erst
entstehen lässt – man legt alles unnötige durch z.B. Auskommentieren
oder Überspringen lahm und lässt nur einen kleinen, zu untersuchenden
Bereich des Programms für die CPU zum Abarbeiten. Wenn dieses Teil wie
erwartet nachweislich und reproduzierbar funktioniert, gibt man einen
weiteren Block des eigenen Codes dazu frei und prüft das dann mit der
neuen Funktion bzw. mit dem zusätzlichen Code. Dupontkabel,
Steckbretter, Steckverbindungen und lange Leitungen sind übrigens für
Interrupteingänge etc. keine gute Wahl – damit macht man sich oft selbst
unglücklich. Und externe Pull-UPs von z.B. 10kΩ können manchmal wahre
Wunder vollbringen, bei manchen Anwendungen muss man mit dem Wert sogar
noch weiter runtergehen. Digitalspeicheroszilloskop unbedingt benutzen,
um sich das alles an den besagten neuralgischen Stellen genau anschauen
zu können – das Arbeiten ohne Oszilloskop gleicht quasi der Arbeit eines
Blinden, wo es darauf ankommt, zu schauen und zu sehen, was vor einem
passiert.
Die Geschichte mit der Überhitzung der ICs ist sehr unwahrscheinlich,
man versucht sich aber damit immer wieder zu trösten und quasi zu
verdrängen, dass es an dem liegen kann, was man da selbst
zusammengebastelt und als Code zusammengedichtet kann. Ich habe in den
letzten 40 Jahren keinen einzigen Transistor, Diode oder IC durch Löten
(mit dem Lötkolben) beschädigen können und bei mancher sehr häufiger,
penetranter Hitzebearbeitung, damit das z.B. fürs Foto gut wird, hatte
ich teilweise auch schon die Befürchtung, dass ich da jetzt vielleicht
übertrieben habe – leider NEIN, alle µC, ICs oder sonstige Halbleiter
haben danach ohne Probleme funktioniert. Das einzige, was ich bem Löten
beschädigt habe, waren sogenannte intelligente SMD-LEDs WS2812 – beim
Erhitzen konnte man durch das Fenster sehen, dass sie im Inneren
platzten, also schlagartig undicht und so geschrottet wurden. Das waren
aber vermutlich Fälschungen, die ich mal vor vielen, vielen Jahren auf
Aliexpress gekauft habe, denn die Orignalteile, die ich mir später bei
TME besorgt hatte, platzten nicht so beim Anlöten. Das Platzen dieser
Fälschungen war übringens reproduzierbar, d.h. es war nicht nur ein IC,
der bei der Herstellung zufällig einen Materialfehler erfahren hatte,
sondern sie waren quasi alle so schlecht hergestellt worden.
S. L. schrieb:> Haben Sie keine anderen? Es ist ja eine große Familie.
Naja, auf dem mega328P läuft es ja, und auf anderen evtl. auch, aber es
geht mir ja im Moment eben darum, warum es auf dem 64DD32 nicht läuft,
und da hilft es mir ja nicht weiter, wenn ich noch andere Devices
versuche.
Die Dupontkabel habe ich eben gegen bessere (die einzelnen von Reichelt)
ausgetauscht, ohne Erfolg, und auch ein externer Pull-Up von 2 kΩ
brachte keine Veränderung.
Nun bin ich gerade dabei, minimale Veränderungen für den 64DD28
vorzunehmen, und werde dann berichten, ob es auf meinem 64DD28-I/SP
funktioniert.
> andere Devices
Ich meinte auch keine AVRe, sondern AVRxt, also 'AVRmxyn', bei denen
keine oder nur minimale Programmänderungen nötig sind. Und wie Sie
selbst auch bemerkten, bringt der simple Wechsel von Hardware manchmal
neue Erkenntnisse in einer so verfahrenen Situation wie der Ihrigen.
Johannes F. schrieb:> warum es auf dem 64DD32 nicht läuft
Vielleicht noch das: um einen Defekt an genau diesem gerade
verwendeteten Chip auszuschließen, müsste man genau in die gleiche
Platine und ohne irgendwelche Veränderungen einen anderen 64DD32 mit
Heißluft etc. einlöten. Diese Änderungen gibt es aber allein schon
aufgrund der Tatsache, dass man für den Lötvorgang z.B. irgendweche
Leitungen abstecken muss. Das heißt, um das wiederum ausschließen zu
können, müsste man anschließend, sofern es tatsächlich mit einem
zweiten, identischen Chip fehlerfrei funktioniert, dann die Chips wieder
umlöten, um zu schauen, ob es mit dem ursprünglichen IC wieder nicht
geht. Damit hätte man zumindest eine gewisse Wahrscheinlichkeit dafür,
dass der erste Chip eine Macke hat oder haben könnte.
Nachtrag: ich habe auch mal einen Blick ein die Errata des 64DD32
geworfen, die scheint aber extrem kurz zu sein bzw. nur sehr wenige
Siliziumfehler zu enthalten, d.h. da ist kaum was drin; das sieht bei
z.B. den AVR_DB und AVR_DA ganz anders aus
Sooo, ich habe endlich den Fehler gefunden: Dieser lag gar nicht beim
Programm 'tn12-isp-simulator', sondern in meinem 'avrispv2', das ich zum
Testen des ersteren benutzte. Dort hatte ich beim Einbau einer
1-ms-Wartezeit zwischen den einzelnen SPI-Bytes (um dem ISP-Simulator
Zeit für die Verarbeitung der Bytes zu geben, bevor das nächste
"geclockt" wird) das Register wri0 mit 1 geladen, und übersehen, dass
dieses zum Zwischenspeichern des empfangenen SPI-Bytes diente ... Daher
konnte natürlich die Erkennung des Echo-0x53 nicht mehr funktionieren.
Also Asche auf mein Haupt und Entschuldigung für die Verwirrungen ...
Ich muss mir wohl eine andere Arbeitsweise angewöhnen, zu oft nehme ich
zu viele Änderungen gleichzeitig an zu vielen Stellen vor, ohne einzeln
zu testen, und weiß dann nicht mehr, wo die Fehler zu suchen sind ...
S. L. schrieb:> Und mit dem ATmega328P als Slave funktionierte alles?
Hmm, ja, das ist allerdings ein guter Einwand. Es ist möglich, dass ich
die fatale Ergänzung im 'avrispv2'-Code erst danach vornahm, nachdem es
mit dem 328P funktionierte; leider kann ich mich an die Abfolge nicht
mehr erinnern.
Wie gesagt, ich arbeite daran, meine Arbeitsweise besser zu
strukturieren, und werde nun erstmal das Interbyte-Delay in 'avrispv2'
eleganter lösen, um danach mit dem Testen des ISP-Simulators fortfahren
zu können. Denn die Signatur wurde soeben nicht korrekt gelesen,
'avrdude' meldete
1
Device signature = 00 01 02
2
Error: expected signature for ATtiny12 is 1E 90 05
Johannes F. schrieb:> Nebenbei bemerkt habe ich auch schon in C programmiert; das war die> erste Sprache
Das ist gut. Bei aller Liebe zu Asm: Wenn man im µC-Bereich unterwegs
ist, führt eigentlich überhaupt kein Weg daran vorbei, C zumindest
"lesend" zu beherrschen. Das ist mindestens genauso wichtig wie
"Datenblatt-Englisch".
"Schreibend" hingegen ist deutlich komplizierter. Selbst sehr viele
Leute, die ausschließlich C schreiben, können es eigentlich nicht
richtig. Witzig ist, dass Assemblerkenntnisse durchaus dabei helfen
können, richtigen Code in C schreiben zu können.
Fakt ist: wer (irgendeinen!) Assembler wirklich kann, wird z.B. sehr
viel seltener in C Fehler der Klassen "off-by-one" oder
"integer-overflow" produzieren. Einfach deshalb, weil er es von Hause
aus gewohnt ist, über derartige Problematiken überhaupt nachzudenken...
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
4
5
System wide configuration file is C:\Users\Johannes\AppData\Local\Programs\avrdude\avrdude.conf
6
7
Using port : com7
8
Using programmer : avrispv2
9
AVR part : ATtiny12
10
Programming modes : ISP, HVSP
11
Programmer type : STK500V2
12
Description : Serial Atmel AVR ISP using STK500v2
13
Programmer model : AVRISP
14
HW version : 0
15
FW Version Controller : 0.00
16
SCK period : 0.1 us
17
18
AVR device initialized and ready to accept instructions
19
Device signature = 1E 90 05 (ATtiny12)
20
Auto-erasing chip as flash memory needs programming (-U flash:w:...)
21
specify the -D option to disable this feature
22
Erased chip
23
Reading 10 bytes for flash from input file 10B.hex
24
in 1 section [0, 9]: 5 pages and 0 pad bytes
25
Writing 10 bytes to flash
26
Writing | ################################################## | 100% 0.16 s
27
Reading | ################################################## | 100% 0.09 s
28
10 bytes of flash verified
29
30
Avrdude done. Thank you.
Damit ist das Eröffnungsproblem dieses Threads endlich gelöst
(ursprünglich wird es sicher eine Folge des vergessenen bzw. falsch
platzierten RAM-Offsets gewesen sein) und ich danke herzlich allen für
die Ratschläge und Hilfe.
Nun kann ich mich weiter der Untersuchung des Flash-Value-Polling im
Zusammenspiel von avrdude, STK500v2 und AVRs ohne RDY/BSY-ISP-Befehl wie
ATtiny12 zur Vervollständigung meines avrispv2-Programms widmen.
Ob S. schrieb:> Das ist gut. Bei aller Liebe zu Asm: Wenn man im µC-Bereich unterwegs> ist, führt eigentlich überhaupt kein Weg daran vorbei, C zumindest> "lesend" zu beherrschen. Das ist mindestens genauso wichtig wie> "Datenblatt-Englisch".
Ja, ich habe mir nun auch vorgenommen, mich mal in "Embedded-C" für AVRs
einzuarbeiten, zunächst mit AVR-GCC oder dem Microchip XC8, da muss ich
noch schauen, für was ich mich entscheide (Empfehlungen wären
willkommen). Kann ja nicht schaden, auch wenn ich für AVRs mich
weiterhin in Assembler vertiefen werde.
Ob S. schrieb:> Fakt ist: wer (irgendeinen!) Assembler wirklich kann, wird z.B. sehr> viel seltener in C Fehler der Klassen "off-by-one" oder> "integer-overflow" produzieren. Einfach deshalb, weil er es von Hause> aus gewohnt ist, über derartige Problematiken überhaupt nachzudenken...
Ja, das kann ich mir gut vorstellen.
> ursprünglich wird es sicher eine Folge des vergessenen> bzw. falsch platzierten RAM-Offsets gewesen sein
Na, da muss ich jetzt aber doch den Bömmel zitieren: "Mer wolle uns nix
weismache" - schließlich lautet der Betreff "... UART-Ausgabe bleibt
hängen ...", und zwar mitten in einer Hex-Ausgabe.
S. L. schrieb:>> ursprünglich wird es sicher eine Folge des vergessenen>> bzw. falsch platzierten RAM-Offsets gewesen sein>> Na, da muss ich jetzt aber doch den Bömmel zitieren: "Mer wolle uns nix> weismache" - schließlich lautet der Betreff "... UART-Ausgabe bleibt> hängen ...", und zwar mitten in einer Hex-Ausgabe.
Ja, der Delinquent hat ziemlich sicher das eigentliche Problem nicht
gefunden. Die beste Näherung war wohl:
> zu oft nehme ich> zu viele Änderungen gleichzeitig an zu vielen Stellen vor, ohne einzeln> zu testen, und weiß dann nicht mehr, wo die Fehler zu suchen sind ...
Ist aber ganz grundsätzlich auch viel schwieriger, wenn es mehr als ein
Programm gibt, sondern zwei auf zwei MCUs, die miteinander hakeln
sollen. Da hilft nur Disziplin und Debug-Erfahrung.
Aber gewinnen kann man diese Debug-Erfahrung halt nur, indem man es tut.
Ich denke, ihm ist zumindest klar geworden, dass er es unbedingt
systematischer tun muss.
Ob S. schrieb:> Ja, der Delinquent hat ziemlich sicher das eigentliche Problem nicht> gefunden.
Scheint so, denn momentan (nach dem Wechsel zurück zum 64DD32) habe ich
wieder das Problem, dass beim Programming Enable nur Nullen empfangen
werden (nachdem es auf dem 64DD28 funktioniert hat):
1
Received command SIGN_ON
2
Received command GET_PARAMETER 90
3
Received command GET_PARAMETER 91
4
Received command GET_PARAMETER 92
5
Received command ENTER_PROGMODE
6
AC 00
7
53 00
8
00 00
9
00 00
10
Received command LEAVE_PROGMODE
Habe also noch einiges zu tun ...
Ob S. schrieb:> Ich denke, ihm ist zumindest klar geworden, dass er es unbedingt> systematischer tun muss.
Ja, definitiv.
Werde gleich mal mein RTC1002 dran hängen und nachsehen, was da auf dem
SPI wirklich abläuft. Hätte ich schon eher mal tun sollen ...
"System muß sein", schreibt Arno Schmidt an einer Stelle - und seinen
Nachsatz verschweige ich jetzt lieber.
Beim Wechsel vom DIP-AVR64DD28 auf den DD32 tritt ein Problem auf? Kann
doch eigentlich nicht sein, ist doch dasselbe Programm. Stromversorgung,
vor allem auch die Masseverbindung, ist aber in Ordnung?
S. L. schrieb:> Stromversorgung,> vor allem auch die Masseverbindung, ist aber in Ordnung?
Ja, die sollte hinreichend gut sein, inzwischen habe ich drei parallele
Dupontkabel als Masseverbindung zwischen den AVRs, die über SPI
kommunizieren. Die werden ja hoffentlich nicht alle drei gleichzeitig
Wackelkontakt haben. Bei nächster Gelegenheit werde ich mir auch
Dupontkabel selbst herstellen, eine Crimpzange und Kontakte dafür habe
ich mir schon besorgt, sodass ich dann sichergehen kann, dass die
Quetschverbindungen dann ordentlich sind.
Stromversorgung erfolgt vom PC über einen CH340-USB-UART-Adapter
(Platine von mq-pcb.de) mit 5,0 V.
Ansonsten ist mein Aufbau schon etwas improvisiert, das muss ich
zugeben, aber elektrisch müsste es eigentlich OK sein. Mit dem
DIP-64DD32 hat es ja auch funktioniert. Ich bin nun schon am überlegen,
ob mit meinen selbst designten und von JLC gefertigten
AVR-DB/DD32-Boards irgendwas nicht stimmt.
Und das haben Sie überprüft: Spannung gemessen an beiden Vdd-GND-Paaren
des DD32, Spannung an VDIO2, Durchgang zwischen den GNDs der beiden uCs,
immer direkt an den ICs?
Johannes F. schrieb:> Ja, ich habe mir nun auch vorgenommen, mich mal in "Embedded-C" für AVRs> einzuarbeiten, zunächst mit AVR-GCC oder dem Microchip XC8, da muss ich> noch schauen, für was ich mich entscheide.
Soweit mir bekannt, basiert xc8 für AVR auf den GNU-Tools (avr-gcc
etc.), allerdings hat Microchip einige Optimierungen deaktiviert, die
man per zu erwerbender Lizenz zukaufen kann...
Ich lasse mich da aber gerne eines besseren belehren.
Die Haupunterschied bei Verwendung der GNU-Tools sind:
1) Es wird der GNU-Assembler verwendet, der etwas andere Direktiven als
AVRA etc. verwendet. Siehe etwa
https://avrdudes.github.io/avr-libc/avr-libc-user-manual/assembler.html#ass_directives
2) Verwendung eines Linker/Locators zur Erstellung eines lauffähigen
Programms. Zunächst werden Ojbect-Dateien erstellt (aus C/C++ oder
Asm), die dann mit (Code aus) Libs wie AVR-LibC und libgcc zum
ausführbaren Programm vervollständigt werden.
S. L. schrieb:> Und das haben Sie überprüft: Spannung gemessen an beiden Vdd-GND-Paaren> des DD32, Spannung an VDIO2, Durchgang zwischen den GNDs der beiden uCs,> immer direkt an den ICs?
Hole ich gleich noch nach ...
Vorab nur schonmal der Zwischenstand: Ich habe nun nochmal exakt
dasselbe .Hex, das auf dem DD32(1) nicht funktionierte, auf den DD28
geflasht, und – dort funktioniert es einwandfrei.
Anschließend habe ich den DD32(2) (zweites Exemplar meiner
selbstgelöteten Breakout-Platine) angeschlossen und nochmal das letzte
.Hex geflasht – auch hier läuft es nun, wie es sein soll.
Danach habe ich das ZIP aus dem Eröffnungsbeitrag wieder heruntergeladen
und darin die bekannt gewordenen Fehler (vergessenes Offset
'simFlash_sram') behoben sowie die Zeichenketten auf wenige Buchstaben
gekürzt, dieses assembliert und geflasht, und auch dieses funktioniert
nun auf DD32(2):
1
SSFE
2
SSFE
3
RSB 00
4
RSB 01
5
RSB 02
6
CE
7
SSFE
8
RPM 0004 00
9
RPM 0005 00
10
WPM 0000 AA
11
WPM 0001 BB
12
WPM 0002 CC
13
WPM 0003 DD
14
WPM 0004 EE
15
WPM 0005 00
16
RPM 0000 AA
17
RPM 0001 BB
18
RPM 0002 CC
19
RPM 0003 DD
20
RPM 0004 EE
21
RPM 0005 00
Somit sind wir ein ganzes Stück weiter, denn der Fehler ist damit auf
die Hardware des DD32(1) eingegrenzt. Nun bleibt nur noch diese zu
untersuchen, ob irgendeine Lötverbindung schlecht ist, ein Kurzschluss
besteht, oder der Chip wirklich beschädigt ist.
Johannes F. schrieb:> Stromversorgung erfolgt vom PC über einen CH340-USB-UART-Adapter> (Platine von mq-pcb.de) mit 5,0 V.> Ansonsten ist mein Aufbau schon etwas improvisiert, das muss ich> zugeben, aber elektrisch müsste es eigentlich OK sein. Mit dem> DIP-64DD32 hat es ja auch funktioniert. Ich bin nun schon am überlegen,> ob mit meinen selbst designten und von JLC gefertigten> AVR-DB/DD32-Boards irgendwas nicht stimmt.
Hier noch ein Foto von meinem ersten und provisorischen Aufbau von
damals mit dem AVR128DB28, um alles genau zu prüfen und sich in die
neue-AVR-Familie einzuarbeiten – ich wollte hier auch wissen, ob man das
alles über den Snap und mit Atmel Studio 7 betreiben kann, incl.
Debugging etc. Die Adapterplatine mit dem µC habe ich direkt mithilfe
von Stiftleisten in das Lochrasterfeld meiner Platine eingelötet, um
keine Steckverbindungen der µC-Pins zu haben – vor allem die
Quarzverbindung ist bei dieser neuen Familie sehr störanfällig. Wenn man
den Quarz in die Präzisionsfassung (rechts vom Chip) einsetzt und z.B.
hin und her bewegt, läuft der µC Amok oder er stürzt regelrecht ab. bzw.
geht in den CFD-Notfallmodus, weil ich das auch getestet habe – durch
diese Wackeldackel-Geschichte scheint diese Umschaltung in den
Notbetrieb aber auch nicht immer sicher zu funktionieren. Das heißt, den
Quarz muss man hier definitiv verlöten, weil durch die relativ niedrige
Core-Spannung der µController und damit durch den LowPower-Betrieb der
Oszillatorschaltung das ganze nicht so robust wie bei den alten AVRs mit
Full-Swing-Betrieb ist – ich habe das hier mit dem Quarz steckbar
gemacht, um es mit verschiedenen Quarzen zu testen, weil es ja in dem
ganzen Spannungsbereich auch bis 24MHz laufen sollte und es auch tut.
Richtige Evaluationsplatinen für AVR128DB128 etc. sind schon in Planung,
3/4 des Kerns habe ich schon fertig entworfen – das dauert aber bestimmt
noch ein paar Wochen, bis ich sie habe, ich kann Dir aber gerne per
eMail Bescheid geben, wenn es Dich interessiert, um z.B. ein paar von
den ersten etwas günstiger zu bekommen.
Hier ein Foto von meinem derzeitigen sehr provisorischen Aufbau mit
einem meiner ATtiny3227-Boards und zwei USB-UART-Bridges, der aber
momentan gut funktioniert. Das USB-Kabel des Snaps ist mit
Paketklebeband an der Tischkante befestigt, damit das Ganze nicht
unkontrolliert umherwandert und evtl. noch Kurzschlüsse verursacht –
einen Adapter für den Snap als 100×100-mm² große Motherboard-Platine
(die hoffentlich schwer genug wird, um auf dem Tisch liegen zu bleiben –
ansonsten werde ich einfach noch eine leere Platine unten drunter mit
Abstandsbolzen schrauben) habe ich bereits fertigen lassen, müsste heute
oder spätestens morgen bei mir ankommen.
Gregor J. schrieb:> ich kann Dir aber gerne per> eMail Bescheid geben, wenn es Dich interessiert, um z.B. ein paar von> den ersten etwas günstiger zu bekommen.
Gerne, ich schreibe dir gleich mal per Mail.
Cyblord -. schrieb:> Wenn ich schon diese Mini-Breadboards und zig zusammengestoppelte> Platinen sehe, dann weiß ich schon dass da nie was zuverlässig> funktionieren kann.
Naja, irgendwie muss man ja mal was ausprobieren und experimentieren
können. Ich kann und will ja nicht für jede erdenkliche Kombination eine
komplette Platine fertigen lassen. Und mit vernünftigen Dupontkabeln
funktioniert das auch.
Wenn es dann wirklich zuverlässig werden soll und die endgültige
Schaltung feststeht, kann man ja immer noch eine Platine dafür machen.
Bis dahin muss es nicht weltraumfest sein.
Johannes F. schrieb:> Gerne, ich schreibe dir gleich mal per Mail.
Habe es heute Morgen nicht mehr geschafft, ich schreib dir dann
nachmittags.
Johannes F. schrieb:> Habe es heute Morgen nicht mehr geschafft, ich schreib dir dann> nachmittags.
Kein Problem, eilt ja nicht. Ach ja, falls Du auch etwas Robustes für
den Snap haben möchtest, dann könnte ich Dir sogar eine unbestückte
Adapterplatine von dem ersten Wurf für den Snap gratis abgeben (Foto im
Anhang). Für die AVR_Dx passt dann die UDPI_v2 mit RESET, VTG, GND und
UPDI, die sich in der Mitte befindet – auf den Evaluationsplatinen wird
es diese Reihenfolge dann auch exakt so geben. Reset braucht man nicht
unbedingt, d.h. drei Leitungen würden reichen, aber falls man es
braucht, ist es da. Die UPDI_v1, die sich innerhalb der
2x3-ISP-Schnittstelle befindet, kann man natürlich auch abgreifen und
nutzen, diese 2x3-Stiftleisten verwende ich auf meinen Leiterplatten
aber nur für die alten AVRs, wo man über ISP programmiert. Die große
Platine (Maxi) für den Snap muss ich noch machen.
Johannes F. schrieb:> Und mit vernünftigen Dupontkabeln funktioniert das auch.
Ich war auch schon am überlegen, alle Anschlüsse meiner Boards auf
Schraubklemmen (im 3,5-mm-Raster oder kleiner, wenn es gibt) zu führen,
und dann mit Litzenabschnitten mit Aderendhülsen zu verbinden. Wäre
natürlich schöner und robuster, aber auch deutlich teurer.
Johannes F. schrieb:> Ich war auch schon am überlegen, alle Anschlüsse meiner Boards auf> Schraubklemmen (im 3,5-mm-Raster oder kleiner, wenn es gibt) zu führen,> und dann mit Litzenabschnitten mit Aderendhülsen zu verbinden. Wäre> natürlich schöner und robuster, aber auch deutlich teurer.
So ganz ohne Dupont wird es beim schnellen, günstigen Prototypen nicht
gehen – ich mache es in der Regel so, dass alles, was verlötet werden
kann oder muss, dazu gehören z.B. VCC und GND, auch verlötet wird. Wenn
VCC+GND nicht verlötet wird, dann habe ich selbstgemachte
Krokodilklemmen-Leitungen, wo es an der Krokodilklemme verlötet ist und
der Querschnitt der Leitung zumindest 100mA ohne nennenswerten
Spannungsabfall durchlässt. Mit diesen Krokodilklemmen kann man relativ
sicher an Stiftleisten andocken – Wackelkontakte gibt es hier nicht,
wenn man mit der Klemme gleich zwei Stiftleisten schnappt. Diese
günstigen, dünnen, fertiggekauften Krokodilklemmen-Leitungen sind dafür
nicht geeignet – wie dünn die Leitung ist, sieht man, wenn man sie
abschneidet oder sie nach intensivem Gebrauch von alleine abbricht.
Taster, LEDs und UART-Verbindung kann man mit frischen (nicht
ausgeleierten) Dupontkabel anbinden, Schnittstellen wie I2C oder SPI
verbinde ich nicht gerne über Dupontkabel bei Tests, aber für einen
kurzen Test geht es auch. Bei dedizierten Interrupteingängen muss man
anders vorgehen – „Antennen” aller Art sind hier extrem kontraproduktiv.
µController verlöte ich in der Regel immer, selbst die Adapterplatine,
auf der sie verlötet wurden, wird wiederum auch verlötet (so wie hier
bei dem AVR128DB28 in SO28), nur bei PDIP nehme ich auch mal Sockel,
allerdings nur Präzisionsfassungen, weil diese einfachen Federkontakte
sehr schnell Kontaktprobleme bereiten können. Ich habe jetzt auch einen
Fall, wo ich eine PLCC-Fassung verwenden werde – diese Fassungen sind
aber ziemlich sicher und robust, insofern auch OK. In ganz speziellen
Fällen verwende ich Zerokraftsockel und dann dafür entsprechend auf
Adapterplatinen aufgelötete ICs mit Stiftleisten im 2,54mm-Raster für
den großen oder auch kleinen Sockel – hier gibt es dann definitiv keine
Wackelkontakte (zwei Fotos im Anhang). Diese Nullkraftsockel sind
natürlich ziemlich teuer, dafür bekommt man aber die Sicherheit, dass es
keine Wackeldackel gibt. Steckbretter benutze ich wegen dieser genannten
Gründe überhaupt nicht – das ist ja quasi eine Ansammlung von
Wackelkontakten und parasitären Kapazitäten, die man sich da auf den
Tisch stellt; wenn etwas provisiorisch aufgebaut werden muss, dann wird
es zumindest auf Lochrasterplatinen ordentlich verlötet (wie ich es z.B.
mit dem AVR128 gemacht habe).
PS: Schraubklemmen gibt es auch im 2,54mm-Raster, sind aber auch relativ
teuer und diese verkleinerte Konstruktion ist entsprechend filigran
Hallo,
@ Johannes,
https://www.mikrocontroller.net/attachment/660229/IMG_20250205_080120.jpg
bei deinem Foto sieht man unten 2 Folien die mindestens dort nichts zu
suchen haben.
Die hellere rötliche könnte Antistatisch sein.
Die untere größere silbrige ist Antistatisch.
Antistatische Folie macht zwar keinen direkten satten Kurzschluss, aber
es bedeutet eine gewisse Leitfähigkeit. Das zusammen mit hochohmigen
Eingängen ... Sowas hat unter Leiterplatten im Betrieb definitiv nichts
zu suchen.
Veit D. schrieb:> Antistatische Folie macht zwar keinen direkten satten Kurzschluss, aber> es bedeutet eine gewisse Leitfähigkeit. Das zusammen mit hochohmigen> Eingängen ... Sowas hat unter Leiterplatten im Betrieb definitiv nichts> zu suchen.
Antistatische Folien haben Ableitwiderstände im Gigaohmbereich pro mm
Abstand. Das bestätigt auch der Test mit zwei Messspitzen, in
geringstmöglichem Abstand voneinander auf die Folie gedrückt, ein
Multimeter zeigt bei mir OL im 200-MΩ-Bereich. Ich bezweifle, dass sich
das bei den Schaltungen, mit denen ich hantiere, auswirken könnte.
Anbei ein Foto meines Snap-Adapters, den ich seit heute Nachmittag in
Benutzung habe. Die 90°-Stiftleiste ist eine Ausführung mit extra langen
THT-Beinchen (Samtec TSW-108-09-L-S-RA), die hier wegen der
Abstandshalter unter dem Snap notwendig ist (und die sind sicher auch
vorteilhaft, damit keine Kurzschlüsse der Beinchen der
Snap-Buchsenleiste zur Massefläche bzw. Leiterbahnen des Motherboards
entstehen).
Hallo,
ESD konform ist alles unter 1GOhm. Und mit einem normalen Multimeter
brauch man dafür nicht anfangen. Aber warum schreib ich hier überhaupt
noch.
Veit D. schrieb:> Aber warum schreib ich hier überhaupt> noch.
Nichts für ungut, sorry dass meine Antwort negativ rüber kam, war nicht
so gemeint. Ich kann mir halt nur nicht vorstellen, dass diese sehr
geringe Leitfähigkeit dieser ESD-Oberflächen in diesem Fall etwas
ausmacht. Vielleicht irre ich mich auch, kenne mich auch nicht genau
damit aus. Hatte die Tütchen auch als Unterlage vorhin direkt entfernt
und durch Papier ersetzt.
Ich habe übrigens noch drei dieser Snap-Motherboards übrig und würde sie
zum Selbstkostenpreis abgeben, falls jemand Bedarf hat.
Johannes F. schrieb:> Anbei ein Foto meines Snap-Adapters, den ich seit heute Nachmittag in> Benutzung habe.
Glückwunsch dazu, denn reale Erfolge sind wichtig fürs Weiterkommen –
damit sollten aber auch die Probleme mit dem Klebeband jetzt beseitigt
sein : )
Gregor J. schrieb:> Glückwunsch dazu, denn reale Erfolge sind wichtig fürs Weiterkommen –> damit sollten aber auch die Probleme mit dem Klebeband jetzt beseitigt> sein : )
Vielen Dank :·) Ist ja ein sehr einfaches Layout, aber das Board erfüllt
seinen Zweck, der Snap bzw. die Verbindung USB-Kabel/-Buchse ist mit dem
Kabelbinder um das USB-Kabel auch gut darauf fixiert.
Das Kabel habe ich dennoch auch wieder an der Tischkante angeklebt,
damit das Board nicht auf dem Tisch umherwandert, getrieben durch
etwaige Bewegungen des recht starren Kabels.
Johannes F. schrieb:> Das Kabel habe ich dennoch auch wieder an der Tischkante angeklebt,> damit das Board nicht auf dem Tisch umherwandert, getrieben durch> etwaige Bewegungen des recht starren Kabels.
Ja, das schwarze USB-Kabel für den Snap scheint auch etwas dick zu sein
– ich verwende hierfür ein einfaches, dünnes Kabel, das auch für meine
Smartfones verwendet werden kann, um sich mit dem PC zu verbinden. Ich
habe im Laufe der Jahre auf dem „Hauptarbeitsplatz” auch ein System der
Anordnung der Kabel entwickelt bzw. es hat sich halt in diese Richtung
entwickelt, wo die Spannungsquelle (Netzteil) links steht und
dementsprechend auch von links an meine Leiterplatten angeschlossen
werden kann und die Signalkabel wie USB oder µC-Programmieranschlüsse in
der Regel von rechts in die Platinen gesteckt werden können, weil auch
der PC auf der rechten Seite steht und sie von dort kommen. Auch das
Oszilloskop steht auf der rechten Seite. Dieses Konzept versuche ich
jetzt bei mir (auf allen Arbeitsplätzen) beizubehalten – es muss aber
schon jeder selbst für sich herausfinden oder herauskristallisieren, was
ihm am besten zusagt. Bei einem meiner Kunden kann das auch genau
umgekehrt und deshalb problematisch sein – aber so ist halt das Leben,
man kann und wird es nicht allen Recht machen können und irgendwo muss
man dann auch einen Punkt machen und das ganze einheitlich festlegen
bzw. durchziehen. Problematisch und chaotisch wird es nur dann, wenn es
jedesmal anders ist, weil man bei den eigenen Entwürfen gar nicht auf
die Ausrichtung der Stecker und Buchsen achtet – aber auch damit muss
dann schon jeder selbst irgendwie klarkommen oder sich arrangieren.
Gregor J. schrieb:> Ja, das schwarze USB-Kabel für den Snap scheint auch etwas dick zu sein> – ich verwende hierfür ein einfaches, dünnes Kabel,
Ja das stimmt, es ist recht dick, aber ich dachte immer, dass das für
höhere Qualität spricht - evtl. bessere Abschirmung - kann aber auch ein
Trugschluss sein.
Leider hat der SNAP keine USB-C-Buchse, denn dafür habe ich bessere
i.S.v. flexiblere Kabel.
Gregor J. schrieb:> Dieses Konzept versuche ich jetzt bei mir (auf allen Arbeitsplätzen)> beizubehalten – es muss aber schon jeder selbst für sich herausfinden> oder herauskristallisieren, was ihm am besten zusagt.
Hmm, ich hatte bisher immer die Anschlüsse so platziert, wie es fürs
Layout am günstigsten war - aber stimmt, wenn ich die Platinen nun
doppelseitig fertigen lasse, habe ich da natürlich mehr Freiheiten und
kann auch an die praktischen Aspekte denken.
Johannes F. schrieb:> Ja das stimmt, es ist recht dick, aber ich dachte immer, dass das für> höhere Qualität spricht - evtl. bessere Abschirmung - kann aber auch ein> Trugschluss sein.
Bei der moderaten Übertragungsgeschwindigkeit, die der Snap nutzt, muss
hier kein Supa-Dupa-Kabel verwendet werden, auch von der
Strombelastbarkeit bzw. vom Spannungsabfall her gesehen ist das ziemlich
egal, denn die USB-Spannung der Buchse wird ausschließlich für die
Snap-Schaltung verwendet, weil das VTG-Konzept des Snaps so gedacht ist,
dass VTG eine separate, externe Spannung sein soll, die gleichzeitig
auch die vielen kleinen Levelshifter, die da am Ende der IOs verbaut
sind, versorgt. Das ist auch besser so, dass man es so explizit getrennt
hat, denn jeder Kurzschluss oder zu hoher Strombedarf, der durch die
Targetschaltung verurascht werden könnte, würde auch Auswirkungen auf
die Stromversorgung des Snaps haben und womöglich zu irgendwelchen
Funktionsstörungen oder Restarts führen – das sollte auch jeder
bedenken, der auf Teufel komm raus die Spannung dieser USB-Buchse nutzen
möchte. Der µC des Snaps wird auch handwarm, aber bei 300 MHz als Takt
(oder womit auch immer der µC da in dieser Größenordung läuft) ist das
ganz normal und bedeutet nicht, dass hier extrem viel Strom fließt –
100mA reichen bei 3,3V völlig aus, um die Wärmeentwicklung am IC-Gehäuse
mit der Hand deutlich zu spüren. Die alten 8751, 68000, die noch nicht
in CMOS hergestellt wurden, wurden bei 5V und 170-200mA mit nur 12 bzw.
8 MHz alt Takt schon richtig heiß.
Habe soeben alle Füßchen des betreffenden AVR64DD32 mit viel Flussmittel
und Lötkolben nachgelötet, die Lötstellen sehen alle m.E.n. gut aus,
nichts auffälliges zu sehen. Trotzdem funktioniert er nach wie vor
nicht, dasselbe Programm auf einem anderen DD32 auf baugleicher Platine
dagegen schon. Ich verbuche den ersten DD32 nun einfach als defekt,
vielleicht hat er auch irgendwie ESD-mäßig mal was abbekommen, obwohl
ich darauf eigentlich immer achte.
Wie auch immer, so langsam vergeht mir die Lust auf die Suche nach der
exakten Ursache, ich werde den Fall jetzt ad acta legen, dieser Thread
kann damit als erledigt betrachtet werden. Vielen aufrichtigen Dank an
alle für die hilfreichen Antworten.