Hallo, ich möchte über die UART (/dev/ttyAMA0) des Raspberry Pi (Modell B v2.0) ein Byte senden. Konfiguration:
1 | rpiFd = open(FILE_PATH, O_RDWR | O_NOCTTY); |
2 | |
3 | if(tcgetattr(rpiFd, &rpiOpt) != 0) |
4 | |
5 | // set baud rate
|
6 | // -------------
|
7 | cfsetispeed(&rpiOpt, B9600); |
8 | cfsetospeed(&rpiOpt, B9600); |
9 | |
10 | // control options
|
11 | // ---------------
|
12 | rpiOpt.c_cflag &= ~PARENB; |
13 | rpiOpt.c_cflag &= ~PARODD; |
14 | rpiOpt.c_cflag &= ~CSTOPB; |
15 | rpiOpt.c_cflag &= ~CSIZE; |
16 | rpiOpt.c_cflag |= CS8; |
17 | rpiOpt.c_cflag |= CLOCAL; |
18 | rpiOpt.c_cflag |= CREAD; |
19 | |
20 | // local options
|
21 | // -------------
|
22 | rpiOpt.c_lflag &= ~ICANON; |
23 | rpiOpt.c_lflag &= ~(ECHO | ECHOE); |
24 | rpiOpt.c_lflag &= ~ISIG; |
25 | |
26 | // input options
|
27 | // -------------
|
28 | rpiOpt.c_iflag |= INPCK; |
29 | rpiOpt.c_iflag &= ~IGNPAR; |
30 | rpiOpt.c_iflag |= PARMRK; |
31 | rpiOpt.c_iflag &= ~ISTRIP; |
32 | rpiOpt.c_iflag &= ~IXON; |
33 | rpiOpt.c_iflag &= ~IXOFF; |
34 | rpiOpt.c_iflag &= ~IXANY; |
35 | rpiOpt.c_iflag &= ~IGNBRK; |
36 | rpiOpt.c_iflag &= ~BRKINT; |
37 | rpiOpt.c_iflag &= ~INLCR; |
38 | rpiOpt.c_iflag &= ~IGNCR; |
39 | rpiOpt.c_iflag &= ~ICRNL; |
40 | rpiOpt.c_iflag &= ~IUCLC; |
41 | rpiOpt.c_iflag |= IMAXBEL; |
42 | |
43 | // output options
|
44 | // --------------
|
45 | rpiOpt.c_oflag &= ~OPOST; |
46 | |
47 | // control characters
|
48 | // ------------------
|
49 | rpiOpt.c_cc[VMIN] = 0; |
50 | rpiOpt.c_cc[VTIME] = 10; |
51 | |
52 | tcflush(rpiFd, TCIOFLUSH); |
53 | tcsetattr(rpiFd, TCSANOW, &rpiOpt); |
Code zum Senden:
1 | uint8_t data = 0x00; |
2 | |
3 | bcm2835_gpio_write(RPI_V2_GPIO_P1_11, HIGH); |
4 | write(rpiFd, &data, 1); |
5 | // tcdrain(rpiFd);
|
6 | bcm2835_gpio_write(RPI_V2_GPIO_P1_11, LOW); |
Problem: Ich möchte beim Senden des Bytes solange blockieren, bis das Byte tatsächlich physikalisch über die UART gesendet wurde (inkl. Stoppbit). Um dies zu überprüfen, ziehe ich einen GPIO vor dem Funktionsaufruf auf HIGH und im Anschluss wieder auf LOW. Das Ergebnis ist im Anhang (write.png) zu sehen. Oben sieht man die Übertragung des Bytes über die UART, unten den GPIO. Wie zu erkennen ist, blockiert die write-Funktion nicht einmal so lange, bis das Startbit übertragen wurde. Als vermeintliche Lösung bin ich auf die Funktion tcdrain() gestoßen. Diese soll warten, bis alle Daten gesendet wurden. Damit erhalte ich dann das Ergebnis im Anhang (write_tcdrain.png). Wie zu erkennen ist, blockiert tcrdain() in der Tat, allerdings um ein Vielfaches länger, als es müsste - etwa 12ms anstatt ca. 1ms. Frage: Gibt es eine Möglichkeit nach dem Schreiben nur genau solange zu blockieren, bis das Senden des Bytes vollständig abgeschlossen ist? (Bei einem uC würde man einfach ein TX oder BUSY-Flag pollen oder auf einen entsprechenden Interrupt warten...) Danke im Voraus! Gruß, Matthias