Forum: Mikrocontroller und Digitale Elektronik SPI mit 2 Mastern und 2 Slaves entkoppeln


von Martin S. (msperl)


Lesenswert?

Hallo!

Um die Bandbreite möglichst hoch zu halten möchte ich folgendes Setup 
umsetzen:

* 2 mal SPI FRAM devices.
* 2 mal ATMegaXXX, an denen jeweils nur der UART-SPI frei ist. (SPI 
hängt auf einem MEGA an einem MCP2515 und auf dem anderen Maga hängt 
eine SD Karte)

Die ATMegas sollen die FRAMS parallel ansprechen können (quasi als 
FIFO).
Der eine schreibt in FRAM1 während der andere gleichzeitig von FRAM2 
lesen können soll.

Wenn der schreibende ATMega ein FRAM fertig geschrieben hat, so soll er 
auf das 2te FRAM wechseln und dort weiter schreiben und der Leser soll 
dann von dem 1ten FRAM lesen.

Die Frage ist: wie kann ich die FRAMS SPI-bus mäßig so separieren, daß 
es immer nur mit einem der beiden ATMega verbunden ist? (Die Annahme ist 
das das die Syncronisierung der Megas gelöst ist)

Eine Lösung könnte sein einen 74HC244 je FRAM (oder ATMega) zu verwenden 
- da kann ich mit 2 OE jeweils 4 Pins schalten und muß mich nicht um 
Seiteneffekte die durch VCC ein/aus  entstehen könnten kümmern...

Ähnliches könne man vielleicht auch unsauber mit zwei 74HC4050 je FRAM 
machen - eines zu jedem ATmega und dann einen GPIO am jeweiligen Atmega 
nutzen um VCC des jeweiligen 74HC4050 zu treiben...

Gibt es (andere?) empfehlenswerte Lösung für eine "derartige" 
Bus-trennung wenn ich die beiden Teil-Busse bei jeweils 8MHz betreiben 
können möchte?
Gibt es etwas zu berücksichtigen?

Danke,
         Martin

von Falk B. (falk)


Lesenswert?

@  Martin Sperl (msperl)

>* 2 mal SPI FRAM devices.
>* 2 mal ATMegaXXX, an denen jeweils nur der UART-SPI frei ist. (SPI
>hängt auf einem MEGA an einem MCP2515 und auf dem anderen Maga hängt
>eine SD Karte)

Hmmm.

>Die ATMegas sollen die FRAMS parallel ansprechen können (quasi als
>FIFO).
>Der eine schreibt in FRAM1 während der andere gleichzeitig von FRAM2
>lesen können soll.

Machbar, aber irgendwie nicht so sinnvoll. Nimm EINEN AVR mit dem 
RICHTIGEN Speicher/FIFO und gut.

>Die Frage ist: wie kann ich die FRAMS SPI-bus mäßig so separieren, daß
>es immer nur mit einem der beiden ATMega verbunden ist? (Die Annahme ist
>das das die Syncronisierung der Megas gelöst ist)

Über Multiplexer.

>Ähnliches könne man vielleicht auch unsauber mit zwei 74HC4050 je FRAM
>machen - eines zu jedem ATmega und dann einen GPIO am jeweiligen Atmega
>nutzen um VCC des jeweiligen 74HC4050 zu treiben...

Nö, VCC und GND sind fest, es werden nur die Signale geschaltet.

>Gibt es (andere?) empfehlenswerte Lösung für eine "derartige"
>Bus-trennung wenn ich die beiden Teil-Busse bei jeweils 8MHz betreiben
>können möchte?

Deine Problem liegt viel tiefer, dein Konzept ist nicht sonderlich 
brauchbar.

http://www.mikrocontroller.net/articles/Netiquette#Klare_Beschreibung_des_Problems

von Peter D. (peda)


Lesenswert?

Ich sehe das auch so, Dein Konzept scheint sehr unausgegoren.

Die AVRs sind nicht dafür gedacht, riesen Datenmengen zwischen mehreren 
zu transferieren.

Entweder man kann die Aufgaben so aufteilen, daß beide MCs vieles 
getrennt machen können. Oder man nimmt nen größeren MC.

Dir geht sonst ein Haufen CPU-Leistung allein zum Transport verloren. 
Obendrein auch ein Haufen Entwicklungszeit für das Datenprotokoll, damit 
nichts verloren geht oder verfälscht wird.


Peter

von Martin S. (msperl)


Lesenswert?

OK, ein wenig Hintergrund:

Das Problem ist, daß ich das "Konzept" meiner CAN blackbox mit nur einem 
AVR mit mcp und SD Karte gemeinsam umgesetzt habe, daß es dort aber auf 
SD Karten seite zu "Verzögerungen" beim schreiben von bis zu 0.15s kommt 
(was - siehe anderer thread "normal" ist).

In diesem Zeitraum sammeln sich dann aber im schlimmsten Fall 400 CAN 
Nachrichten (bei 500khz CAN Bus geschwindigkeit) an, die dann gepuffert 
werden müssen. Erfahrungsgemäß treten diese SD-karten-latenzen aber 
gehäuft auf - sprich bis zu 3 derartiger langer wartezeiten. Daher muß 
ich für den schlimmsten Fall ca 1200 Messages buffer haben um über so 
eine "schwelle" zu kommen - das sind dann 19kb. Die müssen dann 
verspätet geschrieben werden - sprich zwischenzeitlich sammeln sich 
potentiell noch mehr daten an...

Die Blackbox sollte natürlich außerdem im Falle eines Unfalles keine 
Daten verlieren - und die daten im Ram-Buffer sind natürlich bei strom 
aus weg.

Daher der Ansatz 2 AVR zu verwenden, wovon der eine sich um die Daten 
Aquirierung kümmert und diese in einen FRam buffer schreibt (aus 2x 32KB 
Fram chips, auf die nacheinander geschrieben wird FRAM1 - FRAM2 - 
FRAM1).
Und der zeite AVR liest das jeweils nicht gerade beschriebene FRAM aus 
und schreibt die 32KB mit einem SD_WRITE_MULTIPLE_BLOCKS in einem Rutsch 
auf die SD Karte - dies sollte hoffentlich weniger "latenzen" auf der 
SD-Carte verursachen (vorallem wenn ich 64 512-block am stück schreibe).

Das ganze ließe sich mit einem "größeren" AVR (mit 1xSPI und 2x USART 
und mehr SRAM) vielleicht auch machen, die "Programmierung" ist 
allerdings viel komplizierter, da es viel mehr mögliche Zustände gibt, 
die man berücksichtigen müsste:
* Alles "normal" - sende daten direkt auf die SD Karte
* wir haben frische Daten, aber die SD Karte ist "belegt" -> schreibe in 
FRAM
* wir haben frische daten, aber wir holen die Daten vom FRAM um sie auf 
die SD-Karte zu schreiben
* wir haben daten im buffer und daten ältere Daten auf FRAM...

Da sind die möglichen Zustände bei einer Parallelisierung viel 
einfacher:
Die CAN seite:
* schreibe empfangene Daten auf FRAM1
* schreibe empfangene Daten auf FRAM2
* rollover auf das andere FRAM + Signalisierung des "Partners", daß er 
mit dem sichern des FRAMs beginnen kann...
* möglicher Fehler-Fall: der "Partner" liest noch von der Seite, die wir 
schreiben wollen
Die SD-Karten Seite:
* warte auf Signalisierung, daß eines der FRAM daten zum schreiben hat
* lies 32K von FRAM1 und schreibe auf SD Karte in einem Rutsch.
* lies 32K von FRAM2 und schreibe auf SD Karte in einem Rutsch.

Daher: bei hoffentlich minimalem HW-mehraufwand wird die Software-seite 
einfacher und vorhersagbarer.
In 32KB buffer je FRAM kann ich 2048 CAN-nachrichten in einem FRam 
speichern - das entspricht zirka 0.5s buffer - und die 32K kann ich mit 
meinem SPI code bei 8MHz in ca 0.032s auslesen und an die SD-karte 
schicken. Dannach kann die SD-Karte noch einmal 0.46s "trödeln", bis sie 
die 32KB "wirklich" geschrieben hat bevor es zu einem Buffer-rollover 
auf dem FRAM kommt - aber die Daten sind ja eigentlich schon an die 
SD-karte geschickt, sodaß man vermutlich sogar noch mehr Zeit-puffer hat 
und das FRAM frühzeitig für einen Wechsel freigeben könnte...

Durch diesen Ansatz der Trennung ist auch sicher gestellt, daß ich keine 
Daten bei apruptem "Strom-aus" verliere - die allerletzten Nachrichten 
liegen im FRAM und ich habe alle Daten für eine Analyse, warum meinem 
Uboot der Strom ausgegangen ist (Wassereinbruch,...) - ich muß nur bei 
initialisierung die Daten als erstes aus dem FRAM sichern...

Die Frage ist jetzt: was verwende ich am besten als Multiplexer um den 
Zugriff auf die beiden FRAM zu lösen?
Wie schon gesagt fällt mir primär der 74HC244 ein - weiß aber nicht, ob 
der wirklich als Multiplexer geeignet ist.

von xfr (Gast)


Lesenswert?

Du kannst das Empfangen der Nachrichten und Speichern auf der SD-Karte 
auch mit einem AVR in zwei getrennten Tasks erledigen.

Task 1 empfängt ein Paket vom CAN-Bus und schreibt es in den Puffer.

Task 2 holt sich ein Paket aus dem Puffer und schreibt es auf die 
SD-Karte.

Das ist ein typisches Erzeuger-Verbraucher-Szenerio. Beide Tasks rufst 
Du fortlaufend in der Hauptschleife auf. Sie müssen natürlich so 
geschrieben sein, dass sie nicht blockieren, wenn es nichts zu 
empfangen/lesen gibt bzw. während die SD-Karte beschäftigt ist. Sofern 
die Lese/Schreibdatenrate des FRAMs höher als die doppelte CAN-Datenrate 
ist, sollte das unkompliziert laufen.

