Ein PIC32 soll verschiedene Unteraufgaben für ein OMAP3 basiertes Linux System übernehmen. In meinem aktuellen Fall sind das einen CAN Bus bedienen, über zwei I2C Schnittstellen mit vier Touch Panels kommunizieren (2 pro I2C) und ein paar einfache GPIO Aktionen. Nachdem es Datenverkehr in unregelmässigen Zeitabständen in beide Richtungen gibt, würde ich gern eine gesicherte Stream Kommunikation, quasi wie ein TCP Stream aufbauen. Das wäre auch eine wiederverwendbare Lösung. Allerdings ist das mit einer SPI nicht ganz trivial und es muss ja auch irgend einen Handshake-Mechanismus beinhalten, um sicherzustellen, dass der Slave auch kommunikationsbereit ist. Auch ein guter permanenter Durchsatz und eine pünktliche Ereignisübermittlung im <= 10ms Bereich ist wichtig, wobei die Linux CPU nicht zu sehr gestresst werden sollte. Gibt es so etwas schon, oder hat hier jemand Erfahrung mit solch einer Kommunikation?
Ein erster Ansatz ist folgender: fixed block size, e.g. 64 byte block can contain any number of complete data items struct tDataItem { tByte SequenceNo; tByte CRC8; tByte TargetProcess; tByte Cmd; tByte Len; tByte Data[]; }; SequenceNo: high nibble is negated low nibble 0 for no data 1..15 cyclic numbering of DataItems GPIO to simplify and speed up communication Linux-->uC: PrepareForCommunication Linux-->uC: MasterDataAcceptanceToggle uC-->Linux: DataAvailable uC-->Linux: ReadyToCommunicate uC-->Linux: SlaveDataAcceptanceToggle Master will communicate when he has data to transmit or when slave raises DataAvailable Master requests transmission with raising PrepareForCommunication Slave activates SPI DMA and signals readyness by raising ReadyToCommunicate (could be replaced by a very short delay) Both sides evaluate received blocks and toggle Master/SlaveDataAcceptanceToggle when block was valid. Without toggle, the same block would be retransmited
>Ich würde CAN nehmen oder RS-232. >quasi wie ein TCP Stream aufbauen. Oder gleich Ethernet. Dann passt das mit TCP schon;) >Allerdings ist das mit einer SPI nicht ganz trivial SPI ist sowas von trivial. Eigentlich eines der einfachsten Interfaces überhaupt. >Ist eine solche Datenübertragung per SPI so ungewöhnlich? Nö, ich frag mich nur was du eigentlich von uns willst? Mach einfach. Wird schon passen wenn du ein Hardwarehandshake sowieso schon angepeilt hast.
Das Problem an SPI ist, daß es eine hohe Interruptlast bewirkt, da oft nicht gepuffert. Wenn aber beide Seiten das SPI per DMA oder Event System d.h. ohne CPU-Last bedienen können, dann könnte man es nehmen. Allerdings wird das Protokoll recht krude werden, da SPI bidirektional arbeitet. Der Slave sendet also immer die Antwort auf das vorherige Paket wärend der Master das nächste Paket sendet, viel Spaß dabei. CAN hätte den Vorteil, daß es einem einen riesen Rucksack an Protokollsoftware schon abnimmt. Einfacher als mit CAN gehts nicht.
>Allerdings wird das Protokoll recht krude werden, da SPI bidirektional >arbeitet. Der Slave sendet also immer die Antwort auf das vorherige >Paket wärend der Master das nächste Paket sendet, viel Spaß dabei. Nicht zwangsläufig. Der Master kann sein Paket auch komplett absetzen ohne das der Slave auf jedes Byte eine Antwort geben muss. Man kann das sehr einfach gestalten. >CAN hätte den Vorteil, daß es einem einen riesen Rucksack an >Protokollsoftware schon abnimmt. Einfacher als mit CAN gehts nicht. CAN hat den riesen Nachteil das in einem Paket nur 8 Byte Nutzdaten versendet werden können. Der Aufwand für grössere Pakete ist viel höher als mit einer einfachen SPI Verbindung. Wenn die Entfernung zwischen Master und Slave klein ist (ein paar Zentimeter) kann man SPI mit einigen MHz betreiben. Da sieht CAN einfach nur noch alt aus.
holger schrieb: > Der Master kann sein Paket auch komplett absetzen > ohne das der Slave auf jedes Byte eine Antwort geben muss. Dann verschwendest Du Bandbreite bzw. mußt die doppelte Taktfrequenz nehmen. Es senden immer beide Seiten, daher wäre es uneffektiv, wenn einer immer nur Dummy-Bytes sendet. Können Dein PIC und der Linuxer denn nun SPI-DMA? holger schrieb: > CAN hat den riesen Nachteil das in einem Paket nur 8 Byte > Nutzdaten versendet werden können. Und was ist der Nachteil daran? Wir übertragen ohne Probleme längere Datenströme über CAN, z.B. ganze Firmwareupdates. Der SW-Aufwand ist lächerlich, einfach ne Paketnummer mitzählen und gut. Dafür entfällt SW für CRC, ACK, Handshake, Error usw.
>> Der Master kann sein Paket auch komplett absetzen >> ohne das der Slave auf jedes Byte eine Antwort geben muss. > >Dann verschwendest Du Bandbreite bzw. mußt die doppelte Taktfrequenz >nehmen. >Es senden immer beide Seiten, daher wäre es uneffektiv, wenn einer immer >nur Dummy-Bytes sendet. Ist doch egal wenn die Bandbreite sowieso nicht genutzt wird. >> CAN hat den riesen Nachteil das in einem Paket nur 8 Byte >> Nutzdaten versendet werden können. > >Und was ist der Nachteil daran? Das der ganze Protokoll Overhead noch mal genau so viel frisst. Man hat nur die Hälfte Bandbreite für Nutzdaten. Also erzähl mir nichts von Verschwendung. >Der SW-Aufwand ist lächerlich, einfach ne Paketnummer >mitzählen und gut. Dafür entfällt SW für CRC, ACK, Handshake, Error usw. Bei SPI ist der Softwareaufwand noch lächerlicher. CRC können die meisten SPI Module auch schon per Hardware. Bis du dein CAN Modul mal initialisiert hast hab ich schon das erste Megabyte Daten übertragen;)
Ich hab da auch lange drueber nachgedacht wie ich das am besten mache. Ich mach das jetzt mit SPI (beim linux ein kernel modul mit userland interface) und CRC. Da geht das Bit per Bit in Hardware und das sichern des Bytes in Software, beim Linux und beim uC. Beim Linux hat das SPI einen eigenen Buffer auf Kernel ebene, der Kernel sagt mir dann wann die Uebertragung (in meinem Fall eine Pause in der Uebertragung) fertig ist. Die Datenpackete sind (bis MaxBytes) unterschiedlich gross, je nach dem wieviel mal der Master am SCK wackelt. Wenn der Slave was zu sagen hat wackelt er an einem zusaetzlichen Pin der beim Linux eine ISR anspringt, es wird ein "Funktions"-Byte uebertragen was dem Master sagt was er zu tun hat.
Erst mal Danke für eure Anregungen und Kommentare Hier ein paar Antworten auf eure Fragen: - Ja, beide Seiten haben DMA - Hardware CRC für die SPI existiert nicht - es ist eine kurze on-Board Verbindung die man mit 10MBit/s betreiben kann - es muss schon SPI sein, im aktuellen Projekt ist der PIC quasi die CAN Schnittstelle für den OMAP >>Allerdings ist das mit einer SPI nicht ganz trivial >SPI ist sowas von trivial. Eigentlich eines der >einfachsten Interfaces überhaupt. Auf der untersten Ebene gebe ich Dir recht, aber ich spreche von einem höheren Protokoll und das ist alles andere als einfach über SPI zu implementieren. >>Ist eine solche Datenübertragung per SPI so ungewöhnlich? >Nö, ich frag mich nur was du eigentlich von uns willst? >Mach einfach. Wird schon passen wenn du ein Hardwarehandshake >sowieso schon angepeilt hast. Ich möchte nicht das Rad neu erfinden. Da gibt es bestimmt schon Lösungen. Auch frage ich mich wie viel Hardware Handshake sinnvoll und notwendig ist. Einen uC für ein Linux System arbeiten zu lassen und dabei die gut verfügbare SPI zu benutzen scheint mir sinnvoll und in vielen Fällen anwendbar. So ein PIC kann Dinge, die gehen auf einer Linux CPU nicht oder zumindest nicht so gut.
Hi Michael, ich habe öfters solche Sachen zwischen FPGA und Linux-Host gemacht. Bewährt hat sich meist ein einfaches Registerprotokoll. GPIOs als Handshake einzusetzen kann u.U. haarig werden, Du musst das auf jeden Fall im Kernel-Space (eigener Treiber) machen, sonst gibts "Race conditions", d.h. ein GPIO wird ev. gesetzt, bevor der SPI-Transfer abgeschlossen ist. Oder alles pur eventbasiert (mit Interrupts) lösen. Ich habe mir jeweils die Zeit fürs Auslesen eines Status-Registers gegönnt. Wenn Daten da sind, wird dann der entsprechende Block ausgelesen. Grüsse, - Strubi
@strubi: Ja, es soll ein interuptgesteuertes Kernelmodul werden. Mit dem FPGA kannst Du eine Registeraddressierung gut machen (haben wir schon öfters getan) aber mit einem uC als Slave ist das schwierig. Da geht das nur mit 2 Transfers. Und man muss auch höllisch aufpassen, dass man den Slave nicht unvorbereitet anspricht. Will man noch Fehlerkorrektur implementieren, dann kommt ohne Zusatzleitungen noch mindestens ein weiterer Transfer dazu. Ich hatte gehofft es gibt hier eine Art Standardlösung für SPI, aber bisher habe ich leider nichts brauchbares gefunden.
Michael S1. schrieb: > aber mit einem uC als Slave ist das schwierig. Einen praxistauglichen Einsatz eines MC als SPI-Slave habe ich noch nie gesehen, wird wohl seinen Grund haben. Die Slave sind immer nur dumme Device (ADC, DAC, Schieberegister) oder FPGA/ASIC. Als Verbindung zwischen 2 MCs ist aber die UART auch gut geeignet. Mußt mal prüfen, ob man 2MBaud oder mehr einstellen kann.
Ich habe ja auch ein paar Zweifel ob das mit vertretbarem Aufwand eine stabile Lösung wird, aber ich habe in der aktuellen Situation nur SPI zur Verfügung. Allerdings sehe ich auch Chancen solch eine Lösung öfters einzusetzen. @Jürgen: Ich kann zwar keine Userlandlösung einsetzen, weil sich kernel driver an den SPI Paketdienst hängen werden, aber ich bin trotzdem an Deinen Erfahrungen interessiert. Ein paar Fragen wäred: Läuft das bei Dir stabil? Welchen Durchsatz und welche Latenzzeiten hast Du? Benutzt Du Halbduplex?
Peter Dannegger schrieb: > Einen praxistauglichen Einsatz eines MC als SPI-Slave habe ich noch nie > gesehen, wird wohl seinen Grund haben. Das geht nach meiner Erfahrung nur gut, wenn der Chip DMA kannund sofort bei einem "pumped transfer" (gleichzeitig rein/raus) unmittelbar mit einem ersten Statusbyte antworten kann.D.h. sobald der SPI CS low geht, muss der Solave-uC sofort scharfgeschaltet sein. Ansonsten kann das ein rechter "Hack" werden. Oder man kriegt es eben sauber im Kernel-Space mit Hilfe von GPIOs gelöst. Der Software-Aufwand ist aber erheblich und weil es eben ein rechter Hack ist und u.U. Stabilitätsprobleme macht (der SPI-Code in Linux ist nicht grade das gelbe vom Ei was Timing angeht), hätte ich wiederum eher an i2c gedacht (da gibts immerhin einen Handshake), aber das ist vielleicht wieder nicht schnell genug... Juergen G. schrieb: > Wenn der Slave was zu sagen hat wackelt er an einem zusaetzlichen Pin > der beim Linux eine ISR anspringt, es wird ein "Funktions"-Byte > uebertragen was dem Master sagt was er zu tun hat. Damit drehst Du ja quasi die Master/Slave-Rolle um. Habe festgestellt, dass das solche "attention"-Soft-Interrupts recht Protokoll-Overhead verursachen und auch einige Stolperfallen bereithalten. Und mit vielen Soft-Handshake-Phasen ("Biste bereit?" - "ja, bereit" - "Ok, ich rede jetzt") plus sauberen Timeout-Bedingungen dass das Ding nicht hängt, wirds ganz schön komplex. Da gibts so viele Varianten und wenige Lösungswege, die sich arg am konkreten Problem orientieren, deshalb fürchte ich, dass es keine super-effiziente Patentlösung von der Stange gibt. SPI mit Linux ist einfach kein Spass.. Bis meine angepeilte SPI-GPIO-Kombination richtig sauber tat, hat es erst mal einen neuen Xenomai-basierten Treiber gebraucht :-/ Trotzdem: Viel Erfolg :-)
Strubi schrieb: > Xenomai-basierten Treiber gebraucht :-/ oops, Asche auf mein Haupt, das hatte ich ganz vergessen zu erwaehnen. Ich habe mehrere Anwendungsgebiete wo ich uC-SPI mit Linux-SPI laufen lasse. Einige sind zeitkritisch, andere nicht. Aber alle arbeiten nach dem selben Prinzip. Bei den zeitkritischen Systemen arbeitet das Linux mit einem Xenomai Kernel und entsprechendem SPI Kernel Modul. Das der uC immer Slave ist und an einem Pin wackeln muss wenn er was zu sagen hat, hat verschiedene Gruende. Zum einen habe ich es nicht geschafft den Linux SPI mit vernuenftiger Latenz als Slave zu implementieren. Wenn er als Master laeuft weiss ich bei definierten (MaxBytes) und (BlockTime) was die laengste Zeit zur Uebertragung ist und kann unkritische Prozesse auf dem Linux ausblocken. Wenn der Chip auf dem das Linux laeuft DMA am SPI hat ist das eine leichte Uebung, die Uebertragung laeuft immer Duplex und ich muss (durch Queues) sicher stellen das im uC und Linux keine Race Condition entsteht. Bis jetzt ist mir das bei meinen Anwendungen immer gelungen und die Latenzen gehen ohne Xenomai nie >10ms mit Xenomai kommt man auf < 100us mit einem 700MHz Linux. Letzteres setzt aber vorraus das man weiss was im System alles vor sich geht.
@strubi I2C auf 400KHz würde reichen, aber habe ich leider nicht zur Verfügung. @Jürgen Hat Deine Lösung eine geprüfte Übertragung (crc, xor, o.ä.), mit Wiederholung wenn notwendig?
Michael S1. schrieb: > Hat Deine Lösung eine geprüfte Übertragung Bei kritischen Anwendungen wie Maschinencontrollern haengt an jeder Uebertragung ein CRC dran. In diesem Fall verwende ich unterschiedliche Buffer (das ist ein und der selbe Speicherbereich mit unterschiedlichem Index) Die Queues stellen sicher, das auf ein gesendetes Packet ein Error folgt falls es einen gibt, wenn ein Packet ohne oder mit anderem Speicher-Index kommt, war die vorherige Uebertragung erfolgreich und der Speicher wird frei gegeben. Das mag fuer einige Anwendungen recht blauaeugig sein, bei mir reicht es aber aus. Das eigentliche Problem was "Michael S1" hat, OMAP mit Linux + CAN am externen uC oder SPI CAN-Controller, hat mir auch viel Kopfschmerzen bereitet und bestimmt drei Wochen Arbeit gekostet, ohne zufriedenstellende Resultate. Ich hab das dann mit SocketCAN auf dem OMAP gemacht. Laeuft das CAN mal auf dem OMAP kann auch der uC mit CAN daherkommen und die Welt ist wieder in Ordnung.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.