Forum: Compiler & IDEs [AVR32] NGW100 - ttyS0 mit select() -> FD_SET Segmentation fault


von Uwe D. (Gast)


Lesenswert?

Hallo Leute,

habe folgendes Problem mit meinem Programm auf dem Atmel NGW100!

Ich kompiliere mein Programm mit "avr32-linux-g++ test.cpp -o test", 
wenn ich es auf dem NGW100 ausführe, bekomme ich ein 'Segemntation 
fault'.

Fehler
- steigt definitiv immer in Funktion main() bei 'FD_SET(fd, &read)' aus!

Fakten
- Quellcode läuft unter Ubuntu 9.10 wunderbar
- ist egal ob mit '-static' oder ohne kompiliert (mit avr32-linux-g++)
- Schnittstelle /dev/ttyS0 ist definitiv die richtige

Folgendes hab ich mal ausprobiert:

- wenn ich mir mal den Integer-Wert von 'fd' ausgeben lasse, bekomme ich 
bei meinem Ubuntu: fd = 3, auf dem Atmel: fd = 716345196 angezeigt, kann 
das sein?

Die Schnittstelle /dev/ttyS0 die ich nutzen will, wird ja Standardmäßig 
vom Bootloader und von der Linux-Konsole zur Ausgabe benutzt. Die 
Linux-Konsole habe ich für die serielle Ausgabe abgeschaltet (in 
/etc/inittab).
Sobald jetzt die Konsole angezeigt wird, kommt auf dem Hyperterminal - 
wie gewollt - kein Pups mehr an.

Muss ich denn vielleicht auch den Zugriff vom Bootloader ausschalten? 
Aber komme ich denn jemals wieder an den Bootloader ran?

Mein NGW100 läuft mit buildroot-2.3.0 von einer SD-Karte.