von Martin S. (msperl)


Lesenswert?

Randnotiz: auf den 74HC244 bin ich gekommen, weil ich eine Website zur 
AVR-programmierung via Bus-Pirate gestolpert bin 
(http://hintshop.ludvig.co.nz/show/buspirate-avr-programming/), wo 
dieser IC zum "decoupling" der Programmer-Leitungen auf verschiedene 
AVRs verwendet wird...

von Peter D. (peda)


Lesenswert?

Martin Sperl schrieb:
> daß es dort aber auf
> SD Karten seite zu "Verzögerungen" beim schreiben von bis zu 0.15s kommt
> (was - siehe anderer thread "normal" ist).

Die Zeit mußt Du ja nicht dumm rum warten. Es reicht doch völlig, wenn 
Du den FRAM an einen MC zum Puffern hängst.
Du läßt in der Mainloop 2 Tasks laufen:
1. CAN -> FRAM-FIFO
2. FRAM-FIFO -> SD.
Ein zusätzlicher MC ist nicht nötig.

Muß die SD mit einem PC ausgewertet werden?
Ansonsten könnte auch ein Data-Flash reichen, z.B.:
http://de.farnell.com/atmel/at45db321d-su-2-5/speicher-dataflash-32m-8soic-w/dp/1972019

Die haben intern 2 SRAM-Puffer, d.h. einer wird geschrieben, während der 
andere gerade flasht.
Bei Atmel gibt es ne AN, wo der als Audio-Rekorder verwendet wird.

Peter

von Peter D. (peda)


Lesenswert?

Martin Sperl schrieb:
> Durch diesen Ansatz der Trennung ist auch sicher gestellt, daß ich keine
> Daten bei apruptem "Strom-aus" verliere

Sei Dir da nicht so sicher. Die SD-Karte kann Daten verlieren, wenn sie 
beim Schreiben gestört wird.
Du brauchst in jedem Fall eine frühe Unterspannungserkennung und einen 
ausreichend dicken Elko, um den gerade laufenden Schreibzugriff sicher 
zu beenden.


Peter

von Frank K. (fchk)


Lesenswert?

Martin Sperl schrieb:

> Die Blackbox sollte natürlich außerdem im Falle eines Unfalles keine
> Daten verlieren - und die daten im Ram-Buffer sind natürlich bei strom
> aus weg.

Das kann man ändern. Wenn Du konsequent alles in 2.5V/3.3V 
Low-Power-Technik realisiert hast, kannst Du die Versorgungsspannung 
problemlos mit einem großen Kondensator puffern. Wenn Du dann einen 
"Strom weg" Interrupt bekommst, hast Du immer noch genügend Zeit, den 
gesamten Speicher wegzuschreiben und den Prozessor anschließend zu 
stoppen. Normale MMC- und SD-Karten funktionieren bis 2.7V herunter, 
wenn Du Low Voltage Karten nimmst, gehen die bis 1.6V

> Daher der Ansatz 2 AVR zu verwenden

Das ist eigentlich immer eine ziemlich dumme Idee.

fchk

von Falk B. (falk)


Lesenswert?

@  Martin Sperl (msperl)

>AVR mit mcp und SD Karte gemeinsam umgesetzt habe, daß es dort aber auf
>SD Karten seite zu "Verzögerungen" beim schreiben von bis zu 0.15s kommt

Ist halt so.

>(was - siehe anderer thread "normal" ist).

Link?

>In diesem Zeitraum sammeln sich dann aber im schlimmsten Fall 400 CAN
>Nachrichten (bei 500khz CAN Bus geschwindigkeit) an, die dann gepuffert
>werden müssen.

Ja.

> Erfahrungsgemäß treten diese SD-karten-latenzen aber
>gehäuft auf - sprich bis zu 3 derartiger langer wartezeiten. Daher muß
>ich für den schlimmsten Fall ca 1200 Messages buffer haben um über so
>eine "schwelle" zu kommen - das sind dann 19kb. Die müssen dann
>verspätet geschrieben werden - sprich zwischenzeitlich sammeln sich
>potentiell noch mehr daten an...

Dann nimm einen AVR mit ausreichend Speicher, ggf. einen der wenigen 
AVRs mit externem Speicherinterface für SRAM, dann hast du 64 kB.

>Die Blackbox sollte natürlich außerdem im Falle eines Unfalles keine
>Daten verlieren - und die daten im Ram-Buffer sind natürlich bei strom
>aus weg.

Ja und? Die werden soch sowieso nur ein paar hundert Millisekunden 
gepuffert. Wenn der Strom weg ist, ist auch dein AVR aus, was nützen dir 
adann die Daten im FRAM?

>Das ganze ließe sich mit einem "größeren" AVR (mit 1xSPI und 2x USART
>und mehr SRAM) vielleicht auch machen, die "Programmierung" ist
>allerdings viel komplizierter, da es viel mehr mögliche Zustände gibt,
>die man berücksichtigen müsste:

Ja und? Denkst du mit zwei AVRs wird es einfacher?

>* Alles "normal" - sende daten direkt auf die SD Karte
>* wir haben frische Daten, aber die SD Karte ist "belegt" -> schreibe in
>FRAM
>* wir haben frische daten, aber wir holen die Daten vom FRAM um sie auf
>die SD-Karte zu schreiben
>* wir haben daten im buffer und daten ältere Daten auf FRAM...

Falscher Ansatz. Man schreibt IMMER in den FIFO und liest IMMER aus 
dem FIFO, von da an gehts zur SD-Karte. Alles nicht soooo komplex, wenn 
man sauber denkt und programmiert, siehe Statemachine und 
Multitasking.

>Daher: bei hoffentlich minimalem HW-mehraufwand wird die Software-seite
>einfacher und vorhersagbarer.

Irrtum.

>Durch diesen Ansatz der Trennung ist auch sicher gestellt, daß ich keine
>Daten bei apruptem "Strom-aus" verliere

Den kann man durch lokale Puffer verhindern.

http://www.mikrocontroller.net/articles/Speicher#EEPROM_Schreibzugriffe_minimieren

>Die Frage ist jetzt: was verwende ich am besten als Multiplexer um den
>Zugriff auf die beiden FRAM zu lösen?

Denk nochmal über das Konzept nach!

>Wie schon gesagt fällt mir primär der 74HC244 ein - weiß aber nicht, ob
>der wirklich als Multiplexer geeignet ist.

Nö, das ist ein einfacher Puffer. 74HC157 ist dein Freund, du brauchst 
davon aber zwei, ggf. drei.

von Martin S. (msperl)


Lesenswert?

Aber um einen anderen thread über SD-karten zusammenzufassen ( 
Beitrag "AVR+SD-Card: SD-Card legt manches mal 0.13s "pausen" ein" ):

Ich weiß das es via 2 Tasks geht - ich lese vom CAN schon via Interrupt 
aus und im Haupt-programm schreibe ich auf die SD-Karte.

Aber im Schnitt kommen 2 Interrupts (=2 CAN nachrichten) alleine wärend 
der Zeit, wo ich die Daten einen einzigen 512 byte daten-block 
übertrage... Und dann muß ich zumidestens 4ms warten bis die Karte den 
512 byte block geschrieben hat, was weiteren 16 Nachrichten am CAN Bus 
entspricht.

Aber das ist der Idealfall! Es gibt auch Phasen, wo die SD karte 0.13s 
braucht bis sie geschrieben hat. (Und das relativ vorhersagbar alle 32 
512-byte Blöcke = also 16KB) - vermutlich ein Effekt des wear-leveling 
Algoritmus. Umgerechnet sammeln sich in 130ms knapp 520 can-nachrichten 
(und damit bei 16 byte/nachricht 8320byte) an, die verspätet geschrieben 
werden müssen.
Das ginge ja noch mit genügend Speicher ohne FRAM "klimmzüge" - 
allerdings mit dem Risiko des Daten-verlusts bei "strom aus"...

Das 2te Problem ist daß es meist 3 benachbarte Blöcke gibt die ein 
derartiges Verhalten zeigen (meiner Erfahrung nach Block 29,30 und 31)- 
sprich da sammeln sich noch mehr Nachrichten an - meiner Schätzung nach 
knapp 24k.
Aber wenn ich dann diese 24K als jeweils einzelne Blöcke schreiben 
möchte, so ist das "backlog" schon größer 16k und ich komme aus dem 
Teufelskreis nicht herraus.

Allerdings kann man bei SD-Karten auch mehrere Blocks gleichzeitig 
schreiben - je mehr und je größer desto besser (vorallem wenn an 
"flash-grenzen" aligned schreibt), daher sollten sich 32kb am Stück viel 
schneller schreiben lassen, als 64 mal 512 bytes, wo man je block warten 
muß...

Für die SD-Karte wird das ganze auch viel effizienter, denn sie kann 
intern vielleicht sogar ganze Pages schreiben, was um einiges schneller 
gehen sollte, als wenn man für 512 bytes eine ganze Flash page (4k, 
8K,16k..) schreiben muß.

Und das führt zu mehr "Müll", der dann entsorgt werden muß, indem die 32 
Pages gelesen werden und als eine neu geschrieben werden. Wenn ich 
gleich in 16 oder 32K blöcken schreibe, so fällt das nicht ins Gewicht - 
und nur so erreichen die SD-Karten die angegebenen Geschwindigkeit - 
nicht beim schreiben einzelner Blocks!

Der Vorschlag in dem anderen Thread war auf NAND speicher ohne 
wear-leveling zurückzugreifen, aber
a) sind die nur ein paar MB groß
b) sind die Kosten vergleichsweise viel höher als bei SD-Karten
c) ist nicht so leicht am PC auszulesen

