Forum: Compiler & IDEs Probleme mit fdevopen


von T.v.B. (Gast)


Lesenswert?

Hallo,

ich versuche gerafe mit printf und scanf Zeichen über meinen Uart zu
senden und zu empfangen. Ich habe dazu folgenden Sourcecode wieder
ausgegraben.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <avr/io.h>
4
#include <string.h>
5
#include <avr/interrupt.h>
6
#include <avr/signal.h>
7
8
static int  UART_SendByte(char Data_c);
9
static int  UART_ReceiveByte(void);
10
static void UART_Init(void);
11
12
#define UART_CPU               16000000     /* 16MHz */
13
#define UART_BAUD_RATE         19200       /* baud rate*/
14
#define UART_BAUD_SELECT       (UART_CPU/(UART_BAUD_RATE*16l)-1)
15
16
unsigned char   UART_Ready_uc;
17
unsigned char   UART_ReceivedChar_uc;
18
unsigned char   UART_RxChar_uc;
19
20
21
int main(void )
22
{
23
    char c;
24
    UART_Init();            
25
    c = UART_ReceiveByte(); /*funktioniert*/
26
    UART_SendByte(c);       /*funktioniert*/
27
    fdevopen(UART_SendByte,UART_ReceiveByte,0);
28
    printf("Hello, world!\n"); /*funktioniert nicht*/
29
30
    scanf("%c", &c); /*funktioniert nicht*/
31
    printf("%c",c);  /*funktioniert nicht*/
32
    while(1);
33
34
}
35
36
void UART_Init(void)
37
{
38
    UART_Ready_uc        = 1;
39
    UART_ReceivedChar_uc = 0;
40
    UCSR0B |= _BV(RXCIE)|_BV(TXCIE)|_BV(RXEN)|_BV(TXEN);
41
    UBRR0L |= UART_BAUD_SELECT;
42
    sei();
43
}
44
45
int UART_SendByte(char Data)
46
{
47
    while (!UART_Ready_uc || (PINE & _BV(PE2)));
48
    UART_Ready_uc = 0;
49
    UDR0 = Data;
50
    return 0;
51
}
52
53
int UART_ReceiveByte(void)
54
{
55
    while (!UART_ReceivedChar_uc);
56
    UART_ReceivedChar_uc = 0;
57
    return UART_RxChar_uc;
58
}
59
60
61
SIGNAL(SIG_UART0_RECV)
62
{
63
    UART_ReceivedChar_uc = 1;
64
    UART_RxChar_uc = UDR0;
65
}
66
67
SIGNAL(SIG_UART0_TRANS)
68
{
69
    UART_Ready_uc = 1;
70
}

Ich hatte vor einiger Zeit schon mal mit diesen Sourcen gearbeitet. Da
hatte es einwandfrei funktioniert .

Das Problem ist folgendes:

Die Funktionen zum senden und emfpangen funktionieren (UART_ReceiveByte
und UART_SendByte). Versuche ich aber mit fdevopen die printf oder die
scanf Funktion zu benutzen tut sich gar nichts auf dem UART.

Ich habe einen Atmega128 und einen JTAGICE + AVR Studio 4.12 zum
debuggen. Kompiliert habe ich das Ganze mit WinAVR-20040720.

Ich habe mal einen Haltepunkt in die UART_SendByte Funktion gesetzt und
dann versucht einen String mit printf auszugeben. Eigentlich hätte er
auf dem Haltepunkt landen sollen, tat er aber nicht.

Was mache ich falsch? So schwer kann das doch nicht sein!
Bin ziemlich ratlos und für jede Hilfe dankbar.

Vielen Dank schonmal
Gruß T.v.B.

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Leidgeplagter von Leidensgenossem,

würde ich Dein Listing hier durchlesen und finden, was wegen Änderung
an AVRGCC nicht mehr funktioniert, dann hättest Du bald die nächste
Frage und ich die nächste Arbeit.

Selbst ist der Mann.
Lies die stdio.h, aber Wort für Wort.
Und lies das libc_User Manual.

Ciao
Wolfgang Horn

von T.v.B. (Gast)


Lesenswert?

Hi Wolfgang,

habe mir die stdio.h angesehen und wüsste nicht was ich da falsch
gemacht haben könnte. Ich habe das Ganze inzwischen mit der aktuellen
GCC-Version übersetzt. Da hat es genauso wenig funktioniert.

Und ja, da ist der Aufruf von fdevopen etwas anders:
1
fdevopen(UART_SendByte,UART_ReceiveByte)
Das ist doch richtig, oder? Zumindest entnehme ich das so dem Manual

Und eine kleine Bemerkung am Rande.
Das beantworten von Fragen in Foren ist freiwillig.
Zu sagen: "würde ich Dein Listing hier durchlesen und finden, was
wegen Änderung an AVRGCC nicht mehr funktioniert, dann hättest Du bald
die nächste Frage und ich die nächste Arbeit"
Naja, ich sag mal so, das hilft mir nicht weiter. Zumindest sollte man
sich das Listing durchlesen bevor man antwortet. (imo)

