[De-Nut-Discussion] _read()
de-nut-discussion at egnite.de
de-nut-discussion at egnite.de
Fri Aug 20 21:43:14 CEST 2004
Hallo Herr Mausz,
Ethernut ist einfach zu schnell. :-) Aber grundsätzlich ist dies
kein Nut/OS-spezifisches Problem.
_read() wartet nicht, bis alle angeforderten Zeichen empfangen wurden,
sondern kehrt zurück, nachdem mindestens ein Zeichen im Empfangsbuffer
des Treibers steht. Sie müssen also _read() so oft aufrufen, bis Sie
alle 10 Zeichen empfangen haben. Das ist zwar lästig und wurde oft
kritisiert, ist aber kompatibel mit anderen I/O libs. Schließlich
sollen sich Nut/OS Programme genau so verhalten wie Programme unter
Linux oder Windows.
Noch ein Hinweis: Wenn Sie ausschließlich _read() und _write() verwenden,
paßt _open() besser. Sie ersparen sich damit das _fileno(). Ethernut
wird dann zwar noch schneller, aber Sie wissen ja jetzt, was Sie dagegen
tun müssen. :-)
Es gibt aber noch mehr Probleme...Half Duplex hat so seine Tücken.
_write() blockiert eben auch nicht, bis alle Zeichen tatsächlich
die serielle Schnittstelle verlassen haben. Noch nicht einmal
die Abfrage der noch im Sendebuffer des Treibers enthaltenen Zeichen
wäre zuverlässig, denn schließlich dürfen Sie erst umschalten, wenn
das Hardware Schieberegister im UART des ATmega das letzte Byte
inklusive Stopbit vollständig auf die Leitung gebracht hat. Beim
PC benötigen Sie dazu eine kleine Verzögerung, die aber natürlich
von der Baudrate abhängt.
Genialerweise arbeitet der USART Treiber von Nut/OS so, dass der
Receiver automatisch aktiviert wird, sobald das letzte Zeichen
im Puffer vollständig herausgeschoben wurde. Unabhängig von der
Baudrate. Versuchen Sie das mal mit einem RS232 nach RS485 Wandler
am PC...es geht nicht. Es gibt Wandler, die das ignorieren (böse,
böse) und bessere, bei denen man die Baudrate einstellt. Na ja,
nicht wirklich. Man stellt tatsächlich die Verzögerungszeit des
Umschalters ein.
Verwenden Sie devUsart0 oder 1, nicht den alten devUart. Im
Augenblick bleibt es Ihnen nicht erspart, den Treiber neu zu
compilieren, nachdem Sie
#define UART0_HDX_BIT 4
#define UART0_HDX_PORT PORTD
#define UART0_HDX_DDR DDRD
bzw. entsprechend für UART1 in modem.h definiert haben (ist mit
#if 0 ... #endif deaktiviert). Wie üblich, nach den Änderungen
einfach mit
make clean
make install
Nut/OS neu erstellen. Geht natürlich auch mit nutconf.
Wenn Sie dann in Ihrer Applikation den Half Duplex Modus mit
u_long flow = USART_MF_HALFDUPLEX;
_ioctl(_fileno(uart2), UART_SETFLOWCONTROL, &flow);
aktivieren, dann erledigt der Treiber das ganze Umschalten
automatisch. Prüfen Sie unbedingt den Rückgabewert von ioctl,
um sicher zu sein, dass Ihre Nut/OS Änderung auch tatsächlich
übernommen wurde.
Tut mir leid, dass noch niemand ein fertiges Beispiel zur
Verfügung gestellt hat. Ich selbst programmiere schon 48 Stunden
pro Tag und habe es trotzdem auch noch nicht geschafft, seufz.
Einige hilfreiche Geister haben aber zumindest dafür gesorgt, dass
der Treiber nach anfänglichen Schwierigkeiten auch zuverlässig
funktioniert.
Mit freundlichen Grüßen,
Harald Kipp
More information about the De-Nut-Discussion
mailing list