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

Removing Connection Parameter Negotiation BLE library from ble_peripheral ble_app_uart example app

Hello ...

Implementing an app for both nRF51822 and nRF52810 and need a long-term clock with 100 Hz counter frequency to timestamp sensor events. By long-term, I mean at least 5 hours. I'm using TIMER1 and TIMER2 for other timing functions, so that leaves me with RTC0 or RTC1. Need use concurrent with BLE S110 (nRF51) or S112 (nRF52).

I understand RTC0 is used by the SoftDevice and therefore cannot be used. To develop my app I started with the example ble_peripheral/ble_app_uart and have been modifying/trimming. I'm testing on an nRF52 dev kit with nRF52810 emulation. It appears that ble_conn_params.c (Connection Parameters Negotiation library) uses app_timer library (app_timer_create() in ble_conn_params_init(), app_timer_start() in conn_params_negotiation(), and app_timer_stop() in on_disconnect()), which uses RTC1.

A simple solution would be to use RTC1 with prescaler of 327 which would give me 100 Hz resolution and 46+ hours before overflow.

It seems like ble_conn_params.c uses app_timer/RTC1 for connection parameter negotiation and only under erroneous conditions (if (!p_instance->params_ok)). I've found that once a BLE connection has been established, RTC1 is stopped and its counter value is 0, and remains so.

Can I access/control RTC1 directly after BLE connection is established? If yes, then I can set its prescaler to 327 (NRF_RTC1->PRESCALER = 327), start it (NRF_RTC1->TASK_START), and then use NRF_RTC1->COUNTER to read the value to get the number of 10.009574 ms ticks since RTC1 started. After disconnecting BLE, I would stop RTC1 and set its prescaler back to 0. Reasonable? I've implemented this and it appears to work well but I'm concerned about the risk of manipulating RTC1 while ble_conn_params.c is using app_timer/RTC1.

This post suggests it's possible to avoid using the Connection Parameters Negotiation library to avoid the need for/use of app_timer, which would free up RTC1 for exclusive use by my app. I would appreciate any guidance in how to do this. I'm new to Nordic SDK.

I'm also planning to implement RTC synchronization across multiple nRF5 devices using this blog post.

Thanks in advance for any guidance.

Tim

  • Hi,

     

    I've implemented this and it appears to work well but I'm concerned about the risk of manipulating RTC1 while ble_conn_params.c is using app_timer/RTC1.

     The RTC1 peripheral is only used by app_timer, and if you, in your application, have total control over when the app_timer uses it, I do not see any reasons why you shouldn't go forward with that.

    If you can use the same prescaler in app_timer as in your application, you could also modify app_timer.c (irq handler) to check other events than EVENTS_COMPARE[0], as app_timer only uses CC[0] to handle its own queue, so if you ensure that app_timer newer stops the RTC, and you modify the irq-handler; you can use those other CC instances freely.

    That being said; If you have a solution that already works, I wouldn't change it.

     

    Kind regards,

    Håkon

  • Thank you Håkon. I'll proceed with currently working solution. However, I'd still be curious about how to handle connection parameters without the Connection Parameters Negotiation library, as suggested in this post:

    You should however note that the connection parameters module isn't strictly required, since you can send connection parameter update requests manually by using the softdevice API directly. All modules using app_timer are optional, and you can just avoid using them.

    I have a feeling this might be quite involved. Thanks either way.

  • To update your connection parameters, its essentially a call to "sd_ble_gap_conn_param_update" that is performed x amount (configurable) of seconds after the connection has been established - based on if this is needed by the timing that has already been provided to you by the central device. It has a bit more logic in ble_conn_params.c, where it for instance handles retries.

     

    Kind regards,

    Håkon

  • Thank you Håkon. I'll take a closer look at ble_conn_params.c.

    Tim

  • I thought I had a solution for this, but need to revisit.

    Experiencing an intermittent issue whereby somehow RTC1's prescaler is being set to 0. My app was built by starting with ble_app_uart and removing uart and customizing. Here's how my app currently utilizes RTC1:

    1) Following connection between BLE peripheral and central (ble_evt_handler(..) receives BLE_GAP_EVT_CONNECTED in p_ble_evt->header.evt_id), peripheral and central exchange a bit of data (nus_data_handler(..) to receive from central, ble_nus_data_send(..) to send to central).

    2) At this point my app assumes that ble_conn_params.c is done using app_timer/RTC1, and proceeds to set up and start RTC1 with prescaler 255:

    NRF_RTC1->TASKS_STOP = 1;   // Stop RTC1
    NRF_RTC1->TASKS_CLEAR = 1;  // Clear RTC1
    NRF_RTC1->PRESCALER = 255;  // Set RTC1 prescaler
    NRF_RTC1->TASKS_START = 1;  // Start RTC1
    
    NVIC_ClearPendingIRQ(RTC1_IRQn);
    NVIC_DisableIRQ(RTC1_IRQn);
    
    uint16_t current_prescaler = NRF_RTC1->PRESCALER;
    NRF_LOG_INFO("current_prescaler %d", current_prescaler);

    Sometimes NRF_LOG_INFO shows current_prescaler to be 255, sometimes 0. It seems that even at the point a central/peripheral connection has been established, ble_conn_params.c may still be using app_timer/RTC1. Even though my app sets prescaler to 255, app_timer might be setting it back to 0?

    Is there a way I can know for sure when ble_conn_params.c is done with app_timer/RTC1 so my app can safely use RTC1?

    I guess another option is to not use ble_conn_parameters/app_timer, but I don't know how to do that. If simple, I'd appreciate the code to do so.

    Many thanks,

    Tim

Related