Forum: Mikrocontroller und Digitale Elektronik Stm32 SystemInit() C++


von Florian R. (fxlxo)


Angehängte Dateien:

Lesenswert?

Hallo

ich programmiere das Stm32f103c8t6 als Hobby. Dazu nutze ich die AC6 
Toolchain in Eclipse.

Wie das Bild zeigt will ich einen globalen Construktor aufrufen. Der 
Compiler meckert nicht, allerdings wird der Parameter ignoriert.
Ich vermute, dass die Funktion SystemInit() einen kompleten "Reset" 
durchführt und somit die Wirkung der implizieten Ausführung der globalen 
Construktoren direkt am Anfang der main() rückgängig macht.

Kann ich das irgendwie vermeiden? z.B. den Compiler dazu zwingen die 
Ausführung der globalen Konstruktoren nach der SystemInit() auszuführen?
Denn jedem Objekt im nachhinein die Parameter zu übergeben ist nervig.

Danke im Voraus!

von W.S. (Gast)


Lesenswert?

Florian R. schrieb:
> Ich vermute

Du müßtest in deinem System nachschauen, was die dortige Funktion denn 
so alles bewirkt. Aus der Ferne kann dir niemand dazu ne präzise 
Auskunft geben.
Bei mir zum Beispiel macht SystemInit folgendes:
- alle gewünschten Peripherie-Cores einschalten
- allen Pins ihre gewünschte Verwendung und Funktion zuweisen
- den Takt aufsetzen
- bei Systemen mit externem SDRAM der Ram aufsetzen und initialisieren

was sie nicht macht:
- internen RAM ablöschen
- Ram-Vorbelegungen

Aber ich verwende eben mein eigenes SystemInit, das genau das tut, was 
ich haben will - das mag bei dir völlig anders sein. Obendrein wird 
SystemInit bei mir vom Startupcode aufgerufen und nicht aus main heraus.

Ich frag mich allerdings, wieso du überhaupt irgend etwas VOR dem 
System-Init aufrufen willst.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

Florian R. schrieb:
> Der Compiler meckert nicht, allerdings wird der Parameter ignoriert

Was heißt ignoriert? Der Konstruktor nimmt gar keine Parameter aber der 
Compiler erlaubt dennoch die Übergabe, oder was?

Und wie bitte soll lange nach dem Konstruktor Aufruf ein Parameter 
"gelöscht" werden können? Der ist zu dem Zeitpunkt doch längst weg, da 
der Konstruktor lange zurückgekehrt ist.

Bei ST initialisiert die SystemInit nur den Takt, mehr nicht. Sie wird 
automatisch direkt vor der main () aufgerufen. Der Konstruktor wird noch 
davor aufgerufen. Das passiert im Startup Code, falls du den nicht 
geändert hast.

Drücke dich also mal klar aus, was du mit Parameter "ignoriert" 
/"gelöscht" meinst. Es würde gewiss auch nicht schaden, den Code des 
Konstruktors und der Klasse selbst zu zeigen.

von Florian R. (fxlxo)


Angehängte Dateien:

Lesenswert?

danke für die schnellen Antworten!

wenn ich SystemInit() auskommentiere läuft mein ledToggle deutlich 
langsamer.
daher denke ich dass die SystemInit() nicht vom startup_stm32.s 
aufgerufen wird.
Mit Assembler kenne ich mich leider kaum aus. Und ja ich habe die 
startup_stm32.s verändert, da in der StdPeriphirallib von ST kein 
startupcode zur Verfügung stand, der die richtige Vectoren für die alle 
möglichen ISRs beinhaltet.

Wie kann ich es bewerkstelligen, dass meine SystemInit() vom startup.s 
ausgeführt wird?

zur Nachfrage Prameter ignoriert:
Der Parameter des Construktors wird in eine private uint8_t Variable 
gespeichert. "ignoriert" soll heißen, dass das leider nicht geschieht!

hier der Construktor:

PCA9685::PCA9685( uint8_t _channel) {
  channel = _channel;
  //channel = 15; // geht auch nicht bei globalen Aufruf
      // oder allgemein beim Aufruf vor SystemInit()
}


Meine SystemInit() ist unverändert von ST übernommen.

Im Anhang die abgeänderte startup_stm32.s

von Dr. Sommer (Gast)


Angehängte Dateien:

Lesenswert?

Florian R. schrieb:
> da in der StdPeriphirallib von ST kein
> startupcode zur Verfügung stand, der die richtige Vectoren für die alle
> möglichen ISRs beinhaltet.

Wenn ich die STM32F1 Standard Peripheral Library bei ST herunterlade, 
befindet sich darin die angehängte Datei. Das ist genau die Richtige. 
Und siehe da, der einzige Unterschied zu deiner Datei besteht darin, 
dass vor dem Aufruf der main() zuerst die Konstruktoren, dann die 
SystemInit aufgerufen wird (und sich das Programm somit genau so verhält 
wie oben von mir beschrieben):
1
/* Call the clock system intitialization function.*/
2
    bl  SystemInit
3
/* Call static constructors */
4
    bl __libc_init_array
5
/* Call the application's entry point.*/
6
  bl  main
7
  bx  lr

Das ist genau, was dir fehlt.

von Dr. Sommer (Gast)


Lesenswert?

Florian R. schrieb:
> Der Parameter des Construktors wird in eine private uint8_t Variable
> gespeichert. "ignoriert" soll heißen, dass das leider nicht geschieht!
Ja, dein Konstruktor wurde nie aufgerufen. Hat mit der SystemInit aber 
eigentlich nichts zu tun.

Florian R. schrieb:
> PCA9685::PCA9685( uint8_t _channel) {
>   channel = _channel;

Vorsicht bei Variablen/Funktionsnamen die mit Unterstrich beginnen:
http://stackoverflow.com/a/228797

Besser als deine "Java-artige" Initialisierung der Member-Variable ist 
die C++-typische Initializer-Schreibweise:
1
PCA9685::PCA9685 (uint8_t channel_) : channel (channel_) {}

Funktioniert so auch mit Klassen ohne Standard-Konstruktor, ist ggf. 
besser optimierbar, als constexpr verwendbar...

Wo hast du Standard Peripheral Library überhaupt her, die ist ja uralt 
(Version V3.1.2, "aktuell" ist "V3.5.0").

von Florian R. (fxlxo)


Lesenswert?

danke, jetzt macht es das was ich will

allerdings bin ich zu blöd in der IDE einzustellen dass er die neu 3.5V 
von Standard P... zu nehmen wenn ich ein neues Projekt erstelle trotz 
google???
Es heißt zwar es hätte die neue 3.5v gefunden aber im neuen Projekt 
bekomm ich immer noch die alte rein.

wo stelle ich das ein?

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.