Forum: Mikrocontroller und Digitale Elektronik STM32 Retargeting mit GNU/Eclipse-Toolchain (newlib und libgloss)


von Dino H. (hdino)


Lesenswert?

Hallo zusammen,

ich habe mir mit Hilfe der Anleitung und Kommentare aus dem 
Beitrag "STM32-Toolchain mit Eclipse CDT 4.3, GnuArmEclipse, OpenOCD 0.8.0, Gnu Arm GCC 4.8, STM32CubeMX" eine Toolchain für mein 
STM32F401C Discovery Board aufgebaut, die auf Eclipse CDT 4.5.1 (Mars), 
ARM GCC 4.9 2015q3, dem GnuArmEclipse-Plugin, OpenOCD 0.9.0 und 
STM32CubeMX 4.11.0 basiert. Soweit funktioniert schonmal alles, das 
heißt, das Projekt wird gebaut, lässt sich per OpenOCD ausführen und die 
Breakpoints funktionieren auch.

Um die für die newlib bzw. newlib nano erforderlichen Systemaufrufe wie 
_sbrk, _write usw. bereitzustellen, habe ich zunächst mit 
--specs=nosys.specs gelinkt. Das dynamische Allozieren von Speicher 
funktioniert damit auch wunderbar, allerdings würde ich gern die 
_write-Funktion selbst implementieren, um diese z.B. auf einem Display 
auszugeben oder per UART auszuleiten.

In der libgloss hat die _write-Funktion ein weak-Symbol, sodass man sie 
einfach überschreiben können sollte. Hier der Ausschnitt aus dem 
Quellcode von gcc-arm-none-eabi-4_9-2015q3, 
newlib/libgloss/arm/syscalls.c:
1
/* fd, is a user file descriptor. */
2
int __attribute__((weak))
3
_write (int    fd,
4
  char * ptr,
5
  int    len)
6
{
7
...

Also habe ich einfach eine entsprechende write-Funktion in meiner main.c 
implementiert, die durch ein printf aufgerufen werden sollte:
1
int _write (int fd, char *ptr, int len)
2
{
3
  HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
4
  HAL_Delay(300);
5
  return len;
6
}
7
8
int main(void)
9
{
10
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
11
  HAL_Init();
12
13
  /* Configure the system clock */
14
  SystemClock_Config();
15
16
  /* Initialize all configured peripherals */
17
  MX_GPIO_Init();
18
  
19
  HAL_GPIO_TogglePin(LD5_GPIO_Port, LD5_Pin);
20
  printf("Blink");
21
  
22
  while(1)
23
  {
24
    // do nothing
25
  }
26
}

Leider blinkte die LED nicht wie erhofft. Daher habe ich den nosys.specs 
Parameter entfernt und alle Systemaufrufe direkt im Projekt 
implementiert (obwohl es mir lieber wäre, gegen libnosys zu linken und 
die notwendigen Aufrufe wie oben versucht zu überschreiben). Aber auch 
so gab es keine Reaktion.

Hat vielleicht jemand eine Idee, was da falsch laufen könnte? Hab ich 
etwas übersehen? Wäre auf jeden Fall toll, wenn ich das noch zum Laufen 
kriegen würde.

Gruß
Dino

von S. R. (svenska)


Lesenswert?

Das printf der Newlib braucht eine funktionierende dynamische 
Speicherverwaltung, also musst du mindestens sbrk auch implementieren.

Am besten, du implementierst alle Syscalls als Stubs, die ein 
bestimmtes Blinkmuster als Fehlercode zeigen und arbeitest dich durch.

von Dino H. (hdino)


Lesenswert?

Danke für die Antwort. Ich habe daraufhin nochmal die Systemaufrufe 
(sbrk usw.) überprüft, sie werden durch den Linker-Parameter
1
--specs=nosys.specs
 aber "brauchbar" implementiert, d.h. die dynamische Speicherverwaltung 
funktioniert.

Die Lösung war am Ende, dass mein printf die Daten nie geschrieben hat. 
Ich musste ein \n oder ein
1
fflush(stdout)
 hinzufügen.

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.