Daher mein Ansatz der "hybrid-lösung" mit FRAM als permanenter Buffer 
(sollten bis zu 80 Jahre die Daten halten könne) um dann die Daten in 
gößeren Stücken schreiben zu können...

Ich habe daher auch schon an einen AVR mit 1xSPI und 2x USART gedacht, 
allerdings ergibt sich so das Problem, daß ich im IRQ für den 
CAN-Nachrichten-Empfang dann grundsätzlich 3 Varianten vorsehen muß:
* SPI zum FRAM ist blockiert (weil der haupt-thread gerade davon liest) 
-> schreibe daten in buffer
* SPI zum FRAM ist frei, keine Daten im buffer  -> schreibe direkt ins 
FRAM
* SPI zum FRAM ist frei, Daten im Buffer -> schreibe zuerst die 
gebufferten Daten ins FRAM und dann die neuen Daten.
Machbar...

Man muß dann aber gegebenenfalls die Datenmenge von ca. 37 
CAN-nachrichten, die in 9.2ms aufläuft buffern (9.2ms=16KB*9bit(=8bit 
daten plus 1 bit verschenkter cycle)/16MHz ist die Zeit die ich brauche 
um 16K am Stück vom FRAM auszulesen und an die SD-Karte zu schicken).
Diese 37 (=9.2ms/(0.25ms/CANNachricht)) Nachrichten gehen dann im "Strom 
aus" Fall allerdings verloren - nicht was ich mir erhoffe...

