Hi,
I've been working to get a Ublox GPS module to interface with my NRF52840 DK over UART. The GPS device boots up and starts streaming data almost immediately.
I am using SDK 15.2, and trying to use UART with DMA.
My code is as follows:
uint8_t ubx_only_9600[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A, 0x79}; uint8_t ubx_no_msg_out[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x73}; uint8_t ubx_enable_nav_pvt_msg[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xE1}; NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config, GPS_TX_PIN, GPS_RX_PIN, NULL, NULL, NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED, NRF_UART_BAUDRATE_9600, UART_DEFAULT_CONFIG_IRQ_PRIORITY); #define SERIAL_FIFO_TX_SIZE 128 #define SERIAL_FIFO_RX_SIZE 256 NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE); #define SERIAL_BUFF_TX_SIZE 32 #define SERIAL_BUFF_RX_SIZE 64 NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE); #define SERIAL_TIMEOUT 100 void serial_evt_handler(struct nrf_serial_s const *p_serial, nrf_serial_event_t event); NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_DMA, &serial_queues, &serial_buffs, serial_evt_handler, NULL); NRF_SERIAL_UART_DEF(serial_uart, 0); /* starts the serial communication */ void gps_begin(void) { gps_configured = false; ret_code_t ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config); APP_ERROR_CHECK(ret); nrf_serial_rx_drain(&serial_uart); ret = nrf_serial_write(&serial_uart, &ubx_no_msg_out[0], sizeof(ubx_no_msg_out), NULL, SERIAL_TIMEOUT); //DISABLE ALL UART MESSAGES FROM DEVICE, IN AN ATTEMPT TO SYNCHRONISE STREAMS APP_ERROR_CHECK(ret); SEGGER_RTT_printf(0, "msgs disabled %d\n", ret); nrf_delay_ms(1000); nrf_serial_rx_drain(&serial_uart); ret = nrf_serial_write(&serial_uart, &ubx_only_9600[0], sizeof(ubx_only_9600), NULL, SERIAL_TIMEOUT); //RE ENABLE UART MESSAGES FROM DEVICE APP_ERROR_CHECK(ret); SEGGER_RTT_printf(0, "9600 baud set %d\n", ret); nrf_delay_ms(1000); ret = nrf_serial_write(&serial_uart, &ubx_enable_nav_pvt_msg[0], sizeof(ubx_enable_nav_pvt_msg), NULL, SERIAL_TIMEOUT); //ENABLE NAV_PVT MSG FROM DEVICE APP_ERROR_CHECK(ret); SEGGER_RTT_printf(0, "UBS_NAV_PVT msg enabled %d\n", ret); gps_configured = true; SEGGER_RTT_printf(0, "gps_configured\n"); } void serial_evt_handler(struct nrf_serial_s const *p_serial, nrf_serial_event_t event) { if (event == NRF_SERIAL_EVENT_RX_DATA) { uint8_t read_data[SERIAL_BUFF_RX_SIZE]; ret_code_t ret = nrf_serial_read(&serial_uart, &read_data, SERIAL_BUFF_RX_SIZE, NULL, SERIAL_TIMEOUT); APP_ERROR_CHECK(ret); for (int i = 0; i < SERIAL_BUFF_RX_SIZE; i++) { uint8_t input = read_data[i]; SEGGER_RTT_printf(0, "%x ", input); //do something with the data received here. } } else if (event == NRF_SERIAL_EVENT_DRV_ERR) { SEGGER_RTT_printf(0, "NRF_SERIAL_EVENT_DRV_ERR\n"); serial_error(); } }
within nrf_serial.c I have added the following (line 160 ish) to help me debug the error mask set by the UART peripheral.
case NRF_DRV_UART_EVT_ERROR: { nrf_drv_uart_error_evt_t error = p_event->data.error; switch (p_event->data.error.error_mask) { case NRF_UARTE_ERROR_OVERRUN_MASK: SEGGER_RTT_printf(0,"NRF_UARTE_ERROR_OVERRUN_MASK\n"); break; case NRF_UARTE_ERROR_FRAMING_MASK: SEGGER_RTT_printf(0,"NRF_UARTE_ERROR_FRAMING_MASK\n"); break; case NRF_UARTE_ERROR_PARITY_MASK: SEGGER_RTT_printf(0,"NRF_UARTE_ERROR_PARITY_MASK\n"); break; case NRF_UARTE_ERROR_BREAK_MASK: SEGGER_RTT_printf(0,"NRF_UARTE_ERROR_BREAK_MASK\n"); break; } event_handler(p_serial, NRF_SERIAL_EVENT_DRV_ERR); break; }
With my code above and the default driver, I constantly get an "OVERRUN" error. I can't find the in the documentation exactly what this error means? Has the FIFO overrun, or the Buffer?
I can fix this error by moving "event_handler(p_serial, NRF_SERIAL_EVENT_RX_DATA);" on line 150 of nrf_serial.c to line 159, which positions it after the call to "nrf_drv_uart_rx...".
I suspect this probably isn't a bug in the Nordic code, but rather a mistake in how I'm using the Serial driver? Even with the fix I detailed above, I do also occasionally get a Framing Error, which then ends up as another Overrun error.