Forum: Mikrocontroller und Digitale Elektronik stdio retargeting probleme


von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hi Leutz,

kann mir hier jemand helfen?

Ich habe auf dem LPC2148 ein kleines retarget-system aufgesetzt, a la'
1
  FILE *fp_uart0=0;
2
  FILE *fp_uart1=0;  
3
  
4
  // initialises UART0 and gives a handle back
5
  fp_uart0 = th_fopen("uart0", "rw");
6
  if(!(fp_uart0))  return(-1);    // leave main if NULL-Pointer!
7
  
8
  // initialises UART1 and gives a handle back
9
  fp_uart1 = th_fopen("uart1", "rw");
10
  if(!(fp_uart1))  return(-1);    // leave main if NULL-Pointer!
was auch so weit funktioniert.
Damit kann ich dann
1
fprintf(fp_uart0, "text");

verwenden, da die fputc das eigendliche retargeting übernimmt und die 
fprintf den pointer scheinbar nur durchreicht:
1
int fputc(int c, FILE *f)
2
{
3
  f->functionpointer(c);  
4
  return(c);
5
}

Entweder habe ich die Funktionsweise des pointers stdout nicht 
verstanden, oder aber hier liegt was anderes im argen:
1
// Set up stdout
2
  stdout = th_fopen("uart0", "rw");
3
  if(!(stdout))  return(-1);    // leave main if NULL-Pointer!
Das funktioniert nicht,
error:  #137: expression must be a modifiable lvalue


aber
1
fprintf(stdout, "text");
funktioniert, bzw.
1
stdout->functionpointer=u0_putchar;
funktioniert auch ...

Die stdio im Keil/ARM-Compiler erstellt FILE als Typ von __FILE, was man 
dann selbst den eigenen Wünschen nach implementieren kann.
1
struct __FILE
2
{
3
    int handle;
4
    // Add whatever you want here
5
    int (*functionpointer)(int);
6
};

Weiss hier jemand Rat?

Eigendlich wollte ich weiterhin die fopen verwenden, und eine _sys_open 
implementieren. Leider schimpft der linker, trotz Implementierung der 
_sys_open, dass ich die nicht geschrieben hätte...


Leider findet man diesbezüglich auch nur recht spärlich Informationen im 
Netz...



Greetz,
/th.

von Karl H. (kbuchegg)


Lesenswert?

> Entweder habe ich die Funktionsweise des pointers stdout nicht
> verstanden, oder aber hier liegt was anderes im argen:// Set up stdout
>   stdout = th_fopen("uart0", "rw");
>   if(!(stdout))  return(-1);    // leave main if NULL-Pointer!
> Das funktioniert nicht,
> error:  #137: expression must be a modifiable lvalue
>
>
> aber
>   fprintf(stdout, "text");
> funktioniert, bzw.stdout->functionpointer=u0_putchar;
> funktioniert auch ...

dann wird wohl stdout als

  const FILE* stdout = .....;

irgendwo definiert sein, woduch er nicht mehr 'modifiable' ist.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hiho,


vielen Dank für den schnellen Hinweis!


kann man da nen override machen?
Ich möchte/muss den pointer verbiegen, aber nicht mit
1
stdio->functionpointer=u0_putchar;
verbiegen, sondern über (m)eine (th_)fopen mit
1
stdio = th_fopen(...);


Oder gibt es einen "redirect"-befehl, mit dem ich den stdio-pointer neu 
setzen kann?

Gerade gefunden:
1
#define stdout (&__CLIBNS __stdout)
2
   /* pointer to a FILE object associated with standard output stream */
in den Tiefen des Keil/ARM Compilersystems ;-)

Und was mich auch wundert, ist stdout vom Typ FILE oder FILE*? Meine 
Pointer sind alle vom Typ FILE*, und funktionieren.
1
extern FILE __stdin, __stdout, __stderr;
2
...
3
#undef __CLIBNS
4
    #ifdef __cplusplus
5
      namespace std {
6
      #define __CLIBNS ::std::
7
        extern "C" {
8
    #else /* ndef __cplusplus */
9
      #define __CLIBNS
10
    #endif /* ndef __cplusplus */
aus einem der standard-header.
Wenn ich's richtig lese, verschwindet das CLIBNS und das & bleibt als 
adressoperator zurück... also hätten wir die Typen
1
FILE __stdout 
2
FILE *stdout
? Von const oder so find ich allerdings nix, bekomme aber trotzdem die 
Meldung "unmodifiable L-Value"...



Ist das oben eigendlich stdio-konform angewandt, oder "vergewaltige" ich 
hiermit das system?


VG,
/th.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

kennt jemand ein gutes tutorial zu diesem thema?

von Karl H. (kbuchegg)


Lesenswert?

Thorsten De buhr wrote:
> Ich möchte/muss den pointer verbiegen, aber nicht mit
>
1
> stdio->functionpointer=u0_putchar;
2
>
> verbiegen, sondern über (m)eine (th_)fopen mit
>
1
> stdio = th_fopen(...);
2
>
>
>
> Oder gibt es einen "redirect"-befehl, mit dem ich den stdio-pointer neu
> setzen kann?

Wenn es wirklich ein const Pointer ist (worauf die Fehlermeldung
hindeuten würde), dann kannst du das const natürlich auch
wegcasten.
Aber ganz ehrlich:
Ich würde mich da nicht dran vergreifen.

>
> Und was mich auch wundert, ist stdout vom Typ FILE oder FILE*?

Ja das hat mich auch schon etwas gewundert.
Als ich das letzte mal an stdout, stdin, stderr drann war
(mindestens 15 Jahre her, auf einem PC) da waren das eigentlich
nur Zahlenwerte: 1, 2, 3

>
1
> extern FILE __stdin, __stdout, __stderr;
2
> ...
3
> #undef __CLIBNS
4
>     #ifdef __cplusplus
5
>       namespace std {
6
>       #define __CLIBNS ::std::
7
>         extern "C" {
8
>     #else /* ndef __cplusplus */
9
>       #define __CLIBNS
10
>     #endif /* ndef __cplusplus */
11
>
> aus einem der standard-header.
> Wenn ich's richtig lese, verschwindet das CLIBNS und das & bleibt als
> adressoperator zurück... also hätten wir die Typen
>
1
> FILE __stdout
2
> FILE *stdout
3
>

Dann wird das Keil wohl anders gelöst haben

> ? Von const oder so find ich allerdings nix, bekomme aber trotzdem die
> Meldung "unmodifiable L-Value"...

Schwer zu sagen. Diese Fehlermeldung würde eigentlich auf so etwas
hindeuten: Ein konstanter Pointer, der klarerweise nicht modifiziert
werden kann.

> Ist das oben eigendlich stdio-konform angewandt, oder "vergewaltige" ich
> hiermit das system?

Ich würde hier eher zu 'vergewaltigen' tendieren.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hmmm ...

ich denke eher nicht an "vergewaltigen, denn (Auszug aus der Doku):
1
fprintf(& __stdout, ...)
2
3
where __stdout has type __FILE.

also scheine ich doch gar nicht so weit weg vom richtigen weg zu sein?

von Thorsten de Buhr (Gast)


Lesenswert?

any further ideas?

von Bernd S. (mms)


Lesenswert?

hast du das problem schon lösen können?

Bernd

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.