OK, der schreibende Haupt-prozess könnte alle 64 byte oder so nachsehen, 
ob es neue daten gibt die der IRQ handler eingelesen hat und dann das 
Lesen unterbrechen und ins FRAM schreiben - da gehen dann allerding 
einige Cycles verloren nur um diesen Teil der State-machine abzuarbeiten 
(SPI lesen abbrechen (CS High), CS low, Daten Buffer addresse errechnen 
und daten beginnen einzulesen (ist es wirklich nur eine Nachricht), SPI 
WRITECMD+Adresse+16 byte schreiben,CS high, CS low,SPI READCMD+Adresse 
zum weiter lesen, weitere 64 byte lesen) Damit wird der gesamte transfer 
ineffizienter (ich schätze, daß ich in der Zeit in der ich das obige 
umsetze fast 32 byte vom FRam lesen könnte - sagen wir zumindestens 24 
bytes)

Und daher macht IMO eine Separierung der "Aufgaben" auf meherere 
Prozessoren die Programmierung wie schon gesagt einfacher und 
effizienter, da es keine so komplexe state-machine erfordert wie wenn 
ich alle Möglichkeiten in einer State-machine abhandeln müßte (unter 
Berücksichtigung der zeitlichen Limitierungen - wie zum Teil oben 
beschrieben)...

(Ganz zu Schweigen von der Wahrscheinlichkeit von Programmfehlern, 
vergessenen Nebenläufigkeiten, übersehenen seltenen States in der 
state-machine,... und dem damit geparten Zeitaufwand verglichen mit dem 
"einfacheren" code durch Separierung auf zwei AVRs...)

Zusätzlich ließe sich dann das ganze "Werkel" dann bei nur mehr 8-12MHz 
mit 3.3V betreiben und ich brauche keine 5V mehr um die AVRs bei 
16-20MHz zu betreiben (und einen Pegel-Wandler auf 3.3V für die 
SD-Karte) um das ganze zu "stemmen"... (OK, der CAN-bus-treiber braucht 
noch 5V)

Und es ist kostengünstiger 2 Mega168 zu verwenden als einen von den 
größeren SMD-only AVRs mit 16+KB Speicher, die dann obendrein nicht mehr 
so einfach am Breadboard zu montieren sind um das ganze zu entwickeln...
(Und strom-sparender ist es vermutlich obendrein noch, denn da lässt 
sich sehr einfach "extended-standby sleep" einbauen wenn man eine 
externe clock verwendet)

Es steckt daher schon einiges zeitkonsumierende Erfahrung und Gedanken 
hinter dem jetzigen parallelen-Design mit Fram als Buffer - vorallem 
wenn man alle Randbedingungen berücksichtigt...

Ich werde mir jetzt einmal den 74HC157 ansehen - vielleicht löst der das 
Problem...

