Problem running LESC on nRF5 SDK with App Scheduler running

Hi there,

I have a project developed in SES, using nRF5 SDK v15.3.0 with only Just Works security without using LESC running on nRF52840. It has been running fine for 2 years. Recently, I have upgraded it to nRF5 SDK v17.1.0. Everything works fine.

Now we need to improve the security by adding LESC support.

I modify the code using the Glucose Application and (experimental) LE Secure Connections Multirole Example as reference.

1. sdk_config.h:
#define PM_LESC_ENABLED 1
#define NRF_BLE_LESC_ENABLED 1
2. Define the security parameters
3. Add nrf_ble_lesc_request_handler() in idle_state_handle(void) inside the main loop.

#define SEC_PARAM_BOND                  1                       /**< Perform bonding. */
#define SEC_PARAM_MITM                  0                       /**< Man In The Middle protection required. */
#define SEC_PARAM_LESC                  1                       /**< LE Secure Connections enabled. */
#define SEC_PARAM_KEYPRESS              0                       /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_NONE    /**< Display I/O capabilities. */
#define SEC_PARAM_OOB                   0                       /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE          7                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE          16                      /**< Maximum encryption key size. */

#define PASSKEY_TXT                     "Passkey:"              /**< Message to be displayed together with the pass-key. */
#define PASSKEY_TXT_LENGTH              8                       /**< Length of message to be displayed together with the pass-key. */
#define PASSKEY_LENGTH                  6                       /**< Length of pass-key received by the stack for display. */

//......

static void idle_state_handle(void) {
    ret_code_t err_code;

    err_code = nrf_ble_lesc_request_handler();
    APP_ERROR_CHECK(err_code);

    app_sched_execute();
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}

However, when the program is loaded on the target board, it always runs into a hard fault during bebug. The biggest difference with these examples is that I have used the App scheduler. The reason I use App scheduler is that a hardware interrupt takes quite some time to process. I don't want it to cause any issue to the soft device.

Is app scheduler not able to use with LESC? Any suggestions for me to modify / debug the code?

Thank you!

----------------

Hi there,

I did further investigation by modifying the Glucose Monitor example.  Below is what I did to check if app scheduler can be used.

1. Add #include "app_scheduler.h"

2. Add below code

void check_if_put_bmr_to_sleep_seh(void *p_ev_data, uint16_t ev_size) {
    NRF_LOG_INFO("Reached 30 seconds! Reset clock counter to ZERO!");
}

/**@brief Function to check if bmr should be put to sleep
 *
 * @details if m_clock_cnt >= 30; reset m_clock_cnt = 0; 
*/
void check_if_put_bmr_to_sleep() {
    ret_code_t  err_code;
    if (m_clock_cnt >= 30) {
        m_clock_cnt = 0;

        err_code = app_sched_event_put(0,0,check_if_put_bmr_to_sleep_seh);
        APP_ERROR_CHECK(err_code);
    }
}

/**@brief Function for the 1 second clock emulation.
 *
 * @details Run every 1 second, post status, determine ultra low power shutdown, determine timeout shutdown during operations
 */
void clock_em_eh(void *p_context) {
    UNUSED_PARAMETER(p_context);
    m_clock_cnt++;
    check_if_put_bmr_to_sleep();

}

/**@brief Function for starting application timers.
 */
static void application_timers_start(void)
{
    ret_code_t err_code;

    // Start application timers.
    err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);

    // Start clock emulation timer
    err_code = app_timer_start(clock_em_tid, APP_TIMER_TICKS(1000), NULL);
    m_clock_cnt = 0; 
    APP_ERROR_CHECK(err_code);
}

3. After I started debugging in SES, I got the DH_key and had completed the connection.  However, once the "app_sched_event_put(0,0,check_if_put_bmr_to_sleep_seh)" was executed the hardfault error (timer_expire) came out. 

4.  Does it imply that the app scheduler cannot be used with the lesc request handler?  

5.  In my project, I am using fstorage library to save 2 pages of data to flash upon completion of certain operations.  Currently, I put the "save flash" operation in a function in the app scheduler queue.  I also have an interrupt routine which may take up to 100 milliseconds to complete in the app scheduler queue.  If the app scheduler cannot be used with lesc, and if I want to stay using nRF SDK, is there any good way to achieve it?

Thank you!

