Hallo zusammen,
ich habe mit der aktuellsten Version das Problem, dass mir offensichtlich Daten im Buffer verloren gehen oder überschrieben werden.
Vorab:
Über einen Virtual
COM Port Treiber wird ein Gerät via USB angeschlossen. Schicke ich Daten an das Gerät, erfolgt von diesem eine Rückmeldung in einer bestimmten Art und Weise. Die ersten drei Zeichen, der sog. Kopfblock, enthält u.a. die Datenlänge. Diese wiederum bestimmt die Länge der nachfolgenden Daten.
In rudimentären Grundroutinen lesen ich zunächst die den Kopfblock aus und anhand der im Kopfblock übertragenen Länge anschliessend den Datenblock selbst.
Bsp. (stark vereinfacht):
Delphi-Quellcode:
const
HEADBLOCKSIZE = 3;
DATABLOCKSIZE = 4096;
var
Head_Block = array[1..HEADBLOCKSIZE] of char;
Data_Block = array[1..DATABLOCKSIZE] of char;
procedure GetHeadBlock;
begin
repeat
Application.ProcessMessages;
until (TimeoutFlag) or (ApdComPort.InBuffUsed >= HEADBLOCKSIZE);
if (not TimeoutFlag) then
begin
ApdComPort.GetBlock(Head_Block, HEADBLOCKSIZE);
end;
end;
procedure GetDataBlock(ASize: word);
begin
repeat
Application.ProcessMessages;
until (TimeoutFlag) or (ApdComPort.InBuffUsed >= ASize);
if (not TimeoutFlag) then
begin
ApdComPort.GetBlock(Head_Block, ASize);
end;
end;
Vorher wurde ein Timer gesetzt, der nach max. 3 Sek. anspringt und das TimeOutFlag auf TRUE setzt, so dass die Endlosschleife unterbrochen wird.
Diese (grob skizzierten) Routinen arbeiten eigentlich auch ganz wunderprächtig, so lange die Datenmenge zw. PC und Gerät rel. klein ist.
Nun sollen aber auch größere Datenmengen (Dateien) in Blöcke zu max. 4kB vom PC zum Gerät übertragen werden. Dazu wird über eine while not (EoF(...)) do die zu übertragene Datei in 4kB-Häppchen zerlegt und via ApdComPort.PutBlock an das Gerät übertragen.
Nachdem ein 4kB-Block übertragen wurde, warte ich über die beiden Routinen oben die Rückmeldung vom Gerät ab. Der Kopfblock bestimmt wieder die Länge der Rückmeldung und im Datenblock wiederum steht die Rückmeldung.
Leider kommt es mitunter und zu immer anderen Zeitpunkten vor, dass die Daten im InBuffer völlig zerschossen sind, wobei jedoch kurioserweise ein Mitschnitt auf dem USB-Port angibt, dass die Daten noch korrekt vom Gerät an die PC-Schnittstelle kommen. Der Mitschnitt bzw. die Hardware dazu ist ein Gerät, dass quasi in das USB-Kabel zw. Gerät und PC gehängt wird.
Ferner hatte ich festgestellt, dass es eine deutliche Besserung bringt, wenn ich in der while not (EoF(...)) do ein Delay von 30..40ms einbaue. De facto scheint es also irgendwo ein Buffer Overflow zu geben (meine Mutmassung).
Das
PDF-Handbuch zu AsyncPro beschreibt diesbzgl. auf S. 31ff ein "eventually overflow the PC's input buffer and data would be lost".
Ein Hardware Flow Control scheidet auf jeden Fall aus, doch auch ein Software Flow Control sowohl über die Einstellungen bei ApdCOMPort als auch in den
COM-Port Einstellungen über den Gerätemanager bringen nix. Ebenso wenig bringt ein 'Flushen' der beiden Buffer.
Fragen:
1) Ist meine Mutmassung bzgl. Buffer overflow richtig?
2) Hat jemand noch eine gute Idee, das Problem in den Griff zu bekommen?
Dank vorab und Gruß, Carsten