Hier mal mein Code, die Funktion zum auslesen von Daten an ttyS0, habe 
ich rausgenommen, weil er steigt ja eh vorher aus!
1
#include <stdio.h>
2
#include <string>
3
#include <unistd.h>
4
#include <fcntl.h>
5
#include <errno.h>
6
#include <stdlib.h>
7
#include <termios.h>
8
#include <unistd.h>
9
#include <sys/ioctl.h>
10
#include <sys/time.h>
11
#include <sys/types.h>
12
#include <iostream>
13
#include <fstream>    
14
#include <sys/select.h>
15
16
using namespace std;
17
18
int open_input_source(int);
19
int read_input_source(int, int);
20
21
int main() {
22
   int      fd;       // Var für Port
23
   fd_set   readfs;     // file desciptor für select-Subroutine
24
   int      loop=1;
25
   int      res, errorNpb = 0;
26
   struct   timeval Timeout;   // Konstrukt für Time-Out der select-Subroutine
27
   int      port=0;     // Port-Auswahl --> hier /dev/ttyS0
28
29
   ofstream npbLogFile("FILE_OUT.LOG",ios_base::trunc);
30
   if (npbLogFile.fail()) {
31
      cout << "\nFehler! Log-Datei konnte nicht erzeugt werden!\n" <<
32
        "Programmabruch!\n";
33
      exit(1);
34
   }
35
   npbLogFile.close();
36
37
   ofstream npbOutFile("FILE_OUT.001",ios_base::trunc);
38
   if (npbLogFile.fail()) {
39
      
40
      cout << "Programmabruch!\n";
41
      
42
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
43
      npbLogFile  << "time" << " Programmabruch!\n";
44
      npbLogFile.close();
45
      
46
      exit(1);
47
   }
48
   npbOutFile.close();
49
50
51
   /* Serielle Schnittstelle öffnen & konfigurieren */
52
   fd = open_input_source(port);
53
   
54
   /* Schleife zum einlesen von Daten an der Schnittstelle */
55
   while (loop) {
56
      
57
58
      Timeout.tv_usec = 0;   // Millisekunden
59
      Timeout.tv_sec  = 3;   // Sekungen
60
61
      /* Zeitstempel (YYYYMMDDHHMMSS) für LOG-Datei-Werte erzeugen und in Sting 'strTimestamp' ablegen */
62
      time_t Zeitstempel;
63
      struct tm *ltime;
64
      char strTimestamp[15];
65
      Zeitstempel = time(0);
66
      ltime = localtime(&Zeitstempel);
67
      strftime(strTimestamp, 15, "%Y%m%d%H%M%S", ltime);
68
69
      FD_ZERO(&readfs);     // geht
70
      FD_SET(fd, &readfs);   // <-- Segmentation fault
71
      
72
      res = select(fd+1, &readfs, NULL, NULL, &Timeout);
73
74
      if (res == 0) {
75
   cout       << "\nZeitüberschreitung! Keine Input-Daten an seriellen Port /dev/ttyS" << port << 
76
      " vorhanden!\n";
77
   
78
   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
79
   npbLogFile  << strTimestamp << " Zeitüberschreitung! Keine Input-Daten an seriellen Port /dev/ttyS" 
80
         << port << " vorhanden!\n";
81
   npbLogFile.close();
82
}
83
84
      if (FD_ISSET(fd, &readfs)) {
85
   errorNpb = read_input_source(fd, errorNpb);
86
                    
87
   if (errorNpb = 0)
88
      sleep(10);
89
   else if (errorNpb > 3) {
90
      cout << "\nFehler beim einlesenen!\n";
91
92
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
93
      npbLogFile  << strTimestamp << " Fehler beim einlesenen!\n";
94
      npbLogFile.close();
95
   }   
96
      }
97
   }
98
99
   close(fd);    // serielle Schnittstelle schließen
100
   return 0;
101
}
102
103
/***********************************************************************************/
104
/* Funktion zum einlesen der Daten hab ich raus genommen, soweit kommt er ja nicht */
105
/***********************************************************************************/
106
107
108
int open_input_source(int port) {
109
   int fd;
110
   struct termios options;
111
112
   /* Zeitstempel (YYYYMMDDHHMMSS) für LOG-Datei-Werte erzeugen und in Sting 'strTimestamp' ablegen */
113
   time_t Zeitstempel;
114
   struct tm *ltime;
115
   char strTimestamp[15];
116
   Zeitstempel = time(0);
117
   ltime = localtime(&Zeitstempel);
118
   strftime(strTimestamp, 15, "%Y%m%d%H%M%S", ltime);
119
   
120
   /* seriellen Port öffnen */
121
   switch (port) {
122
      case 0: fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); break;
123
      case 1: fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY); break;
124
      case 2: fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY | O_NDELAY); break;
125
      case 3: fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_NDELAY); break;
126
   }
127
   
128
   /* wenn serieller Port nicht geöffnet werden konnte, dann Fehlermeldung, Log-Datei-Ausgabe und Programmabruch! */
129
   if (fd == -1) {
130
      cout    << "\nFehler! Programmabruch!\n";
131
132
      ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
133
      npbLogFile  << strTimestamp << " Fehler! Programmabruch!\n";
134
      npbLogFile.close();
135
      exit(1);
136
   }
137
   
138
   /* wenn serieller Port geöffnet, dann Port konfigurieren */  
139
   else if (fd >= 0) {
140
      fcntl(fd, F_SETFL, 0);
141
      
142
143
      if (tcgetattr(fd, &options) != 0) {
144
   cout      << "\nFehler! Programmabruch!\n";
145
146
   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
147
   npbLogFile << strTimestamp << " Fehler! Programmabruch!\n";
148
   npbLogFile.close();
149
150
   exit(1);
151
      }
152
 
153
      cfsetspeed(&options, B9600);       // Geschwindigkeit: 9600 Baud
154
      options.c_cflag &= ~PARENB;       // kein Paritybit
155
      options.c_cflag &= ~CSTOPB;       // 1 Stopbit
156
      options.c_cflag &= ~CSIZE;       
157
      options.c_cflag |= CS8;         // 8 Datenbits
158
      options.c_cflag |= (CLOCAL | CREAD);   // CD-Signal ignorieren
159
      options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);   // nicht Zeilenbasiert, kein Echo, keine Steuerzeichen, 
