Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage C (Weg)optimierung


von Joachim S. (electribe)


Lesenswert?

Hallo Zusammen,
viel zu spät beginne ich gerade damit, meine C-Kenntnisse aufzufrischen 
(bzw. aufzubauen) und komme an einer Stelle nicht weiter. Ich wollte das 
simpelste schreiben, das mir eingefallen ist: Tastendruck=LED an. Laufen 
soll es auf einem NucleoF429 und STM32CubeIDE. Wenn die C-Optimierung 
auf 0 steht, funktioniert alles wie gewünscht. Bei O=2 klappt es schon 
nicht mehr. Die (zu testzwecken eingebaute Variable) read_result ändert 
beim debuggen mit Tastendruck ihren Wert, aber das Schreiben auf die 
GPIOB Adresse wird nicht mehr ausgeführt. Mehr als eine volatile 
Variable für den Pointer einrichten fällt mir aber nicht ein. Könnt Ihr 
mir bitte einen Tipp geben wo es klemmt und ggf. auch, wie ich in 
Zukunft die Ursache für das Problem beim Debuggen identifizieren kann?
1
#define RCC_ADDR 0x40023800UL
2
#define RCC_AHB1ENR_OFFSET_ADDR 0x30UL
3
#define RCC_AHB1ENR_GPIOBEN_BIT 1
4
#define RCC_AHB1ENR_GPIOCEN_BIT 2
5
6
#define GPIOB_ADDR 0x40020400UL
7
#define GPIOB_MODER_OFFSET_ADDR 0x00UL
8
#define GPIOB_MODER7_BIT 14
9
#define GPIOB_ODR_OFFSET_ADDR 0x14UL
10
#define GPIOB_ODR_ODR7_BIT 7
11
12
#define GPIOC_ADDR 0x40020800UL
13
#define GPIOC_IDR_OFFSET_ADDR 0x10UL
14
#define GPIOC_IDR_ODR13_BIT 13
15
16
volatile uint8_t read_pin(volatile uint32_t *const, uint8_t const);
17
18
int main(void)
19
{
20
  volatile uint32_t * const p_GPIOB_ODR_ADDR = (uint32_t*)(GPIOB_ADDR+GPIOB_ODR_OFFSET_ADDR);
21
  uint8_t read_result = 0;
22
23
  *(uint32_t*)(RCC_ADDR+RCC_AHB1ENR_OFFSET_ADDR) |= (1 << RCC_AHB1ENR_GPIOBEN_BIT);
24
  *(uint32_t*)(RCC_ADDR+RCC_AHB1ENR_OFFSET_ADDR) |= (1 << RCC_AHB1ENR_GPIOCEN_BIT);
25
  *(uint32_t*)(GPIOB_ADDR+GPIOB_MODER_OFFSET_ADDR) |= (1 << GPIOB_MODER7_BIT);
26
27
28
  while(1){
29
    read_result = read_pin((uint32_t*)(GPIOC_ADDR+GPIOC_IDR_OFFSET_ADDR),GPIOC_IDR_ODR13_BIT);
30
    if(read_result)
31
      *p_GPIOB_ODR_ADDR |= (1 << GPIOB_ODR_ODR7_BIT);
32
    else
33
      *p_GPIOB_ODR_ADDR &= ~(1 << GPIOB_ODR_ODR7_BIT);
34
  }
35
}
36
37
38
volatile uint8_t read_pin( volatile uint32_t *const pRegister_address, uint8_t const pin_number){
39
  return (*(pRegister_address) >> pin_number) & 0x01;
40
}

Danke und viele Grüße!
Achim

von Stefan F. (Gast)


Lesenswert?

Ich denke, dass die Fehlerursache nicht in dem gezeigten Code-Schnipsel 
liegt.

Warum benutzt du nicht einfach das bereits von ST gelieferten Makros

READ_BIT(), CLEAR_BIT() und SET_BIT() ?

Die tun, was sie sollen, ohne diese komplexen Klimmzüge.

von Peter D. (peda)


Lesenswert?

Muß diese ganze Pointerei und Casterei denn sein?
Kann man nicht einfach normale Variablen benutzen. Die gibt es doch 
bestimmt in den h-Files schon vordefiniert.

Ein volatile muß man beim Casten mitführen, sonst geht es verloren.
Casten bedeutet immer, ich bin für alle Fehler verantwortlich, der 
Compiler gibt die Kontrolle ab.

von W.S. (Gast)


Lesenswert?

Peter D. schrieb:
> Muß diese ganze Pointerei und Casterei denn sein?

Nö.

Aber manche mögen es heiß und andere manche mögen es so kompliziert wie 
nur möglich.

Der wahre Grund für sowas besteht darin, daß man gern eine gewisse 
Berechtigung für das Benutzen eines Debug-Geschirres haben möchte. Mit 
Casterei&Pointerei kann man das am leichtesten erreichen.

Normalerweise schreibt man sich einen Treiber, der das Drücken einer 
Taste in einen Event verwandelt und hält main() sauber und frei von 
jeglichem plattformabhängigen Krempel.

Und im Treiber greift man schlichtweg auf genau den Port zu, wo die 
Taste (oder was auch immer) dran hängt. Ohne all diesen konfusen Ballast 
wie "GPIOB_MODER_OFFSET_ADDR" und Konsorten. Was soll sowas bloß? Um den 
korrekt verwenden zu können, muß man erstmal nachschlagen, wofür er 
überhaupt vorgesehen und wie er anzuwenden ist.

W.S.

von Joachim S. (electribe)


Lesenswert?

Danke für eure Antworten!

Stefan ⛄ F. schrieb:
> Ich denke, dass die Fehlerursache nicht in dem gezeigten Code-Schnipsel
> liegt.

Es muss irgendwo dort sein - der Schnipsel den ich gezeigt habe ist der 
Inhalt der kompletten main und was anderes macht der Controller nicht. 
Ohne Optimierung funktioniert das ganze ja, aber leider nicht ohne.

Das ganze Gepointer und Gecaste muss bestimmt nicht sein und es wäre 
sicher sauberer, einen Treiber zu schreiben etc., aber Ziel des Ganze 
ist im Moment nicht für eine reale Anwendung zu programmieren, sondern 
programmieren lernen. Bevor ich mit vorgefertigten Makros arbeite, 
wollte ich erstmal verstehen wie man "von Hand" Register beschreibt und 
ließt. Genau genommen ist es das erste mal, dass ich überhaupt mit 
Pointern arbeite :D

Viele Grüße
Achim

von Dirk B. (dirkb2)


Lesenswert?

Schraub mal den Warn-Level hoch.

von Leopold N. (leo_n)


Lesenswert?

Zeile 23 bis 25 solltest du auf volatile uint32_t* casten, statt auf nur 
uint32_t*.
Sonst optimiert der Compiler den Schreibzugriff weg.

Grüße

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.