Forum: Mikrocontroller und Digitale Elektronik STM32F4 CCM / OpenOcd issue


von Oliver W. (sloblo)


Lesenswert?

Hallo Mikrocontroller-Forum,

mein STM32F405RGTx verfügt über 64K CCMRAM und das möchte ich gerne 
nutzen:

Linker Script:
...
MEMORY
{
  ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
  CCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
}
...
SECTIONS {
...
  .ccmram_bss (NOLOAD) : {
    *(.ccmram_bss*)
    . = ALIGN(4);
  } >CCMRAM
...

Define:
#define CCMRAM_BSS __attribute__((section(".ccmram_bss")))

Main cpp:
...
CCMRAM_BSS Ecg ecg[DacInternal::Channels];
...

In der Systemconfig rufe ich außerdem noch

rcc_periph_clock_enable(RCC_CCMDATARAM);

auf (jep, ich benutze libopencm3), aber das ist möglicherweise auch 
nicht nöitg.

Ich habe 2 unterschiedliche Probleme mit dieser Konfiguration.
Problem 1:
So wie hier beschrieben funktioniert das Programm garnicht mehr. Nehme 
ich in der main cpp jedoch die Deklaration "CCMRAM_BSS" wieder weg, so 
dass das Objekt im "normalen" SRAM liegt, ist alles in Ordnung.

Problem 2:
Nehme ich im Linker-Skript (NOLOAD) weg (so findet es sich in den 
meisten Forenbeiträgen), dann schläg das Flashen mit OpenOCD fehl:

Error: checksum mismatch - attempting binary compare
diff 0 address 0x10000000. Was 0xb4 instead of 0x00
diff 1 address 0x10000001. Was 0x01 instead of 0x00
diff 2 address 0x10000004. Was 0xb4 instead of 0x00
...

Es hat entweder den Anschein, dass OpenOCD Probleme hat, auf 0x10000000 
zuzugreifen oder aber der CCMRAM-Mechanismus funktioniert noch nicht wie 
er soll.

Als weiteren Test habe ich eine Variable als einzigen Member von CCMRAM 
einkompiliert
...
static CCMRAM_BSS volatile const  uint32_t meinsuperwert = 204;
...
und nach dem Flashen (nun wieder mit (NOLOAD)) die Speicheradresse 
geprüft. Diese blieb jedoch unverändert (0x01b4, wie oben im Error-Log).

Hat jemand vielleicht einen Tip für mich, wie ich das hinbekomme?

Besten Dank,
Oliver

von Jim M. (turboj)


Lesenswert?

Oliver W. schrieb:
> dann schläg das Flashen mit OpenOCD fehl:

Flashen kann man offensichtlich nur Flash Memory - und nicht den RAM.

Hint: Schau Dir das Linker Script mal ganz genau an - das Datensegment 
landet nämlich im Flash (hinter dem Code).

Da kannste das CCRAM auch hin packen, musst dann aber manuell kopieren 
oder den Startup Code ändern.

von Nop (Gast)


Lesenswert?

Oliver W. schrieb:

> Hat jemand vielleicht einen Tip für mich, wie ich das hinbekomme?

Wenn Du das CCM nicht im Startupcode initialisierst, dann steht da 
natürlich noch Müll drin. Sofern Du dort nur Variablen hinlegst, die mit 
0 initialisiert werden sollen, kannst Du den ganzen Bereich einfach im 
Startup nullen.

Sollen anders vorinitialisierte Variablen rein, muß eine Kopierschleife 
ähnlich der fürs SRAM vorhandenen auch fürs CCM in den Startupcde.

von Oliver W. (sloblo)


Lesenswert?

Hallo Jim, Nop, liebe Community,

tatsächlich sind mir die Initialisierungswerte nicht wichtig, da diese 
in einer separaten init()-Methode gesetzt werden. Dennoch habe ich 
folgendes ausprobiert:

Definition im Linker-Skript angepasst:

  _siccmram = LOADADDR(.ccmram_bss);
  .ccmram_bss : {
    . = ALIGN(4);
    _sccmram_bss = .;   /* create a global symbol at ccmram_bss start */
    *(.ccmram_bss)
    *(.ccmram_bss*)
    . = ALIGN(4);
    _eccmram_bss = .;   /* create a global symbol at ccmram_bss end */
  } >CCMRAM AT> ROM

So klappt es schonmal mit dem Flashen und OpenOCD ohne NOLOAD. Gute 
Sache!

Dann Initialisierung(-sversuch) mit folgendem Code:

...
extern unsigned _sccmram_bss, _eccmram_bss, _siccmram;

static void init_ccmram_bss(void) {
    unsigned *src = &_siccmram;
    unsigned *dst = &_sccmram_bss;
    while (dst < &_eccmram_bss) {
        *dst++ = *src++;
    }
}

__attribute__((used)) __attribute__((section(".preinit_array"))) static 
void (*g_handler[])(void) = { &init_ccmram_bss };
...

Ist jetzt nicht alles auf meinem Baum gewachsen wie man sich vorstellen 
kann, aber kompiliert sauber durch und kann auf den Prozessor geflasht 
werden.

Leider nach wie vor das gleiche Problem: die Objekt-Instanzen, die ich 
in den CCM gehoben habe (siehe Ecg array oben), arbeiten nicht.

Wie sollte ich eurer Meinung nach weiter vorgehen?

Besten Dank,
Oliver

von Martin (Gast)


Lesenswert?

Also ich bin nicht ganz sicher, ob ich verstehe, was Du machen willst 
aber...
Im Blockschaltbild 
(https://www.st.com/resource/en/datasheet/stm32f405rg.pdf Seite 19) 
siehst Du, dass die CPU nur über den D-Bus aufs CCM zugreifen kann, 
nicht über den I- und S-Bus. Du kannst also nur Daten, keinen Code ins 
CCM verlagern. Ich wollte mal Code ins CCM verlagern und das ging 
natürlich (wie mir der IAR-Support dann erklärt hatte) nicht.

- Martin

von Oliver W. (Gast)


Lesenswert?

Hallo Martin,

das ist in Ordnung. Der Code der Methoden ist nach meinem Verständnis im 
ROM und der Prozessor verarbeitet die Klasseneigenschaften über den dort 
bereitgestellten Code. Es geht mir vielmehr um einen möglichst 
effizienten Zugriff auf diese Eigenschaften, da es sich um DSP-Code 
handelt, die innerhalb von Interrupt-Routinen möglichst effizient 
verarbeitet werden sollen. Man liest hier von teils 30% 
Geschwindigkeitszuwachs.

Ich bin inzwischen auch soweit, dass ich wieder Leben im Programm habe. 
Die Ecg-Objekte befinden sich nachvollziehbar an der Adresse 0x10000000 
aufwärts. Ich kann allerdings nicht mehr nachvollziehen, warum es eben 
noch, als ich meinen zweiten Post verfasst habe, nicht funktioniert hat. 
Das ist natürlich nur so mittel hilfreich für das Forum. Aber die 
Code-Schnipsel oben sind dbei unverändert geblieben. Von daher kann ich 
bestätigen, dass dies tatsächlich der richtige Weg ist.

Danke nochmal und viele Grüße,
Oliver

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Ein make clean all wirkt manchmal wunder ;)

Aber wenn du die CCMRAM section initialisieren willst, dann nenn die 
bitte nicht _bss, das suggeriert einen pre init ausschließlich mit 
Nullen.
_data ist das was du willst.
Wenn du später mal ind en Code guckst und as bss heißt dann kommen dir 
sicherlich die Fragezeichen über die Stirn.

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.