lpc1768 arm-non-eabi-gcc printf to uart0

Gast #4004048
Lesenswert?

Hi,

ich schlage mich jetzt schon 3 Tage mit dem Thema rum aber komme einfach 
nicht weiter :(

Eigentlich will ich mit meinem lpc1768 (Mini-DK2) einfach nur per printf 
etwas an den UART0 ausgeben.

Der UART ansich funktioniert wunderbar wenn ich direkt chars an 
LPC_UART)->THR schreibe.

Wie ich das Ganze verstehe muss ich damit printf funktioniert einige 
syscalls wie _write und _sbrk implementieren. Das habe ich auch versucht 
... leider ohne Erfolg.

Zuerst habe ich in meinem Linker Script die Grenzen fuer einen heap 
Bereich festgelegt ...
1
/* define heap size */
2
heap_size = 256;
1
    .heap :
2
    {
3

4
    _heap_start = .;          /* Heap starts directly after bss section */
5
    . = . + heap_size;      
6
    _heap_end = .;                /* Heap end definition */
7

8
    } > RAM

Und danach die _write und _sbrk (fuer malloc) implementiert ...
1
#include <errno.h>
2
#include <stdio.h>
3
#include <sys/types.h>
4
#include <sys/stat.h>
5

6
#include "lpc17xx.h"         /* for _get_PSP() from core_cm3.h*/
7

8
#undef errno
9
extern int errno;
10

11
extern char _heap_start;       /* Defined by the linker */
12
extern char _heap_end;         /* Defined by the linker */
13
static char *heap_curr = 0;
14

15
char* get_heap_end(void)
16
{
17
  return &_heap_end;
18
}
19

20
char* get_stack_top(void)
21
{
22
  return (char*) __get_MSP();
23
  // return (char*) __get_PSP();
24
}
25

26
int _write(int file, char *ptr, int len)
27
{
28
  int i;
29
  char *p = ptr;
30
  (void)file; /* avoid warning */
31

32
  for (i = 0; i < len; i++) {
33

34
    if ((*p) == '\n') {
35
      LPC_UART0->THR = '\r';
36
      while (!(LPC_UART0->LSR & (1U << 5)));
37
    }
38

39
    LPC_UART0->THR = (*p++);
40
    while (!(LPC_UART0->LSR & (1U << 5)));
41

42
  }
43

44
  return len;
45
}
46

47
caddr_t _sbrk(int incr)
48
{
49

50
  char *prev_heap_end;
51

52
  if (heap_curr == 0) {
53
    heap_curr = &_heap_start;
54
  }
55

56
  prev_heap_end = heap_curr;
57

58
  _write(1, "blabla\n", 7);
59
  return (caddr_t) prev_heap_end;
60

61
  char* top = get_stack_top();
62

63
#if 1
64
  if (heap_curr + incr > &_heap_end) {
65
    _write(1, "Heap Overflow!\n", 25);
66
  }
67
#endif
68

69
  heap_curr += incr;
70

71
  return (caddr_t) prev_heap_end;
72

73
}
74

75
int _close(int file)
76
{
77
  (void)file; /* avoid warning */
78
  return -1;
79
}
80

81
int _fstat(int file, struct stat *st)
82
{
83
  (void)file; /* avoid warning */
84
  st->st_mode = S_IFCHR;
85
  return 0;
86
}
87

88
int _isatty(int file)
89
{
90
  (void)file; /* avoid warning */
91
  return 1;
92
}
93

94
int _lseek(int file, int ptr, int dir) {
95
  (void)file; /* avoid warning */
96
  (void)ptr;  /* avoid warning */
97
  (void)dir;  /* avoid warning */
98
  return 0;
99
}
100

101
int _read(int file, char *ptr, int len)
102
{
103
  (void)file; /* avoid warning */
104
  (void)ptr;  /* avoid warning */
105
  (void)len;  /* avoid warning */
106
  return 0;
107
}

Leider rutsche ich jedesmal in die Heap <=> Stack Collition rein und 
mein eigentlicher Text wird nicht ausgegeben.

Hier meine main ...
1
#include <lpc17xx.h>
2
#include <stdio.h>
3

