Forum: Compiler & IDEs printf problem bei STM32F4


von Stm M. (stmfresser)


Lesenswert?

Hallo,

ich habe ein seltsames Problem mit printf beim Programmieren STM32F4 
Discovery Board.

Nur beim Printen von mehreren Gleitkommazahlen bekomme ich entweder ganz 
verfälschte Daten, oder die nur die Hälfte, wenn ich in main schleife 
nach dem printf ohne mindestens 200ms Verzögerung habe. Mit 200ms Delay 
geht printf ohne Problem. Woran liegt das? Ist mein printf keine 
blockierende Methode?


Vielen Dank im Voraus.

PS. Ich schreib deutsch als Fremdsprache. Entschuldigung für die 
schlechtformulierten Sätze.
1
int main(void){
2
3
while(1){
4
 printf("%f %f %f %f \n", zahl1, zahl2, zahl3, zahl4);
5
 Delay(200e3);
6
}
7
}
8
9
void Delay(__IO uint32_t nTime)
10
{
11
    TimingDelay = nTime;
12
    
13
    while(TimingDelay != 0);
14
}
15
16
void TimingDelay_Decrement(void)
17
{
18
    if (TimingDelay != 0x00)
19
    {
20
        TimingDelay--;
21
    }
22
}
Usart wird so konfiguriert.
1
 
2
/* USART1 clock enable */
3
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
4
5
/* USART1 initialisieren PB6=TX PB7=RX*/
6
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
7
    
8
   
9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;  
10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
11
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
12
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
14
GPIO_Init(GPIOB, &GPIO_InitStructure);
15
16
17
USART_InitTypeDef USART_InitStructure;
18
    
19
USART_InitStructure.USART_BaudRate = 115200;
20
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
21
USART_InitStructure.USART_StopBits = USART_StopBits_1;
22
USART_InitStructure.USART_Parity = USART_Parity_No;
23
    
24
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
25
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
26
  
27
USART_Init(USART1, &USART_InitStructure);
28
USART_Cmd(USART1, ENABLE);
29
30
/**
31
 * @brief  Retargets the C library printf function to the USART.
32
 *       Overwrite __io_putchar function used by printf
33
 * @param  None
34
 * @retval None
35
 */
36
PUTCHAR_PROTOTYPE
37
{
38
  /* Put character on the serial line */
39
  USART1->DR = (ch & (uint16_t)0x01FF);
40
    
41
  /* Loop until transmit data register is empty */
42
  while ((USART1->SR & USART_FLAG_TXE) == (uint16_t) RESET);
43
    
44
  return ch;
45
}

für Prinf float zahlen
1
#include <errno.h>
2
#include <sys/stat.h>
3
#include <sys/times.h>
4
#include <sys/unistd.h>
5
#include <stdint.h>
6
7
#include <stm32f4xx_usart.h>
8
9
#ifndef UNUSED
10
#define UNUSED(x) (void)x
11
#endif
12
13
#ifndef STDOUT_USART
14
#define STDOUT_USART 1
15
#endif
16
17
#ifndef STDERR_USART
18
#define STDERR_USART 2
19
#endif
20
21
#ifndef STDIN_USART
22
#define STDIN_USART 1
23
#endif
24
25
#undef errno
26
extern int errno;
27
28
/*
29
 * A pointer to a list of environment variables and their values.
30
 * For a minimal environment, this empty list is adequate.
31
 */
32
char *__env[1] = { 0 };
33
char **environ = __env;
34
35
int _write(int file, char *ptr, int len);
36
37
void _exit(int status) {
38
  UNUSED(status);
39
40
  _write(1, "exit", 4);
41
  while (1) {
42
    ;
43
  }
44
}
45
46
int _close(int file) {
47
  UNUSED(file);
48
49
  return -1;
50
}
51
52
/*
53
 * Transfer control to a new process. Minimal implementation (for a system
54
 * without processes)
55
 */
56
int _execve(char *name, char **argv, char **env) {
57
  UNUSED(name);
58
  UNUSED(argv);
59
  UNUSED(env);
60
61
  errno = ENOMEM;
62
  return -1;
63
}
64
65
/*
66
 * Create a new process. Minimal implementation (for a system without processes)
67
 */
68
int _fork() {
69
  errno = EAGAIN;
70
  return -1;
71
}
72
/*
73
 * Status of an open file. Minimal implementation.
74
 */
75
int _fstat(int file, struct stat *st) {
76
  UNUSED(file);
77
78
  st->st_mode = S_IFCHR;
79
  return 0;
80
}
81
82
/*
83
 * Process-ID; this is sometimes used to generate strings unlikely to conflict
84
 * with other processes. Minimal implementation, for a system without processes.
85
 */
86
int _getpid() {
87
  return 1;
88
}
89
90
/*
91
 * Query whether output stream is a terminal. For consistency with the other
92
 * minimal implementation.
93
 */
94
int _isatty(int file) {
95
  UNUSED(file);
96
97
  switch (file) {
98
  case STDOUT_FILENO:
99
  case STDERR_FILENO:
100
  case STDIN_FILENO:
101
    return 1;
102
  default:
103
    //errno = ENOTTY;
104
    errno = EBADF;
105
    return 0;
106
  }
107
}
108
109
/*
110
 * Send a signal. Minimal implementation.
111
 */
112
int _kill(int pid, int sig) {
113
  UNUSED(pid);
114
  UNUSED(sig);
115
116
  errno = EINVAL;
117
  return (-1);
118
}
119
120
/*
121
 * Establish a new name for an existing file. Minimal implementation.
122
 */
