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.

RTOS/CC1352R: BLE Peripheral Disconnects

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

Tool/software: TI-RTOS

Can someone explain the following parameters in gap.h?

typedef struct
{
  uint16_t connectionHandle; //!< Connection handle of the update
  uint16_t intervalMin;      //!< Minimum Connection Interval
  uint16_t intervalMax;      //!< Maximum Connection Interval
  uint16_t connLatency;      //!< Connection Latency
  uint16_t connTimeout;      //!< Connection Timeout
  uint8_t  signalIdentifier; //!< L2CAP Signal Identifier. Must be 0 for LL Update
} gapUpdateLinkParamReq_t;

The documentation is a bit useless, especially regarding the interval and conn parameters (as you can see).

  • Hi,

    This struct is used when the slave is requesting new parameters for the connection. Please see the BLE5-Stack user's guide for more ino: dev.ti.com/.../gap.html

    I don't understand how this relates to the title of your post.
  • I am doing some complex stuff with regards to the dual mode manager, which is tough to explain. Basically I have everything working, but I added a few more receive packets on the subghz side and it appears the extra time spent in the receive state (on the subghz side) is causing the peripheral to disconnect. It sounded like I need to increase the supervision timeout or adjust the max/min intervals, but that doesnt seem to resolve the issue. (also, that article has the range values that should be in the code documentation. thanks)

    I'm starting to think there must be something else in the BLE stack that is terminating the connection. It seems fairly random so I dont really have much to go on besides speculation. How long can I keep the ble connection alive, while the radio stack state is DMMPOLICY_STACKSTATE_WSNNODE_ACK?
  • Hi,

    You should be able to keep the BLE connection alive as long as the supervision timeout. If you're not exactly sure what's going on, it could be useful to use a logic analyzer and look at the RF pins. See the Technical Reference Manual, chapter 13 I/O Controller (IOC) ( http://www.ti.com/lit/swcu185 ) for instructions on routing the RF pins. This will show you when the radio is in Rx and Tx and may facilitate debugging.

    You will also need to add some padding to allow the DMM to run whenever a new packet is scheduled.
  • BTW what version of the SDK are you using?
  • I'm still on 2.20.0.71. I noticed 2.30.0.45 was just released, but the projectzero base I'm working from is pretty complex and gave me some issues when switching to the newer sdk. Looks like I'm going to have to start from scratch (with a clean project_zero) to update to the newer sdk. Do you think that will solve my problem?

    I caught this stack trace when the connection gets terminated, but I cant make sense of it (i.e. still not sure if something in the ble stack is kicking it out or if its a simple timing issue)

  • Hi,

    We are continuously making updates to the DMM, so it could be worth a try to update the version.

    On the call stack you see the ble stack (LL - link layer) terminating and cleaning up the connection. Can you post the connection termination status? llConnTerminate will be called when a BLE connection is terminated regardless of the reson for the connection breaking.
  • when I try and view the source for the LL_ProcessEvent, it says"
    Can't find a source file at "C:\ti\.ble5\ble5_stack\source\ti\ble5stack\controller\cc26xx\ll/ll.c"
    And I cant find that file in the sdk folder
  • I updated to sdk 2.30, but that didn't seem to resolve the issue. Its still disconnecting the ble device when I am receiving multiple subghz packets. Its receiving on the subghz for just under 2 seconds, which leads back to the original question of how long can the radio be doing other stuff, while keeping the ble device connected. My reading of that document suggests that should not be a problem given a high enough supervision timeout, but the DMM doesnt seem to care about that?

    It seems that something in the BLE stack is trying to access the radio while its tied up in my receive code... I just cant figure out what?

    The disconnects are sort of random. It doesnt happen every time, but its common enough to be a problem. My time scale is to enter the receive once a minute, and it disconnects every 3rd or 4th time.
  • Hi,

    The BLE-Stack is provided as a library, which is why you can't fint the ll.c file in the SDK.

    When the BLE connection is broken, Your application will receive a GAP_LINK_TERMINATED event. Can you post the "reason" of this event?

    /**
     * @ref GAP_LINK_TERMINATED_EVENT message format.
     *
     * This message is sent to the app when connection is terminated.
     */
    typedef struct
    {
      osal_event_hdr_t  hdr;     //!< @ref GAP_MSG_EVENT and status
      uint8_t opcode;            //!< @ref GAP_LINK_TERMINATED_EVENT
      uint16_t connectionHandle; //!< connection Handle
      uint8_t reason;            //!< termination reason from LL, defined in ll.h
    } gapTerminateLinkEvent_t;

    Can you try raising your connection interval and slave latency instead of increasing the supervision timeout? 

  • looks like pPkt->reason in GAP_LINK_TERMINATED_EVENT in ProjectZero_processGapMessage is 0x08, which appears to be defined as LL_STATUS_ERROR_CONNECTION_TIMEOUT in ll.h

    Just recapping the order of events:

    DMM in ble mode (working fine)

    Switches to a subghz receive (if I do one or 2 receives, the BLE side stays connected... but if I take too long there, the ble connection is terminated)

    The timeout reason makes sense, but I cant quite figure out how to increase the timeout to span my subghz exchange. I definitely do not fully understand how BLE connections work in this scenario, but I think it should survive a 2 second block with the right configuration (i.e. supervision timeout).

  • Hi,

    I'm not sure if supervision timeout applies in this situation since the CC1352R is the slave and does not even try to show up for connection events (since it's being starved by the sub-1 GHz receive command).

    Instead of using supervision timeout, can you try setting a high slave latency and connection interval, high enough that the slave is not missing any connection events? E.g. connection interval 200 ms, slave latency 10.
  • So the supervision timeout only applies to the device acting as the central (in my case that is an iphone)? I guess that makes sense, but I'm not sure how to set that on ios (and obviously this isnt the place to ask that).

    My concern is that the disconnect is almost immediate, but from what I've read the default timeout on ios should be about 6 seconds. This seems to be the 1352 actively disconnecting during the DMM/subghz receive, rather than a BLE timeout.


    I have tried the slave latency up to 40 (I'm not sure what the range of acceptable values are)

    I've also tried the connection interval min at 160 (or 200ms) and max at 800 (1000ms). I am not worried about power consumption on this side of the connection, so I'd like to keep these values as low as possible (my understanding is that would help throughput on data)

    None of those parameters in project_zero.c seem to have any impact on the disconnect condition.
  • Hi,

    Can you double check what connection parameters you are actually getting? Supervision timeout, connection interval, slave latency preferrably by sniffing the connection request packet sent by the master.

    I think a sniffer capture of this could also be interesting to see which device is actually timing out. 

  • Any direction on how to sniff the connection?

    I also found an inactivityTimeout in the ble user config that is set to RF_INACTIVITY_TIMEOUT which is set to zero. I couldn’t find anything that describes thie parameter, but it sounds like something interesting.
  • Hi,

    To sniff a BLE conenction, you need a dedicated BLE sniffer device, such as CC2540 USB Dongle running TI Packet Sniffer (  ) 

    Please look up the documentation for the RF Driver before you start changing the values in ble_user_config.c. RF_INACTIVITY_TIMEOUT sets .rfDriverParams.inactivityTimeout, which is described in the RF Driver guide with the following:

    Power-down on inactivity

    Whenever a radio operation completes and there is no other radio operation in the queue, the RF core might be powered down. There are two options in the RF driver:

    • Automatic power-down by setting the parameter RF_Params::nInactivityTimeout. The RF core will then start a timer after the last command in the queue has completed. The default timeout is "forever" and this feature is disabled.
    • Manual power-down by calling RF_yield(). The client should do this whenever it knows that no further radio operation will be executed for a couple of milliseconds.

    During the power-down procedure the RF driver stops the radio timer and saves a synchronization timestamp for the next power-up. This keeps the radio timer virtually in sync with the RTC even though it is not running all the time. The synchronization is done in hardware.

  • Sorting through the documentation always seems like a bit of a treasure hunt. If I could request something, moving the descriptions to the source files, or providing a corresponding document URL in the source file would be of great help, particularly where there are multiple file versions.

    I have some simple steps to reproduce the general scenario:

    • Start with a clean dmm_wsnnode_ble5_sp_cc1352r1lp_app example
    • In node_tack.c, set NODE_ADCTASK_SENSOR_STUB_DURIATION_MS tp 10000
    • In node_radio_task, set NORERADIO_ACK_TIMEOUT_TIME_MS to 1000
    • Run and try to connect via a bluetooth app

    This listens on the subghz for a second every 10 seconds. Since there is no ACK to receive at the bottom of sendDmPacket(), the subghz waits for the full second starving the ble and disconnecting the app. My case differs in that I am doing a bunch of packets on the subghz, but the end result appears to be the same.

    If I set NORERADIO_ACK_TIMEOUT_TIME_MS to 200, the ble remains connected, but if I set it to 300, it disconnects. I've also only tried this on an iphone. I'll see if I can dig up an android device to see if the behavior is the same.

    In simple_peripheral.c, the DEFAULT_DESIRED_[MIN/MAX]_CONN_INTERVAL are set to 100/110ms. If I up those by a factor of 10 (i.e 800/880), it still disconnects at NORERADIO_ACK_TIMEOUT_TIME_MS=300.

    As for the packet sniffer, I happen to have previously ordered one of these (2640 instead of the 2540, but they look pretty similar). Would that work, and is there any firmware source available?

  • Hi,

    I agree, navigating how the BLE-Stack example projects are using TI-RTOS and drivers can be complicated.

    The CC2640 version of the packet sniffer (Packet Sniffer 2) does not yet support Bluetooth Low Energy. This is why I recommend the CC2540. The firmware is fond with the download: 

    Can you print out the connection parameters when the connection is formed? This information is contained in the GAP_LINK_ESTABLISHED event that the application receives. See the gapEstLinkReqEvent_t Struct Reference (  ).

    Are you sending any connection paramerer update requests?

  • Looks like these are the values. I guess that explains why setting those values had no affect:

    #000328 [ 68.578 ] INFO: (project_zero.c:1393) GAP_LINK_ESTABLISHED_EVENT connInterval: 24
    #000329 [ 68.578 ] INFO: (project_zero.c:1394) GAP_LINK_ESTABLISHED_EVENT connLatency:  0
    #000330 [ 68.578 ] INFO: (project_zero.c:1395) GAP_LINK_ESTABLISHED_EVENT connTimeout:  72

    It looks like GAP_UpdateLinkParamReq() is called via ProjectZero_sendParamUpdate() with my desired parameters, and that is done 4 seconds after the initial connection (via a clock set from PZ_SEND_PARAM_UPDATE_DELAY)

    But, I dont see a response in ProjectZero_handleUpdateLinkEvent()

    I'm not quite understanding this whole parameter negotiation exchange. Does the remote device (phone) respond with the parameters to confirm they were updated, or do we just assume they were?

  • Hi,

    Can you make sure the timer that will trigger the connection parameter update request is started in your application? (Is ProjectZero_sendParamUpdate() ever called?)

    Yes, the master should respond to the connection parameter update request (either with a rejection or with a confirmation of connection parameters that will be used).

    You should get a GAP_LINK_PARAM_UPDATE_EVENT from the BLE-Stack when this happens. (see dev.ti.com/.../group___g_a_p.html ).
  • Yes, that is called, but there's no confirmation that it was accepted by the master/central (IOS). I would think ProjectZero_handleUpdateLinkParamReq() or ProjectZero_handleUpdateLinkEvent() should be called after the update, but its not entirely clear.

    I found a post that says L2CAP_ConnParamUpdateReq() should be used on the client (instead of GAP_UpdateLinkParamReq() like in project_zero), but I haven't figured out how to implement that. I keep getting a 0x18 bleInvalidRange, and it is not entirely obvious which parameter is out of range, or if its something completely unrelated.


    I've also found this which indicates that IOS is pretty picky about the parameters... but it also implies I should see a response/rejection if they are wrong.
    e2e.ti.com/.../247819
  • Hi,

    If GAP_UpdateLinkParamReq() is returning bleInvalidRange your parameter update request is rejected by the BLE-Stack, and not being sent over the air. What parameters are you using in the gapUpdateLinkParamReqReply_t?
  • Well, it looks like its working now.

    L2CAP_ConnParamUpdateReq() is what was returning 0x18 bleInvalidRange. I reset my parameters back to the default ones in projectzero and now L2CAP_ConnParamUpdateReq() is working and ProjectZero_handleUpdateLinkEvent() is getting called, printing out the confirmation.

    I cant find the explanation for the timeoutMultiplier in l2capParamUpdateReq_t so I'm just setting that to DEFAULT_DESIRED_CONN_TIMEOUT (or 200)

    I'm using the default values in project_zero

    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     12
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     36
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    #define DEFAULT_DESIRED_CONN_TIMEOUT          200

    For anyone else stuck on this, I replaced ProjectZero_sendParamUpdate() with this:

    static void ProjectZero_sendParamUpdate(uint16_t connHandle) {
        l2capParamUpdateReq_t req;
    
        req.slaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
        req.timeoutMultiplier = DEFAULT_DESIRED_CONN_TIMEOUT; //not sure why this is called timeoutMultiplier???
        req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
        req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    
        bStatus_t status = L2CAP_ConnParamUpdateReq(connHandle, &req, selfEntity);
        Log_error1("ProjectZero_sendParamUpdate status=0x%02x******************************", status);
    }

    I still dont have a good reference for what are "valid" parameters, but at least now I can tweak one at a time to make some forward progress.

    Incidentally, with the wrong parameters, GAP_UpdateLinkParamReq() returns 0x02, which apparently is INVALIDPARAMETER whereas L2CAP_ConnParamUpdateReq() returns 0x18 bleInvalidRange, which is a bit confusing.

  • Hi,

    Glad you got the parameter update request to work. Let me know if your master device accepts the updated parameters, and if it solves the disconnect issue.
  • Thanks for all your help on this.

    The parameters that worked for my application are:

    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     12
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     36
    #define DEFAULT_DESIRED_SLAVE_LATENCY         16
    #define DEFAULT_DESIRED_CONN_TIMEOUT          600
    

    If I go over 600 on the timeout it doesn't seem to work, likewise with the latency. I'm not power-constrained, so i didn't change the intervals. I did this through trial and error since the specs on these parameters are somewhat obscure. I basically stopped once I found a combination that worked and didn't bother to write code to probe out the parameters.

    As with the previous post, these were set via L2CAP_ConnParamUpdateReq()

  • Hi,

    You can see the range for each connection parameter in the Bluetooth core spec (or you can look here: dev.ti.com/.../ble_connections.html ).

    When you say supervision timeout over 600 doesn't work, do you meen that it's rejected by the BLE-Stack ( INVALIDPARAMETER ) or by the peer device?
  • Thanks for that link. I haven't seen that document. For what its worth, TI has a ton of content (much of which is exceedingly verbose, in my opinion), but it is all really difficult to find, either from a google search, or from the source examples. Well commented code, even if its just a trail of in-depth documents like that link, would be incredibly helpful. Even if it was just in the header comments of the files.

    When I say it doesn't work, I mean I don't see a followup call to ProjectZero_handleUpdateLinkEvent().

    Briefly, I call L2CAP_ConnParamUpdateReq() on projectzero (which is acting as the peripheral to the iphone in this arrangement). When I see ProjectZero_handleUpdateLinkEvent() called, and associate message printed, I deem that a success (I haven't dug too deep into that except for my connection stays active, which was my basic goal). If I don't see ProjectZero_handleUpdateLinkEvent() called, I assume it failed, but I'm not sure how.

    L2CAP_ConnParamUpdateReq() returns success (although there are combinations that give me the 0x18 return... whichever invalid/range/parameter that is), it just doesn't get rounded out by the ProjectZero_handleUpdateLinkEvent() response.