Forum: Mikrocontroller und Digitale Elektronik STM32 komisches Verhalten bei include und leerer Funktion


von Matthias L. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich brauch mal Hilfe. Ich hab hier einen STM32F107VCT6 und folgendes 
Programm mit CoIDE (1.7.5, 20130927-3279-1526) draufgeladen: Die main.c 
sieht so aus:
1
#include <stm32f10x.h>
2
#include <stm32f10x_conf.h>
3
#include <stm32f10x_rcc.h>
4
#include <stm32f10x_gpio.h>
5
6
#include <stm32_time.h>
7
//#include <stm32_serial.h>   // <= PROBLEM
8
9
//**************************************************
10
void     Cyclic_1ms     (void)
11
{
12
  static  uint16_t  Count;
13
  //-----------------------------
14
  if ( ++Count >= 1000 )
15
  {
16
    Count = 0;
17
    GPIOE->ODR ^= GPIO_ODR_ODR15;
18
  }
19
  //-------------------------------
20
  GPIOE->ODR ^= GPIO_ODR_ODR14;
21
  return;
22
}
23
24
//**************************************************
25
int main(void)
26
{
27
  //-- System initialisieren ------
28
  SystemInit();
29
  //-- Treiber initialisieren -----
30
  stm32_time_init();
31
  stm32_time_addfct_1ms  ( (void*) &Cyclic_1ms );  // 1ms
32
//  stm32_serial_init();    // <= PROBLEM
33
  //-- Testpins -------------------
34
  GPIO_InitTypeDef GPIO_InitStructure;
35
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
36
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
37
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
38
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO,ENABLE);
39
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);
40
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_All;   // TEST Status LEDs
41
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
42
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
43
  GPIO_Init( GPIOE , &GPIO_InitStructure);
44
  //-- Hauptschleife --------------
45
  while (1)
46
  {
47
    GPIOE->ODR ^= GPIO_ODR_ODR13;
48
  }
49
  //-------------------------------
50
  return 0;
51
}
Mit dem Oszi sehe ich jetzt am Port E an folgende Pins korrekterweise 
folgendes:
Pin15: 0.5Hz
Pin14: 500Hz
Pin13: ca 3.3MHz

Kommentiere ich die zwei mit //Problem markierten Zeilen ein, so 
funktioniert nur noch der Pin13 der main-while-Schleife. Der Timer macht 
irgendwelchen Mist. Warum? Die neue Funktion ist leer:
stm32_serial.h
1
#ifndef  STM32_SERIAL_H
2
#define  STM32_SERIAL_H
3
//**************************************************
4
void     stm32_serial_init( void );
5
#endif

stm32_serial.c
1
//**************************************************
2
#include "stm32_serial.h"
3
//**************************************************
4
void               stm32_serial_init( void )
5
{
6
  return;
7
}

Im Anhang das komplette Projekt als rar.

Ich vermute, das Problem hängt mit dem Einbinden der h-Datei zusammen. 
Aber warum? Die andere (stm32_time.h) scheint doch auch zu 
funktionieren...

Kann sich das bitte mal jemand ansehen und mir helfen?

Thx schonmal

von Nop (Gast)


Angehängte Dateien:

Lesenswert?

Mal auf die Schnelle mit CppCheck geguckt - und es meckert genau bei den 
Timersachen. Könnte es sein, daß das Ganze auch vorher schon mehr 
zufällig funktioniert hat?

von Matthias L. (Gast)


Lesenswert?

Hm.. besagte Zeilen sehen beide so aus:
1
uint8_t u8Max = (uint8_t) (   sizeof(scEsc_SysTick.apfct)
2
                            / sizeof(scEsc_SysTick.apfct[0]) );
mit:
1
volatile
2
struct
3
{
4
  void  ( *apfct[8] ) (void);
5
}
6
scEsc_SysTick;
Ich habs geändert zu;
1
#define       MAX_COUNT1MS   (  8  )
2
...
3
uint8_t u8Max = (uint8_t) ( MAX_COUNT1MS );