Ich habe irgendwo in meinem Programm einen Fehler gemacht, ich finde
ihn aber nicht. Ich habe das fm gelesen, ich finde den Fehler immer
noch nicht. Wer etwas weiß, bitte melden.

Nichts für ungut
T.v.B.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Und ja, da ist der Aufruf von fdevopen etwas anders:
> ...
> Das ist doch richtig, oder?

Im Prinzip ja.  Aber die Funktionen bekommen nun auch noch ihren FILE
* als zweites Argument durchgereicht, welches du zur Vermeidung von
Compilerwarnungen dann bei dir als Dummy mit aufnehmen solltest.

Ansonsten denke ich, dass dein Problem darin besteht, dass du die in
den ISRs gesetzten Flag-Variablen nicht als "volatile" deklariert
hast.  Damit wird der Compiler den Zugriff auf diese in Schleifen wie:

while (!UART_ReceivedChar_uc);

aus der Schleife heraus optimieren, da sich nach seiner Einschätzung
am Wert von UART_ReceivedChar_uc innerhalb der Schleife ja nichts mehr
ändern kann.  Das ist übrigens die FAQ #1 in der avr-libc-Doku...

Apropos ISR: die solltest du jetzt schreiben als:

ISR(USART0_TX_vect) ...
ISR(USART0_RX_vect) ...

Bei interruptgesteuertem Versenden bietet es sich übrigens an, statt
USART0_TX_vect besser USART0_UDRE_vect zu benutzen: damit wird der
Interrupt bereits ausgelöst, wenn wieder Platz in Datenpuffer-Register
ist, sodass ein Versenden der Zeichen ,,Rücken an Rücken'' möglich
wird.  Das Handling ist aber geringfügig komplizierter, da man dann
zwischen ,,es sind gar keine Zeichen mehr zu versenden'' (UDRE-
Interrupt muss ausgeschaltet werden) und dem Sendebetrieb
unterscheiden muss.

von T.v.B. (Gast)


Lesenswert?

Hi Jörg,

das mit dem volatile ist mir im Nachhinein auch aufgefallen, aber auch
das war nicht das eigentliche Problem. Die Ursache liegt ja scheinbar
eine Ebene höher. Das Progamm sollte zumindest nach einem printf in der
UART_SendByte Funktion landen, egal was in dieser drin steht bzw. ob
diese richtig funktioniert. Laut Debugger ist das aber nicht der Fall.

Naja, ich werde das Problem erstmal ein bis zwei Nächte überschlafen um
mich diesem dann mit frischer Kraft und neuem Mut nochmal zu stellen.
;-)
(Man sollte meinen an der Stelle kann man nicht so viel falsch machen,
aber irgendwie habe ich es wohl trotzdem geschafft :-)

Trotdem vielen Dank für die Hilfe
Gruß T.v.B.

von Günter R. (galileo14)


Angehängte Dateien:

Lesenswert?

Hallo, T.v.B.,

versuch's doch mal so, wie ich's im Dateianhang üblicherweise mache
(kannst dann leicht an Deine Bedürfnisse anpassen).

printf würde ich nicht verwenden, sondern in Deinem Fall fprintf bzw.
die ganzen "f"-Funktionen, weil man da das Ausgabe-Device steuern
kann.

Viele Grüße
Günter

von T.v.B. (Gast)


Lesenswert?

@Günter R.

Yep, funktioniert!
Besten Dank also!

Bleibt halt immer noch immer noch die Frage warum meine Version nicht
funktioniert hat.
Naja, für den Moment ist es mir egal, werde mir bei Gelegenheit das
Problem noch mal zur Brust nehmen.
Zunächst reicht mir dieser "Workaround" jedoch völlig aus!

Nochmal Vielen Dank
Gruß T.v.B.

von Bernt (Gast)


Lesenswert?

Gleiches Problem:
Mit fdevopen bewirkt einen Reset,
aber mit fdev_setup_stream funktioniert es!

Hauptsache es gibt immer noch eine funktionierende
Methode ;-)

Bernt

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Mit fdevopen bewirkt einen Reset,

Klingt nach einem Problem mit malloc() dann.  Möglicherweise bist
du bereits an der RAM-Auslastungsgrenze dran.

von Bernt (Gast)


Lesenswert?

Tja,des Rätsels Lösung war Mega103-Kompatibilitäts-Fuse.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bernt wrote:

> Tja,des Rätsels Lösung war Mega103-Kompatibilitäts-Fuse.

Wenn du irgendwo mal die Stichworte ATmega64 oder ATmega128 hättest
fallen gelassen, wäre ich da vielleicht auch drauf gekommen.

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.