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

UART tx stops due to flow control; requires power cycle

tl;dr: UART transmission sometimes stops and never resumes. Only a power cycle resolves the issue; a system reset is not sufficient. The problem only occurs when flow control is used.

Hardware: nRF51dk 51422, PCA10025, V1.2.0, 2015.51, 681740259

Setup: nRF board periodically sends data over its UART to a Linux peer.

UART config: * Baud: 1 Mbps * Flow control: RTS/CTS * Data bits: 8 * Parity: N * Stop bits: 1

My setup consists of a custom Bluetooth controller on the nRF51dk and a Bluetooth host on a Linux machine. The board and linux machine communicate via UART with the settings specified above. The UART communication is sporadic and bidirectional.

At some point, the nRF unexpectedly stops transmitting and never resumes. From the UART state, it appears the hardware thinks the CTS line is deasserted, and it is waiting for the linux machine to be ready to accept more data. However, a logic analyzer shows that the CTS line is asserted (that is, CTS is low), so flow control should not be preventing a transmission.

The strangest thing about this problem is that it is not resolved with a board reset (monitor reset in gdb). After reset, the UART still refuses to transmit after being configured. The only way to get the nRF out of the bad state is a power cycle.

While the board is in the bad state, if I disable flow control in gdb by writing 0 to NRF_UART0->CONFIG, the board immediately begins transmitting over its UART. If I reenable flow control by writing 1 to NRF_UART0->CONFIG, UART transmission halts once again.

Here is the value of NRF_UART0 while the board is in the bad state in case it provides any clues:

(gdb) p/x *(NRF_UART_Type *)0x40002000
$2 = {
  TASKS_STARTRX = 0x0,
  TASKS_STOPRX = 0x0,
  TASKS_STARTTX = 0x0,
  TASKS_STOPTX = 0x0,
  RESERVED0 = {0x0, 0x0, 0x0},
  TASKS_SUSPEND = 0x0,
  RESERVED1 = {0x0 <repeats 56 times>},
  EVENTS_CTS = 0x1,
  EVENTS_NCTS = 0x1,
  EVENTS_RXDRDY = 0x0,
  RESERVED2 = {0x1, 0x0, 0x0, 0x0},
  EVENTS_TXDRDY = 0x0,
  RESERVED3 = 0x0,
  EVENTS_ERROR = 0x1,
  RESERVED4 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1},
  EVENTS_RXTO = 0x0,
  RESERVED5 = {0x0 <repeats 46 times>},
  SHORTS = 0x0,
  RESERVED6 = {0x0 <repeats 63 times>, 0x84},
  INTENSET = 0x84,
  INTENCLR = 0x84,
  RESERVED7 = {0x0 <repeats 93 times>},
  ERRORSRC = 0xc,
  RESERVED8 = {0x0 <repeats 31 times>},
  ENABLE = 0x4,
  RESERVED9 = 0x0,
  PSELRTS = 0x8,
  PSELTXD = 0x9,
  PSELCTS = 0xa,
  PSELRXD = 0xb,
  RXD = 0x0,
  TXD = 0x4,
  RESERVED10 = 0x0,
  BAUDRATE = 0x10000000,
  RESERVED11 = {0x0 <repeats 14 times>, 0x1, 0x1, 0x1},
  CONFIG = 0x1,
  RESERVED12 = {0x0 <repeats 421 times>, 0xfffffffc, 0xfffffffc, 0xfffffffc, 0x0 <repeats 250 times>, 0x1},
  POWER = 0x1
}

In addition, here is the UART code I am running on the nRF51dk: github.com/.../hal_uart.c

I am going to see if I can replicate this issue with other nRF boards. In the meantime, all suggestions and comments are appreciated.

Thanks, Chris

Related