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)
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)
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?
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.
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
Schritt:
Adresse von FUSES.SYSCFG0 in NVMCTRL.ADDR laden: NVMCTRL.ADDR = 0x1285
Schritt:
Daten in NVMCTRL.DATA laden: NVMCTRL.DATA = 0xD4 (Bits 2 und 3 = 01)
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.
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?
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
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.
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.
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.
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.
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?
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.
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.
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.
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.
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.
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)
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.
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.
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:
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?