123
int _link(char *old, char *new) {
124
  UNUSED(old);
125
  UNUSED(new);
126
127
  errno = EMLINK;
128
  return -1;
129
}
130
131
/*
132
 * Set position in a file. Minimal implementation.
133
 */
134
int _lseek(int file, int ptr, int dir) {
135
  UNUSED(file);
136
  UNUSED(ptr);
137
  UNUSED(dir);
138
139
  return 0;
140
}
141
142
/*
143
 * Increase program data space. Malloc and related functions depend on this.
144
 */
145
caddr_t _sbrk(int incr) {
146
147
  extern char _ebss; // Defined by the linker
148
  static char *heap_end;
149
  char *prev_heap_end;
150
151
  if (heap_end == 0) {
152
    heap_end = &_ebss;
153
  }
154
  prev_heap_end = heap_end;
155
156
  /** FIX **/
157
    char * stack = (char*) __get_MSP();
158
    if (heap_end + incr >  stack){
159
      _write (STDERR_FILENO, "Heap and stack collision\n", 25);
160
      errno = ENOMEM;
161
      return  (caddr_t) - 1;
162
      //abort ();
163
    }
164
165
  heap_end += incr;
166
  return (caddr_t) prev_heap_end;
167
168
}
169
170
/*
171
 * Read a character to a file. `libc' subroutines will use this system routine
172
 * for input from all files, including stdin.
173
 * Returns -1 on error or blocks until the number of characters have been read.
174
 */
175
int _read(int file, char *ptr, int len) {
176
  int n;
177
  int num = 0;
178
  switch (file) {
179
  case STDIN_FILENO:
180
    for (n = 0; n < len; n++) {
181
#if   STDIN_USART == 1
182
      while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
183
            char c = (char)(USART1->DR & (uint16_t)0x01FF);
184
#elif STDIN_USART == 2
185
//      while ((USART2->ISR & USART_FLAG_RXNE) == (uint16_t) RESET) {}
186
//      char c = (char) (USART2->TDR & (uint16_t) 0x01FF);
187
#elif STDIN_USART == 3
188
//      while ((USART3->ISR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
189
//      char c = (char)(USART3->TDR & (uint16_t)0x01FF);
190
#endif
191
      *ptr++ = c;
192
      num++;
193
    }
194
    break;
195
  default:
196
    errno = EBADF;
197
    return -1;
198
  }
199
  return num;
200
}
201
202
/*
203
 * Status of a file (by name). Minimal implementation.
204
 * int _EXFUN(stat,( const char *__path, struct stat *__sbuf ));
205
 */
206
int _stat(const char *filepath, struct stat *st) {
207
  UNUSED(filepath);
208
209
  st->st_mode = S_IFCHR;
210
  return 0;
211
}
212
213
/*
214
 * Timing information for current process. Minimal implementation.
215
 */
216
clock_t _times(struct tms *buf) {
217
  UNUSED(buf);
218
219
  return -1;
220
}
221
222
/*
223
 * Remove a file's directory entry. Minimal implementation.
224
 */
225
int _unlink(char *name) {
226
  UNUSED(name);
227
228
  errno = ENOENT;
229
  return -1;
230
}
231
232
/*
233
 * Wait for a child process. Minimal implementation.
234
 */
235
int _wait(int *status) {
236
  UNUSED(status);
237
238
  errno = ECHILD;
239
  return -1;
240
}
241
242
/*
243
 * Write a character to a file. `libc' subroutines will use this system routine
244
 * for output to all files, including stdout.
245
 * Returns -1 on error or number of bytes sent.
246
 */
247
int _write(int file, char *ptr, int len) {
248
  int n;
249
250
  switch (file) {
251
  case STDOUT_FILENO: /*stdout*/
252
    for (n = 0; n < len; n++) {
253
      while ((USART1->SR & USART_FLAG_TXE) == (uint16_t)RESET) {
254
                //USART1->DR = (*ptr++ & (uint16_t)0x01FF);
255
            }
256
      USART1->DR = (*ptr++ & (uint16_t)0x01FF);
257
    }
258
    break;
259
  case STDERR_FILENO: /* stderr */
260
    for (n = 0; n < len; n++) {
261
262
    }
263
    break;
264
  default:
265
    errno = EBADF;
266
    return -1;
267
  }
268
  return len;
269
}

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

: Bearbeitet durch User
von foobar (Gast)


Lesenswert?

Ich hab keine Ahnung, wie das C-Library deines Systems aufgebaut ist. 
Eine Sache ist mir bei deiner Patcherei aber aufgefallen: der 
PUTCHAR_PROTOTYPE und die _write Routine sind nicht kompatibel.  Der 
Prototype schreibt das Zeichen in das TX-Register und wartet dann auf TX 
Empty, die _write Routine macht es umgekehrt.  Wenn nun direkt nach 
einem Aufruf von _write ein PUTCHAR folgt, wird das gerade übertragene 
Zeichen überschrieben.  Beide Routinen sollten die gleiche Reihenfolge 
benutzen.

von Stm M. (stmfresser)


Lesenswert?

seltsamerweise funktioniert printf mit einer Verzögerung mind. 200ms in 
main-Schleife.

Wenn man die Verzögerung rausnimmt, dann bekomme ich entweder Char-Brei 
oder die Hälfte, was man gesendet hat.

Als Compiler und Linker wird GCC ARM Embedded - Launchpad benutzt.

LG

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.