AVR64DD32, UART-Ausgabe bleibt hängen, Assembler

OP #7821361
Lesenswert?

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

Angehängte Dateien:
OP #7821373
Lesenswert?

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:
5
sendDbgByte0:
6
  xin    wri0, USART0_STATUS
7
  sbrs  wri0, USART_DREIF_bp
8
  rjmp  sendDbgByte0
9
  pop    wri0
10
  xout  USART0_TXDATAL, wri0
11
  ret
#7821382
Lesenswert?

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.

#7821393
Lesenswert?

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.

OP #7821396
Lesenswert?

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.

Persönliche Seite #7821458
Lesenswert?

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?

OP #7821470
Lesenswert?

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.

#7821494
Lesenswert?

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.

Persönliche Seite #7821500
Lesenswert?

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.

OP #7821501
Lesenswert?

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."

OP #7821502
Lesenswert?

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.

Persönliche Seite #7821524
Lesenswert?

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

1
long x;
2

3
__attribute__((signal(1)))
4
void my_isr (void)
5
{
6
    __asm ("cli" ::: "memory");
7
    x *= x;
8
    __asm ("sei" ::: "memory");
9
}

zu:

1
0000011e <my_isr>:
2
 11e:  0f 92         push  r0
3
 120:  0f b6         in  r0, 0x3f  ; 63
4
 122:  0f 92         push  r0
5
 124:  1f 92         push  r1
6
 126:  11 24         eor  r1, r1
7
 128:  2f 93         push  r18
8
 12a:  3f 93         push  r19
9
 12c:  4f 93         push  r20
10
 12e:  5f 93         push  r21
11
 130:  6f 93         push  r22
12
 132:  7f 93         push  r23
13
 134:  8f 93         push  r24
14
 136:  9f 93         push  r25
15
 138:  af 93         push  r26
16
 13a:  bf 93         push  r27
17
 13c:  f8 94         cli <---------------------------------------
18
 13e:  60 91 34 01   lds  r22, 0x0134  ; 0x800134 <x>
19
 142:  70 91 35 01   lds  r23, 0x0135  ; 0x800135 <x+0x1>
20
 146:  80 91 36 01   lds  r24, 0x0136  ; 0x800136 <x+0x2>
21
 14a:  90 91 37 01   lds  r25, 0x0137  ; 0x800137 <x+0x3>
22
 14e:  9b 01         movw  r18, r22
23
 150:  ac 01         movw  r20, r24
24
 152:  0e 94 21 02   call  0x442  ; 0x442 <__mulsi3>
25
 156:  60 93 34 01   sts  0x0134, r22  ; 0x800134 <x>
26
 15a:  70 93 35 01   sts  0x0135, r23  ; 0x800135 <x+0x1>
27
 15e:  80 93 36 01   sts  0x0136, r24  ; 0x800136 <x+0x2>
28
 162:  90 93 37 01   sts  0x0137, r25  ; 0x800137 <x+0x3>
29
 166:  78 94         sei <---------------------------------------
30
 168:  bf 91         pop  r27
31
 16a:  af 91         pop  r26
32
 16c:  9f 91         pop  r25
33
 16e:  8f 91         pop  r24
34
 170:  7f 91         pop  r23
35
 172:  6f 91         pop  r22
36
 174:  5f 91         pop  r21
37
 176:  4f 91         pop  r20
38
 178:  3f 91         pop  r19
39
 17a:  2f 91         pop  r18
40
 17c:  1f 90         pop  r1
41
 17e:  0f 90         pop  r0
42
 180:  0f be         out  0x3f, r0  ; 63
43
 182:  0f 90         pop  r0
44
 184:  18 95         reti
OP #7821544
Lesenswert?

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.

#7821573
Lesenswert?

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.

#7821599
Lesenswert?

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.

OP #7821658
Lesenswert?

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.

Angehängte Dateien:
#7821694
Lesenswert?

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.

OP #7821786
Lesenswert?

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.

Angehängte Dateien:
#7821794
Lesenswert?

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:

1
SSFE
2
RSB 00
3
RSB 01
4
RSB 02
5
CE
6
WPM 0000 AB
7
WPM 0001 CD
8
WPM 0002 EF
9
WPM 0003 45
10
WPM 0004 FF
11
WPM 0005 FF
12
WPM 0006 FF
13
WPM 0007 FF
14
WPM 0008 FF
15
...
16
...