Mich wundert allerdings, wie der "decouple"-Vorschlag von dem Bus-pirate 
link (http://hintshop.ludvig.co.nz/show/buspirate-avr-programming/) dann 
mit dem dort verwendeten 74HC244 dann funktioniert, aber vielleicht 
verstehe ich da etwas falsch...

von xfr (Gast)


Lesenswert?

Dein Problem ist also kurz gesagt, dass der Task zum Schreiben auf die 
SD-Karte blockweise arbeiten soll und das lange dauert. Dabei blockiert 
er das FRAM und es können in der Zeit keine neuen CAN-Nachrichten 
gespeichert werden. Deshalb willst Du die neuen CAN-Nachrichten nochmal 
im SRAM puffern, bis der FRAM wieder freigegeben wird.

Warum machst Du es nicht umgekehrt: Der Task zum Schreiben auf die 
SD-Karte holt sich pro Aufruf nur einen Datensatz aus dem FRAM und 
speichert ihn in einem lokalen SRAM-Puffer. Wenn er genug Datensätze in 
seinem Puffer hat, dass er sie blockweise auf die SD-Karte schreiben 
kann, macht er das. Der Task, der Daten vom CAN-Bus abholt, schreibt sie 
dagegen sofort ins FRAM. Das kann er, weil der andere Task das FRAM nie 
länger als zum Lesen von einem Datensatz blockiert.

von Peter D. (peda)


Lesenswert?

Du denkst viel zu kompliziert.
Es ist vollkommen wurscht, wie lange die SD-Karte Gedenkpausen braucht.
Solange der FRAM alle derweil auflaufenden Nachrichten puffern kann, ist 
alles in Butter.
Und die werden dann im nächsten Rutsch geschrieben. Und wenn dann nur 
eine Nachricht aufgelaufen ist, wird eben nur eine geschrieben.

Die SD-Routine sollte auch nur kleine Häppchen (z.B. 16Byte) aus dem 
FRAM lesen, damit der CAN-Interrupt wieder was reinschreiben kann.
Wenn CAN->FRAM ein Interrupt ist, muß ja im Main der FRAM atomar gelesen 
werden.

Dem CAN+FRAM würde ich die UART als SPI geben, dann hat die SD den 
anderen SPI für sich allein.

Ansonsten wirds kompliziert, wenn sich Main und Interrupt um die selbe 
SPI prügeln.


Peter

von xfr (Gast)


Lesenswert?

Und ganz allgemein: Vergiss irgendwelche komplizierten Statemachines. 
Die Daten wandern über genau einen Pfad vom CAN-Interface über die 
Pufferspeicher bis hin zur SD-Karte, ohne irgendwelche Abkürzungen und 
Sonderfälle. Dazu braucht man keine zwei Mikrocontroller. Der 
Programmcode wird mit zwei Mikrocontrollern niemals einfacher als mit 
einem, und schon gar nicht weniger fehleranfällig.

von Martin S. (msperl)


Lesenswert?

Jein  - der "receiver" teil ist im interrupt, der dann die "Erfahrung" 
machen kann, daß CS zum FRam schon low ist - dann kann er den transfer 
nicht sinvoll beenden...

Zum transferieren vom FRAM auf die SD karte brauche ich nur Register - 
das ganze geht interleaved sehr gut ohne nur einen SPI-cycle zu 
verschwenden (sprich 50% SCK duty-cycle) - wenn ich zuerst lese und dann 
schreibe, so verschwende ich mehr Zeit.

Ich könnte alle 32 oder 64 bytes im transfer einen CLI/SEI block 
einführen - der Interrupt kann nur dann triggern. Wengleich ich mir 
nicht sicher bin, ob dann eine "edge" während der zeit mit Interrupt 
disabled dann in diesem CLI/SEI überhaupt triggern würde...

Dann müßte ich - wie schon vorher angedeutet - den Interrupt-pin 
abfragen und außerhalb des IRQs handlen, nachdem ich den Bus freigegeben 
habe.
Mit dem "Hold" pin und alternativer Nutzung der 2 FRams läßt sich das 
vielleicht bewerkstellingen, daß ich mir zumindestens den address setup 
ersparen kann, was es etwas effizienter gestalten würde.

Wie schon gesagt: es geht viel - irgendwo wird es etwas komplizierter 
(entweder auf HW oder auf SW seite)...

Die Frage ist, ob es nicht aufwändiger ist einen anderen als zwei meiner 
"Haus und Hof" AVRMega168 zu verwenden und dann den code in 
funktionalität zu trennen (ist ja im Grunde genommen ja schon da)...

Auf der einen Seite erfordert es nur den IRQ Handler anzupassen, daß er 
statt in den Buffer gleich ins FRAM zu schreibt - brauche ich so oder 
so. und dann sieht die "hauptschleife" wie folgt aus:
1
while (1) { sleep(); }

Und auf der anderen Seite brauche ich nur einen IRQ handler der mich 
nach einen pin state change (z.b: pins FRAM1 und FRAM2 CS from 
"can-receiver" - vieleicht noch ein Pin: "daten zu schreiben" ) aufweckt 
und dann lese ich je nach Pin levels von FRAM1 oder von FRAM2 und ich 
schreibe auf die SD-Card ohne auf irgendetwas Rücksicht nehmen zu 
müssen.

Sieht dann so aus:
1
while (1) {
2
  /* check if there is data to be written SIGNAL */
3
  if (ISSET(WRITE_BUFFER_PIN)) {
4
    /* check which CS line from the Peer is low - select the other FRAM to write */
5
    if (ISSET(FRAM1_CS)) {
6
       writeFRAM1ToSD(); 
7
       notifyMasterOnWritten();
8
    } else if (ISSET(FRAM2_CS)) {
9
      writeFRAM2ToSD(); 
10
      notifyMasterOnWritten();
11
    }
12
  } else {
13
    /* nothing happened */
14
    /* reset watchdog  - there must be a timer interrupt as well to trigger a reset of the watchdog */
15
    wdr_reset();
16
    /* sleep until we get woken again by an interrupt*/
17
    sleep();
18
  }
19
}
(OK, da gehört noch etwas CLI/SEI an die richtigen Stellen)
Dann ist das ganze "einfache lineare" Programmierung, die fast nur 
"sleep" macht wenn nichts los ist...

Alles auf einem AVR erfordert mehrere Sonderfälle, wo dann ein unroll 
und optimieren auf Durchsatz nicht mehr so einfach möglich ist (wie oben 
beschrieben muß ich dann Pausen machen um zu sehen, ob es neue Daten 
gibt und um den bus freizugeben - da bräuchte ich dann eine AVR mit 4 
SPI bussen - einer für CAN, einer für SD, einer für jedes FRAM...
Dann könnte man das "einfach" machen - es soll einfach und verlässlich 
sein
Und die beiden Codes oben sehen für mich "verlässlich" aus - wenn das HW 
setup auch verlässlich ist... (und ich hoffe halt, daß das Multiplexen 
"funktioniert"...)

von Frank K. (fchk)


Lesenswert?

Martin Sperl schrieb:
> Der Vorschlag in dem anderen Thread war auf NAND speicher ohne
> wear-leveling zurückzugreifen, aber
> a) sind die nur ein paar MB groß

Falsch.

http://de.farnell.com/hynix-semiconductor/h27uag8t2btr-bc/speicher-flash-nand-16gb-48tsop/dp/2147273

> b) sind die Kosten vergleichsweise viel höher als bei SD-Karten
> c) ist nicht so leicht am PC auszulesen

Mach doch ein USB-Interface dran. Achso ... dafür brauchst Du wieder 
einen extra Chip. Dann nim doch gleich einen der Aufgabe angemessenen 
Controller. Der hat dann auch CAN gleich eingebaut.

> Und daher macht IMO eine Separierung der "Aufgaben" auf meherere
> Prozessoren die Programmierung wie schon gesagt einfacher und
> effizienter, da es keine so komplexe state-machine erfordert wie wenn
> ich alle Möglichkeiten in einer State-machine abhandeln müßte (unter
> Berücksichtigung der zeitlichen Limitierungen - wie zum Teil oben
> beschrieben)...

Du hast einen Knoten im Kopf und einen offenbar ungeeigneten Controller 
in den Fingern. Normalerweise löst man so etwas mit einem Ringpuffer. 
Ein solcher hat einen Schreibpointer, für den CAN-IRQ und einen 
Lesepointer für den SD-Task. Google mal nach diesem Konzept. Und wie 
gesagt: Ein paar Sekunden kannst Du immer mir einem dicken Elko 
überbrücken.

> Zusätzlich ließe sich dann das ganze "Werkel" dann bei nur mehr 8-12MHz
> mit 3.3V betreiben und ich brauche keine 5V mehr um die AVRs bei
> 16-20MHz zu betreiben (und einen Pegel-Wandler auf 3.3V für die
> SD-Karte) um das ganze zu "stemmen"... (OK, der CAN-bus-treiber braucht
> noch 5V)

Ja, selber schuld, sage ich da nur. Es gibt auch Controller, die mit 40 
MHz laufen und auch nur 3.3V brauchen. Und 32k RAM eingebaut haben. 
Sogar welche im DIL28. Und obendrein noch weniger Strom ziehen, da 
neuere Halbleitertechnologie. Und 3.50€ bei Reíchelt kosten. Du musst 
nur mal Deinen Schädel für was anderes als AVR öffnen.

Schau hier:

http://www.reichelt.de/PIC-32-Controller/32MX150F128B-ISP/3//index.html?ACTION=3&GROUPID=4509&ARTICLE=121326&SHOW=1&START=0&OFFSET=500&;

> Und es ist kostengünstiger 2 Mega168 zu verwenden als einen von den
> größeren SMD-only AVRs mit 16+KB Speicher, die dann obendrein nicht mehr
> so einfach am Breadboard zu montieren sind um das ganze zu entwickeln...
> (Und strom-sparender ist es vermutlich obendrein noch, denn da lässt
> sich sehr einfach "extended-standby sleep" einbauen wenn man eine
> externe clock verwendet)

Kostengünstiger als 3.50€ sicher nicht...

> Es steckt daher schon einiges zeitkonsumierende Erfahrung und Gedanken
> hinter dem jetzigen parallelen-Design mit Fram als Buffer - vorallem
> wenn man alle Randbedingungen berücksichtigt...

Ja, um Erfahrungen zu sammeln, braucht man Zeit.

fchk

