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.