[ART-PI] RT thread start UART6 docking GPS module

Posted by gckmac on Thu, 24 Feb 2022 13:54:39 +0100

introduction

  • Some GPS modules use serial port. Connect the GPS module and adjust the serial port
  • If the GPS chip is used, the interface may be I2C, SPI, UART, etc., so it needs to be connected
  • I register a GPS device here separately, which is used to connect GPS chips of various interfaces. For the upper layer, GPS is just a character device

GPS module verification

  • Hardware usage: [ART-Pi]. Of course, other MCU related to STM32 can still be used. Why use art Pi? Because this is my verification environment
  • I use UBLOX GPS module: This module is a serial port with four external wires: VCC (+ 3V~+5V, I use + 3.3V), GND, RX and TX
  • First, let the GPS module be in place. The computer uses USB to serial port to obtain the data spit out by the GPS module
  • After verification, the transceiver of serial port should be correct, especially if the USB to serial port can be configured as + 3.3V. This GPS module consumes a large amount of power, with a current of about 70mA. In addition, it is difficult to locate indoors. Use the long GPS antenna and put it next to the window. Pay attention to the orientation of the GPS antenna. The effect will be better when it faces outward.

  • You can use GPS tools to view GPS related data

development environment

  • If the GPS module is verified to be OK, it is necessary to use the [ART-Pi] serial port to receive the analysis data
  • Check the schematic diagram of art PI, find a suitable serial port, and finally choose UART6 (USART6)

  • Configure Kconfig and start UART6
    config BSP_USING_UART6
        bool "Enable UART6"
        select RT_USING_SERIAL
        default n
  • To configure UART6 pin, you can use STM32CubeMX graphics to configure, generate, and then update to stm32h7xx of the project_ hal_ msp. C Documents
    void HAL_UART_MspInit(UART_HandleTypeDef* huart) function added:
else if(huart->Instance==USART6)
  {
  /* USER CODE BEGIN USART6_MspInit 0 */

  /* USER CODE END USART6_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART6_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**USART6 GPIO Configuration
    PC7     ------> USART6_RX
    PC6     ------> USART6_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART6;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* USER CODE BEGIN USART6_MspInit 1 */

  /* USER CODE END USART6_MspInit 1 */
  }
  • void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) added
else if(huart->Instance==USART6)
  {
  /* USER CODE BEGIN USART6_MspDeInit 0 */

  /* USER CODE END USART6_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART6_CLK_DISABLE();

    /**USART6 GPIO Configuration
    PC7     ------> USART6_RX
    PC6     ------> USART6_TX
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_7|GPIO_PIN_6);

  /* USER CODE BEGIN USART6_MspDeInit 1 */

  /* USER CODE END USART6_MspDeInit 1 */
  }
  • Configure the clock of UART6. Modify here: board C: system_clock_config, add UART6 related:
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC|RCC_PERIPHCLK_USART3
                              |RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_SPI4
                              |RCC_PERIPHCLK_UART5|RCC_PERIPHCLK_USART6
                              |RCC_PERIPHCLK_SPI1|RCC_PERIPHCLK_SDMMC
                              |RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB
                              |RCC_PERIPHCLK_FMC;
PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;

Software debugging

  • menuconfig configure and enable UART6, scons --target=mdk5 to generate Keil MDK5 project, and then compile and download it
  • It's useless. You need to open the serial port to receive GPS
  • Test uart6 for proper operation:
#include <rtthread.h>

#ifndef GPS_UART_DEVICE_NAME
#define GPS_UART_DEVICE_NAME        "uart6"
#endif

#define DBG_TAG    "gps.uart"
#define DBG_LVL    DBG_INFO
#include <rtdbg.h>

static rt_device_t gps_uart_dev = RT_NULL;
static rt_thread_t gps_uart_thread = RT_NULL;

static rt_err_t gps_uart_rx_ind(rt_device_t dev, rt_size_t size)
{
    LOG_E("%s", __func__);
    return RT_EOK;
}

rt_err_t gps_uart_open(void)
{
    gps_uart_dev = rt_device_find(GPS_UART_DEVICE_NAME);
    if (gps_uart_dev != RT_NULL)
    {
        rt_device_open(gps_uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
        rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind);
        return RT_EOK;
    }
    else
    {
        LOG_E("%s : gps uart error!", __func__);
        return -RT_ERROR;
    }
}

void gps_uart_thread_entry(void *param)
{
    rt_thread_mdelay(5000);
    gps_uart_open();
    while (1)
    {
        rt_thread_mdelay(5000);
        rt_device_write(gps_uart_dev, 0, "gps uart ok", rt_strlen("gps uart ok"));
    }
}

int gps_uart_test(void)
{
    if (gps_uart_thread != RT_NULL)
    {
        LOG_I("%s gps uart thread already!", __func__);
        return -RT_ERROR;
    }

    gps_uart_thread = rt_thread_create("gps_uart", gps_uart_thread_entry, RT_NULL,
        1024, 20, 30);
    if (gps_uart_thread != RT_NULL)
    {
        rt_thread_startup(gps_uart_thread);
        LOG_D("%s gps uart thread ok!", __func__);
    }
    else
    {
        LOG_E("%s gps uart thread failed!", __func__);
    }

    return 0;
}

MSH_CMD_EXPORT(gps_uart_test, gps_uart_test);

  • [summary]

