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

nRF52810 app optimization ble_app_uart

Hello ...

Our BLE peripheral product (nRF52810, SDK 15.3.0, SD 112 6.1.1) is relatively simple. iOS device (central) connects to peripheral. Data is exchanged between the central and peripheral. Peripheral watches a sensor and responds to events (by sending data to the central). The size of data sent between central and peripheral does not exceed 16 bytes (future expansion might increase this by a few bytes). Encryption unnecessary. Peripheral device is powered by 2 AA batteries with adequate battery life. Power optimization is not needed.

I'm new to Nordic SDK and started with the ble_app_uart example. I would like to learn about important considerations in moving towards a final app. Here's, generally, how I've migrated ble_app_uart:

1) Removed all use and reference of/to UART as it's not needed. Simply sending data between central and peripheral.

2) Removed all use and reference of/to Board Support Package, and use nrf_gpio directly for IO.

3) Removed Board.c.

4) Replaced NUS UUIDs with our UUIDs.

App functionality is complete and is working well. I'm able to flash to our custom nRF52810 board using the debug out port of the nRF52 dev kit. All appears good.

Given basic requirements, is there more that can be trimmed to reduce app size and complexity?

Is the Queued Write module necessary?

Low and relatively consistent latency of delivery of messages between central and peripheral is important. Is there anything I can do to reduce message delivery latency? I understand there are many factors out of my control, such as the BLE stack on the iOS device and its sharing of RF resources, etc.

I'm using the Logger module (NRF_LOG_INIT, etc.) for debugging. To build and flash release product, how do I essentially turn off logging? Should I be using #define DEBUG and then surround all NRF_LOG statements with #ifdef DEBUG ... #endif, then remove #define DEBUG for building release app?

Anything else for building/flashing a release app?

Enjoying the learning ... thanks for any guidance.

Tim

  • Hello,

    Step 1-3 sound like reasonable choices to optimize size and reduce complexity. There are a few more files you can remove if you don't need logging (nrf_printf, nrf_atomic.c, nrf_ringbuf.c, etc), but I would consider to keep them in so you can more easily re-enable logging if you ever need that.  There is not much to gain with regards to flash usage, maybe a couple of KB. Of course, that may be significant if you're starting to run out of memory.

    Is the Queued Write module necessary?

     It would probably be ok to remove the Queued Writes module as the ios device should not have to request any queued writes. However, the module is only around 200 bytes with the default setting ('NRF_BLE_QWR_MAX_ATTR' == 0 - reject queued write request), and it will ensure that request is handled if it gets received. 

    Low and relatively consistent latency of delivery of messages between central and peripheral is important. Is there anything I can do to reduce message delivery latency? I understand there are many factors out of my control, such as the BLE stack on the iOS device and its sharing of RF resources, etc.

    iOS usually honors the preferred connection interval range requested by the peripheral if it follows the Apple recommendations (link - see section 25.6). The lowest interval you typically can get is 15 ms, and you should get that if you request Interval Min == Interval Max == 15 ms.

    I'm using the Logger module (NRF_LOG_INIT, etc.) for debugging. To build and flash release product, how do I essentially turn off logging? Should I be using #define DEBUG and then surround all NRF_LOG statements with #ifdef DEBUG ... #endif, then remove #define DEBUG for building release app?

    It should be sufficient to disable the NRF_LOG_ENABLED config option in your sdk_config.h header and recompile.  This will exclude the nrf_log_*  source files from the build and remove processing of the NRF_LOG_* macros.

    Anything else for building/flashing a release app?

    I think the main point is to disable logging. Also make sure the app is compiled without DEBUG flag if you want the app to reset if an error occurs: Error module (note: does not include hard faults)

    Best regards,

    Vidar

  • Thank you Vidar. All makes sense.

    About disabling logging, in sdk_config.h I:

    #define NRF_LOG_ENABLED 0

    As expected, app does not log anything, but also does not behave properly. Normally the app reads some data from EEPROM via TWIM (sets some globals), then sets up BLE (ble_stack_init(), gap_params_init(), gatt_init(), services_init(), advertising_init(), conn_params_init()) and starts advertising (advertising_start()). It does not advertise. I've done a bit of tracing but can't make sense of it.

    Also, how do I "compile without DEBUG flag"?

    Many thanks,

    Tim

  • Hi Tim, disabling the logger may cause the timing of some of your functions to change, but in most cases, it isn't enough to change the behavior. Please try to place a breakpoint at the beginning of app_error_weak.c::app_error_fault_handler() to see if this function gets invoked when you disable logging (let me know if you have redefined it). Here you can also see if the DEBUG flag has been set or not.  

    Regards,

    Vidar

  • Hi Vidar,

    I did some tracing and found that app_error_falt_handler() is never being called. I also found that app seems to hang in call to nrf_pwr_mgmt_run().

    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    

    idle_state_handle() is called from main() loop. If I comment out nrf_pwr_mgmt_run(), all works well, even with NRF_LOG_ENABLED set to 0 (sdk_config.h).

    I'm not so concerned with power consumption and no need for device to ever go into low power/sleep mode. It would be best to understand why app is hanging in nrf_pwr_mgmt_run(), but also helpful to know whether or not it's essential to call it from the main() loop.

    (Also, just discovered another issue with my app's use of RTC1. If you could look at my latest post to this thread also, I'd appreciate it.)

    Many thanks,

    Tim

  • Hi Tim, 

    It's usually a good sign when the program "hangs" in the main loop, given that it wakes up and service interrupts from time to time. Place a breakpoint in one of the event handlers if you are unsure if it actually does that. E.g., inside the ble_evt_handler() and see if it hit when your ios device connects. 

    Tim said:
    idle_state_handle() is called from main() loop. If I comment out nrf_pwr_mgmt_run(), all works well, even with NRF_LOG_ENABLED set to 0 (sdk_config.h).

    That's interesting. It seems like it may be related to the lowest power mode somehow, but I'm not sure how. Is the logging done over UAR (use HF clock source unlike RTT)?

    As a test, can you try to enable the Constant latency mode and see if it has the same effect? sd_power_mode_set()  can be used to change the default power mode after enabling the Softdevice. 

    Tim said:
    (Also, just discovered another issue with my app's use of RTC1. If you could look at my latest post to this thread also, I'd appreciate it.)

     I'm sure Håkon will follow up on it, but I think the problem may be that the RTC has not had time to stop properly before you update the prescaler value. Writes to the PRESCALER register while be ignored in that case. Try to add "nrf_delay_us(50)" after stopping the RTC and see if helps. 

Related