Forum: Compiler & IDEs STM32 ISR execution im RAM


von Ingo S. (ingo-s)


Lesenswert?

Hallo Forum,

ich möchte alle ISR Funktionen beim STM32F05x (M0 Core) im RAM ausführen 
lassen. Grund ist der, das bei meiner EEPROM Simulation ab und zu eine 
Flash Page gelöscht werden muss, das zu einem Stall der CPU von 20ms bis 
60ms bei den Flash zugriffen führt. Das wäre nicht so kritisch, aber 
wenn in dieser Zeit eine ISR Anforderung kommt, führt dies zu einem 
undefiniertem Crash.

Die beste Lösung ist, alle ISR's ins RAM zu verlegen, anstelle alle ISR 
zu dieser Zeit zu deaktivieren.
Die Zusammenhänge sind mir klar.
Der fürs RAM Lauffähige Code muss natürlich erst mal ins Flash und von 
dort ins RAM copiert werden.
Ist das Aufgabe des Reset_Handlers, oder von Main?
Die Interrupt Vector Tabelle muss auf die Adressen der ISR's im RAM 
verweisen.
Beim M0 muss dann noch in der Main die Interrupt Vector Tabelle ins RAM 
copiert werden und der NVIC umconfiguriert werden.

Nur wie bringe ich das dem Compiler und Linker bei?
Als IDE benutze ich CooCox mit dem gcc 4.9 2015q1.

Leider fehlt mir da bisher jede Erfahrung mit Linker Scripts und 
sections.
Einige Recherchen habe ich natürlich angestellt und einige Doku's 
reingezogen, komme aber immer noch nicht klar.
Wenn man es weiß, ist es sicher einfach.

Im ersten Ansatz reicht es mir, die SysTick_Handler() und 
USART1_IRQHandler() Funktions im RAM ausführen zu lassen.

Wenn ich ds richtig interpretiere muss zuerst im Header File die 
Funktion einer section zugeordnet werden.

extern void SysTick_Handler(void) _attribute_ ((section ("isr_ram")));

Ist das so richtig und wie geht es weiter?

Grüße Ingo

von Jim M. (turboj)


Lesenswert?

Ist das ein Cortex M0 oder ein "Cortex M0+"? Ich frage das, weil ein 
Cortex M0 das VTOR Register zum verlegen der Interrupt Tabelle nicht 
im Core eingebaut hat. Man müsste dann im Handbuch nachschlagen ob es 
einen Workaround gibt.

Ingo S. schrieb:
> Der fürs RAM Lauffähige Code muss natürlich erst mal ins Flash und von
> dort ins RAM copiert werden.
> Ist das Aufgabe des Reset_Handlers, oder von Main?

Das ist die Aufgabe des Startup Code, der normalerweise vom Reset 
Handler aufgerufen wird. Die Änderungen dort sind abhängig von Compiler, 
LibC und Toolchain, zu der Du natürlich keine Angaben gemacht hast.

von Ingo S. (ingo-s)


Lesenswert?

Hi.
das ist ein M0, die IDE+Compiler Info hatte ich vergessen und eben 
anchgetragen (CooCox + gcc 4.9 2015q1).

Was und wie man die notwendige Verlegung der Interrupt Tabelle ins RAM 
macht, ist mir bekannt. Musste das in Verbindung mit einem Bootloader 
schon mal machen.

Den Reset Handler bzw. Startup Code habe ich mir angesehen. Der ist 
minimal, nur einige Zeilen Assembler, der zum Schluss in main() springt.

Grüße Ingo

von Steffen R. (steffen_rose)


Lesenswert?

Wenn man die typischen Adresse
0x0800.0000 für Flash und
0x2000.0000 für RAM
nutzt, ist der Rest garnicht so schwer.

Anfangs ist der Flash auf Adresse 0 gespiegelt. Dies läßt sich so 
umschalten, dass der RAM auf Adresse 0 gespiegelt wird.

Du musst somit den vorderen Bereich des Rams für deine Pläne 
reservieren.
Als erstes dann mit der Vectortable und den Funktionen initialiseren
(da noch ab 0x2000.0000).
Dann umschalten.

Ansonsten ist nichts zu ändern. die oben genannten Adressen sind 
weiterhin verfügbar.
1
// Enable the SYSCFG peripheral clock
2
__SYSCFG_CLK_ENABLE();
3
__SYSCFG_RELEASE_RESET();
4
// Remap SRAM at 0x00000000
5
__HAL_REMAPMEMORY_SRAM();

von Ingo S. (ingo-s)


Lesenswert?

Mit der alten STM-Lib sieht das bei mir so aus:

int main(void)
{
#ifdef BOOLOADER_START
   uint32_t *VectorTable = (uint32_t *)0x20000000;

  uint32_t i = 0;
  for(i = 0; i < 48; i++)
    VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
  //  Enable the SYSCFG peripheral clock
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  //   Remap SRAM at 0x00000000
  SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
#endif
....

In der IDE-Configuration, muss RAM Startadresse und Länge um die 48*4 
Bytes angepasst werden.

Gruß Ingo

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Inhalt des Linker-Scripts? Evtl. sind darin schon einige Input-Sections 
vorgesehen. Ansonsten kann man das Linkerscript etwas anpassen.

Im einfachsten Fall, wenn die VMA Start-Adresse der output-section .data 
mit der Adresse übereinstimmt, bei der der die Vector-Tabelle im RAM 
beginnen kann (bei den "CMSIS"-Codes war das zumindest so, aktuellen 
Stand kenne ich nicht), muss man nur dafür sorgen, dass die 
input-section der Vektortabelle im Linker-Script unmittelbar nach der 
Definition der Startadresse (Symbol heisst oft sdata oder ähnlich) in 
der output-section für .data eingetragen ist. Im einfachsten Fall 
einfach die Zeile aus der Definition der output-section .text 
verschieben (KEEP("vectors") o.ä). Dahinter dann die Section, die man 
für die ISR angelegt hat (oben "isr_ram", aber .data als 
input-section-Name tut dafür aber auch, wenn man keine genau Kontrolle 
über die Adresse der ISRen im RAM braucht) und dann die "normalen" .data 
input-sections, die im Linker-Script schon eingetragen sind.

Den Code zum umkopieren der Vektortabelle und der ISR kann man sich dann 
sparen, da mit Startup-Code ohnehin schon die Kopierroutine drin ist, 
die initialiserte Daten vom FLASH(ab .data-LMA-Start) ins RAM (ab 
.data-VMA-Start) kopiert. Vector-Table und ISRs werden dann dabei 
einfach mitkopiert. Im Code sind dann nur doch die erforderlichen 
Anweisungen zum remap zu ergänzen.

MAP-File hilft bei Kontrolle, ob alles wie gewünscht angelegt wurde.

von Ingo S. (ingo-s)


Lesenswert?

Danke für die Hinweise, aber ...

Ich sehe gerade das die CoIDE den Linker Sript dynamisch erzeugt.
In der Linker Configuration kann man aber ein Scatter File angeben.

Ich bin in der Situation, das ein Linker File für mich Neuland ist, und 
ich noch nicht weiss was ein Scatter File ist.
Nur das die CoIDE damit je nach Version, laut Forum, noch Probleme hat.
Das heisst im Endeffekt, viel Einarbeitungs Zeit opfern bis man alles im 
Griff hat.
Das passt im Moment nicht, da werde ich mich später mal schlau machen 
und das Problem im Moment anders lösen.

Vielen Dank
Gruß Ingo

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.