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

UARTE STOPRX on exact byte

Hi there,

I'm issuing a STOPRX at a specific time but I'm noticing that more bytes are being put into the buffer from after the STOPRX was issued.

Is there a way to stop the UARTE on the exact byte and process, and receive all bytes from that point on to a different buffer?

Please advise.

UPDATE

After triggering a STOPRX, the UARTE will hang around for a few more bytes, placing them in the same buffer and then calling ENDRX. This is problematic since these new bytes are part of a different message.

image description

Here you can see that STOPRX is triggered during some small idle times, yet the ENDRX doesn't happen till much later.

This results in ENDRX being called with 11, 6 and 1 bytes read (when it should be 6, 6 and 6 bytes read)

  • As I said, there are some thing which need clarification, and that's one of them. However I think that delay is just the uart waiting for another character, they don't have to be entirely back-to-back, there is a timeout. So you've started a transfer asking for n bytes and it's doing its best to fulfil that.

    I think your use case, now you've described it, is something you just can't really do like this, stopping it at a random time and hoping to get the exact number of bytes left in the buffer. I wondered about setting the byte count to '1' and updating the pointer every byte, that might make it stop instantly after the STOP task as it has nothing else to do, not sure that would work either however.

  • That would most likely work, but then I would be back at firing interrupts every byte in order to switch buffers. The point of this is to avoid interrupting the softdevice.

    I was thinking of never stopping the UARTE and just reading the bytes from the pointer during a Timer interrupt. The problem with that is knowing how many bytes to read, as the AMNT register is not available until after an ENDRX event.

  • Hi,

    First off, I think RK has made some great insights here, so thanks!

    I can tell you that the RXTO is generated via an internal timer which is counting on the baud rate clock. Thus, if you have ample room in your RX buffer, following a STOPRX, it will take the time it takes for 4 bytes to transfer (even if no byte is transferring) for the ENDRX to be generated (followed by the RXTO). If you only have room for say 2 more bytes at STOPRX, then if the external uart is transferring continuously you would get ENDRX after those 2 bytes, and RXTO after 4 bytes, and 2 bytes would be left in the FIFO for you to push.

    It could have been designed to have this feature optional, i.e. that you could make it close the RX buffer immediately or after any byte that was currently in progress, and then generate ENDRX. This is not the case in the hardware on nrf52 though.

    I gather you want the protocol to not relate to a fixed number of bytes received, but rather a fixed timing of each message with a variable amount of bytes received? You just want a clean split on each of the messages? Perhaps there is an alternative (albeit a bit cumbersome) approach you can try. If I’ve misunderstood I suppose you can disregard the rest.

    Use a TIMER on the nrf52-side: start the timer on RXSTARTED, give a compare event on TIMESLOT-(4*Baudrate), stop the UARTE based on the compare event.

    If you keep MAXRX larger than the absolute max bytes you can receive on that baud rate in the timeslot of your protocol, you know that all the bytes in the buffer at ENDRX were transferred as part of a single message. Then do a restart on RXTO and the new RXPTR will be in effect, a new RESTARTED will restart the TIMER etc. The period your UARTE is unable to receive would be basically zero.

  • Thanks for the writeup. It's unfortunate the option to "close RX" is not available in hardware, I feel as though the FLUSHRX task should have that functionality, but it doesn't.

    I'm not sure what TIMESLOT would be equal to. Since the messages are variable length, the time each will take is also variable.

  • But you know when to trigger STOPRX from the CPU? i.e. even if it varies between the messages? The main point was to trigger STOPRX "the time it takes to transfer 4 bytes" earlier than you currently do it to be sure that all bytes in the current RX buffer was from the same message.

Related