PS: Also mein AVRe-'Programm' war einfach:

1
.cseg
2
.db  $AB,$CD,$EF,$45
OP #7821797
Lesenswert?

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 ...

#7821914
Lesenswert?

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:
9
  ld  wri1, z
10
  xout  SPI0_DATA, wri1

Text ausgegeben.

OP #7822021
Lesenswert?

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).

Angehängte Dateien:
(Firma: 1984now) #7822158
Lesenswert?

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"...

#7822163
Lesenswert?

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\inc\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

#7822169
Lesenswert?

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.

OP #7822178
Lesenswert?

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.

OP #7822179
Lesenswert?

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.

OP #7822191
Lesenswert?

Karl B. schrieb:

I2C_Test_.asm

Wenn wir schon bei "Quatsch" waren:

1
.dseg    ; Datensegment (SRAM) Start bei 
2
.org 0x0060  ; Adresse 0x0060;           ; Konstanten-Definitionen:
3
.equ daten = portb
4
.equ zeit0 = 500
5
.equ zeit1 = 65535
6
;

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.

1
; Interrupt Vektoren Einsprungadressen (default)
2
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
.org 0x0001  ; ext IRQ0 Flanke
4
rjmp INT00   
5
.org 0x0002  ; ext IRQ1 Flanke
6
rjmp INT10   
7
.org 0x0003  ; Timer 1 capt
8
rjmp ICP10
9
.....
10
WDTAD:    ; ISR not in use
11
reti
12
PCIAA:    ; ISR not in use
13
reti
14
PCIDA:    ; ISR not in use
15
reti

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).

#7822202
Lesenswert?

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

OP #7822210
Lesenswert?

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".

Persönliche Seite #7822218
Lesenswert?

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...

OP #7822220
Lesenswert?

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 ...

(Firma: 1984now) #7822228
Lesenswert?

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.

OP #7822233
Lesenswert?

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).

(Firma: 1984now) #7822248
Lesenswert?

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.

OP #7822258
Lesenswert?

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.

#7822270
Lesenswert?

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 im Beitrag #7822170:

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

(Firma: 1984now) #7822280
Lesenswert?

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.

OP #7822284
Lesenswert?

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.

OP #7822295
Lesenswert?

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.

(Firma: 1984now) #7822334
Lesenswert?

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).

OP #7822348
Lesenswert?

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 ...

#7822356
Lesenswert?

Derart Kompaktes lässt sich, so man will, als

1
   tst    reg0
2
   breq   pc+2
3
    mov    reg0, reg1
4
   ldi    reg2, 42
5

6
    rcall doit
7
    dec  reg2
8
   brne  pc-2

schreiben. Verlangt allerdings, sobald es über mehr als 2-3 Zeilen geht, eine hohe Disziplin bei Programmänderungen.

(Firma: 1984now) #7822359
Lesenswert?

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".

OP #7822396
Lesenswert?

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.

(Firma: 1984now) #7822418
Lesenswert?

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.

OP #7822422
Lesenswert?

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.

(Firma: 1984now) #7822470
Lesenswert?

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...

OP #7822491
Lesenswert?

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.

Persönliche Seite #7822512
Lesenswert?

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...

(Firma: 1984now) #7822520
Lesenswert?

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.

(Firma: Jasinski) #7822522
Lesenswert?

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.

Persönliche Seite #7822527
Lesenswert?

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.

(Firma: 1984now) #7822534
Lesenswert?

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.

#7822538
Lesenswert?

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:

1
ARM Cortex-M33 – Processor-Datasheet
2
ARM Cortex-M33 – Technical Reference Manual
3
ARM v8-M – Architecture Reference Manual
(Firma: Jasinski) #7822688
Lesenswert?

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?

OP #7822722
Lesenswert?

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

OP #7822775
Lesenswert?

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.

(Firma: Jasinski) #7822781
Lesenswert?

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

OP #7822784
Lesenswert?

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.

Persönliche Seite #7822785
Lesenswert?

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.

(Firma: Jasinski) #7822790
Lesenswert?

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.

#7822792
Lesenswert?

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.

(Firma: Jasinski) #7822824
Lesenswert?

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.

OP #7822833
Lesenswert?

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.

(Firma: Jasinski) #7822846
Lesenswert?

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

Angehängte Dateien:
#7822952
Lesenswert?

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 ...

OP #7822988
Lesenswert?

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.