PS: Der genannte PIC hat kein CAN, wie ich gesehen habe. Dann nimm halt 
einen dsPIC33EP256GP502, der läuft mit 70 MHz und hat LIN und CAN und 
256k Flash und 32k RAM und sollte für Dich geeignet sein. Gibts leider 
nicht bei Reíchelt.

von Falk B. (falk)


Lesenswert?

@  Martin Sperl (msperl)

>Jein  - der "receiver" teil ist im interrupt, der dann die "Erfahrung"
>machen kann, daß CS zum FRam schon low ist - dann kann er den transfer
>nicht sinvoll beenden...

Hier liegt einer deiner Fehler.

>Zum transferieren vom FRAM auf die SD karte brauche ich nur Register -

?? Programmierst du in ASM? OMG!

>das ganze geht interleaved sehr gut ohne nur einen SPI-cycle zu
>verschwenden (sprich 50% SCK duty-cycle) - wenn ich zuerst lese und dann
>schreibe, so verschwende ich mehr Zeit.

Geh mal davon aus, dass es hier viele Leute wissen, was sie erzählen.
Du eher weniger.

>Ich könnte alle 32 oder 64 bytes im transfer einen CLI/SEI block
>einführen - der Interrupt kann nur dann triggern. Wengleich ich mir
>nicht sicher bin, ob dann eine "edge" während der zeit mit Interrupt
>disabled dann in diesem CLI/SEI überhaupt triggern würde...

Du bist viel zu sehr in Details vertieft und hast überhaupt keinen 
gescheiten Überblick. Weder über das Problem, noch über die üblihen 
Lösungsansätze.

>Wie schon gesagt: es geht viel - irgendwo wird es etwas komplizierter
>(entweder auf HW oder auf SW seite)...

Bla Bla.

>Alles auf einem AVR erfordert mehrere Sonderfälle, wo dann ein unroll
>und optimieren auf Durchsatz nicht mehr so einfach möglich ist (wie oben

Du hast einen Tunnelblick.

von Martin S. (msperl)


Lesenswert?

OK - nach einer runde Radfahren muß ich sagen, daß es vermutlich mit 
einem Mega164P gehen könnte. Allerdings würde es ein paar "Verrenkungen" 
im Code erfordern und ein paar weitere Leitungen um hold auf dem FRAM zu 
halten.

Ich werde es doch einmal mit nur einem Mega probieren, für den Fall, das 
es nicht passt, so werde ich es mit 4 74HC157 und 2 Mega168 versuchen...

@fcks: Farnell - geht als Privatmann leider unerfindlichen Gründen 
nicht!
Pic: Ich habe jetzt erst vor kurzem mit AVR begonnen und möchte momentan 
einmal dabei bleiben...

von Frank K. (fchk)


Lesenswert?

Martin Sperl schrieb:

> Pic: Ich habe jetzt erst vor kurzem mit AVR begonnen

Das merkt man.

> und möchte momentan
> einmal dabei bleiben...

Auch wenn Du gegen die Wand fährst? Denk nochmal darüber nach.

fchk

von Frank K. (fchk)


Lesenswert?

Martin Sperl schrieb:
> @fcks: Farnell - geht als Privatmann leider unerfindlichen Gründen
> nicht!

Geht zu hbe-shop.de - das ist die Privatkundenversion mit identischem 
Sortiment.

fchk

von holger (Gast)


Lesenswert?

>> und möchte momentan
>> einmal dabei bleiben...
>
>Auch wenn Du gegen die Wand fährst? Denk nochmal darüber nach.

Billiges STM32F4 Discovery und dann auf USB Stick speichern.
192kB RAM Onboard. DMA für alles mögliche;)
Für CAN braucht man nur noch einen Transceiver.

20 Euro Lösung.

von Ralph (Gast)


Lesenswert?

Die AVR's mögen ja für eine Sachen gut geeignet sein.
Naja ich mag die Dinger nicht, aber das ist meine persönliche Meinung

Nur für das was du machen willst sind die AVR's ungeeignet.
Falsche Schnittstellen, zu klein, zu langsam.

Einzig sinnvolle für das was du da vorhast.
Such dir einen Cortex Mx der direkt einen CanController, eine SPI mit 
DMA und dazu großen Ram hat.

Dann kannst du dir den ganzen Hickhack mit 2 µC zu synchronisieren 
ersparen.

zb die vorgeschlagenen STM  oder die Lm3sxxx von Ti
Bei beiden bekommst du die µC mit IDE für einiges billiger als das ganze 
für den AVR kostet.


Und ja man kann einen Wohnungsumzug mit einem Kombi machen, aber jeder 
der kann wird sich da mindestens einen Lieferwagen besorgen.
und warum ? weil es Sinn macht.

==> Ja sowas geht mit AVR, aber es macht kein Sinn !!

Falls du bei deiner Konstruktion bleiben willst, dann such mal nach dem 
Stichwort "DualPort Ram" damit kommst du näher an dein Ziel.

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
Noch kein Account? Hier anmelden.