This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nRF52 recommended ways to reduce and deal with 3004?

Hello Pros,

I maybe running the nRF52 close to its limit. It appears to have a probability of 1/1000 to 1/2000 to hit a 3004 in a continuous time-gated packets stream.

The packets are scheduled in synchrony with other dependencies at 30ms, 120 bytes each session composed with 6 of 20 byte packets. The central and peripherals are both nrF52, running on NUS calls.

I checked no other BLE events are interfering. The connection seems to be stable. There should be no other interrupts except one I setup to trigger and serviced immediately about every 4ms.

The softdevice is S132. SDK11. HW PCA10040.

Min and max connection intervals are both at 10ms.

I have experimented with a wait using while() on BLE_EVT_TX_COMPLETE, but there are cases this event never happen (I guess), so that the process stuck in a while loop forever.

I tried to add some amount of delays on if (~BLE_EVT_TX_COMPLETE) prior to each transaction, this helped to reduced the number of 3004s.

Are there ways to terminate or clear manually the current transfer if failure is detected (no success error) and resend immediately?

Are there other things you could recommend to improve or deal with 3004s? Error correction techniques? If it can just handle a little faster or a 1e-6 session error rate, I'd be very happy.

Thanks!

FI

  • The proper way to deal with user buffer management is to keep track of the buffers that you can use. Error 0x3004 aka BLE_ERROR_NO_TX_PACKETS is only returned when you try to call a function that consumes a user buffer, but none are free.

    Call sd_ble_tx_packet_count_get() at the start of the connection. This gives you the total number of user buffers assigned to that link. Note that this is the total number of buffers, not the amount of free buffers.

    Save the number that this function outputs, and decrement it every time you call a function that consumes a user buffer - but only if it returns NRF_SUCCESS. If you do not have any free buffers, wait for a BLE_EVT_TX_COMPLETEevent. Or better yet, receive these while you are sending. Increase the number with the "count" field of the event when you received it. That is how many packets the peer side has ACKed.

    If you keep track of your buffers like this, you will never get the 0x3004 error.

    Please also do a search on DevZone for the therms BLE_ERROR_NO_TX_PACKETS and BLE_ERROR_NO_TX_BUFFERS (its previous name) to find similar questions with good answers.

  • I examined the timing between ble_nus_c_string_send commend to BLE_EVT_TX_COMPLETE on a scope. Once in a while, the BLE_EVT_TX_COMPLETE will happen outside a 30ms window, this window is required in my application, as it is the timing between buffer fills, and if previous transmit cannot complete before the next transmit event happens after 30ms, error occurs. Any techniques for packet management to maximize data stream reliability? Thanks FI.

  • No - if the buffer isn't free it's not free because it hasn't been sent yet or is being retransmitted or it needed a reply it hasn't had or the other side has missed a window or you have interference or any other of a host of things. Once a packet is accepted for transfer, it will continue to use a buffer until it's been transferred, in order, to the other side, that's the guarantee of the link layer.

    If you have the connection interval already down to the lowest possible, so the link is going as fast as it can, and you're filling it absolutely to capacity, any drop out, any interference, is going to result in one or more retransmits and you're going to miss your window. If you don't have the connection interval down to the lowest possible, fix that. If you do, you need to figure out what your bandwidth is and give yourself some headroom, say 20%, for interference.

  • Thanks RK, for the clarification especially on the link layer guarantee.

    I already changed the code to queue up more and transmit over several connections in one setting, this spread out the single shot long timing once a while, and seems working good. No 3004s for few hours now. Looks like by doing this I at least has 2x to 3x the margin :)

  • When errors occur, you should still make sure to fail gracefully here. There can (and will) be situations where there is too much interference to keep sending. Examples could be strong Wi-Fi signals, micro wave radiation leakage, or just rooms with bad radio reflections. The peer side, if outside your control, can also end up in a state where it NACKs packets for an extended amount of time. These are all valid scenarios in the field, so please make sure to handle situations outside of your margin too.

Related