The Teseo-LIV3 GPS module (as used in shabaz ' GPS / Galileo / BeiDou / GLONASS receiver) talks UART and I2C. I'm writing an OO driver for it, for embedded systems. In this blog, I validate if ST's example fits for UART read.

What do I try to test?
My Teseo lib works well on a Raspberry Pico. But it's supposed to be device independent. Here, I'm trying to validate if I can get the UART read on a Raspberry Pi in a controlled way.
ST published open source examples for reading via I2C and UART. I'll be reusing that UART example, to see if it works in query / response mode.
Here's the adapted UART read example. It 'll print all replies coming from the Teseo's UART channel:
/**
******************************************************************************
* @file gnss_uart_read.c
* @author SRA-SAIL
* @brief This file contains application to read the data from GNSS module
* over UART
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define BUFF_LEN 83
#define DEBUG 0
#define SERIALTERMINAL "/dev/ttyS0"
#define RESET_CHIP "/dev/gpiochip0"
#define RESET_PIN 23
/*
******************************************************************************
* MAIN FUNCTION
******************************************************************************
*/
int set_interface_attribs(int fd, int speed);
static int GNSS_Reset();
int main()
{
char *portname = SERIALTERMINAL;
int fd;
/*Reset The GNSS Device */
GNSS_Reset();
/*Open the device file*/
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*for X-NUCLEO-GNSS1A1(Teseo-LIV3F) : baudrate 9600, 8 bits, no parity, 1 stop bit */
/*for X-NUCLEO-GNSS2A1(Teseo-VIC3DA) : baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B9600);
/* Continously read the data */
do {
u_int8_t buf[BUFF_LEN];
int rdlen;
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
#if DEBUG
/* display as hex numbers */
printf("Read %d:", rdlen);
for (p = buf; rdlen-- > 0; p++) {
printf(" 0x%x", *p);
if (*p < ' ')
*p = '.'; /* replace any control chars */
}
#endif
printf("%s\n", buf);
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
printf("Nothing read. EOF?\n");
}
/* repeat read */
} while (1);
}
/*Set Terimal Attributes*/
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
tty.c_lflag |= ICANON | ISIG; /* canonical input */
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);
tty.c_iflag &= ~IGNCR; /* preserve carriage return */
tty.c_iflag &= ~INPCK;
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */
tty.c_oflag &= ~OPOST;
tty.c_cc[VEOL] = 0;
tty.c_cc[VEOL2] = 0;
tty.c_cc[VEOF] = 0x04;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int GNSS_Reset()
{
struct gpiohandle_request req;
struct gpiohandle_data data;
char chrdev_name[20];
int fd, ret;
strcpy(chrdev_name, RESET_CHIP);
/* Open device: gpiochip0 for GPIO bank A */
fd = open(chrdev_name, 0);
if (fd == -1) {
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
return ret;
}
/* request GPIO line: GPIO23 */
req.lineoffsets[0] = RESET_PIN;
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
memcpy(req.default_values, &data, sizeof(req.default_values));
strcpy(req.consumer_label, "gnss_reset");
req.lines = 1;
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
ret);
}
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
/* Start led blinking */
data.values[0] = 0;
ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d)\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
}
sleep(1);
ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
data.values[0] = 1;
ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
if (ret == -1) {
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d)\n",
"GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
}
ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
/* release line */
ret = close(req.fd);
if (ret == -1) {
perror("Failed to close GPIO LINEHANDLE device file");
ret = -errno;
}
return ret;
}
Then, I use (for the moment) the Linux command line to configure the Teseo. I'm submitting the same commands as my Teseo library would:
echo $'$PSTMGPSSUSPEND\r\n' > /dev/ttyS0echo $'$PSTMCFGMSGL,0,1,0,0\r\n' > /dev/ttyS0echo $'$PSTMSETPAR,1227,1,2\r\n' > /dev/ttyS0echo $'$PSTMGPSRESTART\r\n' > /dev/ttyS0
In this state, the Teseo is in query response mode, and will only spawn output when it gets a command. Here's what happens when I send the GSV command via the Linux command line:
echo $'$PSTMNMEAREQUEST,80000,0\r\n' > /dev/ttyS0

The Teseo nicely returns one set of GSV data. That looks promising.
Wiring:
![]() |
Current version of the reading software: pi_uart_stream.zip.
Unzip, then move it on you Pi,
make it executable : chmod +x ./pi_uart_stream
launch it: ./pi_uart_stream
Keep the terminal open
In another terminal, execute the Linux commands from this post, to interact with the Teseo. You 'll see the output of pi_uart_stream change. And you 'll see that it nicely sends only the response to your queries.
Prereq: UART must be enabled on your Pi. Use the raspi-config tool:
3 - Interface options -> I6 - Serial Port -> No -> Yes
Link to all posts.

-
DAB
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Comment-
DAB
-
Cancel
-
Vote Up
0
Vote Down
-
-
Sign in to reply
-
More
-
Cancel
Children