Parents
  • Hello,

    The issues you are seeing does not appear to be related to LESC. I'm not aware of any known issues with using LESC and the app scheduler together either.

    3. After I started debugging in SES, I got the DH_key and had completed the connection.  However, once the "app_sched_event_put(0,0,check_if_put_bmr_to_sleep_seh)" was executed the hardfault error (timer_expire) came out. 

    The first screenshot you posted was showing a hardfault, but this one is not. The error handler is invoked because a runtime error check failed in the timer_expire() function. Perhaps you have exhausted the scheduler queue due to long-running tasks. If that's the case, it's likely failing here:

    You will get a more detailed crash log if you debug your project using the 'Debug' build configuration instead of 'Release' 

    Best regards,

    Vidar

  • Hi Vidar,

    Thank you for your reply.

    You are right that the modified code from glucose example was not a hard fault.  Instead it is ERROR 4 [NRF_ERROR_NO_MEM].  Sorry about that. 

    However, I don't understand why this error happens.  What I have changed to the glucose example was to add a 1 second counter from the app timer.  When it reaches 30 times (roughly 30 seconds), it puts the event check_if_put_bmr_to_sleep_seh into the scheduler queue.  In fact, it only happens once and the NRF_ERROR_NO_MEM error shows up.  I don't understand why putting 1 single event into the scheduler event queue cause this NRF_ERROR_NO_MEM error.  I have probably overlook something.  Can you please educate me on it?

    /* 
       Added timestamp to the log
    */
    static uint64_t   m_clock_cnt;
    
    uint32_t get_rtc_counter(void)
    {
        return NRF_RTC1->COUNTER;
    }
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(get_rtc_counter);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    ......
    
    static void timers_init(void)
    {
        ret_code_t err_code;
    
        // Initialize timer module.
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        // Create timers.
        err_code = app_timer_create(&m_battery_timer_id,
                                    APP_TIMER_MODE_REPEATED,
                                    battery_level_meas_timeout_handler);
        APP_ERROR_CHECK(err_code);
    
        // Timer to emulate clock
        err_code = app_timer_create(&clock_em_tid, APP_TIMER_MODE_REPEATED, clock_em_eh);   
        APP_ERROR_CHECK(err_code);                                                                        
    
    }
    
    
    static void application_timers_start(void)
    {
        ret_code_t err_code;
    
        // Start application timers.
        err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    
        // Start clock emulation timer
        err_code = app_timer_start(clock_em_tid, APP_TIMER_TICKS(1000), NULL);
        m_clock_cnt = 0; 
        APP_ERROR_CHECK(err_code);
    }
    
    void check_if_put_bmr_to_sleep_seh(void *p_ev_data, uint16_t ev_size) {
        NRF_LOG_INFO("Reached 30 seconds! Reset clock counter to ZERO!");
    }
    
    /**@brief Function to check if bmr should be put to sleep
     *
     * @details if m_clock_cnt >= 30; reset m_clock_cnt = 0; 
    */
    void check_if_put_bmr_to_sleep() {
        ret_code_t  err_code;
        if (m_clock_cnt >= 30) {
            m_clock_cnt = 0;
    
            NRF_LOG_INFO("Put function in Scheduler!");
            err_code = app_sched_event_put(0,0,check_if_put_bmr_to_sleep_seh);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    /**@brief Function for the 1 second clock emulation.
     *
     * @details Run every 1 second
     */
    void clock_em_eh(void *p_context) {
        UNUSED_PARAMETER(p_context);
        m_clock_cnt++;
        check_if_put_bmr_to_sleep();
    
    }

    BTW, I use the original Glucose Application main.c without making any changes.  Then I change the following 

          #define APP_TIMER_CONFIG_USE_SCHEDULER 1

          #define NRF_LOG_BACKEND_RTT_ENABLED 1

          #define NRF_LOG_BACKEND_UART_ENABLED 0

    in sdk_config.h 

    Then the error ERROR 9 [NRF_ERROR_INVALID_LENGTH] shows up.  I think I must be missing something here.  Please help.

    Thank you.

    Best Regards

    Sunny 

  • Hi Sunny,

    It seems like you may have forgotten to initialize the scheduler with APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); in main()?

    Best regards,

    Vidar

  • Hi Vidar,

    Yes, you are right.  I missed the APP_SCHED_INIT macro.  Now I added it back.  The timer use scheduler works.  But something strange happens if I add the app_sched_execute() in the idle_state_handle().  

    As long as I add the macro APP_ERROR_HANDLER(err_code) after the app_sched_event_put(...), an error pops up.  If I remove this macro, everything works fine.  Do you see anything wrong with my code? 

    Commented out APP_ERROR_HANDLER(err_code), no error.  Program runs fine.

    With APP_ERROR_HANDLER(err_code), program halt even though the error code is "ERROR 0 [NRF_SUCCESS]"

Reply
  • Hi Vidar,

    Yes, you are right.  I missed the APP_SCHED_INIT macro.  Now I added it back.  The timer use scheduler works.  But something strange happens if I add the app_sched_execute() in the idle_state_handle().  

    As long as I add the macro APP_ERROR_HANDLER(err_code) after the app_sched_event_put(...), an error pops up.  If I remove this macro, everything works fine.  Do you see anything wrong with my code? 

    Commented out APP_ERROR_HANDLER(err_code), no error.  Program runs fine.

    With APP_ERROR_HANDLER(err_code), program halt even though the error code is "ERROR 0 [NRF_SUCCESS]"

Children
Related