The serial port needs to enable [receive interrupt]. When it is open, add the flag bit: RT_DEVICE_FLAG_INT_RX
rt_device_open(gps_uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
In this way, the serial port driver will configure the serial port receiving interrupt. After receiving the data, it will call:
rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind);
Callback function set: gps_uart_rx_ind, I didn't care at first. I found that the serial port can send but can't receive. I thought the pin matched
It was wrongly set. Later, the software was debugged step by step and found that it forgot this flag bit: RT_DEVICE_FLAG_INT_RX

  • drv_gps.c: Realize GPS serial port transceiver
#include "drv_gps.h"
#include "board.h"

#ifndef BSP_GPS_DEVICE_NAME
#define BSP_GPS_DEVICE_NAME        "gps"
#endif

#ifndef GPS_UART_DEVICE_NAME
#define GPS_UART_DEVICE_NAME        "uart6"
#endif

#define GPS_UART_BAUDRATE           BAUD_RATE_9600

static struct rt_device _gps_dev;
static rt_device_t gps_uart_dev = RT_NULL;
static rt_bool_t gps_uart_open_flag = RT_FALSE;

static rt_err_t  _gps_dev_init(rt_device_t dev)
{
    return RT_EOK;
}

static rt_err_t gps_uart_rx_ind(rt_device_t dev, rt_size_t size)
{
    RT_ASSERT(dev != RT_NULL);
    if (_gps_dev.rx_indicate != RT_NULL)
    {
        _gps_dev.rx_indicate(&_gps_dev, size);
    }
    return RT_EOK;
}

static rt_err_t  _gps_dev_open(rt_device_t dev, rt_uint16_t oflag)
{
    struct serial_configure gps_uart_config = RT_SERIAL_CONFIG_DEFAULT;

    if (dev == RT_NULL)
        return -RT_ERROR;

    gps_uart_dev = rt_device_find(GPS_UART_DEVICE_NAME);
    if (gps_uart_dev != RT_NULL)
    {
        if (gps_uart_open_flag == RT_FALSE)
        {
            gps_uart_config.baud_rate = GPS_UART_BAUDRATE;
            rt_device_control(gps_uart_dev, RT_DEVICE_CTRL_CONFIG, &gps_uart_config);
            rt_device_open(gps_uart_dev, oflag);
            rt_device_set_rx_indicate(gps_uart_dev, gps_uart_rx_ind);
            gps_uart_open_flag = RT_TRUE;
        }
    }

    return RT_EOK;
}

static rt_err_t _gps_dev_close(rt_device_t dev)
{
    rt_err_t ret = RT_EOK;

    if (gps_uart_open_flag == RT_TRUE)
    {
        ret = rt_device_close(gps_uart_dev);
        gps_uart_open_flag = RT_FALSE;
    }
    return ret;
}

rt_size_t _gps_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    return rt_device_read(gps_uart_dev, pos, buffer, size);
}

rt_size_t _gps_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    return rt_device_write(gps_uart_dev, pos, buffer, size);
}



static rt_err_t _gps_dev_control(rt_device_t dev, int cmd, void *args)
{
    if (dev == RT_NULL)
        return -RT_ERROR;

    switch (cmd)
    {
    default:
        break;
    }

    return RT_EOK;
}

#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops gps_dev_ops =
{
    _gps_dev_init,
    _gps_dev_open,
    _gps_dev_close,
    _gps_dev_read,
    _gps_dev_write,
    _gps_dev_control
};
#endif

static int gps_device_register(const char *name, void *user_data)
{
    _gps_dev.type = RT_Device_Class_Char;
    _gps_dev.rx_indicate = RT_NULL;
    _gps_dev.tx_complete = RT_NULL;

#ifdef RT_USING_DEVICE_OPS
    _gps_dev.ops = &gps_dev_ops;
#else
    _gps_dev.init = _gps_dev_init;
    _gps_dev.open = _gps_dev_open;
    _gps_dev.close = _gps_dev_close;
    _gps_dev.read = _gps_dev_read;
    _gps_dev.write = _gps_dev_write;
    _gps_dev.control = _gps_dev_control;
#endif

    _gps_dev.user_data = user_data;

    /* register device */
    rt_device_register(&_gps_dev, name, RT_DEVICE_FLAG_RDWR);

    return 0;
}

int gps_device_init(void)
{
    return gps_device_register(BSP_GPS_DEVICE_NAME, RT_NULL);
}

INIT_BOARD_EXPORT(gps_device_init);
  • Here we use the [dolls] method to register a gps device and actually call uart6 serial port device
  • [summary 2] the baud rate adjustment method of GPS serial port is initialized to 115200 by default. Here, the default of GPS module is 9600. The change method is as follows
struct serial_configure gps_uart_config = RT_SERIAL_CONFIG_DEFAULT;
gps_uart_config.baud_rate = GPS_UART_BAUDRATE;
rt_device_control(gps_uart_dev, RT_DEVICE_CTRL_CONFIG, &gps_uart_config);
  • RT_ DEVICE_ CTRL_ The config control command will eventually call drv_usart.c, re configure the serial port

debugging

  • UART6 at the bottom layer has been built. The upper layer only needs to receive and analyze the data received by GPS.
  • For the reception of the upper layer, please refer to the article on the implementation of virtual GPS equipment

Summary

  • Familiar with the receiving configuration and baud rate setting method of uart serial port
  • Familiar with GPS debugging

Topics: rt-thread gps