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

Nordic UART (NUS) Flow control

Hi! I did see a post about this, but is there a way to implement any kind of throttling/flow control over the Nordic UART service?

About the only thing I can imagine is attempting to renegotiate the connection interval, but in the case of a write with response, is it possible to delay that response? Or would a delay of too long just cause connection issues?

Parents
  • Hello,

    Can you please share where you found the post on flow control on the Nordic UART Service?

     

    Flow control is usually something you use on physical UARTs, but when you use BLE you don't need that. The softdevice will ensure that packets that are lost are retransmitted. This is always ensured when you use notification in BLE, like the ble_app_uart example (which uses the Nordic UART Service) does.

     

    Best regards,

    Edvin

Reply
  • Hello,

    Can you please share where you found the post on flow control on the Nordic UART Service?

     

    Flow control is usually something you use on physical UARTs, but when you use BLE you don't need that. The softdevice will ensure that packets that are lost are retransmitted. This is always ensured when you use notification in BLE, like the ble_app_uart example (which uses the Nordic UART Service) does.

     

    Best regards,

    Edvin

Children
  • Thanks! It was this post: devzone.nordicsemi.com/.../99565

    "There is no flow management on top of NUS Characteristic Value data (Write or Notify) methods. So whatever you need to do (...) you need to define and implement on application layer (in your apps)."

    But that's really interesting. In my code, I'm using 'ble_nus', and 'data_handler' is called whenever data is available - there is no way to avoid accepting the data. Is there some way to jump in and 'nack' the BLE_GATTS_EVT_WRITE that causes the data_handler to be called?

  • Hello,

    What endnode wrote there is correct. You can't not accept characteristics with notification. As soon as the softdevice receives this event, you must handle it. As he explains,  you may use a separate characteristic to tell the other device to stop pushing data, if you need some time to handle it.

     

    Alternatively, you may implement this using indication instead of notification. However, this means that you have to ack each packet in the application layer, meaning the other device can send maximum one packet per connection interval, which will drastically decrease the throughput. When using notification, the softdevice will ACK the packet if the CRC is correct (you will not see any of this from the application). But in order to validate the incoming data in the application, there is not enough time to do this within the same connection interval. And since the maximum number of indications "queued" is 1, this means only one packet per connection interval.

     

    Best regards,

    Edvin

  • Thanks! Do most implementations of NUS central support using indications, or would I have to make sure I wrote my own to communicate properly?

    So basically without changing the NUS implementation I am out of luck for flow control - I'd be better off trying to implement XON/XOFF or something on top of it...

  • Hello,

    I realize that some parts of my reply may be a bit confusing.

     

    On physical UARTs, you use flow control to prevent the other device to send when you are not ready to receive new packets, if you have not yet had time to handle the RX buffers.

     

    In BLE, when you use notifications, you have a flow control to some degree. The other device will not be able to write to the NUS service if the queue is already full. The two devices will decide on a buffer size upon connection (MTU size). This is protocol is decided in the BLE specification, and hence, all BLE devices will follow this protocol.

    When the nRF ACKs a message, the other device will get this message, and it will have some new space in the queue. If you make sure to handle all the data in the nus_data_handler() (in main.c), in the BLE_NUS_EVT_RX_DATA event, you will be fine. You will only get this event once per message.

    If you still need the other device to stop sending data for some reason, you must add your own flow control.

     

    You can either change the ble_nus service to use indication instead of notification. This means that you have to send the ACK message from the application layer. This is possible, but it will significantly decrease the throughput of the link, as only one message can be sent per connection_interval. If that is OK, then this may be the most elegant solution.

    Another possibility is to use some other characteristic to tell the other device that you are not ready to receive more packets. You can use the TX characteristic for this. However, this is application specific, so you need to implement this in the connected device as well. There is nothing preventing the device from sending more data, but if it follows the same application specific protocol as the peripheral, this could work.

    As a last option, you can use some third (or 4) characteristic for this. You can either add it to the NUS service, or create another service for this. Then it would probably be intuitive to set up two more characteristics, RTS and CTS, which will work as the physical UARTs flow control. Also in this solution, there is nothing actually preventing the other device from sending, but as long as both devices follow these rules, it should work.

     

    Best regards,

    Edvin

  • Thanks for the in-depth reply! It looks like given the lower transfer speed of using indications I am better off building flow control on top of what's there already.

Related