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/ttyS0
echo $'$PSTMCFGMSGL,0,1,0,0\r\n' > /dev/ttyS0
echo $'$PSTMSETPAR,1227,1,2\r\n' > /dev/ttyS0
echo $'$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.