4
void initUART() {
5

6
  // setup uart0
7
  LPC_PINCON->PINSEL0 |= (1 << 4) | (1 << 6);
8
  LPC_UART0->LCR = 0x83;            // 8bit, no parity, 1 stop bit, DLAB=1
9
  LPC_UART0->DLL = 0x0D;            // divide by 13
10
  LPC_UART0->DLM = 0x00;
11
  LPC_UART0->LCR &= ~(0x01U << 7);      // disable DLAB
12
  LPC_UART0->IER |= (0x01U << 0);        // enable interrupt if data received
13
  LPC_UART0->FCR |= (0x01U << 0);        // enable fifo's
14
  LPC_UART0->FCR |= (0x02U << 6);        // interrupt if 8 char
15

16
  char* m = "Init Complete!\r\n";
17
  while(*m != '\0') {
18
    LPC_UART0->THR = *m++;
19
    while (!(LPC_UART0->LSR & (1U << 5)));
20
  }
21

22
  printf("test");
23
  printf("test");
24

25
}
26

27
int main(void) {
28

29
  SystemInit();
30
  SystemCoreClockUpdate();
31

32
  initUART();
33

34
  while(1) {
35

36
  }
37

38
  return 0;
39

40
}

Normalerweise sollte der Stack doch vom Ende des RAM's wachsen. Wieso 
habe ich dann schon bei einer 256Byte groesse des Heap eine collition?

Im Linker Script habe ich _stack_start = ORIGIN(RAM) + LENGTH(RAM); 
stehen.

Ich weis leider echt nicht mehr wo ich noch ansetzen soll.

Vielen Dank im voraus.
Angehängte Dateien:
#4004114
Lesenswert?

Mache den Heap größer. So 2048 Byte oder mehr. Wenn ich weniger 
einstelle, funktioniert bei mir nichtmal ein puts("abc"). Außerdem ist 
es guter Stil, in den ganzen anderen Syscall-Stubs errno passend zu 
setzen (ENOENT, EBADF oder EINVAL, notfalls ENOMEM).

Die Newlib puffert relativ kräftig. Wenn du deine Strings nicht mit \n 
abschließt, solltest du fflush(NULL) hinterherschießen, sonst wird dir 
u.U. nie was angezeigt.

Nachtrag: sbrk gibt den alten Wert des Breaks zurück, nicht den neuen. 
Und du solltest dir vielleicht mal den alten Break, den neuen Break und 
das Increment ausgeben lassen.

PS: Die ganzen "void(variable);" habe ich bei mir nicht, der Compiler 
spuckt trotzdem keine Warnungen dafür aus. Vermutlich optimiert er die 
Variablen direkt weg.
Gast #4004393
Lesenswert?

Hey,

vielen Dank fuer deine Hilfe!

Nachdem ich den heap vergroessert hatte funktioniert printf. Meine 
collition detection hat allerdings noch einen fehler iwo.

Zu meiner sbrk:

ich fuehre ja eine variable mit der aktullen heap Position (heap_curr) 
welche ich mit _heap_start initialisiere, welche aus dem linker script 
kommt. Und als return geht die aktuelle heap pos bevor dem addieren von 
incr zurueck. Von daher mache ich das ja wie du gesagt hast oder?

mit dem fflush hast du auch recht :) habs gerade verifiziert :D
#4004663
Lesenswert?

Ja. Ich fands nur etwas umständlich gelöst.
Grob aus dem Kopf (und ungetestet) sieht es bei mir so aus:
1
int _write(int file, char *ptr, int len)
2
{
3
  int todo = len;
4
  while(todo--) {
5
    if(*ptr == '\n')
6
      uart_putc('\r');
7
    uart_putc(*ptr++);
8
  }
9
  return(len);
10
}
11

12
extern const char _heap_start;
13
caddr_t _sbrk(int incr)
14
{
15
  static int heap_size = 0;
16

17
  if(&_heap_start + heap_size > HEAP_SIZE) {
18
    panic("out of memory");
19
  } else if(heap_size < 0) {
20
    panic("heap problem");
21
  }
22

23
  heap_size += incr;
24
  return((caddr_t)(&_heap_start + heap_size - incr));
25
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren