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

Bit loss on NRF52840 UARTE at 115,200

Summary

I am using UARTE on NRF52840 at 115,200 but am experiencing "bit loss", i.e. the UARTE is losing a few bits in the incoming stream causing corruption of all incoming characters from that point onwards. I am setting the baud rate correctly, using UARTE_BAUDRATE_BAUDRATE_Baud115200 (0x01D60000UL) in my call to nrf_uarte_baudrate_set().  What might I do to fix this problem?

Detail

I'm using UARTE on NRF52840 with DMA, my own driver (full source code here).  My driver is working but every so often I find that the received character stream becomes corrupted; sometimes this happens in the middle of a long burst (several hundred characters), other times it happens even on a very short burst of data (e.g. 15 characters).

You might expect a bug in my code but the weird thing is that the corrupted data is not random, it follows the pattern of the data I know should arrive. For instance the ASCII text:

01234567890123456789

arrives as:

0[92][9a][a2][aa][b2][ba][c2][ca][82][8a][92][9a][a2][aa][b2][ba][c2][ca]

As you can see, the pattern of 10 rising things in a row is still there, it's just not the 10 things I expect: after the error has occurred 0123456789 arrives as [82][8a][92][9a][a2][aa][b2][ba][c2][ca].  This is completely consistent: every time the problem occurs the expected characters end up as the same pattern of corrupted characters.  And it's not the kind of thing that a bug in my code could cause: random data, yes, the expected data modified in some way, no.

I have captured the received characters at the input to the NRF52840 DK board with a Saleae logic probe and the probe sees the characters correctly. See below a trace captured at the start of the sequence above, all is correct up to __1300:0 then the characters 123456789 arrive in the DMA buffer as [92][9a][a2][aa][b2][ba][c2][ca] etc.

Saleae probe

Looking at a simpler received pattern, if the corruption occurs when I am meant to receive the five ASCII underscores _____, binary 01011111 01011111 01011111 01011111 01011111, then around that time what ends up in my DMA buffer is [ca]}}}[e9] or binary 11001010 01111101 01111101 01111101 01111101 11101001, which as you can see is the expected sequence shifted by two bits to the left.

So I think what's happening is that the UARTE is skipping bits, losing sync with the incoming data stream.  My software times out, having not received what it is meant to receive, and on subsequent receives things have fixed themselves in UARTE land and the correct character do appear.

Parents
  • Are you getting framing errors reported by the UART ?

  • An excellent question, I should have thought to check that.

    Dumping the return value of nrf_uarte_errorsrc_get_and_clear() in the NRF_UARTE_EVENT_ERROR part of the interrupt into an array and printing the values out afterwards, when there is no problem I get no error events and when the problem occurs I get alternating framing errors/breaks followed by lots of framing errors, something like this:

    framing error
    framing error
    break
    framing error
    break
    framing error several 10s of times

  • can you get the sender to add an extra Stop bit? or an inter-character delay ... ?

  • Unfortunately this is multi-platform code intended to work with multiple chipsets (i.e. other than NRF52840) and multiple AT modems so the answer is "not without a lot of pain".

    In this particular instance I can hack the AT modem by sending it an AT command to switch it into sending 2 stop bits but that stops everything working unless I also set 2 stop bits on the NRF52840 side and, curiously, the NRF API omits the ability to do that (nrf_uarte_configure() doesn't include a "number of stop bits" parameter).  If I hack that as well by writing to the register directly then of course it doesn't work to begin with because the AT modem doesn't initially send two stop bits it has to be told to do so via an AT command, etc...

    So it would be a last resort as I would have to introduce platform dependencies up in the generic AT driver code.

    Running a pair of UARTs talking to each other at 115,200 shouldn't be much of a strain on the system: is there anything I might configure on the NRF52840 side to improve matters?

Reply
  • Unfortunately this is multi-platform code intended to work with multiple chipsets (i.e. other than NRF52840) and multiple AT modems so the answer is "not without a lot of pain".

    In this particular instance I can hack the AT modem by sending it an AT command to switch it into sending 2 stop bits but that stops everything working unless I also set 2 stop bits on the NRF52840 side and, curiously, the NRF API omits the ability to do that (nrf_uarte_configure() doesn't include a "number of stop bits" parameter).  If I hack that as well by writing to the register directly then of course it doesn't work to begin with because the AT modem doesn't initially send two stop bits it has to be told to do so via an AT command, etc...

    So it would be a last resort as I would have to introduce platform dependencies up in the generic AT driver code.

    Running a pair of UARTs talking to each other at 115,200 shouldn't be much of a strain on the system: is there anything I might configure on the NRF52840 side to improve matters?

Children
Related