Hallo zusammen,
ich spiele gerade mit einem ATTiny3216 und möchte über die
UPDI-Schnittstelle einen Reset auslösen. Dazu habe ich das folgende
Python-Script geschrieben: 1 | import serial
| 2 | import time
| 3 |
| 4 | def send_reset(serial_port):
| 5 | # Verbindungsaufbau mit dem seriellen Port
| 6 | with serial.Serial(serial_port, baudrate=225000, timeout=1) as ser:
| 7 | # Warten, bis die Verbindung stabil ist
| 8 | time.sleep(2)
| 9 |
| 10 | # 1. SYNCH-Zeichen senden (0x55)
| 11 | ser.write(bytes([0x55]))
| 12 | print("SYNCH: 0x55 gesendet")
| 13 |
| 14 | # Kurze Verzögerung nach SYNCH
| 15 | time.sleep(0.1)
| 16 |
| 17 | # 2. Sende den STS-Befehl (010) mit der Adresse von ASI_RESET_REQ (0x08) und dem Wert 0x59
| 18 | # Format: Opcode STS (010), Adresse, und Wert für den Soft-Reset (0x59)
| 19 | # Opcode für STS ist 0b010
| 20 | # ASI_RESET_REQ-Adresse ist 0x08
| 21 | # Wert für den Reset ist 0x59
| 22 | # Sende STS-Befehl: Opcode | Adresse | Wert
| 23 | ser.write(bytes([0x40, 0x08, 0x00, 0x59])) # STS (Opcode 010), Adresse 0x08, Wert 0x59
| 24 | print(f"Reset-Befehl gesendet: STS 0x08 0x59")
| 25 |
| 26 | # Optionales Lesen der Antwort vom Mikrocontroller (falls gewünscht)
| 27 | response = ser.read(10) # Lesen von bis zu 10 Bytes (timeout nach 1 Sekunde)
| 28 | if response:
| 29 | print(f"Antwort vom ATTiny3216: {response.hex()}")
| 30 | else:
| 31 | print("Keine Antwort erhalten.")
| 32 |
| 33 | if __name__ == "__main__":
| 34 | # Seriellen Port angeben (z.B. COM3 unter Windows oder /dev/ttyUSB0 unter Linux)
| 35 | serial_port = "COM9" # Beispiel für Windows, ändere zu deinem spezifischen Port
| 36 |
| 37 | try:
| 38 | send_reset(serial_port)
| 39 | except serial.SerialException as e:
| 40 | print(f"Fehler beim Zugriff auf den seriellen Port: {e}")
|
Leider wird nach der Übertragung kein Reset ausgelöst.
Kann mir jemand sagen, woran das liegen könnte?
VG Woto
Nur ganz oberflächlich (mangels Zeit): STS? Das muss doch STCS sein,
oder?
PS:
So sieht es bei mir aus: 1 | u_system_reset:
| 2 | ; "Write the Reset signature into the UPDI.ASI_RESET_REQ register. This will issue a System Reset."
| 3 | ; "Write 0x00 to the Reset signature in UPDI.ASI_RESET_REQ register to clear the System Reset."
| 4 | ldi XL,$08 ; ASI Reset Request
| 5 | ldi tmp0,$59 ; "Reset signature 0x59h"
| 6 | rcall u_STCS
| 7 | ldi XL,$08 ; ASI Reset Request
| 8 | ldi tmp0,$00 ; 0x00 RUN Clear Reset condition
| 9 | rcall u_STCS
| 10 | rjmp wait10ms
| 11 | ;----------------------
| 12 |
| 13 | u_STCS: ; register-address: XL, data: tmp0 ->
| 14 | push tmp0
| 15 | ori XL,0b110_00000 ; STCS
| 16 | mov tmp0,XL
| 17 | rcall u_instruction
| 18 | pop tmp0
| 19 | rjmp u_out
|
ja, das könnte sein. Werde es mal probieren.
Was ist der Unterschied zwischen den beiden Registern? (STS und STCS)?
Ist der Unterschied, dass beim STS ein Acknowledge gesendet wird und
beim STCS nicht? Oder gibt es noch einen anderen Grund, anstatt das
STS-Register das STCS-Register zu verwenden?
Das ergibt sich ja aus den Namen:
'ST - Store Data from UPDI to Data Space Using Indirect Addressing'
(allgemeines Memory)
'STCS Store Data to Control and Status Register Space' (des UPDI)
Ich kenne mich mit Assembler nicht (mehr) so gut aus, aber veroderst du
mit dem Befehl mit $59?
Nein, es wird die CS-Adresse ($08) mit dem STCS-Opcode ($C0 = 11000000)
verodert.
Und eben war es etwas überhastet (immer schlecht), es ging ja um STS:
'STS - Store Data to Data Space Using Direct Addressing'
S. L. schrieb:
> Nein, es wird die CS-Adresse ($08) mit dem STCS-Opcode ($C0 = 11000000)
> verodert.
ok, aber das müsste ich ja auch dann machen. Momentan sende ich
nacheinander die Bytes 0x40 und 0x08. Dann müsste ich 0xC8 senden und
dann den Wert (0x00 und 0x59), richtig?
Ist schon länger her, und Ihr '0x40' sagt mir gerade nichts.
So auf die Schnelle aus meinem Programm gelesen: $55 $C8 $59, dann $55
$C8 $00.
Jetzt bin ich aber endgültig weg ...
Hallo,
habe das jetzt mal probiert. Funktioniert leider nicht.
Ich sende jetzt folgendes: 1 | ser.write(bytes([0xC8, 0x59])) # STCS (Opcode 110), Adresse 0x08, Wert 0x59
|
und anschließend 1 | ser.write(bytes([0xC8, 0x00])) # STCS (Opcode 110), Adresse 0x08, Wert 0x00
|
Als Antwort erhalte ich: 1 | SYNCH: 0x55 gesendet
| 2 | Reset-Befehl gesendet: STS 0xC8 0x59
| 3 | SYNCH: 0x55 gesendet
| 4 | Reset-Befehl löschen: STS 0xC8 0x00
| 5 | Antwort vom ATTiny3216: 55c85955c800
|
Muss man eventuell noch das Register über CPU.CCP mit dem Key IOREG
freischalten?
Die beiden Sequenzen sollten stimmen. Ich vermute, dass UPDI nicht
korrekt aktiviert wurde gemäß Datenblatt 'UPDI Enabling - One-Wire
Enable'. Und zu Beginn zwei BREAKs senden kann auch nicht schaden, ich
mache das generell.
Mal ein Beispiel, Teil einer Kommunikation mit einem AVR128DB28:
Auslesen der Device-Signatur: 1 | ... 55 C8 59 55 C8 00 55 69 00 11 55 24 55 24 55 24 ...
| 2 | ^-> Sync
| 3 | ^-> Reset
| 4 | ^-> Reset-Freigabe
| 5 | ^-> Laden UPDI-Pointer (ptr)
| 6 | ^-> low-byte SIGROW-Adresse
| 7 | ^-> high-byte SIGROW-Adresse
| 8 | ^-> lesen 1. Byte: per *(ptr++)
| 9 | ^-> 2.
| 10 | ^-> 3.
|
Aber natürlich muss davor UPDI korrekt aktiviert worden sein.
S. L. schrieb:
> Die beiden Sequenzen sollten stimmen. Ich vermute, dass UPDI nicht
> korrekt aktiviert wurde gemäß Datenblatt 'UPDI Enabling - One-Wire
> Enable'. Und zu Beginn zwei BREAKs senden kann auch nicht schaden, ich
> mache das generell.
Guten Morgen,
wie müsste die Sequenz aussehen, um UPDI zu aktivieren?
Herausgefunden habe ich folgendes:
Fuses Base Adress = 0x1280
SYSCFG0 Offset = 0x05
1. Schritt:
Adresse von FUSES.SYSCFG0 in NVMCTRL.ADDR laden: NVMCTRL.ADDR = 0x1285
2. Schritt:
Daten in NVMCTRL.DATA laden: NVMCTRL.DATA = 0xD4 (Bits 2 und 3 = 01)
3. Schritte:
Schreiben der Fuses initiieren: CTRLA = 0x07
Aber wie müsste jetzt die Sequenz aussehen, die ich übertragen müsste?
Wenn Du sicher wissen willst, wie Microchip das selber macht, dann
besorge Dir ein MPLAB SNAP Programmer, MPLABX und einen dieser
15€-Logicanalyzer, mache aus der IPE einen Reset und schau mit dem
Logicnalyzer nach, was das die IPE da sendet. Dann weißt Du es sicher,
und Du siehst nicht nur die Bytesequenz, sondern auch das Timing, wenn
das wichtig ist.
fchk
Ja, an sowas ähnliches habe ich auch schon gedacht.
Wenn man mit avrdude über UPDI das EEPROM ausliest, wird anschließend
der ATTINY resetted.
Da müsste man sich zwischenhängen und den Datenverkehr mitschneiden.
Könnte man diesen dafür verwenden:
https://www.elektor.de/products/usb-logic-analyzer-8-ch-24-mhz?srsltid=AfmBOoo3Nhkmq-t7IWx1L525FQ8akSZrD8JDSSTHO9gdKumcuy31X4EM
> wie müsste die Sequenz aussehen, um UPDI zu aktivieren?
Das steht, wie bereits gestern geschrieben, im Datenblatt unter 'UPDI
Enabling':
"The UPDI pin has a constant pull-up enable, and by driving the UPDI pin
low for more than 200 ns, a connected programmer will initiate the
start-up sequence ...".
Siehe dazu auch das Diagramm 'UPDI Enable Sequence with UPDI PAD Enabled
By Fuse'.
PS:
> Fuses ... FUSES ... Fuses ...
Als Anfänger beim ersten Gehversuch mit den Fuses zu arbeiten ist eine
schlechte Idee - ich begann damals mit dem Auslesen des SIB (System
Information Block).
PPS:
Dieses "UPDI PAD Enabled By Fuse" steht da nur, um den Gegensatz zu
"Override of Reset" zu verdeutlichen - Letzteres gibt es ohnehin nicht
bei z.B. den AVRmDx.
Ich habe an meinem USB-Port am Rechner einen USB-Seriell-Adapter
angeschlossen, der mit einer einfachen Beschaltung an den UPDI Daten
schickt und empfängt.
Wenn ich dann über avrdude den EEPROM-Inhalt auslese, wird anschließend
ein Reset beim ATTiny ausgelöst. Diesen Reset wollte ich dann mal
interessehalber mit einem einfachen Python-Programm nachstellen.
Dazu bräuchte ich aber die richtige Sequenz.
Das der UPDI-Pin für mehr 200ns low sein muss, müsste doch der
USB-Seriell-Adapter übernehmen, oder?
Wie macht das avrdude?
> Wie macht das avrdude?
Tut mir leid, das kann ich nicht beantworten - ich arbeite nicht mit
avrdude. Aber es gibt hier sicher Mitleser, die das wissen.
S. L. schrieb:
> Tut mir leid, das kann ich nicht beantworten - ich arbeite nicht mit
> avrdude. Aber es gibt hier sicher Mitleser, die das wissen.
Alles gut, du hast mir schon sehr viel geholfen. Zum Anfang wusste ich
noch gar nichts, jetzt ein wenig.
Mir juckt es in den Fingern, den Logic-Analyzer dazwischen zuhängen. Ich
habe nur das Problem dafür Zeit zu finden. Aber interessant wäre es
schon.
VG woto
Meldet sich niemand ... ?
Haben Sie es schon mit $FE als erstes Byte versucht? Das Startbit zieht
UPDI auf low, sollte reichen, und das lsb von $FE ist nötig wegen der
geraden Parität. Also vom PC aus senden: $FE $55 $E5, sollte den SIB
als Antwort bringen (oder Sie versuchen mit $FE $55 $C8 $59 Ihr
'reset').
Wird vermutlich nur einmal pro Einschalten funktionieren, da UPDI
nicht korrekt deaktiviert wird, wäre ja aber erstmal egal.
Stelle ich mir zumindest so vor, ausprobiert habe ich es nicht.
PS:
korrigiert zu 'wegen der geraden Parität'
PPS:
Mir fällt gerade auf:
> with serial.Serial(serial_port, baudrate=225000, timeout=1) as ser:
Wo wird da der Rest konfiguriert: 8 Datenbits, gerade Parität, 2
Stoppbits? Und für den Anfang würde ich es bei 115200 Bd belassen.
Wolfgang T. schrieb:
>
> Mir juckt es in den Fingern, den Logic-Analyzer dazwischen zuhängen. Ich
> habe nur das Problem dafür Zeit zu finden. Aber interessant wäre es
> schon.
Du könntest Dir updiprog ansehen:
https://github.com/Polarisru/updiprog
Das ist übersichtlicher C-Code bei dem man gut sehen kann was genau
passiert.
Das Ganze gibt es auch für Python (darauf basiert updiprog):
https://github.com/mraardvark/pyupdi
S. L. schrieb:
> Haben Sie es schon mit $FE als erstes Byte versucht? Das Startbit zieht
> UPDI auf low, sollte reichen, und das lsb von $FE ist nötig wegen der
> geraden Parität. Also vom PC aus senden: $FE $55 $E5, sollte den SIB
> als Antwort bringen (oder Sie versuchen mit $FE $55 $C8 $59 Ihr
> 'reset').
Guten Abend,
habe das jetzt mal mit dem Senden von $FE versucht, leider kein Erfolg.
Auch die Schnittstellenparameter 8 Datenbits, gerade Parität, 2
Stoppbits habe ich jetzt eingestellt und die Baudrate auf 57600
gestellt.
Damit arbeitet die Arduino-IDE. Aber alles kein Erfolg.
Dieter S. schrieb:
> Das Ganze gibt es auch für Python (darauf basiert updiprog):
>
> https://github.com/mraardvark/pyupdi
Auch das habe ich mir angesehen und dort werden genau die Bytes
gesendet, die auch ich sende.
Morgen kommt der Logic-Analyzer. Da bin ich gespannt was dabei
herauskommt, wenn ich mit avrdude das EEPROM auslese.
Wenn ich neue Erkenntnisse habe, werde ich mich melden.
Schönen Abend noch, Woto
Wolfgang T. schrieb:
>
> Auch das habe ich mir angesehen und dort werden genau die Bytes
> gesendet, die auch ich sende.
updiprog (also die C Variante von pyupdi) funktioniert auf jeden Fall
mit einem ATtiny3227. Die UART ist dabei mit 115200 Baud, Even Parity
konfiguriert, Rx direkt an UPDI, Tx über einen 1 kOhm Widerstand an
UPDI.
Hallo,
ich habe jetzt den Logicanalyzer am UPDI-Eingang installiert und die
Daten mitgeschrieben (s.A.).
Wie man sieht, ist das die Bytereihenfolge, die das Python-Programm
momentan sendet.
Jetzt möchte ich die übertragenden Bytes bei Verwendung von avrdude
mitschneiden. Dazu brauche ich aber die Schnittstellenparameter.
Kennt jemand die Schnittstellenparameter bei der Verwendung von
serialupdi?
VG, Woto
Wolfgang T. schrieb:
> Jetzt möchte ich die übertragenden Bytes bei Verwendung von avrdude
> mitschneiden. Dazu brauche ich aber die Schnittstellenparameter.
Die Bitrate kannst Du Dir doch anhand der Länge eines Bits ausmessen.
Und die Anzahl der Daten- und Stopbits siehst Du dann auch im
Wellenformdiagramm.
fchk
> die Bytereihenfolge, die das Python-Programm momentan sendet
Das verstehe ich nicht: was soll die Sequenz '55 40 34 00 D8' bewirken?
Zumal nach meiner Meinung ein Byte zuviel ist: STS mit 'Size A'="Byte
- can address 0-255 B" und 'Size B'="Byte". Was dann wohl auch der Grund
dafür ist, dass vom uC die beiden ACK nicht rückgemeldet werden.
PS: Datenblattauszug
Frank K. schrieb:
> Die Bitrate kannst Du Dir doch anhand der Länge eines Bits ausmessen.
> Und die Anzahl der Daten- und Stopbits siehst Du dann auch im
> Wellenformdiagramm.
Stimmt, werde ich versuchen. Danke.
S. L. schrieb:
> Das verstehe ich nicht: was soll die Sequenz '55 40 34 00 D8' bewirken?
> Zumal nach meiner Meinung ein Byte zuviel ist: STS mit 'Size A'="Byte
> - can address 0-255 B" und 'Size B'="Byte". Was dann wohl auch der Grund
> dafür ist, dass vom uC die beiden ACK nicht rückgemeldet werden.
Ja, schaue ich mir nochmal genauer an.
Mit angehängtem Programm(auszug) erhalte ich den SIB
(System-Information-Block) "...tinyAVR P:0D:0-3" von einem ATtiny412
zurück. Sie erkennen das Muster, und die Umsetzung von Pascal nach
Python ist wohl klar.
S. L. schrieb:
> Mit angehängtem Programm(auszug) erhalte ich den SIB
> (System-Information-Block) "...tinyAVR P:0D:0-3" von einem ATtiny412
> zurück. Sie erkennen das Muster, und die Umsetzung von Pascal nach
> Python ist wohl klar.
Vielen Dank. In Pascal habe ich früher auch programmiert.
Wenn Sie mein SIB-Auslesen nicht mögen, hier Ihr RESET.
Super, vielen Dank.
Probiere ich heute aus.
Hallo,
habe das jetzt getestet, leider ohne Erfolg.
Im Anhang die gesendete Bytereihenfolge.
(Leider habe ich zwei Dateianhänge in den Beitrag hochgeladen und kann
die zweite nicht mehr löschen, gesendet habe ich aber immer nur einmal
die Bytereihenfolge)
Auch die Wartezeit von 4s habe ich eingehalten.
Tja, dann weiß ich (erstmal) nicht weiter. Bei mir läuft es. Die 4 s
sind übrigens völlig unbedeutend, es geht nur darum zu sehen, dass das
LED-Blinken auf dem ATtiny412 so lange aufhört.
An der Hardware liegt es wohl nicht, da bei Ihnen ja avrdude läuft, aber
ich schildere trotzdem mal meine: USB-seitig ein CP2102, dahinter (zur
Potenzialtrennung, aber eigentlich unbedeutend) ein ADuM1201. Wie im
gezeigten COM_UPDI.pas beschrieben geht Rx direkt auf UPDI, Tx per 100
Ohm und Siliziumdiode 1N4448. Zusätzlich zum internen UPDI-Pullup
verwende ich noch extern 100 kOhm, kann aber auch entfallen.
Was ich bislang nicht erreichte ist die Wiederherstellung der Verbindung
durch zwei BREAKs (wie im Datenblatt beschrieben); wenn sich also etwas
"verhaspelt" hat, hilft nur Aus- und wieder Einschalten der
Stromversorgung des ATtiny412.
Da ich dies alles aber nur aus allgemeinem Interesse angeschaut habe
(ich selbst arbeite mit einem Selbstbauprogrammiergerät, damit läuft
alles perfekt (auch die Wiederherstellung)), verabschiede ich mich an
dieser Stelle.
Vielen Dank.
Ich bleibe dran und melde mich wieder, wenn ich etwas herausgefunden
habe.
Im Anhang die Bytereihenfolge mit avrdude. Dabei schreibe ich mit
avrdude einen Wert ins Byte 0 vom EEPROM. Nach dem Schreiben wird der
ATTiny resetted.
Hier der Aufruf von avrdude: 1 | avrdude -p attiny3216 -c serialupdi -P com9 -U eeprom:w:eeprom_adr_write.hex:i
|
Genau so wie in dem avrdude Trace fängt auch updiprog bzw. pyupdi mit
der Kommunikation an:
1 | Tx: 00 BREAK
| 2 | Tx: 55 C3 08 UPDI_STCS | UPDI_CS_CTRLB CCDETDIS
| 3 | Tx: 55 C2 80 UPDI_STCS | UPDI_CS_CTRLA IBDLY Inter-Byte Delay Enable
| 4 | Tx: 55 80 UPDI_LDCS | UPDI_CS_STATUSA
| 5 | Rx: 40 UPDIREV[3:0] UPDI Revision
| 6 | ...
| 7 | ...
|
Man sieht in dem Trace dass avrdude einen zweiten Anlauf braucht weil
die erste Abfrage der UPDI Revision keine Antwort liefert.
Ich würde zuerst die Verschaltung mit der UART prüfen und schauen ob es
mit updiprog bzw. pyupdi funktioniert und dann die eigenen Experimente
wiederholen.
Guten Abend,
ich habe das jetzt mit pyupdi (bzw. jetzt pymcuprog) gemacht. Erst hat
es nicht funktioniert. Aber dann habe ich die Schaltung gemäß der
Vorgabe von pymcuprog gemacht (Rx über einen 1kOhm-Widerstand an den
UPDI-Eingang und den Tx direk an den UPDI-Eingang) und damit hat der
Reset mit den folgenden Befehl funktioniert: 1 | pymcuprog reset -t uart -u COM9 -d attiny3216
|
Die dann gesendete Bytereihenfolge resettete den Attiny (endlich). Im
Anhang die Bytereihenfolge.
Leider löst mein Python-Programm (noch) kein Reset aus, aber die
Anpassung ist jetzt nur noch eine Fleißarbeit.
Vielen Dank für eure Unterstützung.
VG Woto
Wolfgang T. schrieb:
>
> ich habe das jetzt mit pyupdi (bzw. jetzt pymcuprog) gemacht. Erst hat
> es nicht funktioniert. Aber dann habe ich die Schaltung gemäß der
> Vorgabe von pymcuprog gemacht (Rx über einen 1kOhm-Widerstand an den
> UPDI-Eingang und den Tx direk an den UPDI-Eingang) und damit hat der
> Reset mit den folgenden Befehl funktioniert:
Die Beschaltung laut pymcuprog ist so (das ist auch bei updiprog so),
bei Deiner Beschreibung ist Rx und Tx vertauscht:
1 | Vcc Vcc
| 2 | +-+ +-+
| 3 | | |
| 4 | +---------------------+ | | +--------------------+
| 5 | | Serial port +-+ +-+ AVR device |
| 6 | | | +----------+ | |
| 7 | | TX +------+ 1k +---------+ UPDI |
| 8 | | | +----------+ | | |
| 9 | | | | | |
| 10 | | RX +----------------------+ | |
| 11 | | | | |
| 12 | | +--+ +--+ |
| 13 | +---------------------+ | | +--------------------+
| 14 | +-+ +-+
| 15 | GND GND
|
Oh, Entschuldigung an alle.
Du hast natürlich recht.
> Leider löst mein Python-Programm (noch) kein Reset aus
Sind Sie sicher, dass das erste Byte in Ihrer Tabelle wirklich ein
'normaler' Null-Character ist und nicht etwa ein BREAK? Also 0x00 mit
stark reduzierter Übertragungsrate, z.B. 300 Bd, womit dann die im
Datenblatt geforderten 24.6 ms Low erreicht wären?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|