160
                  // keine Interrupts
161
      options.c_oflag &= ~OPOST;       // Setze RAW-Output  
162
      options.c_cc[VMIN] = 0;         // Warten auf min. 0 Zeichen beim lesen
163
      options.c_cc[VTIME] = 0;         // Timeout beim lesen "read()" nicht setzen
164
      
165
166
      tcflush(fd, TCIOFLUSH);
167
168
      if (tcsetattr(fd, TCSAFLUSH, &options) != 0) {
169
   cout       << "\nFehler! Programmabruch!\n";
170
171
   ofstream npbLogFile("FILE_OUT.LOG",ios_base::app);
172
   npbLogFile  << strTimestamp << 
173
      " Fehler! Programmabruch!\n";
174
   npbLogFile.close();
175
176
   exit(1);
177
      }
178
179
      fcntl(fd, F_SETFL, FNDELAY);
180
      fcntl(fd, F_SETFL, 0);
181
      
182
      return fd;
183
   }
184
}


Schon mal vielen Dank an euch.

Gruß
Uwe

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Kann auch sein, dass du als Bootparamter noch console=ttyS0 drinstehen 
hast. Wenn ja, nimm das auch noch raus. Du hast zwar keine Konsole mehr 
laufen, aber der Kernel meldet sich immer noch auf ttyS0.

von abdo (Gast)


Lesenswert?

Hi, kannst du auch dein "read_input_source"-listing zeigen? weil an der 
Programmausführung konnte ich bis jetzt keinen Fehler sehen?
Abdo

von abdo (Gast)


Lesenswert?

abdo schrieb:
> Programmausführung

programmlisting

von Uwe D. (Gast)


Lesenswert?

Hallo Leute,

da ich die letzten zwei Wochen sehr wenig Zeit hatte, hier nochmal der 
aktuelle Stand...

1. Console hab ich ausgeschalten, jetzt auch in den 'bootargs', aber was 
ich nicht verstehe, warum wird der Kernel-Prozess immer noch über die 
ttyS0 ausgegeben?
1
U-Boot> printenv
2
baudrate=115200
3
ethaddr=00:04:25:1C:88:84
4
bootdelay=1
5
ethact=macb0
6
serverip=172.24.41.2
7
tftpip=172.24.41.2
8
eth1addr=00:04:25:1C:88:85
9
filesize=131B8C
10
bootcmd=mmcinit; ext2load mmc 0:1 0x10400000 /boot/uImage; bootm
11
bootargs=root=/dev/mmcblk0p1 rootwait
12
stdin=serial
13
stdout=serial
14
stderr=serial
15
16
Environment size: 294/65532 bytes

2. Habe ich versucht, mit meinem Programm auf die anderen 
UART-Schnittstellen zu zugreifen, hier steigt er dann - wie es natürlich 
auch sein soll - schon mit einer Fehlermeldung beim konfigurieren aus.

3. ich habe mir mal den Rückgabewert von 'fd' anzeigen lassen, nach dem 
die Schnittstelle über die Funktion konfiguriert wurde, der ist 
'716345188' unter Ubuntu war der Wert '3'

4. er scheint die Schnittstelle aber richtig zu konfigurieren, weil nach 
meinem Programmstart ist die ttyS0 auf 9600 Baud und nicht mehr auf 
115200 gesetzt. Hier die Ausgabe von 'stty'
1
~ # stty -a -F /dev/ttyS0
2
speed 9600 baud; rows 24; columns 80;
3
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
4
eol2 = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
5
lnext = ^V; flush = ^O; min = 0; time = 0;
6
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
7
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
8
-iuclc -ixany -imaxbel
9
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0
10
ff0
11
-isig -icanon iexten -echo -echoe echok -echonl -noflsh -xcase -tostop -echoprt
12
echoctl echoke