Ändert leider nichts am Problem...

von aSma>> (Gast)


Lesenswert?

Servus,
guck mal ins Errata. Da hast du 100 pro ein Konflikt mit uart.

von Nop (Gast)


Lesenswert?

OK, also ich hab da mal das Hexfile mit dem Mapfile abgeglichen, der 
Systick-Handler steht korrekt in der Vektortabelle. Das ist schonmal 
gut.

Versuch doch mal im ersten Schritt, das LED-Wackeln direkt hart im 
Systick-Handler zu codieren. Wenn das geht, deklarier die 
cyclic-Funktion als extern in der Time-Datei und ruf die hart aus dem 
Systick-Handler auf.

Wenn das geht, weiß man schonmal, das System geht, wie es soll. Dann 
kann das nur noch was mit der Liste aus den FUnktionspointern sein, daß 
sich da was verschluckt.

von Matthias L. (Gast)


Lesenswert?

Aber ich mach doch garnichts mit dem UART. Die Funktion ist leer. Und 
wie ich die Funktion oder die c/h-Dateien nenne, ist egal.

Das Ergebnis ist dasselbe

;-(

von Matthias L. (Gast)


Angehängte Dateien:

Lesenswert?

>Versuch doch mal im ersten Schritt, das LED-Wackeln direkt hart im
>Systick-Handler zu codieren.


Kein Unterschied wo ich das mache.


TEK0000 zeigt das Bild ohne den AUfruf der Leerfunktion. Die gelbe Linie 
springt alle 1s zwischen HI und LO hin und her. Die blaue sind 500Hz. 
Die untere ist das main-while. Dort sieht man, wielange er etwa im 
TimerInt ist.

Die anderen zeigen das Fehlverhalten. Es sieht irgendwie so aus, als ob 
der Test-pin beim Beenden des TimerInts wieder gelöscht wird...

Aber warum?

von aSma>> (Gast)


Lesenswert?

Guck dir den ASM Code an. Vielleicht kompremiert der Compiler die 
Meehode: void seriel return; zu return;.

von Nop (Gast)


Lesenswert?

Hm, Du verwendest eine recht alte Version der CoIDE - der Compiler wird 
vermutlich auch nicht der aktuellste sein? Mach außerdem mal die 
Optimierung auf Größe raus und geh auf O0.

Hast Du nach dem Einblenden der beiden Zeilen das komplette Projekt mit 
Rebuild neu gemacht? Ich würde IDEs da nie vertrauen.

von pegel (Gast)


Lesenswert?

coocox 1.7.7 mit gcc 4.9 hat keine Probleme mit dem Projekt.

von Johannes S. (Gast)


Angehängte Dateien:

Lesenswert?

der Stack ist 0x100 gross und liegt direkt hinter dem .bss. Ich sehe 
jetzt zwar keine Funktion die viel Stack braucht, lag da beim Testen 
evtl. ein grosser Buffer auf dem Stack? Mit der CoIde hast du ja auch 
einen Debugger, wie sieht der Stack da aus vor/nach dem 
stm32_serial_init() ?

Dann wird SystemInint() im Startup schon vor main() aufgerufen, der 
Aufruf in main() ist also überflüssig.

Die Pointeraktionen sehen ok aus, habe ich mal im VS angesehen. Für den 
Funktionspointer würde ich ein typedef verwenden, siehe Anhang.
In der Pointertabelle hast du ja schon einen Füllstand, im SysTick muss 
die Schleife dann auch nur bis zum max. Anzahl fnPtr laufen.

von Matthias L. (Gast)


Lesenswert?

>Hm, Du verwendest eine recht alte Version der CoIDE - der Compiler wird
>vermutlich auch nicht der aktuellste sein?

CoIDE 1.7.5
GNU  5.4 2016q2


>Hast Du nach dem Einblenden der beiden Zeilen das komplette Projekt mit
>Rebuild neu gemacht? Ich würde IDEs da nie vertrauen.

Mache ich immer.


>Mach außerdem mal die Optimierung auf Größe raus und geh auf O0.

Yup. Mit O0, O1 und O2 gehts. Mit O3 und Os nicht. Warum?

von Nop (Gast)


Lesenswert?

Ok, den Compiler habe ich auch, die Version ist OK. Mit dem Q3-Update 
wird sich vermutlich nichts ändern, ich bekomme damit jedenfalls 
dieselben Binaries wie mit Q2 bei meinen Projekten. Vermutlich ist die 
Leerfunktion auch gar nicht die Ursache, sondern nur ein Symptom. Das 
wird etwas Herumgestochere.

Stackgröße glaube ich nicht als Ursache; die ist im Startfile zwar mit 
0x100 definiert, also 256, aber vom Typ unsigned long int, mithin sind 
das auf STM32 immerhin 1kB.

Erstmal vielleicht den überflüssigen SystemInit()-Aufruf aus der Main 
nehmen, wie Johannes schon gesagt hat. Das wird im Default-Resethandler 
schon gemacht.

Dann in cyclic_1ms mal den Blinker für den Sekundentakt rausnehmen und 
nur den 500Hz drinlassen. Einfach mal gucken, was passiert mit O3. 
Cyclic_1ms direkt ohne die Pointertabelle aus dem SysTick aufzurufen 
hattest Du ja schon gemacht?

Eine weitere Idee ist, den Compiler Stück für Stück mit 
Compiler-Optionen auf O3 anzufüttern und zu testen, ob eine davon was 
bringt - das kann bei der ziemlich vertrackten Fehlersuche helfen. Ich 
würde es Stück für Stück mit denen hier versuchen:

-fno-gcse -fno-unsafe-loop-optimizations -fno-inline 
-fno-delete-null-pointer-checks -fno-strict-aliasing 
-fno-strict-overflow -fno-isolate-erroneous-paths-dereference

Wenn das nichts hilft, dann als nächstes mal so compilieren, daß Du 
jeweils alle Dateien bis auf eine mit O2 compilierst, und die eine mit 
O3. Dann sieht man immerhin schonmal, für welche Datei das einen 
Unterschied macht. Kann ja auch in dem Sumpf der ST-Software begründet 
liegen.

Wie das aus CoIDE geht, weiß ich nicht, ich nutze 
Batchfiles/Shellscripte. Allerdings kann man sich den Compiler-Aufruf 
aus dem Statusfenster bei CoIDE in ein Batchfile kopieren.

Ich würde auch ein Update der CoIDE auf 1.78 andenken. Keine Ahnung, was 
sich da geändert hat, aber immerhin hast Du ja im Moment kein eigenes 
Linkerfile.

von Achim (Gast)


Lesenswert?

Die #include-zeile allein darf doch nicht stören.

Tut sie es, fehlt vermutlich ein Zeilenumbruch am include-guard

von Nop (Gast)


Lesenswert?

Nochwas.. ich weiß nicht, was auf Deiner Hardware alles an Port E hängt, 
aber ich würde testhalber mal
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_All;
durch
GPIO_InitStructure.GPIO_Pin   = (GPIO_Pin_13 | GPIO_Pin_14 | 
GPIO_Pin_15);
ersetzen. Oder so ähnlich, irgendwie so heißt das bei der ST-Lib aber.

von Matthias L. (Gast)


Lesenswert?

Ich habe noch bischen rumprobiert. Keine logische Erklärung gefunden, 
wanns geht und wann nicht. Meist ists so, wenn ich einen leeren 
Fkt-aufruf mache, geht der Timer nicht mehr richtig..

Ich habe vor zwei Jahren mal ein Projekt mit CoIDE realisiert. Dort 
hatte ich solche Probleme bei demselben Evalboard nicht.

Zwischenzeitlich habe ich avon Win7 auf Win10 umgestellt und CoIDE/gcc 
neu installiert..

Ob das was damit zutun hast?

Mich kotzt das hier an..

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.