This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

UART lock up

Hi,

I'm having some trouble using the UART protocol (4800 8N1) communicating with a GPS device.

It happen that the nRF51 device is not getting an interrupt (nothing at all, even not an error) when a NMEA character have been sent from the GPS. (I check on an oscilloscope and the data is well coming out of the GPS device).

I'm using UART FIFO provided by the SDK10 on the nRF51422.

Does someone have an idea of what happening?

void gps_init(void) {
  uint32_t err_code;
  const app_uart_comm_params_t comm_params = {
    GPS_TX, // RX pin number
    GPS_RX, // TX pin number
    0xFF, // RTS pin number, only if flow control is enabled
    0xFF, // CTS pin number, only if flow control is enabled
    APP_UART_FLOW_CONTROL_DISABLED,
    false, // parity configuration
    UART_BAUDRATE_BAUDRATE_Baud4800
  };

  APP_UART_FIFO_INIT(&comm_params,
          GPS_RX_BUFF_SIZE,
          GPS_TX_BUFF_SIZE,
          uart_handler,
          APP_IRQ_PRIORITY_LOW,
          err_code);
  APP_ERROR_CHECK(err_code);
}

static void uart_handler(app_uart_evt_t * p_event) {
  switch (p_event->evt_type) {
    case APP_UART_DATA_READY:
      sys.gps.comm_status = true; // Variable set to notify the state of the communication
      SEGGER_RTT_printf(0, "A character received");
      break;

    case APP_UART_TX_EMPTY:
      SEGGER_RTT_printf(0, "transmission done");
      break;

    case APP_UART_DATA:
      // Not used here because of the UART FIFO mode
      break;

    case APP_UART_COMMUNICATION_ERROR:
      sys.gps.comm_status = false;
      app_uart_flush();

      if (p_event->data.error_communication & UART_ERRORSRC_BREAK_Msk) {
        SEGGER_RTT_printf(0, "UART communication error: The serial data input is '0' for longer than the length of a data frame.\n");
      }
      if (p_event->data.error_communication & UART_ERRORSRC_FRAMING_Msk) {
        SEGGER_RTT_printf(0, "UART communication error: A valid stop bit is not detected on the serial data input after all bits in a character have been received.\n");
      }
      if (p_event->data.error_communication & UART_ERRORSRC_PARITY_Msk) {
        SEGGER_RTT_printf(0, "UART communication error: A character with bad parity is received. Only checked if HW parity control is enabled.\n");
      }
      if (p_event->data.error_communication & UART_ERRORSRC_OVERRUN_Msk) {
        SEGGER_RTT_printf(0, "UART communication error: A start bit is received while the previous data still lies in RXD. (Data loss).\n");
      }

      break;

    case APP_UART_FIFO_ERROR:
      app_uart_flush();

      SEGGER_RTT_printf(0, "error UART FIFO, code: %d\n", p_event->data.error_code); // check code error in nrf_error.h file
      break;

    default:
      break;
  }
}
  • Hi,

    Make sure that both the GPS and the nRF51 device are configured with the same settings (Baud-rate, parity, flow-control) and connected correctly(RX_PIN_NUMBER/ TX_PIN_NUMBER). Also make sure that the UART is initialized properly without error(see this post about debugging).

    Also check that you are not running to the isssue described here.

  • Thank Sigurd for your answer.

    I tried to run my program with the patch you suggest me (see this link). But it didn't help to solve my issue.

    After further research in the nordic library I found what was causing me trouble and patch it (see bellow), which resolved everything in my case.

    My problem because I wasn't reading my FIFO buffer fast enough (this happen in purpose) I started to have the length between my reading pointer and my writing pointer bigger than the FIFO length buffer than I declared.

    file modified: components/libraries/uart/app_uart_fifo.c (line 21)

    static __INLINE uint32_t fifo_length(app_fifo_t * const fifo)
     {
       uint32_t tmp = fifo->read_pos;
    -  return fifo->write_pos - tmp;
    +  return (uint32_t)((uint32_t)fifo->write_pos - tmp) & fifo->buf_size_mask;
     }
    

    file modified: components/libraries/fifo/app_fifo.c (line 30)

    static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo)
    {
      uint32_t tmp = p_fifo->read_pos;
    -  return p_fifo->write_pos - tmp;
    +  return (uint32_t) ((uint32_t) p_fifo->write_pos - tmp) & p_fifo->buf_size_mask;
    }
    

    Of course if anyone think at a better solution to solve this issue I'm open to any suggestion.

Related