Vielleicht kann mir jemand von euch weiter helfen... Vielen Dank.

Gruß Uwe

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

>warum wird der Kernel-Prozess immer noch über die
>ttyS0 ausgegeben?
Der Kernel nimmt sich immer das erste verfügbare und brauchbare Gerät 
für die Ausgabe, du musst es explizit auf was anderes legen. Zweite 
Serielle Schnittstelle vlt? Hat das NGW100 eine?

>ich habe mir mal den Rückgabewert von 'fd' anzeigen lassen, nach dem
>die Schnittstelle über die Funktion konfiguriert wurde, der ist
>'716345188' unter Ubuntu war der Wert '3
Und du willst uns damit was sagen?

von Uwe D. (Gast)


Lesenswert?

1. Wenn ich eine andere Schnittstelle nehme z.B. ttyS3 wird der 
Kernel-Bootprozess nicht mehr ausgegeben, aber funktionieren tut es dann 
immer noch nicht...

2. Naja, da er ja an der Stelle aussteigt, wenn er 'fd' aufruft... 
dachte ich, könnte was damit zu tun haben, das der Wert nicht stimmt.


Danke & Gruß

von Uwe D. (Gast)


Lesenswert?

So, ich habe jetzt mal den Debugger laufen lassen... bekomme im 
DBG-Clienten folgende Meldung:
1
warning: .dynamic section for "/usr/lib/libstdc++.so.6" is not at the expected address (wrong library or version mismatch?)
2
3
Program received signal SIGSEGV, Segmentation fault.
4
0x000036b8 in main ()


Der DGB-Server spuckt folgenden Error raus...
1
Child terminated with signal = b
2
3
Child terminated with signal = 0xb (SIGSEGV)
4
GDBserver exiting

Folgendes ist zu erwähnen, die libstdc++.so.6 war bei mir nach dem 
compilieren des buildroot 2.3.0 nicht dabei, da die Datei aber im 
staging_dir des GNU-Toolchain vorhanden war, hab ich diese nach /usr/lib 
auf dem NGW100 kopiert...

Mit --static kompilieren bringt keine Veränderung.

Ich kompiliere immer mit "avr32-linux-g++ prog.cpp -o prog" oder ist das 
nicht ausreichend?


Vielen Dank & Gruß

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

>dachte ich, könnte was damit zu tun haben, das der Wert nicht stimmt.
Woher willst du wissen, dass der Werte nicht simmt? Das ist ein 
File-Descriptor, der ist nicht immer und auf jeder Architektur gleich ;)

von ... (Gast)


Lesenswert?

Der Wert '716345188' für fd sieht trotzdem ziemlich daneben aus.
'fd_set' ist meist ein Array fester Größe (FD_SETSIZE) und FD_SET 
benutzt fd als index in dieses Array. Wenn fd>=FD_SETSIZE ist, dann 
knallts halt. Kann man sich ja einfach in den entsprechenden *.h 
ansehen.

von Uwe D. (Gast)


Lesenswert?

Hallo,

Problem ist gelöst!

Das "return fd" aus der zweiten Funktion, muss außerhalb der 
if-Anweisung sein, also vor die letzte geschweifte Klammer!

Der AVR32-GNU-Compiler 4.2 macht sonst Probleme.

Danke für eure Hilfe...


Gruß Uwe

von abdo (Gast)


Lesenswert?

Hi Uwe D,
kannst du mir Bitte dein Programm auf diese Mail"t.abderrahim@web.de" 
schicken? ich habe auch Probleme mit select und ttyS1 auf dem 
ICnova-OEM, und ich bin ratlos.
Vielen Dank im vorraus.
Abdo

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.