This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2541: OAD seems really slow (3 minutes for ~100K)

Part Number: CC2541
Other Parts Discussed in Thread: CC2540, BLE-STACK

Is 3 minutes the expected amount of time for the Over-the-Air Download (OAD) code to send ~100K of code?  I'm using a SmartRF05 eval board with a CC2540 daughter board running the OADManager app and connecting to a CC2541-based module.

If this is the "normal" speed, it may end up being a show-stopper for us.

Are there any tricks or suggestions people can offer to help speed this up?  Ideally by a factor of 10 or more.

I realize I sound a little nitpicky - but Bluetooth routinely sends data at a much faster overall rate than this - so OAD must be doing something "weird" to make it that slow.  Especially considering the comment in section 14.3 of the OAD manual about OAD being designed "to reduce code size and increase data throughput as much as possible."

Thanks.

  • Hi Jim,

    This might be possible. Based on a back of the napkin calculation:

    OAD blocks are 16B large, so a 100K image has 6400 blocks.
    The OAD protocol is written such that a single block of data is sent every other connection event(CE)
    CE1 : OAD target requests block N
    CE2: OAD manager/downloader sends block N

    Thus, it would take around 12800 connection events to send a 100K image.
    If you are using the stock OAD Manger project it will use a connection interval of 10ms.

    So total time = 12800*(10e-3) = 128s which is a little over 2min, and that assumes no missed connection events.
    There are ways to make this faster, such as using a larger OAD block size, but that would require an MTU exchange before hand to ensure that both sides of the link can support a larger block size.

    You can also try to burst block write commands without waiting for the notification from the target, but this doesn't have a good flow control mechanism.
  • This is very encouraging. Thanks. I'll start digging and see what I can come up with...

    One question: Is "an MTU exchange" something that the BLE stack takes care of for me - or will I have to add new code to the OAD layer?
  • Hi Jim,

    MTU exchange is handled by stack, but upon further review, it looks like it is fixed to 23 in the 1.4.x stack, my apologies for being misleading.

    It looks like the best option is for you to attempt to send block writes without waiting for the request notification. This should cut the download time in about half.
  • I've tried a few things, but feel like I'm fishing blind...
    I tried lowering the connection interval values in the call to GAPCentralRole_UpdateLink() in OAD Manager - but it didn't seem to make a difference.
    Can someone offer specific instructions for either increasing the block size or lowering the connection interval?
    And pretending like I'm an idiot newbie might be for the best... :-)
    Thanks.
  • Hi Jim,

    The OAD manager is already setup to use a pretty low connection interval (10ms) set by DEFAULT_OAD_MIN_CONN_INTERVAL in oad_mgr_app.c

    Changing this will not make much difference in your overall throughput, but you can try. The acceptable range for this define is 6-3200 (7.5ms to 4s).

    As I mentioned in the last post, changing the block size is unfortunately impossible on BLE-Stack 1.4.2.

    The best way you can optimize throughput is to have the OAD Manger not pend on each notification from the target and instead to send blocks without this flow control mechanism. Right now the block handling mechanism is processed in oadManagerHandleNoti() under the case of pNoti->handle == oadManagerHandles[OAD_CHAR_IMG_BLOCK].

  • OK, this is starting to gel - but I'm still a little fuzzy...

    As I see it, the sequence is as follows:

    • Target sends a notification (GATT_Notification()) with the block number being requested.
    • OAD Manager sees the notification (via the method ATT_HANDLE_VALUE_IND).
    • OAD Manager sends the requested data block via GATT_WriteNoRsp().
    • OAD Manager then waits for the next notification.

    So what I'd like to do is have the OAD Manager send the next block without waiting for a notification.  However, I obviously need to wait until the current block has been sent before attempting this.

    Is there a GATT event generated when GATT_WriteNoRsp() finishes sending its message?  If so, I could add a case to the oadManagerProcessGATTMsg() function that would queue up the next block.

    Am I on the right track?

    Thanks.

  • One step forward (maybe?), one step back...
    I changed the call to GATT_WriteNoRsp() to a call to GATT_WriteCharValue() and then added a handler for the event ATT_WRITE_RSP.
    My intention was to send the next block as soon as possible. However, I'm getting a return code of 2 (ATT_ERR_READ_NOT_PERMITTED) from the first call to GATT_WriteCharValue().
    Obviously, I'm missing some important concept here.
    Any help would be appreciated.
    Thanks.
  • Hi Jim,

    Unfortunatley there is no event generated when GATT_WriteNoRsp completes, however packets are acknowledged at the Link Layer and the TI BLE Controller will not dequeue a packet until it sends. Since this is guaranteed to be safe, you are able to queue up packets on the OAD manager side until the buffer is full (bleNoResources or other type of error from your WriteNoResponse call). These packets will be sent in order.

    I would recommend against GATT_WriteCharValue as this is an acknowledged procedure and requires an "ack" from the other device, this will significantly reduce throughput.