Guten Abend,
ich spiele mit einem STM32F334. Mir ist aufgefallen das dieser µC einen
CCMRAM hat. Leider verstehe ich nicht was ich Sinnhaftes damit machen
kann.
Kann mir bitte jemand kurz erklären welchen Zweck dieses Ram erfühlt?
Danke für Eure Hilfe
Walter T. schrieb:> BinnenFreund schrieb:>> Kann mir bitte jemand kurz erklären welchen Zweck dieses Ram erfühlt?>> Es ist schneller als das andere SRAM angebunden.
Danke
Matthias S. schrieb:> Du kannst im CCRAM alles speichern, was nicht von DMA bedient> werden> muss.
Und wie kann ich dem CCMRam variablen zuweisen?
Danke für die Hilfe
BinnenFreund schrieb:> Und wie kann ich dem CCMRam variablen zuweisen?
Du musst dein Linkerskript leicht anpassen. Ich habe für die F3 Serie
keines da, aber ich hänge dir mal eines für den F429ZI an, um zu zeigen
wies gemacht wird.
Im Code kannst dann sowas schreiben:
Matthias S. schrieb:> BinnenFreund schrieb:>> Und wie kann ich dem CCMRam variablen zuweisen?>> Du musst dein Linkerskript leicht anpassen. Ich habe für die F3 Serie> keines da, aber ich hänge dir mal eines für den F429ZI an, um zu zeigen> wies gemacht wird.> Im Code kannst dann sowas schreiben:char CCRAM buf[32];> uint32_t CCRAM maxA, maxB ;
Vielen Dank!
Wo finde ich das Linkerskript das ich anpassen muss?
Ich verwende das Atolic True Studio.
Sorry aber ich kenne mich nicht so gut aus!
BinnenFreund schrieb:> Wo finde ich das Linkerskript das ich anpassen muss?
Im Datei-Verzeichnisbaum des Project Explorers. Was bitte hast
du bis jetzt gemacht dass du eine solche Frage stellen musst?
Das derzeitig benutzte Linkerskript findest du in den Einstellungen zum
Projekt unter Tools->Linker-> Settings (oder so ähnlich). Kopiere dieses
Skript und ergänze es mit den Erweiterungen zum CCMRAM. Wähle dann diese
Kopie als neues Setting für den Linker.
Matthias S. schrieb:> Das derzeitig benutzte Linkerskript findest du in den> Einstellungen zum> Projekt unter Tools->Linker-> Settings (oder so ähnlich). Kopiere dieses> Skript und ergänze es mit den Erweiterungen zum CCMRAM. Wähle dann diese> Kopie als neues Setting für den Linker.
oh danke für deine Hilfe! Werde es morgen ausprobieren!!!
im CCM sollte der Stack sein ...
Das reduziert die zeit für den contextwechsel bei interrupts
oder bei verwendung eines RTOS
der stack aller Tasks sollte dann im CCM liegen
wenn auch ITCM RAM vorhanden ist ist es gut alle ISRs da reinzulegen
gfdgd schrieb:> im CCM sollte der Stack sein ...
Hey, gute Idee! Da bin ich noch gar nicht drauf gekommen :-P Logisch,
das das was bringt. Und DMA braucht man da auch nicht...
gfdgd schrieb:> im CCM sollte der Stack sein ...> Das reduziert die zeit für den contextwechsel bei interrupts> oder bei verwendung eines RTOS> der stack aller Tasks sollte dann im CCM liegen
Nein. Das ist falsch. Du kannst das machen, aber es bringt dir nix.
Das interne SRAM und das CCMRAM lassen sich beide ohne wait states
ansteuern.
Du hast nur einen Vorteil wenn du Code im CCMRAM ausführst. Dadurch hast
du zero-waitstate fetches und der Code läuft etwas schneller. Sinnvoll
kann das z.b. bei ISR Routinen sein.
Erwarte aber keine Wunder. Das ist ein nettes Feature bringt etwas
Performance
meckerziege schrieb:> Erwarte aber keine Wunder. Das ist ein nettes Feature bringt etwas> Performance
Es ist schon etwas mehr als nett.
Wie der Name schon sagt, hat der Prozessor direkten Zugriff auf das RAM.
Damit entfallen ggf. Wartezeiten über die Busmatrix und Zugriffe können
parallel ausgeführt werden. Das trifft für den F334 zu.
Bei neueren Controllern mit AXI können auch Wartezyklen auf AXI-SRAM
eingefügt sein. Mit CCM als Standard für den Stack und allgemeine
Variablen liegt man sicher auf der schnelleren Seite.
richtig ..
keine wunder...
aber bei mir reicht ein M7 für MJPEG streaming inkl SW decoding für
25fps
ohne diese features liegt die bildrate bei knappen 10fps
so gesehen ... jedes bisschen hilft irgendwo
warum also nicht mitnehmen
hatte das auch mal gemessen.
stack im SRAM und vergleich dazu im CCM
der CCM war nicht viel aber immer schneller
... vor allem ist es einfach praktisch, wenn der Stack aus dem Weg ist.
CCMRAM ist zwar meist nicht viel da, aber ehe der brachliegt, ist der
Stack da gut aufgehoben.
Hier noch mal ein ausführliches Topic zum CCMRAM:
https://www.openstm32.org/Using%2BCCM%2BMemory
Matthias S. schrieb:> Nee, da fehlt noch das Macro zum Umschnurzeln von> __attribute__((section("ccmram")))> in den vereinfachten Ausruck, den ich benutze. Moment ich suche das> mal...> Ahh, habs gefunden - das steht bei mir in der main.h:#ifndef CCRAM> #define CCRAM __attribute__((section(".ccmram")))> #endif> Sorry für das Versäumnis.
Super Danke!
Kompilieren geht!
Also variablen die ich mit dem DMA nicht verwende kann ich nun in das
CCMRam legen? Oder muss ich noch andere Sachen beachten?
BinnenFreund schrieb:> Oder muss ich noch andere Sachen beachten?
Eigentlich nicht. Beachte die Hinweise bei den opemstm32 Jungs, dann
kannst du auch den Stack da rein legen. Der CCMRAM liegt eben nicht auf
dem internen Bussystem, deswegen kann die Peripherie nicht direkt da
reinschreiben oder -lesen (also auch der ADC). Aber sonst gibts wenig
Beschränkung.
BinnenFreund schrieb:> Also variablen die ich mit dem DMA nicht verwende kann ich nun in das> CCMRam legen? Oder muss ich noch andere Sachen beachten?
Zur Sicherheit ins Datenblatt schauen, da gibt es eine Matrix mit der
Busübersicht.
> Kann mir bitte jemand kurz erklären welchen Zweck dieses Ram erfühlt?
Beim CCM geht es hauptsächlich um deterministische Laufzeiten - eine
bestimmte Codesequenz braucht immer exakt die gleiche Anzahl Taktzyklen.
Was bei den 8-Bittern oft selbstverständlich ist, ist bei komplexeren
und schnelleren 32-Bittern oft schwierig zu erreichen.
Insbesondere Zugriffe aufs Flash benötigen bei höheren Taktfrequenzen
Waitstates und werden typischerweise durch einen kleinen Cache
beschleunigt. Dies führt zu einem nicht-deterministischen
Laufzeitverhalten - je nach Cache-Inhalt oder Lage des Codes im Flash
ändert sich dessen Laufzeit (wenn's blöd läuft Faktor 2!).
Das kann man umgehen, indem man kritische Codefragmente ins RAM kopiert
und von dort ausführt. Das führt allerdings zum nächsten Problem:
konkurierende Einheiten, die ebenfalls aufs RAM zugreifen wollen (z.B.
DMA oder andere Cores), können die CPU ausbremsen und man hat wieder
keine garantierte Laufzeit. Die Lösung: dediziertes RAM für jeden Core.
Das kann wie z.B. beim RP2040 mehrere, parallel ansprechbare
Speicherbänke an der Busmatrix sein oder einfacher, ein direkt an den
Core angebunder RAM-Block, das Core-Coupled-Memory.
Wenn man dann noch sicherstellt, dass die Datenzugriffe (inkl Stack!)
ebenfalls nur auf dem lokalen Speicher stattfinden, hat man endlich sein
Ziel erreicht (z.B. jitterfreies Bit-banging oder Interruptbehandlung).
foobar schrieb:> Beim CCM geht es hauptsächlich um deterministische Laufzeiten> .......
Das war ja mal eine schöne und erleuchtende Erklärung, Danke dafür.
Jetz wäre meine Frage was denn die Designer von STM dazu
bewegt hat ein CCM vorzusehen.
Anders herum gefragt: welche ernsthafte moderne Anwendung
für 32-Bit Controller hatten die STM-Designer im Auge
um CCM zu implementieren. Oder ist das ein Feature das
schon von ARM im Core vorgesehen ist, aber wofür?
Also für's timing-getreue synchrone Bitbanging wird man
es wohl nicht gedacht haben ....
Matthias S. schrieb:> Eigentlich nicht. Beachte die Hinweise bei den opemstm32 Jungs, dann> kannst du auch den Stack da rein legen. Der CCMRAM liegt eben nicht auf> dem internen Bussystem, deswegen kann die Peripherie nicht direkt da> reinschreiben oder -lesen (also auch der ADC). Aber sonst gibts wenig> Beschränkung.
Hmm ist das Stack auslagern eine Sichere Sache? Hatte mal vor langer
Zeit auf einem ATTiny26 das Problem das ich mir den Stack während der
Laufzeit überschrieben habe....Das war nicht Lustig.
Wie lagert man den Stack aus?
Johannes S. schrieb:> Zur Sicherheit ins Datenblatt schauen, da gibt es eine Matrix mit der> Busübersicht.
Ok hast du ein Beispiel damit ich weiß nach was ich suchen soll.
Danke
foobar schrieb:> Wenn man dann noch sicherstellt, dass die Datenzugriffe (inkl Stack!)> ebenfalls nur auf dem lokalen Speicher stattfinden, hat man endlich sein> Ziel erreicht (z.B. jitterfreies Bit-banging oder Interruptbehandlung).
Das klingt ja sehr gut Danke für deine Erklärung.
> Oder ist das ein Feature das schon von ARM im Core vorgesehen ist,> aber wofür?
Das ist ein Design-Feature der Cortex-M-Familie, eine extra für
Steuerungsaufgaben optimierte Version ihrer CPUs und da möchte man schon
definierte, jitterfreie Laufzeiten haben (sonst fängt der Motor an zu
brummen, der DC/DC-Wandler erzeugt Rauschen, der externe ADC verpasst
Samples, das Bild wackelt, etc). Klar, man versucht so weit wie möglich
die dedizierten HW-Blöcke zu verwenden, aber häufig genug passen die
nicht (insb Interfaces zu Custom-HW, FPGAs etc). Einige Hersteller
gehen so weit, selbst die GPIO-Ports direkt an die Cores zu hängen (die
hängen normalerweise asynchron an der Bus-Matrix) um Jitter weiter zu
minimieren.
foobar schrieb:> (die hängen normalerweise asynchron an der Bus-Matrix)
... war mir klar.
foobar schrieb:> Einige Hersteller> gehen so weit, selbst die GPIO-Ports direkt an die Cores zu hängen (die> hängen normalerweise asynchron an der Bus-Matrix) um Jitter weiter zu> minimieren.
Das hätte ich jetzt nicht erwartet ... kannst du mir Beispiele von
Controllern nennen bei denen die Direktkopplung vom Core zum GPIO
realisiert ist? Ich dachte immer das macht kein Schwein ...
Ergänzung: wenn ich von deterministischen Laufzeiten spreche geht es
nicht nur im einen Takt plus/minus. Wenn mein Sinus/FFT/Filter nicht
1000 Taktzyklen sondern durch einen DMA plötzlich 1200 Zyklen braucht,
kann mir das u.U. den gesamten Programmablauf durcheinander werfen.
BinnenFreund schrieb:> Kompilieren geht!> Also variablen die ich mit dem DMA nicht verwende kann ich nun in das> CCMRam legen? Oder muss ich noch andere Sachen beachten?
Es könnte sein dass - ja nach IDE oder sonstigem Environment -
der Startup-Code nicht die Initialisierung von Variablen
die im CCM angelegt sind, mit erledigt. Vielleicht muss man
da seine eigene Kreation einbringen, oder im eigentlichen
C-Code nach dem Startup sicherstellen dass diese Variablen
initialisiert werden.
foobar schrieb:> (sonst fängt der Motor an zu> brummen, der DC/DC-Wandler erzeugt Rauschen, der externe ADC verpasst> Samples, das Bild wackelt, etc).
Hauptsächlich ging es wohl darum, bei Audioanwendungen einen räumlichen
Klang zu erzielen.
mitlesa schrieb:> Es könnte sein dass - ja nach IDE oder sonstigem Environment -> der Startup-Code nicht die Initialisierung von Variablen> die im CCM angelegt sind, mit erledigt.
Das ist ja eine üble Falle.
Kinders, heute ist Sonntag und nicht Freitag. Bleibt mal auf dem Teppich
statt hier rumzuspinnen.
Wenn Euch schnelle Controller überfordern, bleibt bei den AVRs!
m.n. schrieb:> Kinders, heute ist Sonntag und nicht Freitag. Bleibt mal auf dem Teppich> statt hier rumzuspinnen.> Wenn Euch schnelle Controller überfordern, bleibt bei den AVRs!
Ich versuche was zu lernen ;-)
> kannst du mir Beispiele von Controllern nennen bei denen die> Direktkopplung vom Core zum GPIO realisiert ist? Ich dachte> immer das macht kein Schwein ...
Bei den Cortex-M0 verbreitet, nennt sich Cortex-M0+ single-cycle IOBUS.
Beispielsweise SAMD11, LPC83, RP2040, ...
BinnenFreund schrieb:> Hmm ist das Stack auslagern eine Sichere Sache? Hatte mal vor langer> Zeit auf einem ATTiny26 das Problem das ich mir den Stack während der> Laufzeit überschrieben habe....Das war nicht Lustig.
Hahaha, das ist ein STM32, kein Tiny26. Wer sich das Linkerskript mal
anguckt, sieht schnell, das 64kByte mehr als genug für Stack und
reichlich Variable sind:
1
/* Highest address of the user mode stack */
2
_estack = 0x10010000; /* end of CCM RAM */
3
4
/* Generate a link error if heap and stack don't fit into RAM */
5
_Min_Heap_Size = 0x400; /* required amount of heap */
6
_Min_Stack_Size = 0x800; /* required amount of stack */
7
8
/* User_heap_stack section, used to check that there is enough RAM left */
9
._user_heap_stack :
10
{
11
. = ALIGN(4);
12
PROVIDE ( end = . );
13
PROVIDE ( _end = . );
14
. = . + _Min_Heap_Size;
15
. = . + _Min_Stack_Size;
16
. = ALIGN(4);
17
} >CCMRAM
Ich habe gestern mal eins meiner komplexeren Programme so kompiliert.
Keine Probleme soweit.
mitlesa schrieb:> m.n. schrieb:>> Kinders, heute ist Sonntag und nicht Freitag.>> Wie soll man denn das verstehen?
Daß hier herumgesponnen wird, um dem CCM "alternative Wahrheiten"
anzudichten.
Wenn bei einer Anwendung der Motor brummt oder rauscht, dann liegt das
nicht am RAM-Zugriff sondern u.U. an der falschen Timerprogrammierung.
Welche RAM-Bereiche initialisiert werden oder nicht, liegt am
startup-Code. Die Initialisierung ist alleinige Sache des Programmieres
und hat absolut garnichts mit CCM zu tun.
Mw E. schrieb:> mitlesa schrieb:>> Wie soll man denn das verstehen?>> Er ist einfach nur ein Troll, einfach ignorieren.
Warum soll "mitlesa" ein Troll sein?
Hier ist die Matrix der Busübersicht "Figure 1".
Der CCM RAM kann nur vom Prozessor aus angesteuert werden, nicht vom
DMA.
Damit kann der DMA zeitgleich auf den SRAM die Daten kopieren und der
Prozessor im CCM RAM zugreifen.
Zudem ist der CCM RAM auch vor falsches Überschreiben aus der DMA
geschützt, da der da einfach nicht hin kommt.
Schlussendlich macht es Sinn alle Variablen und den Stack in den CCM RAM
zu legen, vor allem wenn man den DMA nutzt. Damit hat man auch mehr
Platz für den DMA Speicher.
Man kann das Linkerscript auch so aufbauen, dass per Default alle
Variablen im CCM RAM landen und nicht im SRAM.