Forum: Mikrocontroller und Digitale Elektronik STM32 - printf


von Mirco H. (mirq)


Lesenswert?

Hallo,

ich möchte mittels printf() über die serielle Schnittstelle des 
MCBSTM32-Boards schreiben. Nutze die StdPeriph_Lib und Keil-IDE.
Entsprechend printf-Example habe ich einen Prototypen für putchar und 
die <stdio.h> included. Ergebnis sind 0 Compiler Errors und 0 Linker 
Errors, aber mein Programm bleibt hängen.
1
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
2
3
int main(void)
4
{
5
  Init();
6
  while(1)
7
  {
8
    GPIOB->BSRR = GPIO_Pin_8;
9
    wait();
10
    //USART_SendData(USART1, (uint8_t) 65);
11
    GPIOB->BRR = GPIO_Pin_8;
12
    wait();
13
    printf("a");  
14
  }
15
}
16
17
void wait(void)
18
{
19
  for(i=0; i<0xFFFFF; i++)
20
  {
21
    a = a + i;
22
  }
23
}
24
  
25
PUTCHAR_PROTOTYPE
26
{
27
  /* Place your implementation of fputc here */
28
  /* e.g. write a character to the USART */
29
  USART_SendData(USART1, (uint8_t) ch);
30
31
  /* Loop until the end of transmission */
32
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
33
  {}
34
35
  return ch;
36
}

Wenn ich die pritnf("a")-Zeile auskommentiere und die andere in der 
while(1) einkommentiere funktioniert alles; LED toggelt und A wird 
gesendet. So wie oben passiert garnichts. Im Projekt sind 
stm32f10x_usart.c, stm32f10x_gpio.c, stm32f10x_rcc.c und misc.c.

Hat jemand einen Tip?

Grüße, Mirco

von Random .. (thorstendb) Benutzerseite


Lesenswert?

schau mal bitte in die examples des MCBSTM32.
Dort findest du Code, der leicht lesbar ist und läuft, ohne driver 
library.

Ausserdem findest du in der datei "retarget.c" in einigen der Beispiele 
ein minimal retargeting, was du verwenden solltest.

Ebenso kannst du die ITM_Sendchar() Funktion aus der CMSIS verwenden, 
die daten kommen beim Debuggen im ITM/printf Viewer (View Menue) an. 
Terminalsequenzen sind auch möglich seit UV4, ausserdem gibt es ein paar 
neue interessante Terminal Modes.

Eingabe ist auch möglich (memory write), direkt im ITM window, entweder 
aktuelle CMSIS GetChar, oder:
1
volatile unsigned int ITM_RxBuffer;        // 0x5AA55AA5 is handshake value
2
3
// ITM Serial Window Input Watch and Init function
4
void ITMRx_InInit(void) {
5
  ITM_RxBuffer = 0x5AA55AA5;
6
}
7
8
int ITMRx_Getc(void) {
9
  int recChar=0;                    // zero is default if no new char recv
10
  
11
  if(ITM_RxBuffer != 0x5AA55AA5)
12
  {
13
    recChar = ITM_RxBuffer & 0xff; 
14
    ITM_RxBuffer = 0x5AA55AA5;  
15
  }
16
  return(recChar);
17
}

DL und Code zu mischen ist meist eine schlechte Idee, am besten die DL 
als Beispielcode nutzen.



VG,
/th.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Anmerkung:

die ITMRx_Getc() in meinem Beispiel ist non-blocking, d.h. sie liefert 
NULL oder ein valid char zurück.

Für die Verwendung mit scanf() muss im fgetc - retarget eine schleife 
eingebaut werden, die auf valid char prüft und erst dann (diesen) 
zurückliefert.


VG,
/th.

von Star K. (starkeeper)


Lesenswert?

Also mich wundert es etwas, dass du printf einfach so verwenden können 
sollst. Normalerweise sind ja für printf noch einige andere 
Basis-Funktion notwendig die der Entwickler implementieren muss, damit 
printf funktioniert. Ist das bei Keil schon alles geschehen?

Kannst du in das printf hinein steppen? Kommst du bei deiner 
putchar-Funktion an? Gibt es eventuell beim Ausführen von Printf eine 
Exception, die dein Debugger aber nicht fängt?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hi,

So im Groben:
fopen --> lib  --> _sys_open
printf --> fputc --> lib --> _sys_write
scanf --> fgetc --> lib --> _sys_read
fclose --> lib --> _sys_close

Für ein einfaches Retargeting reicht es, die fputc zu überladen, 
use_no_semihosting zu verwenden und noch ein paar wenige 
Zusatzfunktionen, die von der libc benötigt werden, einzubauen
--> siehe retarget.c

Will man ein komplettes Konzept basierend auf den file streaming 
funktionen aufbauen, muss man auf die _sys_x - ebene runter (siehe 
RTAgent.c), und dort einen IO Layer einziehen.


VG,
/th.

von Mirco H. (mirq)


Lesenswert?

Hallo,

Danke Thorsten für den Tip mit Retarget.c!
Dort kann man sehen dass FILE eine Struktur ist und wie sie 
initialisiert wird.
Habe in meinen Code noch die beiden folgenden Zeilen eingefügt. Dann hat 
alles funktioniert.
1
struct __FILE { int handle; /* Add whatever you need here */ };
2
FILE __stdout;


Bei meinem Projekt muss ich auf bereits bestehendem Code aufbauen und in 
diesem sind die std driver verwendet worden... Deshalb wollte ich es auf 
diese Weise lösen.
Danke für die ausführlichen Beschreibungen.

Grüße, Mirco

von Axel (Gast)


Lesenswert?

Hallo,

ich habe das selbe Problem nur komme ich auch mit den angegebenen Hilfen 
nicht weiter. fputc habe ich schon überladen, mit dem ganz oben 
beschriebenen Code. Ich benutzt eine IAR Umgebung und habe alle 
wichtigen Header eingebunden. Zusätzlich auch noch DLIB_Config, 
DLIB_Default etc.
Dort wird dann FILE deklariert. Meine Fehler geschieht zur Laufzeit und 
zwar direkt nach dem Übergang in den Debug Modus derartig, dass ich 
keine Möglichkeit habe Breakpoints zu setzten.

Nun würde ich gerne wissen was ich hiermit anfangen kann:

Random ... schrieb:
> printf --> fputc --> lib --> _sys_write

Wo kann ich mir die Funktion fputc anschauen um eventuell weitere 
Informationen darüber zu erhalten.

Random ... schrieb:
> use_no_semihosting zu verwenden und noch ein paar wenige
> Zusatzfunktionen, die von der libc benötigt werden, einzubauen
> --> siehe retarget.c

Diese Retarget.c gibt es in meiner Entwicklungsumgebung nicht unter 
Beispielen. Wie kann ich use_no_semihosting vermenden?
Im Netz habe ich nur die üblichen Informationen (printf, scanf 
formatierung etc.) im Umgang mit stdio.h gefunden, kennt jemand 
vielleicht einen Link der darauf tiefer eingeht?

Ich bin ebenfalls gezwungen in diesem Projekt auf die Library 
zuzugreifen. Auf dem Demoboard funktionieren Ein- und Ausgabe wunderbar 
und deswegen bin ich hier am verzweifeln. Vielen Dank für eure 
Aufmerksamkeit schon mal vorab und viele Grüße
Axel

von Axel (Gast)


Lesenswert?

ok, use_no_semihosting ist wohl keil IDE eigen. Die lib finde ich leider 
immernoch nicht! Gruß Axel

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.