Wie kann V-USB das eingebaute SPI eines ATmega328p vermasseln?

Ich arbeite an einem V-USB-Projekt, das mit einem ATmega328p als Tastatur angezeigt wird. Der USB-Teil funktioniert großartig (es ist nicht mein erstes V-USB-Projekt), aber nachdem ich den V-USB-Stack mit gestartet habe, schlagen usbInit()alle Aufrufe der SD-Kartenbibliothek fehl. Wenn ich vorher die gleichen Funktionen aufrufe usbInit(), funktioniert alles einwandfrei.

Ich verwende einen Arduino-Klon namens Diavolino, aber ohne das Arduino/Verdrahtungs-Framework. Ich habe den USB an Digital I/O 2 und 3 angeschlossen und die SD-Karte an 10-13 (eingebaute SPI-Leitungen).

Ich habe die SD-Kartenbibliothek durchgesehen und keine Anzeichen dafür gefunden, dass sie andere Interrupts oder Register als verwendet SPxx. Ich hatte auch grepden V-USB-Code, aber er berührt nicht einmal die SPxxRegister.

Das erste Anzeichen des Problems war, als das Gerät die Verbindung trennte, als es auf die SD-Karte zugreifen sollte. Dann habe ich alle SD-Karten-Handling-Loops eingefügt usbPoll()und wdt_reset()aufgerufen und festgestellt, dass die Karte beim Schreiben ewig auf eine Bestätigung von der Karte wartet, nachdem sie die letzten beiden Bytes (CRC-16) gesendet hat.

Die SD-Kartenbibliothek, die ich verwende, ist sd_rawvon Roland Riegel.

Soweit ich weiß, ist V-USB sehr CPU-intensiv und führt wahrscheinlich zu inakzeptablen Verzögerungen in den SPI-Routinen. Normalerweise sind SPI-Operationen nicht zeitabhängig, aber Schreib- und Löschoperationen auf SPI FLASH sind es definitiv.
Das Problem ist, dass selbst Leseoperationen die meiste Zeit nicht funktionierten, und wie ich gelesen habe, werden SPI-Kommunikationen unabhängig ausgeführt, sobald die Daten- und Steuerregister durch den laufenden Code gesetzt werden.
@DaveTweed - zeitkritisch in Bezug auf das Warten auf die Karte ja, aber in Bezug darauf, dass Sie die Karte nicht auf Ihr Programm warten lassen können??
Wahrscheinlich warten Sie auf etwas, das entweder nicht passieren kann oder nicht erkannt werden kann; Beispielsweise könnte der E / A-Pin neu konfiguriert worden sein und kein Eingang mehr sein, oder es könnten falsche Daten / Takte an die Karte gesendet worden sein, die sie in einen unerwünschten Zustand versetzt haben. Stellen Sie außerdem sicher, dass der Mechanismus, mit dem die SD-Bibliothek die erforderlichen Verzögerungen erreicht, nicht unterbrochen oder beschleunigt wurde.
@ChrisStratton Ich verwende die Pins B2-5, also habe ich egrep -r '(PIN|DDR|PORT)B' . | grep -v sd_rawkeine vernünftigen Ergebnisse erzielt. Die erforderlichen Verzögerungen werden über den SPI-Port (Dummy-Reads) durchgeführt. Ich werde versuchen, die Bibliothek durch etwas anderes zu ersetzen, obwohl ihre Implementierung allem anderen, das ich gefunden habe, ziemlich nahe kommt.
@dnet, wenn Sie grep verwenden, versuchen Sie, eine Listendatei mit dem objdump zu generieren, das mit avr gcc geliefert wird, und schauen Sie dort nach, damit Sie sicher sind, dass Sie alles erhalten, was enthalten ist.
Möglicherweise haben Sie auch Rausch- oder Stromversorgungsprobleme. Überprüfen Sie Ihre Schienen mit einem Oszilloskop und die SD-Leitungen mit einem Logikanalysator, um zu sehen, was los ist.
Die V-USB-Implementierung hängt davon ab, dass USB in ein paar Zyklen des Prozessors funktioniert (ich glaube, 8 ist der Schlüssel), daher bin ich nicht überrascht, dass es an einigen Stellen die gesamte Verarbeitung in Beschlag nehmen wird.
Sie können auch überprüfen, ob irgendwann ein Stapelüberlauf auftritt. Sowohl der USB-Stack als auch eine SD-Kartenbibliothek (insbesondere wenn sie auch ein Dateisystem verwendet, das Ihnen zumindest erspart geblieben ist) können Puffer ziemlich stark nutzen und im Allgemeinen CPU-intensiv sein (hauptsächlich zum Herumschieben von Daten, nicht zum Zahlen). und neigen auch dazu, tiefe Call-Stacks zu haben. Keines davon verheißt wirklich etwas Gutes für etwas so Kleines wie einen ATMega. Selbst wenn es Funktionen gibt, die Puffer als lokale verwenden (im Gegensatz zu im Heap als "globale"), würden Sie nach Ärger fragen.

Antworten (1)

Ich hatte ein solches Problem mit USART und löste es, indem ich die Watchdog-Einstellungen änderte. Wie Sie wissen, verwendet V-USB einen Watchdog und wenn Sie zusätzliche Zeit in einen Vorgang investieren, wird der Watchdog aktiviert. Versuchen Sie, den Watchdog zu deaktivieren, und wenn Sie sehen, dass alles gut geht, können Sie die Watchdog-Zeit ändern oder den störenden Code (in Ihrem Fall die SD-Kartencodes) in kleinere Teile aufteilen und den Watchdog zwischen ihnen "zurücksetzen". Aber vergessen Sie nicht, Ihren Watchdog nach dem Debuggen wieder zu aktivieren, da es nicht empfohlen wird, V-USB ohne ihn zu verwenden.

Beachten Sie, dass die Frage erwähnt, dass wdt_reset() Aufrufe in den SD-Code eingefügt wurden; obwohl es natürlich möglich ist, dass dies nicht überall so gemacht wurde.
Ja, aber es lohnt sich wirklich, den Code mit Deaktivierung des Watchdogs auszuprobieren. Manchmal, besonders wenn die zurückgegebenen Daten in einer Interrupt-Routine verarbeitet werden, bleibt der Code dort hängen und der Watchdog wird aktiviert, bevor er zurückgesetzt wird