Anzeige:
Ergebnis 1 bis 7 von 7

Thema: Segfault beim Ansprechen der seriellen Schnittstelle

  1. #1
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719

    Segfault beim Ansprechen der seriellen Schnittstelle

    Ich muss demnächst ein Gerät über die serielle Schnittstelle ansteuern. Dazuhab ich hier im Board schon diverse Threads gefunden und sogar ein Beispielprogramm, das ich ganz gut benutzen konnte. Ich hab das Beispiel jetzt aufgedröselt und in eine Qt-App verpackt. Leider ergibt sich das Problem, das ein Segfault auftaucht, den ich nicht nachvollziehen kann und GDB meldet auch nur, das er auf den Speicher an der Stelle 0xirgendwas nicht zugreifen kann. Der Segfault soll in der Methode QObject::recievers(const char*) auftritt, und zwar immer dann, wenn ich die Methode closePort aufrufe. Ich nehme stark an, das es nicht an tim->stop() liegt, weil ich das vorher nicht drinn hatte und der Fehler trotzdem auftrat. Erschwerend kommt hinzu, das ich den Quelltext zwar nachvollziehen kann, aber zum Teil nicht verstehe, warum der Originalautor das so und nicht anders gemacht hat. Entsprechende Stellen habe ich gekennzeichnet. Vielleicht kann sich jmd. einene Reim drauf machen, warum das so gemacht wurde. Ich verstehe z.B. nicht, warum lowlevel-DateiIO verwendet wurde. Mit Highlevel-DateiIO könnte ich aus dem FILE* ein QFile machen und wär fein aus dem Schneider. Ich bedanke mich schonmal im Vorraus für jegliche Mühen, weil ich finde, es ist schon recht viel von mir verlangt. Zum Testen verwende ich im Moment ein HandGPS, das nur Ascii-Daten rausgibt und als Flowcontroll Software nimmt (Kabel hat nur drei Adern). Wie man an den verschiedensprachigen Kommentaren sieht, hat der Autor woll auch ganz gut mit der Zwischenablage gearbeitet.

    Code:
    #include <qvbox.h>
    #include <qapplication.h>
    #include <qtextedit.h>
    #include <qtimer.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <qpushbutton.h>
    
    class TerminalWidget : public QVBox
    {
     Q_OBJECT
     public:
      TerminalWidget(QWidget* parent = 0);
      ~TerminalWidget();
    
     public slots:
      void readComData();
      void openPort();
      void closePort();
     private:
      QTextEdit* out;
      int fd;
      QTimer* tim;
      QPushButton* btnOpen, *btnClose;
      QString outbuffer;
    };
    
    TerminalWidget::TerminalWidget(QWidget* parent) : QVBox(parent), fd(0)
    {
     out = new QTextEdit(this);
     out->setTextFormat(LogText);
    
     btnOpen = new QPushButton("Open Port", this);
     btnClose = new QPushButton("Close Port", this);
    
     connect(btnOpen, SIGNAL(clicked()), this, SLOT(openPort()));
     connect(btnClose, SIGNAL(clicked()), this, SLOT(closePort()));
    
     tim = new QTimer(this);
     connect(tim, SIGNAL(timeout()), this, SLOT(readComData()));
    
    }
    TerminalWidget::~TerminalWidget()
    {
     closePort();
    }
    void TerminalWidget::openPort()
    {
        closePort() ;
    
        fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd < 0)
        {
            printf("FEHLER : Kann Port nicht Oeffnen : %d %s\n", errno, strerror(errno));
        }
        else
        {
            struct termios my_termios;
            tcgetattr(fd, &my_termios);
            tcflush(fd, TCIFLUSH);
            /* Baudrate und BIT-Flags werden hier gesetzt */
            my_termios.c_cflag = B4800 | CS8 |CREAD | CLOCAL | HUPCL | IXON | IXOFF;
            cfsetospeed(&my_termios, B4800);
            tcsetattr(fd, TCSANOW, &my_termios);
         }
     tim->start(10);
    }
    
    void TerminalWidget::closePort()
    {
     if (fd > 0)
     {
      tim->stop();
      close(fd); // <-- Das ist wohl was ganz böses
     }
    }
    
    void TerminalWidget::readComData()
    {
        int iIn;
        char buffer[4096];
        int iMax = 4096;
        if (fd < 1)
        {
        printf("FEHLER : Kein Port offen \n");
        return;
        }
    
        strncpy (buffer, "N/A", iMax < 4 ? iMax : 4); // <-- Wozu?
    
        /* Hier werden die Daten vom Port eingelesen */
        iIn = read(fd, buffer, 4095);
    
        if (iIn < 0)
        {
            if (errno == EAGAIN)
              return; // assume that command generated no response
            else
              printf("FEHLER : Lesefehler %d %s\n", errno, strerror(errno));
        }
        else
        {
            buffer[iIn<iMax?iIn:iMax] = '\0';
        }
        outbuffer.append(buffer);
    	out->setText(outbuffer);
    }
    
    #include "serial.moc.cpp"
    
    int main(int argc, char ** argv)
    {
     QApplication app(argc, argv);
     TerminalWidget tw;
     app.setMainWidget(&tw);
     tw.show();
     return app.exec();
    }

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    fd ist nicht initialisiert.
    Wenn du am Anfang von openPort() closePort() aufrufst und fd irgend ein Wert > 0 ist -> zack.

    Btw: QSocketNotifier könnte statt dem Timer auch gehen.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719
    Neinnein, einmal kann man das schon machen, dann sehe ich auch den Output von dem GPS. Aber wenn ich dann zumache -> zack

    QSocketNotifier würde ich gerne nutzen, das mit dem Timer finde ich auch höchst unelegant. Aber dazu müsste ich erstmal wissen, warum derjenige, der den Code geschrieben hat, lowlevel-fileio benutzt hat und nicht FILE*, aus dem man ja einfach ein QFile machen könnte. Vielleicht kann man auch erst die Portsettings setzen und die serielle schnittstelle dann direkt mit QFile öffnen?

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Original geschrieben von axeljaeger
    Neinnein, einmal kann man das schon machen, dann sehe ich auch den Output von dem GPS. Aber wenn ich dann zumache -> zack
    In dem Fall hast du am Anfang immer Glück.
    Wäre schon besser, die Variable auf einen sicheren Wert zu setzen, auch nach dem Close.


    Aber dazu müsste ich erstmal wissen, warum derjenige, der den Code geschrieben hat, lowlevel-fileio benutzt hat und nicht FILE*, aus dem man ja einfach ein QFile machen könnte.
    Mit einem Filedescriptor kann man auch ein QFile aufmachen. QFile:pen(int, int)


    Vielleicht kann man auch erst die Portsettings setzen und die serielle schnittstelle dann direkt mit QFile öffnen?
    Möglich, die Frage ist, wie man da feststellt, ob was im Lesepuffer is, bzw. ob der Sendepuffer bereit ist.
    Vielleicht kann man ein QSocketDevice benutzen.

    Hab zum Thema folgendes Posting in qt-interest gefunden:
    http://qt-interest.trolltech.com/new...ad00332-0.html

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719
    Original geschrieben von anda_skoa
    In dem Fall hast du am Anfang immer Glück.
    Wäre schon besser, die Variable auf einen sicheren Wert zu setzen, auch nach dem Close.
    Auf 0 setzen zum Beispiel?

    Original geschrieben von anda_skoa

    Mit einem Filedescriptor kann man auch ein QFile aufmachen. QFile:pen(int, int)
    Das werd ich probieren
    Original geschrieben von anda_skoa

    Möglich, die Frage ist, wie man da feststellt, ob was im Lesepuffer is, bzw. ob der Sendepuffer bereit ist.
    Vielleicht kann man ein QSocketDevice benutzen.
    Was ich heut noch alles probieren möcht...
    Das werd ich probieren
    Original geschrieben von anda_skoa

    Hab zum Thema folgendes Posting in qt-interest gefunden:
    http://qt-interest.trolltech.com/new...ad00332-0.html
    Das QExtSerial kenne ich, das kompiliert bei mir nicht und ich warte seit Mittwoch abend auf eine Mail vom Autor.

  6. #6
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Original geschrieben von axeljaeger
    Auf 0 setzen zum Beispiel?
    -1, 0 ist ein gültiger fd.


    Das QExtSerial kenne ich, das kompiliert bei mir nicht und ich warte seit Mittwoch abend auf eine Mail vom Autor.
    Eventuell hilft ein Blick in den Source von KDE Programmen, die Serial benutzen.
    KPilot, Kandy, etc.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  7. #7
    Registrierter Benutzer
    Registriert seit
    08.07.2002
    Beiträge
    719
    Ic hab Post vom Autor von QExtSerial bekommen. Die Library kompiliert jetzt, ich hab sie aber noch nicht ausprobiert. QExtSerial stellt ein QIODevice zur Vefügung, genauso wie ein QFile auch ein QIODevice wäre. Deswegen glaube ich kaum, das ich um den Timer herumkommen werde.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •