Changes between Initial Version and Version 1 of serial


Ignore:
Timestamp:
10/21/2017 10:28:45 PM (13 months ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • serial

    v1 v1  
     1[[PageOutline]]
     2
     3
     4= UART Communication =
     5This page gives some tips and tricks regarding serial communcation.
     6
     7Gateworks boards often have connectors available for either RS232 or TTL level UART with and without hardware handshaking. Refer to the board specific hardware manual for pinout details.
     8
     9Cables are available from Gateworks in the online shop:
     10 * [http://shop.gateworks.com/index.php?route=product/product&path=70_75&product_id=27 GW10001 10 pin IDC header to DB9]
     11 * [http://shop.gateworks.com/index.php?route=product/product&path=70_75&product_id=30 GW10019 DB9 Gender Changer]
     12 * [http://shop.gateworks.com/index.php?route=product/product&path=70_75&product_id=28 GW10005 DB9 male to DB9 female 6ft cable]
     13
     14
     15[=#mapping]
     16== Linux serial port devices ==
     17Serial UARTS will be represented as /dev/tty* devices depending on the CPU architecture. For avila/cambria/laguna product families the first UART is /dev/ttyS0 and for Ventana product families the UARTs are /dev/ttymxc*.
     18
     19The following table describes the various on-board UARTs for standard Gateworks products. Please consult the board specific hardware user manual for additional details:
     20||= Family =||= Board =||= Device =||= Function         =||
     21|| Avila    || GW2347  || ttyS0    || console: 3.3V TTL JTAG J2 / RS232 J5   ||
     22||          ||         || ttyS1    || UART: RS232 J3                         ||
     23||          || GW2348  || ttyS0    || console: 3.3V TTL JTAG J7 / RS232 J13  ||
     24||          ||         || ttyS1    || UART: RS232 J6                         ||
     25||          || GW2355  || ttyS0    || console: 3.3V TTL JTAG J3 / RS232 J5   ||
     26||          ||         || ttyS1    || GPS                                    ||
     27||          || GW2357  || ttyS0    || console: 3.3V TTL JTAG J2 / RS232 J6   ||
     28||          ||         || ttyS1    || UART: RS232 J36                        ||
     29|| Cambria  || GW2350  || ttyS0    || console: 3.3V TTL JTAG J1/J10          ||
     30||          ||         || ttyS1    || GPS                                    ||
     31||          ||         || ttyS2    || RS485 J6                               ||
     32||          || GW2358  || ttyS0    || console: 3.3V TTL JTAG J10 / RS232 J17 ||
     33||          ||         || ttyS1    || GPS                                    ||
     34||          ||         || ttyS2    || RS485 J3                               ||
     35|| Rincon   || GW2361  || ttyS0    || console: 3.3V TTL JTAG J2              ||
     36||          ||         || ttyS1    || RS232 J7                               ||
     37||          ||         || ttyS2    || RS485 J6                               ||
     38|| Laguna   || GW2380/2/3 || ttyS0    || console: 3.3V TTL JTAG J2 / 3.3V TTL J4 ||                           
     39||          ||         || ttyS1    || GPS                                        ||
     40||          ||         || ttyS2    || UART: 3.3V TTL J8                          ||
     41||          || GW2387  || ttyS0    || console: 3.3V TTL JTAG J3/J7 / RS232 J13   ||
     42||          ||         || ttyS1    || RS232 J13 / 3.3V TTL J7                    ||
     43||          ||         || ttyS2    || GPS                                        ||
     44||          || GW2388  || ttyS0    || console: 3.3V TTL JTAG J8 / RS232 J21      ||
     45||          ||         || ttyS1    || RS232 J21                                  ||
     46||          ||         || ttyS2    || GPS                                        ||
     47||          || GW2391  || ttyS0    || console: 3.3V TTL JTAG J1 / RS232 J15      ||
     48||          ||         || ttyS1    || RS232 J15                                  ||
     49||          ||         || ttyS2    || GPS                                        ||
     50|| Ventana  || GW51xx  || ttymxc0  || GPS ||
     51||          ||         || ttymxc1  || console: 3.3V TTL JTAG J10/J11 ||
     52||          ||         || ttymxc4  || TTL J11 ||
     53||          || GW52xx  || ttymxc0  || RS485/CAN/TTL J12 / RS232 J10 ||
     54||          ||         || ttymxc1  || console: 3.3V TTL JTAG J14 / RS232 J10 ||
     55||          ||         || ttymxc4  || GPS ||
     56||          || GW53xx  || ttymxc0  || RS485/CAN/TTL J11 / RS232 J12 ||
     57||          ||         || ttymxc1  || console: 3.3V TTL JTAG J14 / RS232 J12 ||
     58||          ||         || ttymxc4  || GPS ||
     59||          || GW54xx  || ttymxc0  || RS485 J13 ||
     60||          ||         || ttymxc1  || console: 3.3V TTL JTAG J17 / RS232 J15 ||
     61||          ||         || ttymxc4  || GPS ||
     62||          || GW551x  || ttymxc1  || console: exp 3.3V TTL J3             ||
     63||          ||         || ttymxc2  || exp 3.3V TTL J3           ||
     64||          || GW552x  || ttymxc1  || console: 3.3V TTL JTAG J7 ||
     65||          ||         || ttymxc2  || exp 3.3V TTL J5           ||
     66||          ||         || ttymxc4  || exp 3.3V TTL J5           ||
     67||          || GW553x  || ttymxc1  || console: 3.3V TTL JTAG J11 ||
     68||          ||         || ttymxc2  || exp 3.3V TTL JTAG J10 ||
     69||          ||         || ttymxc3  || GPS ||
     70||          ||         || ttymxc4  || exp 3.3V TTL JTAG J10 ||
     71||          || GW16111 || ttymxc1  || console: 3.3V TTL JTAG J8 / RS232 J16 / RS485 J20 ||
     72||          ||         || ttymxc2  || RS232 J16 ||
     73
     74
     75[=#baud]
     76== Baudrates ==
     77The maximum baudrate supported depends on the product family and sometimes whether or not you are using TTL or RS232 as at times a transceiver may limit the stream to below 250000 (consult the hardware manual). A safe and typical baudrate is 115200.
     78
     79
     80[=#flowcontrol]
     81== Flow control ==
     82Flow control refers to hardware or software handshaking that can tell a transmitter when its ok to send more data.
     83
     84Hardware flow control is typically via RTS/CTS (request-to-send / clear-to-send) or via DTR/DSR (data-terminal-ready / data-set-ready). Depending on the board and port used you may be able to use hardware flow control.
     85
     86Software flow control uses a specific character for start and stop and therefore cannot be used in binary data transfer.
     87
     88Take care to set flow control properly. Typically this is done in Linux with the stty application. For example to disable the first UART's flow control on an IMX6 based Ventana product:
     89{{{
     90stty -crtscts -F /dev/ttymxc0
     91}}}
     92
     93
     94== Serial Port Types (DCE vs DTE) ==
     95The Data Communication Equipment (DCE) (Typically used on a Gateworks board) pin assignments permit direct connection to a standard Data Terminal Equipment (DTE) PC running terminal emulation software.
     96
     97In certain scenarios, a null modem cable may be needed [http://en.wikipedia.org/wiki/Null_modem Null Modem Information]
     98
     99Please read more about the RS232 Specification [http://en.wikipedia.org/wiki/RS-232 here]
     100
     101
     102[=#console]
     103== Linux serial Console ==
     104There are times when one may not care about serial Linux console because the serial port is desired for other uses.
     105
     106By default the Gateworks bootloader's configure one of the board's UARTs for serial console. This can be disabled by changing the bootargs in the bootloader:
     107 * Example: Laguna uboot
     108{{{
     109setenv bootargs console= root=/dev/mtdblock3 rootfstype=squashfs,jffs2 noinitrd
     110saveenv
     111}}}
     112 * Example: Ventana uboot:
     113{{{
     114setenv console null
     115saveenv
     116}}}
     117
     118If using Yocto or a more traditional Linux based OS, you may need to take additional steps to disable the OS enabling the serial port for a Login terminal by removing the line with that serial port from /etc/inittab.
     119
     120The bootloader will still output data upon power up - see below.
     121
     122
     123[=#bootloader]
     124== Bootloader Serial Console ==
     125If you wish to disable the bootloader's use of the serial port, you will need to recompile the bootloader.
     126
     127Notes:
     128 * For Lagunu u-boot-2008.10 modify CONFIG_CONS_INDEX in include/configs/cavium_cns3000*.h setting it to a non-existent port.
     129 * Define CONFIG_SILENT_CONSOLE to enable support for silent mode (must custom compile bootloader as discussed on the wiki [wiki:laguna/bootloader here])
     130 * Set the u-boot envvar silent to disable some u-boot output
     131 * One should probably tweak the bootdelay to 1 second (or turn it off)
     132 * One can still interrupt u-boot by pressing the specified key (you won't see output, but your input will be processed)
     133
     134
     135
     136[=#rs323]
     137== RS232 ==
     138[https://en.wikipedia.org/wiki/RS-232 RS-232] is a standard for serial communication transmission of data. The most important aspects of the spec are:
     139 * defines electical signal characteristics such as voltage levels, signalling rate, timing and slew-rate of signals
     140 * mechanical characteristics such as pinouts
     141
     142Many Gateworks boards have RS232 support (not to be confused with TTL level UART support which has different voltage and signalling specifications).
     143
     144
     145=== Example usage: RS232 connection to a PC ===
     146
     1471. Connect all hardware / cables
     148{{{
     149#!html
     150<h3 style="color: red">
     151 Note: A NULL MODEM adapter / cable may need to be used between the Gateworks board and a PC!
     152</h3>
     153}}}
     154[[Image(serial2391.jpg,400px)]]
     155
     1562. The serial port must be configured on the Gateworks board using the stty command for the baud rate:
     157{{{#!bash
     158# stty --help
     159BusyBox v1.19.4 (2013-06-26 04:34:22 PDT) multi-call binary.
     160
     161Usage: stty [-a|g] [-F DEVICE] [SETTING]...
     162
     163Without arguments, prints baud rate, line discipline,
     164and deviations from stty sane
     165
     166        -F DEVICE       Open device instead of stdin
     167        -a              Print all current settings in human-readable form
     168        -g              Print in stty-readable form
     169        [SETTING]       See manpage
     170
     171root@OpenWrt:/# stty -F /dev/ttyS1 115200
     172}}}
     173
     1743. Configure PC:
     175 * On the receiving PC, a terminal program can be used. For example:
     176  - Windows: putty, hyperterm
     177  - Linux: screen, minicom
     178   - Example (adjust as necessary)
     179    {{{
     180screen /dev/ttyS1 115200,cs8
     181}}}
     182 * Be sure to select the same baud rate, format (ie 8 data bits, no parity, 1 stop bit - aka 8N1 or cs8) and flow control as configured on the Gateworks board.
     183
     1844. Test Connection:
     185 * A quick way to test this is to use an echo statement from the console of the Gateworks board like so:
     186{{{#!bash
     187# echo "0" > /dev/ttyS1
     188}}}
     189The character '0' should appear on the serial console on the PC.
     190
     191Troubleshooting:
     192 * make sure you are either not using hardware/software flow control, or in the case that you do have hardware flow control (CTS/RTS or DTR/DSR) they are properly connected.
     193 * use a null-modem if needed (DTE vs DCE)
     194 * make sure both ends are RS232 compliant (as opposed to TTL level logic)
     195
     196== Specific Model Notes ==
     197
     198=== GW2382 ===
     199J8 is an expansion header and is by default mapped to /dev/ttyS2.  J2 and J4 are connected to /dev/ttyS0.  The GPS is hooked to /dev/ttyS1.
     200
     201=== Laguna: Baud Rate ===
     202The Laguna Family has the option of 2 clocks for the serial port, 24MHz and 14.7456MHz.
     203
     204By default the 24MHz clock is loaded.  This clock creates drift for some baud rates as seen below.
     205
     206Because this drift is consistent on Laguna boards, Laguna to Laguna serial will work at all baud rates.
     207
     208Therefore, we suggest using rates below 115200. Please contact support at Gateworks if higher baud rates are required.
     209
     210[[Image(baudrates.jpg)]]
     211
     212
     213[=#rs485]
     214== RS485 ==
     215Some Gateworks boards have RS485 transceivers connected to host CPU UART's. This often is an optional feature that must be loaded at the factory. Please contact support@gateworks.com via email for more information.
     216
     217RS485 uses a differential pair and is typically half-duplex such that the TX and RX share a differential pair on a multi-master bus and the TX and an enable that is controlled via one of:
     218 1. always enabled (only useful if there is only a single transmitter on the bus)
     219 2. connected to UART RTS line
     220 3. connected to host CPU GPIO
     221
     222Because of the half-duplex nature, typically custom software needs to be written to:
     223 * control the enabling of the transmit driver (sometimes this is done for you in the driver)
     224 * receive the data you sent directly after sending (unless the driver does this for you)
     225 * implement a protocol such that multiple masters know when it is there turn to transmit
     226
     227RS485 Networks also require termination. Most Gateworks boards which have RS485 have on-board 4.75Kohm pulls and an optional on-board 121ohm load termination resistor.
     228
     229In a typical scenario you may have two devices on an RS485 half-duplex bus, NodeA and NodeB and a conversation would look like this:
     230 1. NodeA enables its transmitter, sends out a request packet, then disables its transmitter and waits for a response
     231 2. NodeB waits for a request packet and until it sees one its transmitter is not enabled. When it receives the request it enables its transmitter, sends a response, then disables its transmitter.
     232 3. NodeA knows the exact nature of the response so it can wait until the message is complete then knows that it can transmit again
     233
     234The following table and sections below provides per-board details of RS485:
     235||= Family  =||= Board        =||= TXEN =||= Termination =||= Notes =||
     236|| Cambria   || GW235x         || DTR    || optional      || use tcdrain() and TIOCMBIC/TIOCMBIS ioctl ||
     237||                 ||
     238|| Rincon    || GW2361         || RTS    || off-board     || use tcdrain() and TIOCMBIC/TIOCMBIS ioctl ||
     239||                 ||
     240|| Laguna    || GW2380+GW16067 || gpio3  || optional      || use tcdrain() and userspace /sys/class/gpio/gpio3 ||
     241||                 ||
     242|| Ventana   || GW551x+GW16111 || gpio19  || optional     || see [#ventana-rs485 below] ||
     243|| Ventana   || GW52xx '''(optional)''' || gpio193 || optional     || TIOCSRS485 support ||
     244|| Ventana   || GW53xx '''(optional)'''         || gpio193 || optional     || TIOCSRS485 support ||
     245|| Ventana   || GW54xx '''(optional)'''         || gpio193 || optional     || TIOCSRS485 support ||
     246
     247Note that if a driver supports TIOCSRS485 (in other words it handles the assertion/de-assertion of TXEN in the driver) this is preferred over using tcdrain() to determine when the FIFO is empty as tcdrain() can have considerable latency at small transmit sizes.
     248
     249References:
     250 * [http://www.ti.com/lit/an/slla272b/slla272b.pdf TI RS-485 Design Guide] - excellent source of info regarding termination, multi-master transmission, line length etc
     251 * https://en.wikipedia.org/wiki/RS-485
     252
     253
     254[=#cambria-rs485]
     255=== Cambria ===
     256The Cambria GW2350 and GW2358 optionally supports half-duplex, multi-drop RS485:
     257 * TL16C752B UART
     258 * MAX3485 transceiver
     259 * TXEN connected to DTR
     260 * '''optional termination
     261
     262By 'optional' this means the baseboard design supports this, but it is not loaded on standard product therefore would be a Gateworks Special. Contact sales@gateworks.com if interested to see if a configuration already exists.
     263
     264Your software must assert/de-assert DTR manually (see [#rs485-example] example code) or the uart driver would need to be modified to add TIOCSRS485 ioctl support.
     265
     266
     267[=#rincon-rs485]
     268=== Rincon ===
     269The Rincon GW2361 supports half-duplex, multi-drop RS485:
     270 * DM6446 (CPU) UART2 (/dev/ttyS2)
     271 * MAX3485 transceiver
     272 * TXEN connected to RTS
     273
     274Your software must assert/de-assert RTS manually (see [#rs485-example] example code) or the uart driver would need to be modified to add TIOCSRS485 ioctl support.
     275
     276
     277[=#laguna-rs485]
     278=== Laguna ===
     279The GW16067 IO Expansion module for the GW2380/2/3 supports half-duplex, multi-drop RS485:
     280 * CNS3xxx UART2 (/dev/ttyS2)
     281 * MAX3485 transceiver
     282 * TXEN connected to gpio3
     283 * '''optional termination (R5)
     284 * 4.75k pull-up on D+, 4.75k pull-down on D- (bus defaults to logic 1 - never idle)
     285
     286By 'optional' this means the baseboard design supports this, but it is not loaded on standard product therefore would be a Gateworks Special. Contact sales@gateworks.com if interested to see if a configuration already exists.
     287
     288Your software must assert/de-assert gpio3 manually (see [#rs485-example] example code) or the  uart driver would need to be modified to add TIOCSRS485 ioctl support.
     289
     290
     291[=#ventana-rs485]
     292=== Ventana ===
     293The GW52xx/GW53xx/GW54xx support optional half-duplex, multi-drop RS485:
     294 * IMX6 UART1 (/dev/ttymxc0)
     295 * MAX14840 transceiver
     296 * TXEN connected to gpio193
     297 * '''optional termination
     298 * '''optional D+ pull-up and D- pull-down
     299
     300By 'optional' this means the baseboard design supports this, but it is not loaded on standard product therefore would be a Gateworks Special. Contact sales@gateworks.com if interested to see if a configuration already exists.
     301
     302Your software must use the TIOCSRS485 ioctl to configure TXEN (see [#rs485-example] example code).
     303
     304The GW551x + GW16111 breakout module support half-duplex, multi-drop RS485:
     305 * IMX6 UART2 (/dev/ttymxc1)
     306  - Note that a jumper must be placed on '''J10:2-3''' to enable RS485 RX (routes UART2 RX to RS485 vs RS232 transceiver)
     307  - Note that a jumper must be placed on '''J10:1-2''' to enable RS232 (routes UART2 to RS232 transceiver)
     308 * MAX14840 transceiver
     309 * TXEN connected to gpio19, or always enabled, or enable on transmit (selected via J10 jumper)
     310  - '''always drive mode''' - jumpers placed on '''J10:2-3''' and '''J10:4-5''' will cause the transceiver to always have its transmit enabled. This is useful for fast signal switching (fast/large bus) if you are using a single master and one or more receivers.
     311  - '''TXD drive mode''' - jumpers placed on '''J10:2-3''' and '''J10:7-8''' will cause the transceiver to be enabled only when TX is asserted. Because there are 4.75k pull's on D+/D- the bus is never 'idle'. This is useful for multi-master scenarios but could pose issues with fast/large busses if the 4.75pull's are not strong enough to switch the signals quick enough.
     312  - '''DIO-drive mode''' - jumpers placed on '''J10:2-3''' and '''J10:7-8''' will cause the transceiver to be enabled only when IMX_DIO1 (gpio19) is asserted high. This is useful for fast/large busses where the TXD drive mode doesn't provide fast enough switching. If using this mode you either need to manage the assertion/de-assertion of gpio19 in usersapce or modify the GW551x device-tree to configure rs485-txen for TIOCSRS485 support by adding '''fsl,rs485-gpio-txen = <&gpio1 19 GPIO_ACTIVE_HIGH>;''' to the uart2 device-tree node in arch/arm/boot/dts/imx6qdl-gw551x.dtsi
     313 * 121ohm termination can be enabled by placing a jumper on '''J10:9-10'''
     314 * 4.75k pull-up on D+, 4.75k pull-down on D- (bus defaults to logic 1 - never idle)
     315
     316
     317[=#rs485-example]
     318=== Example Application ===
     319Here is an example application that uses the TIOCSRS485 ioctl to configure RS485 for drivers that directly control the transmit enable:
     320{{{#!c
     321#include <ctype.h>
     322#include <errno.h>
     323#include <stdlib.h>
     324#include <stdio.h>
     325#include <string.h>
     326#include <termios.h>
     327#include <time.h>
     328#include <fcntl.h>
     329#include <sys/ioctl.h>
     330#include <linux/serial.h>
     331
     332/** main function
     333 */
     334int main(int argc, char** argv)
     335{
     336        struct termios orig_ttystate, ttystate;
     337        int fd, sz, rz, bytes;
     338        speed_t speed;
     339        const char *baud, *mode, *dev, *txen = NULL;
     340        int timeout = 2; // time in seconds to wait for response
     341        char *msg;
     342        char buf[8192];
     343        time_t start;
     344
     345        if (argc < 5) {
     346                fprintf(stderr,
     347                        "usage: %s <device> <baud> <mode> <message> [<txen>]\n",
     348                        argv[0]);
     349                exit(1);
     350        }
     351
     352        dev = argv[1];
     353        baud = argv[2];
     354        mode = argv[3];
     355        msg = argv[4];
     356        if (argc > 5)
     357                txen = argv[5];
     358
     359        // open device
     360        fd = open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY);
     361        if (fd <= 0) {
     362                perror("open");
     363                exit(-1);
     364        }
     365
     366        // get original ttystate
     367        tcgetattr(fd, &orig_ttystate);
     368
     369        // create a sane TTY state (raw mode, no HW/SF flow control)
     370        memset(&ttystate, 0, sizeof(ttystate));
     371
     372        // enable receiver and ignore modem status lines
     373        ttystate.c_cflag |= CREAD;
     374        ttystate.c_cflag |= CLOCAL;
     375
     376        // data-size
     377        ttystate.c_cflag &= ~CSIZE;
     378        switch(mode[0]) {
     379        case '5': ttystate.c_cflag |= CS5; break;
     380        case '6': ttystate.c_cflag |= CS6; break;
     381        case '7': ttystate.c_cflag |= CS7; break;
     382        case '8': ttystate.c_cflag |= CS8; break;
     383        default: fprintf(stderr, "invaid character size in %s\n", mode); break;
     384        }
     385
     386        // parity
     387        ttystate.c_cflag &= ~PARODD;
     388        ttystate.c_cflag &= ~PARENB;
     389        switch(toupper(mode[1])) {
     390        case 'N': break; // no parity
     391        case 'O': ttystate.c_cflag |= (PARENB | PARODD); break; // odd
     392        case 'E': ttystate.c_cflag |= PARENB; break; // even
     393        default: fprintf(stderr, "invaid parity in %s\n", mode); break;
     394        }
     395
     396        // stop bits
     397        switch(toupper(mode[2])) {
     398        case '1': ttystate.c_cflag &= ~CSTOPB; break;
     399        case '2': ttystate.c_cflag |= CSTOPB; break;
     400        default: fprintf(stderr, "invaid stop bit mode in %s\n", mode); break;
     401        }
     402
     403        // baudrate
     404        switch(atoi(baud)) {
     405        case 1200: speed = B1200; break;
     406        case 2400: speed = B2400; break;
     407        case 9600: speed = B9600; break;
     408        case 19200: speed = B19200; break;
     409        case 38400: speed = B38400; break;
     410        case 57600: speed = B57600; break;
     411        case 115200: speed = B115200; break;
     412        case 230400: speed = B230400; break;
     413        case 460800: speed = B460800; break;
     414        default: fprintf(stderr, "invalid baud rate %s\n", baud); break;
     415        }
     416        if (cfsetispeed(&ttystate, speed))
     417                perror("cfsetispeed");
     418        if (cfsetospeed(&ttystate, speed))
     419                perror("cfsetospeed");
     420
     421        // set tty state
     422        printf("setting ttystate\n");
     423        if (tcsetattr(fd, TCSANOW, &ttystate))
     424                perror("tcsetattr");
     425
     426        // configure rs485
     427        if (txen) {
     428                struct serial_rs485 rs485;
     429
     430                printf("enabling rs485 for %s txen\n", txen);
     431                memset(&rs485, 0, sizeof(rs485));
     432                rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
     433                if (ioctl(fd, TIOCSRS485, &rs485))
     434                        perror("TIOCSRS485");
     435        }
     436
     437        // flush in/out data
     438        tcflush(fd, TCIOFLUSH);
     439
     440        sz = atoi(msg);
     441        if (!sz) {
     442                sprintf(buf, "%s", msg);
     443                sz = strlen(msg) + 1;
     444        }
     445        printf("transmitting %d bytes...\n", sz);
     446        if (write(fd, buf, sz) != sz)
     447                perror("tx");
     448
     449        // receive data
     450        printf("reading...\n");
     451        bytes = 0;
     452        memset(buf, 0, sizeof(buf));
     453        start = time(NULL);
     454        while (1) {
     455                rz = read(fd, buf + bytes, sz - bytes);
     456                if (rz < 0) {
     457                        perror("read failed");
     458                        break;
     459                }
     460                bytes += rz;
     461
     462                if (bytes >= sz)
     463                        break;
     464
     465                if ((int)(time(NULL) - start) >= timeout) {
     466                        printf("timeout\n");
     467                        break;
     468                }
     469
     470                usleep(100000);
     471        }
     472        printf("received %d bytes in %ds\n", bytes, (int)(time(NULL) - start));
     473        if (!atoi(msg))
     474                printf("%s\n", buf);
     475
     476        // restore terminal state
     477        tcsetattr(fd, TCSANOW, &orig_ttystate);
     478
     479        close(fd);
     480
     481        return 0;
     482}
     483}}}
     484
     485Ventana boards with on-board RS485 use ARM gpio193 as the TXEN and our Ventana BSP's support the TIOCSRS485 ioctl such that you do not need to manage the transmitter enable other than enable it and set its polarity when you configure the serial port:
     486{{{#!c
     487struct serial_rs485 rs485;
     488
     489memset(&rs485, 0, sizeof(rs485));
     490rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
     491if (ioctl(fd, TIOCSRS485, &rs485))
     492  perror("TIOCSRS485");
     493}}}
     494
     495If a board connects RTS, DTR, or a gpio to TX-Enable but does not support the TIOCSRS485 you can alter your code to enable/disable the TX-Enable as needed.
     496
     497For example the following function:
     498{{{#!c
     499/** write_file - write to a file
     500 * @param str to write
     501 * @param fname to write to
     502 *
     503 * This is used to set/configure GPIO's via the sysfs interface to gpio class
     504 */
     505int write_file(const char* str, const char* fname)
     506{
     507        FILE *file;
     508        int ret = -EIO;
     509
     510        file = fopen(fname, "w");
     511        if (file) {
     512                ret = fprintf(file, "%s\n", str);
     513                if (ret <= 0)
     514                        ret = -EIO;
     515                fclose(file);
     516                return 0;
     517        }
     518        return ret;
     519}
     520
     521
     522/** assert_tx - enable/disable TX on a device
     523 * @param dev - serial device
     524 * @param enable - enable or disable
     525 * @returns 0 on success otherwise error
     526 */
     527int assert_tx(int fd, const char *txen, unsigned char enable)
     528{
     529        char str[64];
     530        int t;
     531
     532        if (!txen)
     533                return 0;
     534
     535        printf("%sasserting %s\n", (enable)?"":"de-", txen);
     536        if (strcasecmp(txen, "DTR") == 0) {
     537                // assert DTR on enable, de-assert on disable
     538                t = TIOCM_DTR;
     539                return ioctl(fd, (enable)?TIOCMBIC:TIOCMBIS, &t);
     540        } else if (strcasecmp(txen, "RTS") == 0) {
     541                // assert RTS on enable, de-assert on disable
     542                t = TIOCM_RTS;
     543                return ioctl(fd, (enable)?TIOCMBIC:TIOCMBIS, &t);
     544        } else if (strncasecmp(txen, "gpio", 4) == 0) {
     545                t = atoi(txen + 4);
     546                sprintf(str, "/sys/class/gpio/gpio%d/value", t);
     547                write_file((enable)?"1":"0", str);
     548        }
     549
     550        return 0;
     551}
     552
     553int main(int argc, char **argv) {
     554        ...
     555
     556        // txen is a string: DTR, RTS, or gpio<n>
     557        if (txen && (0 == strncasecmp(txen, "gpio", 4)))
     558        {
     559                char str[64];
     560                int gpio = atoi(txen + 4);
     561
     562                printf("exporting gpio%d\n", gpio);
     563                sprintf(str, "%d", gpio);
     564                write_file(str, "/sys/class/gpio/export");
     565                sprintf(str, "/sys/class/gpio/gpio%d/direction", gpio);
     566                write_file("out", str);
     567                sprintf(str, "/sys/class/gpio/gpio%d/value", gpio);
     568                write_file("0", str); // assuming TXEN active-high
     569        }
     570
     571        // transmit data
     572        assert_tx(fd, txen, 1); // assert TXEN
     573        write(fd, buf, sz); // transmit data
     574        tcdrain(fd); //wait for all characters to be transmitted
     575        assert_tx(fd, txen, 0); // de-assert TXEN
     576
     577        // receive data
     578        ...
     579}}}