SerialPort OVERLAPP I/O error 997 WriteFile



  • Hallo Leute,

    ich habe mich hinsichtlich des Problems schon durch Google geackert, aber komme nicht weiter.
    Folgendes: Ich verbinde mich auf einen COM Schnittstelle, habe ein "listen" thread der auf neue Daten wartet, und gleichzeitig möchte ich daten senden. So generell funktioniert das auch, aber eben mit dem Fehler 997 I/O OVERLAPP Pending, was ja scheinbar "normal" ist wenn ich die Serielle Schnittstelle im OVERLAPPT mode verwendet?

    der listener (siehe thread func) wartet bei brav bis daten kommen

    auto i = WaitForSingleObject(_wait_o->hEvent, INFINITE);
    

    wenn ich die write funktion ausführe, bekomme ich auch direkt die "richtige" Antwort, und ich sehe auch dass die message von writeFile komplett ankam.. allerdings (writtenBytes= 0) also asychron.. vermutlich einfach ein normale verhalten bei OVERLAPPED mode!?

    hier mein Code (modifiziert zum fehler evaluieren) :

    
        std::string comPort("COM5");
        std::wstring stemp = std::wstring(comPort.begin(), comPort.end());
        LPCWSTR sw = stemp.c_str();
    
       HANDLE  comHandle = 0;
    
        DCB dcb;
       
        comHandle = CreateFile(
            sw,
            GENERIC_WRITE | GENERIC_READ,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
            NULL
        );
    
        if (!GetCommState(comHandle, &dcb))
            return false;
    
        dcb.BaudRate = CBR_38400; //9600 Baud
        dcb.ByteSize = 8; //8 data bits
        dcb.Parity = NOPARITY; //no parity
        dcb.StopBits = ONESTOPBIT; //1 stop
       
        if (!SetCommState(comHandle, &dcb))
            return;
    
          OVERLAPPED _wait_o = { 0 };
           _wait_o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
             
             if (_wait_o.hEvent == NULL)
             {
                  return 0;
              }
    

    listener (thread) :

    COMSTAT  stat;
       DWORD error, msk;
     
       SetCommMask(comHandle , EV_RXCHAR | EV_ERR);
    
       while (!s)
       {
           msk = 0;
           WaitCommEvent(comHandle , &msk,  &_wait_o); // non-block => OVERLAPPED MOE
    
           //Wait until comm has a event
           auto i = WaitForSingleObject(_wait_o.hEvent, INFINITE);
    
           if (i == WAIT_OBJECT_0)
           {
               ClearCommError(comHandle , &error, &stat);
    
               /* Exit loop */
               if (msk == 0 && s) 
               {
                   break;
               }
    
               /* read data */
               if (msk & EV_RXCHAR)
               {
                   ClearCommError(comHandle , &error, &stat);
    
                   std::unique_ptr<char[]> ReadBuf(new char[stat.cbInQue]);
             
                   DWORD actualReadLen;
                   if (!ReadFile(comHandle , ReadBuf.get(), stat.cbInQue, &actualReadLen, &_wait_o))
                   {
                       auto erro = GetLastError();
                       std::cout << "Read error: " << s << " " << erro << std::endl;
                       continue;
                   }
    
                   std::string s(ReadBuf.get(), stat.cbInQue);
    
                   std::cout << "Read event: " << s << " " << stat.cbInQue << std::endl;
               }
           }
       }
       std::cout << "Exit thread\n" << std::endl;
    }
    

    write:

    std::string s("set-do 0001");
    DWORD writtenBytes;
    bool res = WriteFile(hPort, s.c_str(), s.size(), &writtenBytes, &_wait_o);
    std::cout << "Write: " << s << "[" << std::to_string(res) << "] (" << writtenBytes << ")" << GetLastError() << "\n";
    

    Danke fürs reinschauen:=)



  • Entsprechend der Antwort in serial port WriteFile() error 997 overlap schau dir mal das MS MTTY Sample an. Eine aktuelle Version davon scheint mttty zu sein (dort dann den Code in Writer.c).

    Aber muß es denn unbedingt im OVERLAPPED-Modus sein (also möchtest du während des Schreibens noch andere Aktionen im selben Thread ausführen oder schreibst du viele Daten am Stück)?

    Edit: s.a. Serial Communications ("Reading and Writing" / "Overlapped I/O").



  • @Th69 sagte in SerialPort OVERLAPP I/O error 997 WriteFile:

    Entsprechend der Antwort in serial port WriteFile() error 997 overlap schau dir mal das MS MTTY Sample an. Eine aktuelle Version davon scheint mttty zu sein (dort dann den Code in Writer.c).

    ok schau ich mir an, danke dir 🙂

    @Th69 sagte in SerialPort OVERLAPP I/O error 997 WriteFile:

    Aber muß es denn unbedingt im OVERLAPPED-Modus sein (also möchtest du während des Schreibens noch andere Aktionen im selben Thread ausführen oder schreibst du viele Daten am Stück)?

    Das ist ne gute frage.. ich dachte ich bauche den OVERLAPPED Mode um auf neue daten horch zu können, und gleichzeitig daten schreiben können.. oder habe ich das falsch verstanden. Primär ist es wichtig, dass ich schnell auf neue daten reagiere.. schreiben tu ich nur sporadisch und wenige bytes...



  • In einer Multithread-Anwendung (mit jeweils Lesen und Schreiben in verschiedenen Threads) brauchst du i.d.R. kein OVERLAPPED-Modus (das ja nichts anderes als asynchrones Lesen bzw. Schreiben innerhalb eines Threads darstellt).

    Wenn du doch mal längere Daten senden willst, dann könntest du ja selber in einer Schleife (mit kurzer Zeitunterbrechnung) kleine Datenblöcke senden (quasi eine Queue), so daß der SerialPort nicht für längere Zeit fürs Lesen blockiert ist (kommt aber auch dann auf die Gegenstelle an, wie diese damit umgeht).



  • @Th69 sagte in SerialPort OVERLAPP I/O error 997 WriteFile:

    In einer Multithread-Anwendung (mit jeweils Lesen und Schreiben in verschiedenen Threads) brauchst du i.d.R. kein OVERLAPPED-Modus (das ja nichts anderes als asynchrones Lesen bzw. Schreiben innerhalb eines Threads darstellt).

    hmm ok, habe es aber so verstanden, dass wenn ich mit :

    WaitCommEvent(_serial_handle, &msk, _wait_o); // non-block => OVERLAPPED MOE
    
           //Wait until comm has a event
           auto i = WaitForSingleObject(_wait_o->hEvent, INFINITE);
    

    warten möchte , brauch ich den OVERLAPPED Mode, sonst muss ich ja zyklisch in ner loop den FileRead aufrufen!? is das gleich "agil" ?



  • Was soll denn dann der Unterschied sein, ob du jetzt bei WaitForSingleObject wartest oder bei WaitCommEvent?



  • @Th69 sagte in SerialPort OVERLAPP I/O error 997 WriteFile:

    Was soll denn dann der Unterschied sein, ob du jetzt bei WaitForSingleObject wartest oder bei WaitCommEvent?

    das habe ich so gemacht, weil ich OVERLAPP Mode machen wollte, und weil ich statt WaitForSingleObject
    die WaitForMultipleObjects verwende um auf ein zweites "listerne exit" event warten will..

    Aber wenn wenn ich während ich warte mit "waitCommEvent" auch aus nem anderen Thread aus schreiben kann, da ich es eben so verstanden habe, dass es nur mit OVERLAPPT ,versuche ich es mal anders..

    EDIT: Wenn ich das ganze ohne OVERLAPPED mache, dann block er mit bei WriteFile bis neue daten kommen, da will ich eben vermeiden...

    EDIT2: @Th69 ich hab mich durch das MTTY sample durchgehangelt, und siehe da, habe da async OVERLAPPT write funktion implementieren können. Danke dir.. aber so wie es aussieht hat die Write und Read funktionen jeweils einen eigenen OVERRLAPPT handle.. is das korrekt!?


Anmelden zum Antworten