cancel
Showing results for 
Search instead for 
Did you mean: 

Nucleo F767 - Serial com. over virtual com port on Linux

Sebastian K.
Associate II
Posted on May 26, 2017 at 16:25

Hello,

I am having problems communicating with my NUCLEO-F767ZI board over the virtual COM port on Linux. The board uses USART3 to communicate via the ST-Link USB port with the PC.

The ST-Link connects fine to the PC on device /dev/ttyACM0 and I can program it fine. I can even mount its disk partition as a mass storage device.

I am using the re-routing of printf() to the USART interface to output debug text, as proposed in the ST examples, and this works fine on a Windows PC. On a Linux machine however, I don't get the output.

I have tried 'screen' to open a serial console, as well as an Arduino IDE serial console, no luck. I have added udev rules for the ST-Link device in /etc/udev to be able to access the device without being root. I can work with other, Arduino-compatible boards over the same /dev/ttyACM0 device just fine.

Does anyone have experience with these boards under Linux and can help me out? What am I missing here?

#serial-interface #nucleo-f767zi #linux

Note: this post was migrated and contained many threaded conversations, some content may be missing.
16 REPLIES 16
AvaTar
Lead
Posted on May 26, 2017 at 16:41

Serial ports under Linux are opened in a terminal emulation mode, i.e. character are filtered and lines are buffered.

You need to switch it to 'raw' mode, to get every character directly, and unmodified.

I need to look up some older example code I have.

Perhaps you find some example elswhere in the meantime...

Posted on May 27, 2017 at 13:49

Thanks for the hint. I tried playing around with setting the serial port to 'raw' but still can't get anything out of the board.

I looked a little closer at what the Arduino boards do in terms of serial communication, and apparently it's much more complex than the simple code I use on the F767 that just retargets the printf function to the USART. I guess that simple solution just does not work on Linux.

So if anyone has any working code that allows printing strings over the USB serial port, that would be really helpful.

Posted on May 27, 2017 at 20:00

Something like this, incomplete example, error checking and other stuff skipped:

(Seems the 'Formatting as Souce Code' option is pretty useless)

♯ include <unistd.h>

♯ include <stdio.h>         // Standard input/output definitions

♯ include <stdlib.h>        // standard library functions

♯ include <fcntl.h>         // File control definitions

♯ include <termios.h>       // POSIX terminal control definitions

♯ include <string.h>        // String function definitions

♯ include <errno.h>         // Error number definitions

your_function_here ()

{

    ...

    struct termios  options, oldoptions;

    ...

    iFD = openLine (iSerLine, devtype);

    ...

    // Configure port reading; block read(), until data arrive

    fcntl (iFD, F_SETFL, 0);

    // Get the current options for the port, and copy for restoration

    tcgetattr (iFD, &oldoptions);

    memcpy (&options, &oldoptions, sizeof (struct termios));

    // Set the baud rates to the defined value

    cfsetispeed (&options, iBaudRate);

    cfsetospeed (&options, iBaudRate);

    // Enable the receiver and set local mode

    options.c_cflag |= (CLOCAL | CREAD);

    options.c_cflag &= ~PARENB;                 // Mask the character size to 8 bits, no parity

    options.c_cflag &= ~CSTOPB;

    options.c_cflag &= ~CSIZE;

    options.c_cflag |=  CS8;                    // Select 8 data bits

    if (hwFCntl)

        options.c_cflag |= CRTSCTS;             // enable hardware flow control

    else

        options.c_cflag &= ~CRTSCTS;            // Disable hardware flow control

    // Enable data to be processed as raw input

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    options.c_iflag &= ~(ICRNL | INLCR | IXON | IXOFF);

    options.c_oflag &= ~OPOST;

    options.c_cc[VTIME] = 0;                    // no inter-character timer

    options.c_cc[VMIN]  = 1;                    // number of characters expected

    // options.c_cc[VEOF] = 4;

    // enable the new options for the port

    tcsetattr (iFD, TCSANOW, &options);

}

static int  openLine (int iSerLine, int devtype)

{

    if (devtype == DEVTYPE_SERIAL)

        sprintf (devName, '/dev/ttyS%d', iSerLine);

    else

        sprintf (devName, '/dev/ttyUSB%d', iSerLine);

    // (fd == -1) -> Could not open the port

    return (iFD = open (devName, O_RDONLY | O_NOCTTY | O_NDELAY));

}

Works for me, at least (Linux Mint 17 Distro).

Posted on May 27, 2017 at 20:23

Seems like every ******* code example goes into moderation now ...

Posted on May 27, 2017 at 22:35

But you can cuss

Using source code formatting has put stuff into moderation for months now, forum coding is complicated stuff...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 28, 2017 at 12:59

But you can cuss

I better use '*' for that - at least for now...

My code example is moderated for almost one day now...

nichtgedacht
Senior
Posted on May 29, 2017 at 12:43

stty is your friend.

Posted on May 29, 2017 at 11:01

To add some comments on the example code:

Pay special attention to the

tcgetattr()/tcsetattr()

calls, and the port settings modifications in between.

Keep you old settings (

oldoptions

struct here), write a function where you restore these settings back before closing the file (serial line), and register this function with atexit().

This way, you can safely terminate you application with Ctrl-C/Ctrl-D without changing serial device settings.

Posted on May 29, 2017 at 11:26

Thank you, I will try that. Basically I am writing my own serial terminal client, right? I was hoping to find some code for the microcontroller that makes it behave like any Arduino-compatible board, which would make many things easier. Anyway, I will try your example, if it works that is at least another option.