Datum:
Hallo, auf http://www.fischl.de/usbasp/ steht derzeit: * Planned: serial interface to target (e.g. for debugging). Genau das möchte ich umsetzen. Dazu habe ich mir folgendes überlegt: Da der ISP-Programmieradapter schon die SPI-Leitungen belegt, soll das Target über SPI mit dem USBasp reden, welches dann mit USB weiter mit dem Hostrechner redet. Um die den Overhead im Target so gering wie möglich zu halten, möchte ich das Target als SPI master und das USBasp als slave konfigurieren. Denn dann kann man im Target komfortable aussuchen wann man die Debugging Informationen sendet, als Slave können die Lese/Schreibanfragen zu den unpassendsten Zeiten kommen. Da das USBasp auch schon ein USB slave ist, also insgesamt 2 Schnittstellen als Slave bedient, benötigt es einen Puffer um die beiden Schnittstellen zu synchronisieren. Der Puffer funktioniert, dieser kann auch schon per USB ausgelesen werden. Immer wenn ich Bytes hineinschreibe, kann man sie am Hostrechner emfangen. Die SPI Schnittstelle selber funktionert auch, ich kann also Daten von dem Target zu dem USBasp senden. Das Problem ist die Synchronisation der beiden Schnittstellen: Da das USBasp im SPI-slave modus arbeitet, nimmt es die Daten per Interrupt an. Wenn aber so ein Interrupt in das usbPoll() an der unpassenden, da zeitkritischen Stelle einschlägt, gibt es Fehler im USB Stack. Wie geht man jetzt am besten vor? * Man könnte mit noch einer Leitung dem Target signalisieren, wann SPI erwünscht ist und wann nicht. * Ignorieren der SPI Nachrichten während der aktiven USB Phase. * Doch den USBasp als SPI-Master und das Target als slave konfigurieren? Was ist aus Benutzersicht am einfachsten? Die Kommunikation über einen Verlust-behafteten Kanal oder die ein bestimmtes Timing zum Senden der Debugnachrichten? Ich habe schon Code geschrieben, dieser funktioniert allerdings nur sehr begrenzt, da eben dieses Synchronisationsproblem auftaucht. https://github.com/stefanbeller/USBasp Der Code kann auf 2 USBasps getestet werden (eins als echtes USBasp, das andere als Target, welches hin und wieder Daten per SPI verschickt.) Gruß, Stefan
Datum:
Hallo! Zuerst mein Kompliment, ich finde es klasse, dass sich mal jemand an diese Baustelle herantraut! Stefan B. schrieb: > Die SPI Schnittstelle selber funktionert auch, ich kann also Daten von > dem Target zu dem USBasp senden. :-) > Das Problem ist die Synchronisation der beiden Schnittstellen: > Da das USBasp im SPI-slave modus arbeitet, nimmt es die Daten per > Interrupt an. > Wenn aber so ein Interrupt in das usbPoll() an der unpassenden, da > zeitkritischen Stelle einschlägt, gibt es Fehler im USB Stack. Klingt so, als bräuchtest du ein USIBR (USI Buffer Register), wie ich es vom ATtiny85 her kenne. Gibts aber wohl bei den ATmegas nicht... oder? Was passiert, wenn du die Interrupts während dieser "zeitkritischen Stelle" sperrst? > * Man könnte mit noch einer Leitung dem Target signalisieren, wann SPI > erwünscht ist und wann nicht. Fürs Target zu aufwändig auszuwerten, find ich. > * Ignorieren der SPI Nachrichten während der aktiven USB Phase. Du meinst, die Nachrichten, die das Target sendet? Ich hab nicht verstanden, was die "aktive USB-Phase" ist. Ist das nur dann, wenn der USBasp zum Programmieren genutzt wird? Dann wär das sicher kein Problem für den User. > * Doch den USBasp als SPI-Master und das Target als slave konfigurieren? Auch wieder zu aufwändig für das Ziel, denk ich...
Datum:
Markus W. schrieb: > Klingt so, als bräuchtest du ein USIBR (USI Buffer Register), wie ich es > vom ATtiny85 her kenne. Gibts aber wohl bei den ATmegas nicht... oder? > > Was passiert, wenn du die Interrupts während dieser "zeitkritischen > Stelle" sperrst? Ein USIBR habe ich nicht in dem Datenblatt des Atmega8 finden können. Bisher sah die Hauptschleife so aus:
for (;;) {
usbPoll();
}
|
Wenn ich die Interrupts während des usbPoll() ausstelle, dann kommen in derzeit keine Nachrichten mehr an, es kann also maximal eine Nachricht (1Byte) geschickt werden. Jedes weitere Byte würde das bisherige in dem SPDR Register überschreiben. Der USB Host pollt regelmäßig alle angeschlossenen Geräte, diese müssen innerhalb von 50ms antworten, sonst wird das Gerät abgemeldet. Dieses Antworten passiert innerhalb des usbPoll(). die usbPoll Funktion hingegen, muss Zyklen-genau sein laut deren Dokumentation, um die Zeiten auf dem USB Bus zu einzuhalten. Ich habe bisher die Hauptschleife so erweitert:
for (;;) { SPCR &= ~(1 << SPIE); usbPoll(); SPCR |= (1 << SPIE); if (prog_state == PROG_STATE_SERIAL) { if (--blink_counter == 0) { toggleLedRed(); blink_counter = (unsigned int)(1UL << 15); } } } |
Weiterhin könnte man noch soetwas wie pollSPI() einfügen in der Funktion wird dann auf die Nachrichten von dem Target gewartet. Lange Rede, kurzer Sinn: Falls der SPI Interrupt deaktiviert wird, kann man nie sicher sein, ob Nachrichten von dem Target bei dem USBasp ankommen. Man kann sogar ziemlich sicher sein, dass Packetverluste (heh, Byteverluste) auftreten und muss definitiv ein Data-Link-Layer Protokoll einsetzen, welches die Übertragung sicherstellt. Alternativ kann man versuchen die usbPoll() Funktion zu sezieren und nur an den wirklich zeitkritischen Stellen den SPI Interrupt deaktivieren. Bisher habe ich die USB Schnittstelle nicht näher untersucht. > Du meinst, die Nachrichten, die das Target sendet? Ich hab nicht > verstanden, was die "aktive USB-Phase" ist. Ist das nur dann, wenn der > USBasp zum Programmieren genutzt wird? Dann wär das sicher kein Problem > für den User. Mit der "aktiven USB-Phase" meinte ich die usbPoll() Funktion, die also nicht nur während des Flashen des Target, sondern die ganze Zeit regelmäßig ausgeführt wird. Gruß, Stefan
Datum:
OK, danke, nun hab ichs begriffen. :-) So ganz einfach wird die Sache vermutlich nicht sein, sonst hätten die Entwickler von damals es schnell erledigt. Kann also gut sein, dass ein gehöriger Schluck Aufwand drinsteckt und du deine Ergänzungen in die Funktion usbPoll() integrieren musst. Du könntest aber auch mal bei fischl.de direkt anklopfen, vielleicht haben die noch eine Idee, wo man anpacken sollte. Bitte meld dich wieder, es interessiert mich brennend, ob du mit dem Vorhaben weiterkommst. Vielleicht schau ich auch mal in den Quellcode, schadet ja nichts, auch wenn ich AVR-Assembler viel besser kann als AVR-C.
Datum:
Markus W. schrieb: > Bitte meld dich wieder, es interessiert mich brennend, ob du mit dem > Vorhaben weiterkommst. Vielleicht schau ich auch mal in den Quellcode, > schadet ja nichts, auch wenn ich AVR-Assembler viel besser kann als > AVR-C. Heh, bei mir ist es genau andersherum. Ich kann C viel besser als Assembler jeglicher Art. Das usbPoll() scheint mir auch nur eine Wrapper Funktion für die Assembler Sachen zu sein.
Datum:
Stefan B. schrieb: > Heh, bei mir ist es genau andersherum. Ich kann C viel besser als > Assembler jeglicher Art. Du kriegst das bestimmt hin. > Das usbPoll() scheint mir auch nur eine Wrapper Funktion für die > Assembler Sachen zu sein. Sieht nicht unbedingt so aus. Die Funktion ist in der Datei usbdrv.c definiert:
USB_PUBLIC void usbPoll(void) { schar len; uchar i; len = usbRxLen - 3; if(len >= 0){ /* We could check CRC16 here -- but ACK has already been sent anyway. If you * need data integrity checks with this driver, check the CRC in your app * code and report errors back to the host. Since the ACK was already sent, * retries must be handled on application level. * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); */ usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len); #if USB_CFG_HAVE_FLOWCONTROL if(usbRxLen > 0) /* only mark as available if not inactivated */ usbRxLen = 0; #else usbRxLen = 0; /* mark rx buffer as available */ #endif } if(usbTxLen & 0x10){ /* transmit system idle */ if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */ usbBuildTxBlock(); } } for(i = 20; i > 0; i--){ uchar usbLineStatus = USBIN & USBMASK; if(usbLineStatus != 0) /* SE0 has ended */ goto isNotReset; } /* RESET condition, called multiple times during reset */ usbNewDeviceAddr = 0; usbDeviceAddr = 0; usbResetStall(); DBG1(0xff, 0, 0); isNotReset: usbHandleResetHook(i); } |
Wenn ich den Kommentar weglasse und die Konstante mit der Flusssteuerung auflöse, bleibt das hier übrig:
USB_PUBLIC void usbPoll(void) { schar len; uchar i; len = usbRxLen - 3; if(len >= 0){ usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len); usbRxLen = 0; /* mark rx buffer as available */ } if(usbTxLen & 0x10){ /* transmit system idle */ if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */ usbBuildTxBlock(); } } for(i = 20; i > 0; i--){ uchar usbLineStatus = USBIN & USBMASK; if(usbLineStatus != 0) /* SE0 has ended */ goto isNotReset; } /* RESET condition, called multiple times during reset */ usbNewDeviceAddr = 0; usbDeviceAddr = 0; usbResetStall(); DBG1(0xff, 0, 0); isNotReset: usbHandleResetHook(i); } |
Auf den ersten Blick relativ übersichtlich. In der Datei usbdrv.h ist einiges an Doku drin. Ich werd das mal durchsehen.
Datum:
Noch ein Gedanke: Du schreibst, dass es Probleme gibt, wenn über SPI ein Byte ankommt und damit ein Interrupt ausgelöst wird, während die oben genannte USB-Funktion läuft. Kann es sein, dass die betreffende Interrupt-Routine einfach zu lang ist, also zu viel Zeit braucht? Vielleicht kann man die verkürzen oder optimieren. Magst du sie posten?
Datum:
Die Interruptroutine für spi sieht so aus:
ISR(SPI_STC_vect )
{
comBuffer[comStop] = SPDR;
comStop ++;
}
|
Das dissassemblierte binary sieht dann so aus:
00000ba0 <__vector_10>: ba0: 1f 92 push r1 ba2: 0f 92 push r0 ba4: 0f b6 in r0, 0x3f ; 63 ba6: 0f 92 push r0 ba8: 11 24 eor r1, r1 baa: 8f 93 push r24 bac: 9f 93 push r25 bae: ef 93 push r30 bb0: ff 93 push r31 bb2: 80 91 79 01 lds r24, 0x0179 bb6: 9f b1 in r25, 0x0f ; 15 bb8: e9 e7 ldi r30, 0x79 ; 121 bba: f0 e0 ldi r31, 0x00 ; 0 bbc: e8 0f add r30, r24 bbe: f1 1d adc r31, r1 bc0: 90 83 st Z, r25 bc2: 8f 5f subi r24, 0xFF ; 255 bc4: 80 93 79 01 sts 0x0179, r24 bc8: ff 91 pop r31 bca: ef 91 pop r30 bcc: 9f 91 pop r25 bce: 8f 91 pop r24 bd0: 0f 90 pop r0 bd2: 0f be out 0x3f, r0 ; 63 bd4: 0f 90 pop r0 bd6: 1f 90 pop r1 bd8: 18 95 reti |
Zu den Zeitkritischen Sachen: In der Datei usbdrvasm12.asm steht: > Do not link this file! Link usbdrvasm.S instead, which includes the > appropriate implementation! > Since almost all of this code is timing critical, don't change unless you > really know what you are doing! Many parts require not only a maximum number > of CPU cycles, but even an exact number of cycles! Jetzt müssen wir untersuchen, in welcher Datei die Interruptsperren/freigaben eingebaut werden müssen. Die usbPoll() Funktion ist zu weit oben im USB STack angesetzt, die Assemblerdateien wohl zuweit unten.
Datum:
Danke!
Ich hab mal durchgezählt, die ISR schluckt 52 Takte. Das ist ziemlich
lang für zwei Zeilen Code. C arbeitet leider sehr viel über den Stack,
jedes push braucht 2 Takte - jedes pop auch.
Gibt es bei C die Möglichkeit, den Compiler anzuweisen, bestimmte
Register nicht zu benutzen? Falls ja, könnte man die ISR evtl. in
Assembler schreiben, sie würde dann weniger als halb so lang laufen.
Zum C-Code:
Die Übersetzung des Compilers find ich ok, lediglich das zweite "push
r0" und das erste "pop r0" sind überflüssig. Aber darauf kommt es
wahrscheinlich auch nicht mehr an.
In welchem Wertebereich bewegt sich comStop? Könntest du statt mit
comBuffer[comStop] auch mit einem Zeiger arbeiten (z.B. *comPointer++ )?
Falls ja, würde das eine 16-Bit-Addition in der ISR sparen. Außerdem
könnte Post-Inkrement verwendet werden (statt "st Z,r25" dann "st
Z+,r25"), das spart die zweite Addition ("subi r24,0xff") ein. Ob das
alles das Problem löst, weiß ich natürlich nicht... :-(
Datum:
Wozu eigentlich die Kopfstände? Quelle usbdrv.h (20120109):
Interrupt latency: The application must ensure that the USB interrupt is not disabled for more than 25 cycles (this is for 12 MHz, faster clocks allow longer latency). This implies that all interrupt routines must either have the "ISR_NOBLOCK" attribute set (see "avr/interrupt.h") or be written in assembler with "sei" as the first instruction. |
Mit ISR_NOBLOCK sollte also alles im grünen Bereich sein. Gruß Oliver
Datum:
Oliver J. schrieb: > Mit ISR_NOBLOCK sollte also alles im grünen Bereich sein. Hm. Das bedingt, dass alles Zeitkritische des bisherigen Programms sich nur in Interrupt-Routinen befindet. Davon war ich nicht ausgegangen, aber du hast völlig Recht, das ist einen Versuch wert! Ein Problem könnte es geben, wenn die ISR(SPI_STC_vect) aufgerufen wird, während sie noch läuft, aber das ist sehr unwahrscheinlich.
Datum:
Markus W. schrieb: > > In welchem Wertebereich bewegt sich comStop? Könntest du statt mit > comBuffer[comStop] auch mit einem Zeiger arbeiten (z.B. *comPointer++ )? > Falls ja, würde das eine 16-Bit-Addition in der ISR sparen. Außerdem > könnte Post-Inkrement verwendet werden (statt "st Z,r25" dann "st > Z+,r25"), das spart die zweite Addition ("subi r24,0xff") ein. Ob das > alles das Problem löst, weiß ich natürlich nicht... :-( Im ersten Beitrag ist der bisherige Code verlinkt:
// choose size to 2^8, so comStart, comEnd can wrap around as ringbuffer // indexes. static uchar comBuffer[256]; static uchar comStart = 0; static uchar comStop = 0; |
Datum:
Markus W. schrieb: > Hm. Das bedingt, dass alles Zeitkritische des bisherigen Programms sich > nur in Interrupt-Routinen befindet. In der usbPoll-Funktion steckt sicher nichts Zeitkritisches: Quelle usbdrv.h (20120109):
USB_PUBLIC void usbPoll(void); /* This function must be called at regular intervals from the main loop. * Maximum delay between calls is somewhat less than 50ms (USB timeout for * accepting a Setup message). Otherwise the device will not be recognized. * Please note that debug outputs through the UART take ~ 0.5ms per byte * at 19200 bps. */ |
Markus W. schrieb: > Ein Problem könnte es geben, wenn die ISR(SPI_STC_vect) aufgerufen wird, Das könnte man über ein Globales Flag abfangen:
volatile uint8_t X_Y_alredy_started = 0; ISR(X_Y_vect, ISR_NOBLOCK) { /* Flag setzen oder zurückkehren */ if (X_Y_alredy_started == 1) { /* evenuell noch irgendwo vermerken */ return; } else { X_Y_alredy_started = 1; } /* Hier Steht Code */ /* Flag zurücksetzen */ X_Y_alredy_started = 0; } |
Gruß Oliver
Datum:
Oliver J. schrieb: > Mit ISR_NOBLOCK sollte also alles im grünen Bereich sein. Heh, Ich sollte die Doku besser lesen. Danke für den entscheidenen Hinweis. Ich habe den SPI Interrupt auf ISR_NOBLOCK gesetzt und das Auslesen von Daten aus dem Target über das USBasp funktioniert jetzt. Wenn zuviele Daten per SPI versandt werden, gibt es immer noch Packetverlust, aber das ist ja normal bei Überlast. Bei einer Last von 2 Bytes in 10 ms (unregelmäßig aufgeteilt, dh. 9.6 ms lang nichts und dann 2 Bytes kurz hintereinander) funktioniert es. Als nächsten Schritt könnte Ich einen Treiber für die Hostseite bereitstellen, derzeit habe ich nur ein rudimentäres Python Skript welches die Daten entgegennimmt und in der Konsole ausgibt. https://github.com/stefanbeller/USBasp/blob/master... Was erwartet ein Benutzer von einem Hostseitigen Treiber für so eine Kommunikation? Vielleicht einfach nur ein Programm, welches die Daten auf stdout ausgibt, sodass man diese in anderen Programmen wieterverarbeiten kann? Andere Detailfrage: Soll die rote LED, die sonst den Programmiervorgang anzeigt, während der SPI Kommunikation auch konstant an sein? Derzeit habe ich sie auf Blinken eingestellt, sodass man das Programmieren und die SPI Kommunikation voneinander unterscheiden kann.
Datum:
Stefan B. schrieb: > Danke für den entscheidenen Hinweis. Dem Dank an Oliver schließ ich mich an! > Ich habe den SPI Interrupt auf ISR_NOBLOCK gesetzt und das Auslesen von > Daten aus dem Target über das USBasp funktioniert jetzt. Schööön! Wie liest du eigentlich? So ähnlich wie mit dem Befehl hier? cat /dev/irgendwas > Wenn zuviele Daten per SPI versandt werden, gibt es immer noch > Packetverlust, aber das ist ja normal bei Überlast. Bei einer Last von 2 > Bytes in 10 ms (unregelmäßig aufgeteilt, dh. 9.6 ms lang nichts und dann > 2 Bytes kurz hintereinander) funktioniert es. Hmmm... der Puffer müsste mit 256 Bytes auf jeden Fall groß genug sein. Woran liegt das? Eventuell noch ein Bug? Viele werden später Daten zeilenweise mit printf() versenden wollen, da gäbs dann schon ein kleines Problem... > Als nächsten Schritt könnte Ich einen Treiber für die Hostseite > bereitstellen, derzeit habe ich nur ein rudimentäres Python Skript > welches die Daten entgegennimmt und in der Konsole ausgibt. > https://github.com/stefanbeller/USBasp/blob/master... "Treiber" klingt so nach Windows – da halte ich mich mal raus. :-) > Andere Detailfrage: > Soll die rote LED, die sonst den Programmiervorgang anzeigt, während der > SPI Kommunikation auch konstant an sein? Derzeit habe ich sie auf > Blinken eingestellt, sodass man das Programmieren und die SPI > Kommunikation voneinander unterscheiden kann. Mir würde das Blinken gefallen, dann sieht man, dass Daten kommen. Sie blinkt nur, wenn der angeschlossene Mikrocontroller Daten sendet oder zumindest einen Takt anlegt, oder? Wenn sie IMMER blinken würde, wärs vielleicht doch zu nervig. :-) Mit welchem USBasp experimetierst du eigentlich? Ich hab zwei verschiedene China-USBasps hier rumliegen, wär natürlich toll, wenn deine Software dann auf beiden laufen würde. :-)
Datum:
Markus W. schrieb: > Hmmm... der Puffer müsste mit 256 Bytes auf jeden Fall groß genug sein. > Woran liegt das? Eventuell noch ein Bug? > Viele werden später Daten zeilenweise mit printf() versenden wollen, da > gäbs dann schon ein kleines Problem... Da nun die SPI isr unterbrochen werden kann und ich nicht weiß wie lange die USB isr braucht, können Bytes verloren gehen, wenn man die zu schnell hintereinander sendet. Ich habe nicht ausgemessen, wie klein der minimale zeitliche Abstand zwischen zwei Bytes sein muss, um definitiv 'Packetverlust' zu vermeiden, 320µs als Wartezeit waren halt einfach zu bekommen. ;) Meine USBasps sind aus dem Shop von Ullrich Radig, die Schaltpläne findet man hier http://www.ulrichradig.de/home/index.php/avr/usb-avr-prog Um die Erweiterung schnell testen zu können, habe ich einfach die Hauptschleife umgebaut, siehe https://github.com/stefanbeller/USBasp/blob/master... (clockWait wartet 320µs und war schon da) Zu dem Treiber... Naja ich benutze derzeit in python die python-usb lib version 0.4.3-1 (Standard in Ubuntu 12.04) Da USB Kommunikation über sogenannte Setup Packete erfolgt, können pro USB Packet nur 8 Byte Nutzdaten an den Hostpc gesendet werden. (Es gibt noch sogenannte Bulk Transfers oder Interrupt Transfers, aber da USB Neuland für mich ist, benutze ich die Packete die auch alle anderen Befehle des USBasps benutzen.) Und in python habe ich jetzt die Funktionen
def getHandle() # return the correct USB handle for the USBasp programmer def enableSerialMode(USBaspHandle) # enables Serial listening def disableSerialMode(USBaspHandle) # basically turns off red LED blinking def getData(USBaspHandle) # returns 0 up to 8 bytes of data depending on buffer size in USBasp |
Die Funktion getData müsste noch so umgebaut werden, sodass man einen kontinuierlichen Bytestrom bekommt.
Datum:
Stefan B. schrieb: > Ich habe nicht ausgemessen, wie klein der minimale zeitliche Abstand > zwischen zwei Bytes sein muss, um definitiv 'Packetverlust' zu > vermeiden, > 320µs als Wartezeit waren halt einfach zu bekommen. ;) Kann man dem Anwender sowas wie eine maximale Taktfrequenz fürs SPI als Richtwert geben? Ich nehm an, dass es kein Problem ist, wenn es keine Wartezeit zwischen den Bytes gibt, wenn die SPI-Frequenz entsprechend gering ist. Das wär für den User am einfachsten zu verstehen und umzusetzen. Auch printf() und andere Routinen halten sich dann daran. > Meine USBasps sind aus dem Shop von Ullrich Radig, die Schaltpläne > findet man hier > http://www.ulrichradig.de/home/index.php/avr/usb-avr-prog Werd ich mir anschauen, danke! Ich nehm an, du setzt mit deiner Software auf dem letzten Entwicklungsstand von fischl.de auf (Mail 2011)? > Um die Erweiterung schnell testen zu können, habe ich einfach die > Hauptschleife umgebaut, siehe > https://github.com/stefanbeller/USBasp/blob/master... > (clockWait wartet 320µs und war schon da) Ich schau morgen mal rein. Danke. > Zu dem Treiber... Naja ich benutze derzeit in python die python-usb lib > version 0.4.3-1 (Standard in Ubuntu 12.04) Schon drauf, wenn man Ubuntu neu installiert? Ich denk jetzt einfach mal an die Neulinge... > (Es gibt noch sogenannte Bulk Transfers oder Interrupt Transfers, aber > da USB Neuland für mich ist, benutze ich die Packete die auch alle > anderen Befehle des USBasps benutzen.) Mach da bloß keinen Aufwand, es geht erst einmal darum, Textausgaben auf den Schirm zu bringen. Je einfacher, desto leichter lässt sich die Software hinterher pflegen. > Und in python habe ich jetzt die Funktionen > (...) > Die Funktion getData müsste noch so umgebaut werden, sodass man einen > kontinuierlichen Bytestrom bekommt. Als einfacher Anwender stelle ich es mir ideal vor, wenn man ein Binary hat, das Linux-mäßig auf stdout schreibt. Dann kann man es beliebig in Pipes einbauen usw. Vielleicht kann avrdude schon von Haus aus sowas? Ich hab keine Ahnung.
Datum:
Stefan B. schrieb: > Da nun die SPI isr unterbrochen werden kann und ich nicht weiß wie lange > die USB isr braucht, können Bytes verloren gehen, wenn man die zu > schnell hintereinander sendet. Wenn Daten verloren gehen, dann muss man die Geschichte irgendwie synchronisieren. Ich hätte dazu folgende Idee: Beide Geräte sind abwechselnd Master oder Slave. Also: Ein Multimaster-Bus. Target-AVR | Datenrichtung | usbasp | Aktion ------------+-----------------+-------------+--------------------------- --- Master | --> | Slave | Byte wird versendet Slave | <-- | Master | usbasp schickt ACK Zuerst wartet der usbasp auf die Daten und danach wartet der Target-AVR auf das Acklowledge-byte. Und das immer im Wechsel. Dabei sendet niemand zu viel und man hat immer Zeit die Bytes abzuholen, ohne dass ein Overrun auftritt. Könnte das nicht so funktionieren? Gruß Oliver
Datum:
Oliver J. schrieb: > Target-AVR | Datenrichtung | usbasp | Aktion > ------------+-----------------+-------------+--------------------------- --- > Master | --> | Slave | Byte wird versendet > Slave | <-- | Master | usbasp schickt ACK Das ist eine gute Idee für eine Flusssteuerung. Würde bestimmt prima funktionieren. Das schränkt aber die Einsatzmöglichkeiten von Stefans Projekt ein. Ziel sollte es sein – so denke ich – Testausgaben und andere Ausgaben per printf() zu ermöglichen.
Datum:
Oliver J. schrieb: > Wenn Daten verloren gehen, dann muss man die Geschichte irgendwie > synchronisieren. Ich hätte dazu folgende Idee: > > Beide Geräte sind abwechselnd Master oder Slave. Also: Ein > Multimaster-Bus. Woher weiß das Gerät (beide), wann es den Status umschalten soll? Wenn das Target zufällig ziemlich lange keine Daten verschickt und dann viele Daten in kurzer Zeit? Ich denke so ein Multimasterbus verkompliziert die ganze Sache nur. (Das wäre auf dem USBasp kein Problem, obwohl auch da wegen des zeitkritischen USB Stacks die Umschaltung getimed werden muss. SPI ist ein voll Duplex Bus, das bedeutet, das immer wenn A ein Byte nach B sendet, auch automatisch ein Byte von B nach A gesendet wird. Man könnte also im SPI-Slave (USBasp) ein ACK als nächstes zu sendendes Byte in die SPI Register schreiben sobald das Byte gesichert ist. Bisher sieht der Interrupt so aus
ISR(SPI_STC_vect, ISR_NOBLOCK)
{
comBuffer[comStop] = SPDR;
comStop ++;
}
|
Als Erweiterung wird jedes Byte invertiert und im nächsten Nachrichtenaustausch als ACK zurückgesendet:
ISR(SPI_STC_vect, ISR_NOBLOCK)
{
const uchar recv = SPDR;
comBuffer[comStop] = recv;
comStop ++;
SPDR = ~recv;
}
|
Nun kann das Target selber feststellen ob die SPI-Nachrichten zu schnell in dem USBasp auflaufen > Dabei sendet niemand > zu viel und man hat immer Zeit die Bytes abzuholen, ohne dass ein > Overrun auftritt. > > Könnte das nicht so funktionieren? Heh, "niemand sendet zuviel", das ist meiner Meinung nach einfacher umsetzbar mit der Idee von Markus, nämlich eine maximale Taktfrequenz anzugeben, mit der Daten gesendet werden dürfen. > Als einfacher Anwender stelle ich es mir ideal vor, wenn man ein Binary > hat, das Linux-mäßig auf stdout schreibt. Dann kann man es beliebig in > Pipes einbauen usw. > Vielleicht kann avrdude schon von Haus aus sowas? Ich hab keine Ahnung. Wahrscheinlich müsste man dann avrdude erweitern, mal schauen was sich da machen lässt :) Das Problem auf dem PC ist auch folgendes: Wir können keine Annahmen über die Anzahl der gesndeten Nachrichten von dem Target machen, außer die maximale Taktfrequenz als obere Schranke. Daher muss man auf der PC Seite eigentlich ununterbrochen USB-Control Nachrichten verschicken, mit der Bitte die Daten aus dem Puffer des USBasps zum Host zu senden. Meine Pythonlösung (ist übrigens nicht standardmäßig installiert) hat daher eine CPU Auslastung von 100% :( Mit avrdude wäre das nicht anders. > > > Gruß Oliver Gruß Stefan
Datum:
Stefan B. schrieb: > SPI ist ein voll Duplex Bus, das bedeutet, das immer wenn A ein Byte > nach B sendet, auch automatisch ein Byte von B nach A gesendet wird. Wie stellst du dir das genau vor? > Woher weiß das Gerät (beide), wann es den Status umschalten soll? > Wenn das Target zufällig ziemlich lange keine Daten verschickt und dann > viele Daten in kurzer Zeit? Ich dachte mir das so: Der usbasp ist quasi immer Slave. Er wird nur kurz zum Master wenn er das Ack verschickt. Das würde ich vom Hauptprogramm aus machen, um auch gleich danach wieder umschalten zu können. Der Target-AVR sendet ein Byte und schaltet um auf Slave. Wenn er das ACK bekommt, dann schaltet er wieder auf Master und sendet das nächste Byte, wenn vorhanden. Hmm das wird aber nichts, wenn der USB-Interrupt feuert, bevor der USB-asp wieder auf Slave geschalten hat. Dann würde nämlich wenn der Target-AVR der Meinung ist, dass er wieder senden darf, der usbasp immer noch ein Master sein. Das kann so nicht funktionieren. Gruß Oliver
Datum:
Ich glaube ich habe die Handshake Lösung gefunden: http://www.avrfreaks.net/index.php?name=PNphpBB2&f... Der Master setzt in seinem Telegramm das Busyflag, sendet es heraus und pollt dann solange die MISO-Leitung, bis der Slave sein Byte in das SPDR herein geschrieben hat und damit das Busyflag toggelt. Dann kann der Master das nächste Byte senden. Kommt einem Handshake über die MISO-Leitung gleich. Man könnte einfach gestalten indem man nur 7 Datenbit verwendet und das höchste dann als Busyflag nutzt. Da könnte man dann immer 7 Bit in beide Richtungen übertragen. Null wird als kein Zeichen gewertet. Da müsste man aber vom Target-AVR aus den USBasp dann ständig pollen, wenn in beide Richtungen übertragen werden soll. Für ASCII reichen 7 Bit denke ich. Gruß Oliver
Datum:
Denkt bitte dran, dass es hinterher für den Anwender möglichst einfach sein soll. printf() auf dem Mikrocontroller soll möglichst ohne Änderungen oder Rücksichtnahme auf ein Flusssteuerungsprotokoll fehlerfrei funktionieren. Wahrscheinlich geht das wirklich nur mit der Vorgabe einer maximalen Taktfrequenz. Was mir vorhin auch durch den Kopf ging: Wenn der USBasp Master ist, kann die Übertragung trotzdem in Gegenrichtung stattfinden, ja, es stört auch nicht, wenn sie nur in Gegenrichtung läuft. Der USBasp schickt dann nur den Takt, mehr nicht. Beim regelmäßigen Wechsel zwischen Master uns Slave muss auch immer der Takt-Master wechseln, das heißt, man braucht Sicherheitsvorkehrungen auf der Taktleitung – z.B. nach dem Open-Kollektor-Prinzip. Das verkompliziert die Sache. Trotzdem wär es am einfachsten, wenn der Mikrocontroller der Master bleiben darf – eben mit langsamem Takt.
Datum:
Markus W. schrieb: > Denkt bitte dran, dass es hinterher für den Anwender möglichst einfach > sein soll. Wenn man dem Anwender eine Lib oder eine fertige putc-Funktion gibt, ist dem das sicher zum Schluss egal, wie die Kommunikation intern funktioniert. > printf() auf dem Mikrocontroller soll möglichst ohne > Änderungen oder Rücksichtnahme auf ein Flusssteuerungsprotokoll > fehlerfrei funktionieren. Warum sollte das kompliziert sein. Einfach ein spi_putc gemäß der avr-libc bauen und stdout darauf umleiten. Die putc Funktion blockiert halt solange bis der Slave nicht mehr busy ist. > Trotzdem wär es am einfachsten, wenn der Mikrocontroller der Master > bleiben darf – eben mit langsamem Takt. Das kann er bei dem MISO-Polling definitiv. Ich denke, dass man das tatsächlich so machen kann/sollte, wie ich es bereits vorhin beschreiben habe (MISO-Busy-Polling). Für eine Richtung ist das fast schon trivial. Damit hätte man den maximal möglichen Durchsatz und kann auch noch buffer-overflows verhindern, wenn der Slave seinen Zustand erst auf nicht busy setzt, wenn Platz im Ringpuffer ist. Wenn ich heute Abend etwas Zeit habe, dann probiere ich das mal aus. PS. Wäre das denn nicht schön, wenn man den maximal möglichen Durchsatz erreichen kann und nicht um ein einziges Byte bangen müsste? Gruß Oliver
Datum:
Man könnte auch 8 Bit versenden und nutzt ein Toggeln des MSB im usbasp für den Handshake. Da müsste man nur den Kommunikationsstart irgendwie synchronisieren. Vielleicht reicht es aus, wenn man das erste Byte nach dem Reset des Target-AVR einfach heraus schreibt und danach erst Handshake betreibt. Gruß Oliver
Datum:
Oliver J. schrieb: > Warum sollte das kompliziert sein. Einfach ein spi_putc gemäß der > avr-libc bauen und stdout darauf umleiten. Die putc Funktion blockiert > halt solange bis der Slave nicht mehr busy ist. Hallo! Denke doch bitte auch an die Leute, die z.B. einen ATtiny13 in Assembler programmieren. Gerade für die ist das USB-SPI sehr wertvoll, weil sie nur schwer auf andere Wege umsteigen können (die kleinen Tinys haben keinen UART). Hier kostet jedes Byte wertvollen Platz, und eine Lib lässt sich da kaum "einbinden". Ich seh es deswegen genauso wie Markus: maximale SPI-Geschwindigkeit vorsehen
Datum:
Hubi schrieb: > Hier kostet jedes Byte wertvollen Platz, und eine Lib > lässt sich da kaum "einbinden". Wenn man das Handshake nicht verwenden will, dann schreibt man halt einfach Zeichen raus und gut ist. > Ich seh es deswegen genauso wie Markus: maximale SPI-Geschwindigkeit > vorsehen Ich bin eher für die sichere Variante. Gruß Oliver
Datum:
Die Hostseite ist soweit fertig. Es werden exakt die empfangenen Bytes auf stdout ausgegeben. Derzeit bin ich dabei auszumessen, mit welcher maximalen Taktrate das SPI des USBasp befeuert werden kann. Dabei stelle ich fest, dass hin und wieder manche USB Packete anscheinend doppelt ankommen.
Datum:
Stefan B. schrieb: > Die Hostseite ist soweit fertig. > Es werden exakt die empfangenen Bytes auf stdout ausgegeben. Gratuliere! :-) > Dabei stelle ich fest, dass hin und wieder manche USB Packete > anscheinend doppelt ankommen. Verschwinden im Subraum? ;-) Das heißt, manche Zeichenfolgen erscheinen dann doppelt am Bildschirm? Ich mach mir grad Gedanken, ob sich dein Host-Script später vielleicht auch auf Bash oder C portieren lässt. Vielleicht wage ich mich an einen Versuch – aber das dauert noch.
Datum:
Wie stellt ihr euch eigentlich den Betrieb dieses Projektes vor? Damit diese Geschichte überhaupt funktionieren kann, darf nicht die Resetleitung des Target-AVR auf /SS des usbasp gehen. Bei allen AVR-Schaltungen, die ich kenne (Ausnahme: usbasp), ist aber Reset auf den Programmierstecker geführt. Reset ist aber normalerweise kein GPIO. Gruß Oliver
Datum:
Soweit ich den USBASP verstanden habe, soll die Erweiterung eine echte UART zum Target bereitstellen. Dies wäre ein nettes Feature, aber nicht unbedingt erforderlich, da es ein billiger USB-UART-Adapter (gibt es auch mit TTL-Pegel) auch tut. SPI zwischen Target und Umsetzer (ASP), noch dazu mit Flusssteuerung, da AVR-SPI mangels Empfangspuffer nicht so richtig Slave-fähig ist, halte ich für nicht unbedingt erstrebenswert. Ein kleines Platinchen mit MAX232 und 4 Pins zum AVR (Vcc, GND, RXD, TXD) habe ich sowiso immer an einem RS232-Verlängerungskabel hängen, da ich dieses Interface regelmäßig zum Parametrieren verschiedener AVR-Schaltungen nutze. Dies ermöglicht in Verbindung mit HTERM problemloses Debuggen über UART sowie mittels spezieller kleiner VB6-Programme komfortables Parametrieren des Targets. ...
Datum:
Oliver: Soweit ich mich an den Schaltplan erinnere, wird die Resetleitung des Targets vom USBasp immer dann (und nur solange) auf GND gezogen, wenn programmiert wird. Danach ist die Leitung wieder auf VCC, und man kann die Zielschaltung mit den 5 Volt aus USB betreiben. Manche USBasps lassen sich sogar auf 3,3 Volt umschalten, so dass man auch Zielschaltungen programmieren und versorgen kann, die mit 3,3 Volt arbeiten, weil sie z.B. ein LCD oder eine SD-Karte ansteuern. Also: alles im grünen Bereich. :-) Hannes Lux schrieb: > Dies wäre ein nettes Feature, aber nicht > unbedingt erforderlich, da es ein billiger USB-UART-Adapter (gibt es > auch mit TTL-Pegel) auch tut. Klar, mit einem eigenen RS232-Umsetzer gehts auch. Das bedingt aber 1. dass der Mikrocontroller einen UART hat (einige haben das nicht), 2. dass du (wie du auch schreibst) einen MAX232 brauchst, also zusätzliche Hardware, und 3. dass dein PC eine serielle Schnittstelle bzw. einen Adapter dafür braucht. Das von Stefan angestoßene Projekt kommt ohne 1., 2. und 3. aus. Deswegen ist es ja so genial. :-)
Datum:
Markus W. schrieb: > Also: alles im grünen Bereich. :-) Muss denn der Target-AVR nicht am usbasp den SS-Pin gegen Masse ziehen, um ein Byte übertragen zu können? Wie soll er das mit seinem Reset-PIN tun? Oder soll das Ganze nur für usbasps und Spezialschaltungen sein? Gruß Oliver
Datum:
Der usbasp wird sich eben einfach immer angesprochen fühlen, so viel Leitungen gibt der ISP nunmal nicht her.
Datum:
Martin Wende schrieb: > Der usbasp wird sich eben einfach immer angesprochen fühlen, so viel > Leitungen gibt der ISP nunmal nicht her. Wie soll das funktionieren, wenn die Resetleitung des Targets auf 5V liegt und diese Leitung mit dem SS vom usbasp verbunden ist. Um als Slave Daten empfangen zu können, muss SS auf low-Pegel liegen. Gruß Oliver
Datum:
Das ist ein super interesantes Thema! Bin grad darauf gestoßen als ich nach etwas gesucht habe, wie ich mit dem USBasp Adapter Signale von meinem µC ablesen kann. Gibt es schon irgendwelche Updates? So wie ich es verstanden habe wurde am originalen Layout des Adapters nichts geändert, oder? Nur die Firmware wird neu geschrieben. Bin jedenfalls sehr gespannt wie das hier weitergeht!
Datum:
Matthias Kesenheimer schrieb: > Gibt es schon irgendwelche Updates? Hallo Matthias, auch ich hoffe noch auf Updates. Fürchte aber, der Thread-Ersteller ist im wohlverdienten Pfingsturlaub.
Datum:
Matthias Kesenheimer schrieb: > So wie ich es verstanden habe wurde am originalen Layout des Adapters > nichts geändert, oder? Nur die Firmware wird neu geschrieben. > Bin jedenfalls sehr gespannt wie das hier weitergeht! Genau, es gab keine Hardware Änderung. (Ich benutze die USBasp Hardware aus dem Shop von Ulrich Radig.) Die Firmware wurde nur minimal verändert. Stand der Dinge: Vom dem Targetavr kann man per SPI Daten verschicken. Dieser Bytestream wird genauso auf dem Hostrechner auf stdout ausgegeben. Für meinen Anwendungszweck ist das genug, was würdet ihr da noch erweitern?
Datum:
Ist das dann die aktuelle Firmware, mit der das funktioniert? https://github.com/stefanbeller/USBasp
Datum:
Matthias Kesenheimer schrieb: > Ist das dann die aktuelle Firmware, mit der das funktioniert? genau das ist es.
Datum:
Stefan B. schrieb: > Matthias Kesenheimer schrieb: >> Ist das dann die aktuelle Firmware, mit der das funktioniert? > > genau das ist es. Super! Ist die Firmware-Basis von Mai 2011? Will heißen, funktioniert damit auch das "-B"-Kommando, oder hast du eine ältere Firmware als Basis verwendet? Gibt es noch irgendwelche Probleme mit Bytes, die verloren gehen?
Datum:
https://github.com/stefanbeller/USBasp/commit/da7b... > Initial commit. > This includes the files as of > wget http://www.fischl.de/usbasp/usbasp.2011-05-28.tar.gz > tar -xf usbasp.2011.05-28.tar.gz Markus W. schrieb: > Ist die Firmware-Basis von Mai 2011? Will heißen, funktioniert damit > auch das "-B"-Kommando, oder hast du eine ältere Firmware als Basis > verwendet? Ich habe die anderen Kommandos nicht explizit getestet, zumindest das flashen eines weiteren usbasps mit dieser Firmware funktioniert. ;)
Datum:
Stefan B. schrieb: > Ich habe die anderen Kommandos nicht explizit getestet, zumindest das > flashen eines weiteren usbasps mit dieser Firmware funktioniert. ;) Guuut! :-) Magst du bei fischl.de anfragen, ob sie deine Verbesserungen übernehmen? Die meisten User suchen ja direkt bei fischl, wenn sie ein Firmware-Update brauchen. Die Hex-Dateien in USBasp/bin/firmware müsste man dann auch noch entsprechend updaten. Langfristig findet sich sicher jemand, der dein Host-Script in C übersetzt und nach Windows portiert. Aber ok, ich persönlich brauch kein Windows. :-)
Datum:
Markus W. schrieb: > Magst du bei fischl.de anfragen, ob sie deine Verbesserungen übernehmen? > Die meisten User suchen ja direkt bei fischl, wenn sie ein > Firmware-Update brauchen. Vor 11 Tagen (also als ich gefühlt fertig war), habe ich fischl eine mail geschrieben, er wolle sich das mal ansehen, habe aber 2 Wochen lang keine Zeit. Die Zeit ist fast vorbei, mal sehen ob was kommt. Ulrich Radig habe ich auch auf diesen Thread hingewiesen, habe aber noch keine Antwort bekommen. Zusätzlich habe ich die Firmware kompiliert und gepushed. https://github.com/stefanbeller/USBasp/tree/master... Ich persönlich würde so vorkompilierte Software für den PC nicht einfach so aus dem Web nutzen. Auf Mikrocontrollern macht man nicht viel falsch, aber generell für meinen Computer möchte ich es entweder selbst kompilieren, oder aus einer vertrauenswürdigen Quelle herunterladen. (zb. Repositories einer großen Distribution.) Das selberkompilieren bringt nochmal einen gewisses Vertrauen in den Code, da man es ja reviewen kann. ;) (Das tue ich nur manchmal, zumindest ein Überfliegen, ob offensichtliche Probleme bestehen.) Gruß, Stefan
Datum:
Tja, was nun?
name:firmware name$ sudo make main.hex Password: avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o In file included from usbdrv/usbdrv.c:12:0: usbdrv/usbdrv.h:455:6: Fehler: Variable »usbDescriptorDevice« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:461:6: Fehler: Variable »usbDescriptorConfiguration« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:467:6: Fehler: Variable »usbDescriptorHidReport« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:473:6: Fehler: Variable »usbDescriptorString0« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:479:5: Fehler: Variable »usbDescriptorStringVendor« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:485:5: Fehler: Variable »usbDescriptorStringDevice« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.h:491:5: Fehler: Variable »usbDescriptorStringSerialNumber« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.c:70:14: Fehler: Variable »usbDescriptorString0« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.c:80:14: Fehler: Variable »usbDescriptorStringVendor« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.c:89:14: Fehler: Variable »usbDescriptorStringDevice« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.c:111:14: Fehler: Variable »usbDescriptorDevice« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden usbdrv/usbdrv.c:142:14: Fehler: Variable »usbDescriptorConfiguration« muss konstant sein, um mit »__attribute__((progmem))« in Nur-Lese-Abschnitt gelegt zu werden make: *** [usbdrv/usbdrv.o] Error 1 |
Datum:
Hm, gute Frage, genau die aktuelle Version aus dem repository ergibt hier folgendes:
$ make main.hex avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c usbdrv/oddebug.c -o usbdrv/oddebug.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c isp.c -o isp.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c clock.c -o clock.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -x assembler-with-cpp -c tpi.S -o tpi.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c main.c -o main.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -o main.bin usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o isp.o clock.o tpi.o main.o -Wl,-Map,main.map rm -f main.hex main.eep.hex avr-objcopy -j .text -j .data -O ihex main.bin main.hex |
Mit
avr-gcc --version avr-gcc (GCC) 4.5.3 |
Welche Version des avr-gcc hast benutzt du?
Datum:
Trippelpost, yay! @Matthias Kesenheimer Ich habe die relevanten Stellen mal mit dem const keyword versehen, bei mir kompiliert das immer noch ohne Fehler. Vielleicht kannst du den jetzigen Stand mal ausprobieren?
Datum:
Stefan B. schrieb: > Welche Version des avr-gcc hast benutzt du? Ich habs mit der Version 3 und mit 4 probiert.
avr-gcc --version avr-gcc (GCC) 4.7.0 |
Stefan B. schrieb: > Ich glaube hier > Beitrag "Re: Fiese Zeiger Hacks und PROGMEM" > wird dieser Fehler diskutiert. Ok, das kann sein, ich kann leider nicht so arg viel damit anfangen :) Stefan B. schrieb: > Trippelpost, yay! > > @Matthias Kesenheimer > Ich habe die relevanten Stellen mal mit dem const keyword versehen, bei > mir kompiliert das immer noch ohne Fehler. Vielleicht kannst du den > jetzigen Stand mal ausprobieren? Versuch ich gleich, moment...
Datum:
scheint zu funktionieren, danke!
avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c usbdrv/oddebug.c -o usbdrv/oddebug.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c isp.c -o isp.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c clock.c -o clock.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -x assembler-with-cpp -c tpi.S -o tpi.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -c main.c -o main.o avr-gcc -Wall -O2 -Iusbdrv -I. -mmcu=atmega8 -o main.bin usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o isp.o clock.o tpi.o main.o -Wl,-Map,main.map rm -f main.hex main.eep.hex avr-objcopy -j .text -j .data -O ihex main.bin main.hex |
Gut, wenn ich dann die Firmware geflasht habe, wie lese ich dann die Daten von meinem µC ab? Was muss ich also avrdude mitteilen, dass mein µC die Daten an stdout sendet?
Datum:
Auf dem Hostrechner startest du das Ausgabeskript
cd ./host/ python pipeout.py |
Dann werden die Ausgaben auf den Bildschirm angezeigt. Alternativ kannst du die Daten anstelle auf den Bildschirm auch in eine Datei (hier daten.bin) leiten:
cd ./host/ python pipeout.py > daten.bin |
Auf dem Mikrocontroller versendest du die Daten per SPI, also zum Beispiel so etwas (ungetestet):
#include <avr/io.h> #include <util/delay.h> int main(void) { SPCR = (1 << SPE | 1 << MSTR); // aktiviere SPI als Master. SPDR = 'H'; delay_us(10); SPDR = 'a'; delay_us(10); SPDR = 'l'; delay_us(10); SPDR = 'l'; delay_us(10); SPDR = 'o'; delay_us(10); SPDR = ' '; delay_us(10); SPDR = 'W'; delay_us(10); SPDR = 'e'; delay_us(10); SPDR = 'l'; delay_us(10); SPDR = 't'; delay_us(10); SPDR = '.'; while (1); } |
Datum:
Angehängte Dateien:Hallo Zusammen Sorry das ich mich kurz einmische, ohne alles gelesen zu haben, ich bin gleich wider weg;-) Vor einem halben Jahr habe ich selbst USBAsp erweitert um eine Serielle Kommunikation über UART zu erhalten. Ich habe dazu auch noch ein kleines "Terminal" geschrieben, um das ganze unter Linux anzusprechen. Für mich reichts, ich habe den Code auch wider zurück an Fischl gesendet, der hat gesagt beim nächsten Release wird dieser eingebaut. Da dies offenbar noch nicht geschehen ist veröffentliche ich hiermit den Code unter der GPL. Die Kommunikation hat funktioniert. Die Konsole ist eher dürftig. Ich arbeite momentan nicht mehr daran. Falls jemand diesen Code weiterverwendet, bitte schreibt mir doch kurz ein Mail oder eine Nachricht im Forum. Ich werde ggf. irgendwann auch mal wieder an dem Code weiterentwickeln. mfg Andreas
Datum:
@Stefan: Danke für die ausführliche Anleitung! Ich hab es bis jetzt noch nicht an Hardware ausprobieren können, sondern nur mal das Pythonscript gestartet und geschaut was dabei rauskommt. Es treten ein paar Fehler auf, aber ich denke mal, das kommt daher, dass mein USBasp adapter noch nicht richtig geflasht wurde. Würde nur mal gerne wissen ob ich bis jetzt alles richtig gemacht habe :) Das ist das was beim starten des Skriptes ausgegeben wird:
Traceback (most recent call last):
File "pipeout.py", line 28, in <module>
handle = getHandle()
File "pipeout.py", line 9, in getHandle
busses = usb.busses()
File "/Library/Python/2.6/site-packages/usb/legacy.py", line 333, in busses
return (Bus(),)
File "/Library/Python/2.6/site-packages/usb/legacy.py", line 329, in __init__
self.devices = [Device(d) for d in core.find(find_all=True)]
File "/Library/Python/2.6/site-packages/usb/core.py", line 846, in find
raise ValueError('No backend available')
ValueError: No backend available
|
Treten die Fehler wegen dem noch nicht geflashten USBasp auf?
Datum:
der obige Post ist von mir (Matthias Kesenheimer)
Datum:
Ich habe kurz in die Lösung von Andreas B. geschaut und gebe zu die sieht technisch eleganter aus. Ich werde Sie auf jeden Fall mal ausprobieren. (Wahrscheinlich erst nächstes Wochenende.) @bartimaeus Heh, das ist das Problem mit 'mal eben zusammengehacktem Code'. Keine Doku und nix ;) Ich habe folgende Packete installiert (Ubuntu 12.04)
$ dpkg -l |grep libusb ii libusb-0.1-4 2:0.1.12-20 userspace USB programming library ii libusb-1.0-0 2:1.0.9~rc3-2ubuntu1 userspace USB programming library ii libusb-1.0-0-dev 2:1.0.9~rc3-2ubuntu1 userspace USB programming library development files ii libusb-dev 2:0.1.12-20 userspace USB programming library development files ii libusbmuxd1 1.0.7-2 USB multiplexor daemon for iPhone and iPod Touch devices - library $ dpkg -l |grep usb |grep python ii python-usb 0.4.3-1 USB interface for Python |
Ich nehme an du brauchst ähnliche Packete insbesondere python-usb in der Version 0.4.3 (Die Autoren behaupten die Version 1.0, welche komplett neu geschrieben ist, sei kompatibel. Also sollte es auch mit der neueren Version gehen.)