#7822992
Lesenswert?

im Datenbuch stehen dort natürlich JMPs

1
Gewöhnlich glaubt der Mensch, wenn er nur Worte hört,
2
Es müsse sich dabei doch auch was denken lassen.

Aber zugegeben, es geht in diesem Fall nur um einen einzigen Takt; das restliche Programm bietet ganz anderes Potenzial.

OP #7823009
Lesenswert?

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.

Angehängte Dateien:
#7823028
Lesenswert?

?

Läuft doch - also ich kann (mit meinem Selbstbauprogrammiergerät) schreiben und lesen.

1
f
2
~ 2M5  ~ 2M0  ~ 1M25 ~ 833k ~ 200k ~  50k ~  25k ~  7k7 ~ 0k95
3
4H > 0000
4
0000  0000 0000 0000 0000 0000 0000 0000 0000
5
0008  0000 0000 0000 0000 0000 0000 0000 0000
6
0010  0000 0000 0000 0000 0000 0000 0000 0000
7
0018  0000 0000 0000 0000 0000 0000 0000 0000
8

9
F
10
~ 2M5  ~ 2M0  ~ 1M25 ~ 833k ~ 200k ~  50k ~  25k ~  7k7 ~ 0k95
11
*0004 v
12
0004
13
f
14
~ 2M5  ~ 2M0  ~ 1M25 ~ 833k ~ 200k ~  50k ~  25k ~  7k7 ~ 0k95
15
4H > 0000
16
0000  2301 6745 AB89 EFCD FFFF FFFF FFFF FFFF
17
0008  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
18
0010  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
19
0018  FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF

bei 'Programm': .db $01,$23,$45,$67,$89,$AB,$CD,$EF

#7823040
Lesenswert?

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.

#7823050
Lesenswert?

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:

1
F
2
~ 2M5  ~ 2M0  ~ 1M25 ~ 833k ~ 200k
3
*0004 v
4
0004
5
f
6
~ 2M5  ~ 2M0  ~ 1M25 ~ 833k ~ 200k
7
4H > 0000
8
0000  2301 6745 AB89 EFCD FFFF FFFF FFFF FFFF
(Firma: Jasinski) #7823208
Lesenswert?

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.

OP #7823229
Lesenswert?

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?

OP #7823275
Lesenswert?

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.

#7823390
Lesenswert?

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.

(Firma: Jasinski) #7823391
Lesenswert?

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.

OP #7823424
Lesenswert?

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.

Beitrag #7823434 wurde von einem Moderator gelöscht.
#7823442
Lesenswert?

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.

(Firma: Jasinski) #7823446
Lesenswert?

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

OP #7823452
Lesenswert?

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 ...

OP #7823462
Lesenswert?

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
(Firma: 1984now) #7823524
Lesenswert?

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...

OP #7823539
Lesenswert?

Nach dem Einfügen des Inter-Byte-Delays funktioniert es nun endlich auch auf dem AVR64DD:

1
C:\Users\Johannes>avrdude -c avrispv2 -p attiny12 -P com7 -v -U flash:w:"D:\temp\10B.hex":i
2
Avrdude version 8.0
3
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.

OP #7823547
Lesenswert?

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.

#7823552
Lesenswert?

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.

(Firma: 1984now) #7823575
Lesenswert?

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.

OP #7823597
Lesenswert?

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 ...

#7823607
Lesenswert?

"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?

OP #7823618
Lesenswert?

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.

Persönliche Seite #7823652
Lesenswert?

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.

OP #7823657
Lesenswert?

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.

(Firma: Jasinski) #7823745
Lesenswert?

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.

Angehängte Dateien:
OP #7823754
Lesenswert?

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.

Angehängte Dateien:
OP #7823779
Lesenswert?

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.

(Firma: Jasinski) #7823817
Lesenswert?

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.

Angehängte Dateien:
(Firma: Jasinski) #7823881
Lesenswert?

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

Angehängte Dateien:
#7824103
Lesenswert?

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.

OP #7824221
Lesenswert?

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).

Angehängte Dateien:
OP #7824269
Lesenswert?

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.

Angehängte Dateien:
OP #7824354
Lesenswert?

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.

(Firma: Jasinski) #7824378
Lesenswert?

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.

OP #7824416
Lesenswert?

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.

(Firma: Jasinski) #7824481
Lesenswert?

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ß.

OP #7824767
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren