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.

CC2650STK: OAD Update Recovery from OAD_BUFFER_OFL error

Part Number: CC2650STK
Other Parts Discussed in Thread: CC2640, CC2640R2F

I am working on a project based heavily on the Sensortag both in firmware and hardware.  My current task is to improve the reliability of the OAD update.  I am using the BLE Device Monitor program to characterize failures and have narrowed down our most reoccurring problem to an OAD_BUFFER_OFL error.  In the firmware, I have found that this is the section of code that causes the error (in red below)

In oadService.c, OADService_ImgBlockWrite():

...

if (oadBlkNum == blkNum)
{
    // Calculate address to write as (start of OAD range) + (offset into range)
    uint32_t addr = imageAddress + (oadBlkNum * OAD_BLOCK_SIZE);

    // If address starts a new page, erase that page first.
    if ((addr % HAL_FLASH_PAGE_SIZE) == 0)
    {
        if (!OADTarget_eraseFlash(addr / HAL_FLASH_PAGE_SIZE))
        OADTarget_systemReset();
    }

    // Write a 16 byte block to Flash.
    OADTarget_writeFlash(imagePage, (blkNum * OAD_BLOCK_SIZE), pValue+2, OAD_BLOCK_SIZE);

    // Increment received block count.
    oadBlkNum++;
}
else
{
    // Overflow, abort OAD
    oadBlkNum = 0;

    flagRecord = 0;

    // Close the target device
    OADTarget_close();

    // Send status
    OAD_sendStatus(connHandle, OAD_BUFFER_OFL);

    delay_ms(1000);
    OADTarget_systemReset();
}

So oadBlkNum and blkNum could be used as a sequence counter - in the case that they do not match, I would like to request the current oadBlkNum again but the BLE Device Monitor does not seem to respond to a:

// Request the next OAD Image block.
OAD_getNextBlockReq(connHandle, oadBlkNum);

if that oadBlkNum block has already been sent.  In essence, this is a request for the downloader application to retransmit a block.  It seems like the BLE Device Monitor downloader keeps track of its own block sequence and is unwilling to retransmit a packet instead of responding to the OAD_getNextBlockReq.  Has anyone tried implementing this?  

Thanks,

Tom

  • Hi,

    This is likely due to a limitation of BLE Device Monitor. Try turning the blks/connection to 1.

    Also, for a better implementation of this, please see the latest version of BTool, which is provided with the CC2640R2F SDK. This will likely help you find the implementation that you are looking for. More information on doing OAD with BTool can be found in the CC2640 BLE OAD User's Guide found here: processors.wiki.ti.com/.../CC2640_OAD_User's_Guide.

    -Nathan
  • Hi Nathan,

    I tried BTool, and while the OAD does work, it is very slow.  I do know that I can change the blks/connections in the BLE Device Monitor, I have chosen 4 because it updates relatively quickly, and would work even faster if more blocks were sent.

    I would like to stay focused on my previous question regarding recovery from getting out of sync on the target.  I'm hoping that you are a BLE OAD guru, or you can put me in touch with one.

    From my first post:

    So oadBlkNum and blkNum could be used as a sequence counter - in the case that they do not match, I would like to request the current oadBlkNum again but the BLE Device Monitor does not seem to respond to a:

    // Request the next OAD Image block.
    OAD_getNextBlockReq(connHandle, oadBlkNum);

    if that oadBlkNum block has already been sent.  In essence, this is a request for the downloader application to retransmit a block.  It seems like the BLE Device Monitor downloader keeps track of its own block sequence and is unwilling to retransmit a packet instead of responding to the OAD_getNextBlockReq.  Has anyone tried implementing this?

    I also thought of another challenge with this approach since the first post:

    If blks/connection are greater than one, say four - it is possible for the target to have multiple block messages received, in the BLE queue or stack.  If the block counters get out of sync, all of the other blocks/messages waiting to be processed are also out of sync.  Is there a way to flush the buffer on a characteristic (correct term?) in target in this case?

    Thanks for your help,

    Tom 

  • Hi,

    That is a limitation of BLE Device Monitor. If you were using your own downloader you could allow this to happen. Also, what exactly do you mean by flushing the buffer?

    -Nathan
  • Nathan,

    I get it, The BLE Device monitor has limitations.

    Please focus on my question from my previous posts which are going unanswered.

    When I say "flush the buffer" I mean that if the OAD uploader gets out of sync on the client, and the blocks/connection is greater than one, it is possible for more blocks that will be out of sequence to be in the BLE stacks buffer.  I would like to flush it out of the stack so the OAD application does not have to process those blocks.

    Thanks,

    Tom

  • Hi,

    The way that the OAD service is currently set up, it is a sequential operation that just processes the current block and then requests the next one, based on the block number. BLE device monitor waits for the next block that it is expecting, so asking it to retransmit a block would be an issue. You could change this in the code by allowing a block request from any block number, even if it has already been sent. This does not violate anything in the Bluetooth spec, nor should it cause any issues with the stack.

    On the OAD target side, you could request that only the blocks that were received at the wrong time (the block number does not match what was expected) be resent. This can all be facilitated by using the block number that is embedded in the block. When the block is correctly received, the target device will write it to the location that is specified, which should be fine because it was not written the first time.

    I hope that this answers your questions,
    -Nathan
  • Hi Nathan,

    Thanks for the reply - that's what I was thinking, use the block ID as a sequence counter that can be resent if a block is received that is not expected.

    Now for my other question about a flush command:

    Here is an example:

    Let's say that the updater app is sending 4 blocks/connection.  That means that there are four blocks received by the client and they are processed one at a time.  Here is the use case I am working through:

    Blocks 5,6,7,8 are sent by the updater app.

    Block 5 is lost.

    Blocks 6,7,8 are sitting in the BLE stack in the client.

    Client processes block 6.  Blocks 7,8 are still in the BLE stack waiting to be processed.

    Client is expecting Block 5 but is processing Block 6.  Out of sequence error.

    Send another request for block 5.

    Updater receives a request for block 5 and sends block 5,6,7,8 (because it is set to 4 blocks per connection)

    Client still has blocks 6,7,8 in the stack, and now receives 5,6,7,8 from the updater.

    Client now has blocks 6,7,8,5,6,7,8 in the stack.

    What I would like to do (if the client gets out of sequence)  is be able flush any blocks that are still in the stack because they are also out of sequence.

    Is there a BLE stack operation that would accomplish this with regards to the OAD implementation?

    Make sense?

    Thanks,

    Tom

  • Hello Tom,

    Unlike classic BT, there is no flush command to the Controller for BLE. This is current as of BT 5.0. Once you enqueue a packet in the stack, i.e., via GATT_Notification, that packet will be transmitted unless the connection is terminated.

    Best wishes
  • Hi Nathan,
    Thanks for the quick response.

    I don't mean to flush before transmission on the updater side, I mean to flush what is in the receive buffer on the client. Is there a way to do that?

    Thanks,
    Tom
  • Hi Tom,

    I would suggest that you deal with this on the OAD Downloader side. In your example, just because the target asks for block 5 to be re-sent doesn't mean that 6,7 and 8 have to be as well. You could resend block 5 and then continue where you left off, again using the block number in the block to keep all of this straight.

    -Nathan
  • Nathan,
    Yes, this is an option for the updater app, but remember, the client still has those other blocks in it's stack ready to be processed and they are all out of sequence and will all trigger a resend block request. Unless I can flush that buffer things will be very problematic.

    Is there a BLE stack buffer flush command on the client side?

    Thanks,
    Tom
  • Hi,

    Unfortunately, no there is not. This would have to be dealt with by the OAD target where the blocks are received, probably by incrementing or decrementing the block count depending on the number of blocks that need to be re-sent. Then the blocks on the target side could be processed when the block count gets to that block number.

    -Nathan
  • Hi Nathan,
    Okay, I was hoping that there was a nice flush function I could call - but I can handle it at a higher layer.

    Thanks for your help.

    Thanks,
    Tom