Forum: Mikrocontroller und Digitale Elektronik lpc1768 arm-non-eabi-gcc printf to uart0


von whoami (Gast)


Angehängte Dateien:

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.

von S. R. (svenska)


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.

: Bearbeitet durch User
von whoami (Gast)


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

von S. R. (svenska)


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
}

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.