DEUTSCHE VERSION |
|
Links | | | Forums | | | Comments | | | Report news |
Chat | | | Polls | | | Newsticker | | | Archive |
amiga-news.de Forum > Programmierung > SDCMD_QUERY-io_Actual | [ - Search - New posts - Register - Login - ] |
-1- | [ - Post reply - ] |
2007-01-16, 17:12 h MaikG Posts: 5172 User |
Wie verwendet man SDCMD_QUERY richtig? Ich rufe es auf um zu erfahren wieviel Bytes im Puffer sind, sind es nicht soviele wie ich erwarte rufe ich es wieder auf, solange bis die gewünschte Anzahl von Bytes da ist. Auf meinem 060 ist das auch gar kein Problem, aber auf einem 020 geht das nicht, da kommt eine zeit gar nichts an und dann scheint es einen Buffer overflow zu geben, wo dann nur noch müll rauskommt. Im NDK hab ich gelesen(serial.device) man soll Query aufrufen und wenn nichts da ist einen 1 Byte Read Request schicken und dann nochmal Query aufrufen. Da steht aber das es der beste weg ist, aber ist das auch Pflicht? [ - Answer - Quote - Direct link - ] |
2007-01-16, 17:41 h VMC Posts: 115 User |
Hallo MaikG, es ist so wie du oben beschrieben hast aus dem NDK. Über das Query abfragen wieviel schon im Puffer des Treibers an Daten liegt. Wenn es genug sind einfach einen READ mit der Anzahl schicken die du brauchst. Die meisten Programme handlen das indem Sie einen READ für 1 Zeichen schicken, wenn der vom Device in erhalt ausreichender Daten quitiert wird den READ nochmal schicken mit der Anzahl von Daten auf die du noch wartest. Die Idee dahinter ist aufwendiges Pollen des Puffers zu verhindern und sich quasi wecken zu lassen wenn der 1 Zeichen READ Request erledigt ist. Wenn man das noch verfeinert kann man parallel zu dem READ auch noch einen eigenen Timer Request laufen lassen um hierüber einen Timeout zu implementieren. Mit freundlichen Grüßen, Harald Frank [ - Answer - Quote - Direct link - ] |
2007-01-16, 18:05 h geit Posts: 332 [Former member] |
Ich schätze mal der Grund warum Du Probleme auf dem 020 bekommst ist das Polling, das Du durch den ständigen Query erzeugst. Dein Task schluckt die Rechenzeit und wenn der Devicetask mal dran kommt, ist der Buffer voll. Du solltest, wenn du schon eine auf query basierende Methode verwendest einen Timerwait oder Delay() durchführen. Generell ist folgendes zu bevorzugen, wenn man nicht warten will. (abstraiert) code:do{ if( CheckIO() ) { SendIO( CMD_READ, Length 1 ); } sigs = Wait( 1<<portsignal | SIGBREAKF_CTRLC ); if( sigs & (1<<portsignal) ) { if( CheckIO() ) { DoIO( SDCMD_QUERY ); if( actual ) { DoIO( CMD_READ, Length actual); total += actual; } } } } until( total >= wanted ); Ggf. natürlich nicht all actual bytes lesen, sondern nur noch die fehlenden Bytes. Es wird gewartet, bis 1 Byte gelesen wurde und dann nachgesehen, ob weitere Bytes anliegen, die man dann abholt. Wenn man sicher ist, dass mehrere Daten kommen, kann man natürlich statt einem Byte auch 100 oder 1000 lesen. Der Query sollte nur verwendet werden, um nicht mehr Daten zu lesen, als bereits vorhanden sind. Dinge wie While( actual < 100 ) { DoIO( SDCMD_QUERY ); } sollte man natürlich vermeiden, weil man eine Endlosschleife mit 100% Tasklast verursacht, bis alle Daten komplett eintreffen. Selbst mit einem Delay() dazwischen ist das nicht so clever. Mit dem asyncronen Lesen von einem Byte verhindert man, das man direkt in DoIO() wartet und zweitens bekommt man einen Trigger, der den eigenen Task bei eintreffen von Daten aufweckt. Einfach gesagt, mit SDCMD_Query fragt man nach der Anzahl der *NOCH* im Puffer verbliebenen Daten *NACH* einem CMD_READ Event. Geit [ - Answer - Quote - Direct link - ] |
2007-01-16, 19:21 h MaikG Posts: 5172 User |
>Über das Query abfragen wieviel schon im Puffer des >Treibers an Daten liegt. Wenn es genug sind einfach >einen READ mit der Anzahl schicken die du brauchst. Na dann bekomme ich einerseits einen enforcer Hit von der vmcresource.libarary und andererseit kommt nur 1 Byte zu wenig an hängt mein Programm und die Serielle Karte ist auch auf dem anderen Port blockiert. >Du solltest, wenn du schon eine auf query basierende Methode >verwendest einen Timerwait oder Delay() durchführen. Ja, aber nehmen wir an ich mache ein Delay und grade in der Zeit läuft der Puffer voll, ist doch dann das selbe. >Generell ist folgendes zu bevorzugen, wenn man nicht warten will. >(abstraiert) Also sowas ähnliches wie bei einem Fenster, das prinzip kann ich erkennen, aber wie man nun wirklich auf einem Port wartet weiss ich nicht. >Einfach gesagt, mit SDCMD_Query fragt man nach der Anzahl der *NOCH* im Puffer verbliebenen Daten *NACH* einem CMD_READ Event. Wenn jetzt aber 0 Bytes ankommen, weil meinetwegen einer das kabelrauszieht hängt das auch. [ - Answer - Quote - Direct link - ] |
2007-01-16, 22:39 h VMC Posts: 115 User |
@MaikG: >Na dann bekomme ich einerseits einen enforcer Hit von der >vmcresource.libarary und andererseit kommt nur 1 Byte zu >wenig an hängt mein Programm und die Serielle Karte ist auch >auf dem anderen Port blockiert. hui, das ist doch schon mal eine Information Also, von dem was du bisher geschrieben hast und der Info hier würde ich sagen da ist irgendwie der von dir verwendete IORequest Kaputt oder nicht richtig initialisiert worden. Wie genau erstellst du deinen IORequest? Hast du evtl. ein Stück Sourcecode, weil vieleicht ist es nur ein einfacher Fehler den man leicht sehen kann Mit freundlichen Grüßen, Harald Frank [ - Answer - Quote - Direct link - ] |
2007-01-16, 22:42 h geit Posts: 332 [Former member] |
Zitat: Nein, eben nicht. Du startest mit SendIO einen ReadRequest von 1 Byte. Der SendIO() kehrt *sofort* zurück, darum machen wir das ja. DoIO() wartet gnadenlos bis zum Ende und wenn jemand das Kabel zieht ist das Programm tod. Ob jemand das Kabel sieht oder nicht ist hier egal. Alles was du braucht ist ein Timer, den du zusätzlich vor dem Transfer startest und mit dem gleichen Wait() abfragst. Das habe ich mit dem Control-C oben angedeutet. Du kannst den Kram zu jederzeit abbrechen mit einem Timer würde dieses Abbrechen automatisch nach einiger Zeit passieren. Wenn der Request ageschlossen ist und SDCMD_Query 200 Bytes ausgibt, dann ist ein CMD_READ über 200 Bytes sicher und zwar egal ob jemand ein Kabel zieht oder nicht. Die Daten sind ja schon im Rechner angekommen. Zitat: Nein, ich meine nicht einen Delay von Sekunden oder so, sondern einen Delay(1). Der verhindert, das der Task 100% Systemlast bekommt. Für Testzwecke zu empfehlen, aber für die finale Benutzung ehr nicht. Geit [ - Answer - Quote - Direct link - ] |
2007-01-16, 23:41 h MaikG Posts: 5172 User |
>Also, von dem was du bisher geschrieben hast und der >Info hier würde ich sagen da ist irgendwie der von >dir verwendete IORequest Kaputt oder nicht richtig >initialisiert worden. code:Sub OpenSerialDevice port& = CreateMsgPort&() SerIO&=CreateIORequest&(port&,IOExtSer_sizeof%) POKEB(SerIO&+io_ReadLen%), 8 POKEB(SerIO&+io_WriteLen%),8 device& = OpenDevice&(SADD(dev$), Unit&, SerIO&, 0&) IF device&<>0 THEN Fehlerausgabe("Kann "+LEFT$(dev$,LEN(dev$)-1)+" Unit"+STR$(unit&)+" nicht öffnen"):EXIT SUB POKEW(SerIO&+IORequestio_Command%), SDCMD_SETPARAMS& POKEL(SerIO&+io_Baud%), 115200 POKEL(SerIO&+io_RBufLen%), 32768 POKE(SerIO&+io_StopBits%), 1 IF DoIO&(SerIO&) THEN Fehlerausgabe("Kann Serial Parimeter nicht setzten"):EXIT SUB End Sub FUNCTION SerInput&(BYVAL laenge&, buffer&) LOCAL in& t!=TIMER 10 IF TIMER-t!>2 THEN EXIT FUNCTION POKEW(SerIO&+IORequestio_Command%), SDCMD_QUERY& junk&=DoIO&(SerIO&) 'Query Ist immer erfolgreich(NDK) in&=PEEKL(SerIO&+IOStdReqio_Actual%) IF in&>=laenge& OR in&>0 AND TIMER-t!>1 THEN POKEW(SerIO&+IORequestio_Command%), CMD_READ& POKEL(SerIO&+IOStdReqio_Length%),MIN(laenge&,in&) POKEL(SerIO&+IOStdReqio_Data%), buffer& IF DoIO&(SerIO&) THEN Fehlerausgabe("Fehler DOIO4"):EXIT FUNCTION ELSE GOTO 10 END IF SerInput&=MIN(laenge&,in&) END FUNCTION >Wie genau erstellst du deinen IORequest? Hast du evtl. >ein Stück Sourcecode, weil vieleicht ist es nur ein >einfacher Fehler den man leicht sehen kann Ja, klar, ist aber Basic. Diese Methode mit dem Anfordern der Byteanzahl die benötigt wird zeigt die selbe Fehlfunktion. >Nein, eben nicht. Du startest mit SendIO einen ReadRequest >von 1 Byte. Der SendIO() kehrt *sofort* zurück, darum machen wir >das ja. DoIO() wartet gnadenlos bis zum Ende und wenn jemand das >Kabel zieht ist das Programm tod. Ja, SendIO, aber wie warte ich auf das SendIO denn? Fenster ist so: code:junk&= xWait&(1& << PEEKB(PEEKL(win&+UserPort%)+mp_SigBit%)) >Nein, ich meine nicht einen Delay von Sekunden oder so, sondern >einen Delay(1). Der verhindert, das der Task 100% Systemlast >bekommt. Für Testzwecke zu empfehlen, aber für die finale Benutzung >ehr nicht. Ich habe Delay 1, 5 und 10 Probiert, immer das selbe. Dann hab ich die Taskpriorität des Programms auf -1 und -5 geändert, nicht erfolgreich. Immerhin konnte ich durch das abschalten aller Caches das ganze auf meinem 68060 System reproduzieren. [ - Answer - Quote - Direct link - ] |
2007-01-17, 00:39 h geit Posts: 332 [Former member] |
Zitat: Genauso. Du hast ja den Port für den IOrequest allokiert. Den benutzt du genauso. code:junk&= xWait&(1& << PEEKB(PEEKL(win&+UserPort%)+mp_SigBit%) | 1& << PEEKB(PEEKL(port%)+mp_SigBit%)) Ist jetzt warscheinlich falsch, aber dieses Basic &% Zeugs versteh ich nicht wirklich. Du verschiebst eine 1 um die Signalnummer aus dem Port vom IORequest. Diese Maske oderst du z.B. zu dem Wert , den du aus dem Fensterport emittelst. Dann wartet der Wait() auf beide Signale. Mit dem junk Feld und dem Masken Wert kannst du dann geziehlt Abfragen, ob eines oder mehere der Signale aktiv sind und entsprechend handeln. Zitat: Sollte nicht sein. Wo hast du den eingebaut. Der sollte in "Zeile 10" oder direkt vor dem Goto nach 10 liegen, um bei jedem Schleifenumlauf zu wirken. Wie gesagt diese Lösung ist nicht perfekt und tuagt allenfalls für Testzwecke (wenn man keinen timer öffnen will). Geit [ - Answer - Quote - Direct link - ] |
2007-01-17, 03:26 h Holger Posts: 8116 User |
Zitat: foo& ist eine 32 Bit Variable, bar% eine 16 Bit Variable. Dass die MB-includes mal das ein und mal das andere benutzen, ist nicht wirklich immer begründbar. Es gibt jedenfalls keine Unterschiedung zwischen Pointer und 32 Bit-Integer. PEEKL(win&+UserPort%) ist vergleichbar mit win->UserPort in C und fällt für den Device-Port komplett weg. Und dann gibt's vermutlich kein | in Basic, aber es gibt definitiv OR. Also: code:junk&= xWait&((1& << PEEKB(PEEKL(win&+UserPort%)+mp_SigBit%)) OR (1& << PEEKB(port&+mp_SigBit%))) mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2007-01-17, 04:09 h VMC Posts: 115 User |
@MaikG: hallo und um das ganze ein wenig besser zu verstehen, welches Device verwendest du denn genau (inkl. Version) und welche Schnittstelle auf welchem Rechner versuchst du damit anzusprechen? Mit freundlichen Grüßen, Harald Frank [ - Answer - Quote - Direct link - ] |
2007-01-17, 10:29 h MaikG Posts: 5172 User |
>Genauso. Du hast ja den Port für den IOrequest allokiert. Den >benutzt du genauso. Stimmt, irgendwo müsste ich noch ein Beispiel für "auf Port warten" haben. Aber leider ist Query nicht das Problem, ich habs komplett rausgenommen und immer genau die menge Byte angefordert die ich brauche. >Ist jetzt warscheinlich falsch, aber dieses Basic &% Zeugs versteh >ich nicht wirklich. % = integer & = Long >Sollte nicht sein. Wo hast du den eingebaut. Der sollte in "Zeile 10" >oder direkt vor dem Goto nach 10 liegen, um bei jedem Schleifenumlauf >zu wirken. Wie gesagt diese Lösung ist nicht perfekt und tuagt >allenfalls für Testzwecke (wenn man keinen timer öffnen will). vor dem Goto 10. >hallo und um das ganze ein wenig besser zu verstehen, >welches Device verwendest du denn genau (inkl. Version) >und welche Schnittstelle auf welchem Rechner versuchst >du damit anzusprechen? hyperCOM3.device 2.98 (24.12.00) SilverSurfer 2.104 (13.11.00) serial.device 43.7 (25.02.02) Obwohl das letzte für diese Baudrate ungeignet ist liefert es die Daten die am nächsten am Original sind. Rechner ist nicht wichtig 68060 @60MHZ, 68030 @50MHZ, 68020 @14MHZ. Auf dem 060 mit Caches an geht es, ohne caches nicht, sowie auf den anderen. Der Datenaufbau ist folgender 0-807 Okay 807-3899 &hFF Fehlerhaft Ende der Datei an falscher Position und unbekanntes 11612-20283 &hFF Fehlerhaft Ende der Datei an falscher Position und unbekanntes 27996-36667 &hFF Fehlerhaft Ende der Datei an falscher Pos und unbek. usw. Der Serial buffer hat 32768, von daher dürften die Daten erst ab da falsch sein beim buffer Overrun. [ - Answer - Quote - Direct link - ] |
2007-01-17, 16:36 h Holger Posts: 8116 User |
@MaikG: So, wie ich das verstehe, soll Deine FUNCTION SerInput& einen Wert zurückliefern, wohl die Anzahl gelesener bytes. Ich sehe aber mindestens zwei EXIT FUNCTION Anweisungen, bei denen keinerlei Rückgabewert angegeben wird. Was wird da an den Aufrufer zurückgegeben? Schon mal überprüft? Außerdem beginnt Deine Funktion bereits mit t!=TIMER 10 IF TIMER-t!>2 THEN EXIT FUNCTION Auch wenn die Wahrscheinlichkeit sehr gering ist, dass zwischen diesen Anweisungen 2 Sekunden vergehen, ist es doch eine Annahme, die man in einem Multitasking-System nicht treffen sollte. Schon gar nicht, wenn man Probleme auf langsamen Rechnern, die zudem mit serieller Daten bombardiert werden, feststellt. Die Routine sollte wenigstens einmal abgefragt haben, ob Daten anliegen, unabhängig von der Systemzeit. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2007-01-17, 18:30 h MaikG Posts: 5172 User |
>@MaikG: >So, wie ich das verstehe, soll Deine FUNCTION SerInput& einen Wert >zurückliefern, wohl die Anzahl gelesener bytes. Ich sehe aber >mindestens zwei EXIT FUNCTION Anweisungen, bei denen keinerlei >Rückgabewert angegeben wird. Was wird da an den Aufrufer >zurückgegeben? Schon mal überprüft? Bei MB ist das dann ein wert im Negativen bereich. Bei einigen sachen im Programm wird die Länge überprüft, wenn diese unerwartet ist wird eine Fehlermeldung ausgegeben. Der rest prüft die länge gar nicht und daher macht Negativ dann auch nichts. >Außerdem beginnt Deine Funktion bereits mit >t!=TIMER >10 IF TIMER-t!>2 THEN EXIT FUNCTION >Auch wenn die Wahrscheinlichkeit sehr gering ist, dass zwischen >diesen Anweisungen 2 Sekunden vergehen, ist es doch eine Annahme, >die man in einem Multitasking-System nicht treffen sollte. >Schon gar nicht, wenn man Probleme auf langsamen Rechnern, die >zudem mit serieller Daten bombardiert werden, feststellt. Ja, das stimmt, ich werde das mal korregieren. [ - Answer - Quote - Direct link - ] |
2007-01-17, 19:20 h Holger Posts: 8116 User |
Zitat: Irgendein Wert im negativen Bereich?! Steht das so im Handbuch oder irgendeiner Spezifikation? Oder nimmst Du an, dass er immer negativ ist, nur weil der nicht initialisierte, sprich zufällige Wert bei Deinem ersten Test gerade negativ war? mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Answer - Quote - Direct link - ] |
2007-01-17, 21:40 h MaikG Posts: 5172 User |
>Irgendein Wert im negativen Bereich?! Steht das so im Handbuch oder >irgendeiner Spezifikation? Ich hab das kürzlich bei einem anderen Programm ausprobiert, da war der Rückgabewert undefiniert und ich bekam immer die gleiche Zahl. Also ich hab mein Programm jetzt normal Optimiert, auch den Cluser von 1024 Bytes auf 2048,4096, 8192 und 16384 erhöht ohne erfolg. Interressant ist der Serial Puffer zustand: Puffer Angeforderte Bytes 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 2 2 0 217 0 217 0 217 0 217 0 217 0 217 0 217 0 217 - ca. Hier stragniert der Statusbalken was normal 185301 217 - nicht so ist, Maus cursor hängt in der Zeit 185084 807 184277 8192 176085 8192 usw. Einmal ist der Serialpuffer auf 31k eingestellt und sollte daher 1853084 nie erreichen können. Dann ist fraglich warum an dieser stelle auf einmal so eine CPU Last ist und warum der Puffer dann nicht gelert werden kann. [ - Answer - Quote - Direct link - ] |
-1- | [ - Post reply - ] |
amiga-news.de Forum > Programmierung > SDCMD_QUERY-io_Actual | [ - Search - New posts - Register - Login - ] |
Masthead |
Privacy policy |
Netiquette |
Advertising |
Contact
Copyright © 1998-2024 by amiga-news.de - all rights reserved. |