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

Why does the NRF52840 application stops working when i add code to the timeout handler of the application timer?

I have a function which writes data to the external flash which is using a FAT file-system further using block device implementation of the SDK. Whenever I am calling the function in the Application timer timeout handler, the total crashes after 10 to 60 seconds of operation. I also saw an error log as "Softdevice assertion failed". I understand there is timing issues because of which this might be happening. I want to know the right way to synchronize all the small tasks i have in my App. What is the correct way to run all the different peripherals with synchronization and call functions inside the timer handler? 

And how can i program the nrf52840 correctly to do all the tasks when the program in running in the while(1) loop.

Parents
  • Hi Rit,

    All app_timer timeout handlers are called from the RTC interrupt handler context. So if the operation takes long, then it is ok to request those operations in the timeout handlers as long as those operations are asynchronous. It looks to me that something in your operation is not letting the softdevice pre-empt your code. That most likely will happen when you are running on a very high priority context. Did you make sure that all your peripheral drivers are running on the interrupt priority NOT reserved by the softdevice as mentioned here? If you have not initialized any priority for the peripheral you are using, it takes a default highest priority of 0 on ARM NVIC, which is reserved only for softdevice and application are not allowed to use this high priority when working with softdevice..

  • Yes, all the peripherals have priority 6 and not 0.
    Is it a stack overflow that's happening? Because the "NO MEMORY" error also came.
    The application timer just stops after 181 seconds even where I don't have any operation in the timeout handler?

  • <debug> nrf_sdh_ble: BLE event: 0x26.
    <debug> app: pm_whitelist_get returns 0 addr in whitelist and 0 irk whitelist
    <info> app: Slow advertising
    <debug> ble_cts_c: BLE event handler called with event 0x26
    <error> app: ERROR 4 [NRF_ERROR_NO_MEM] at /home/user/Documents/nRF5SDK1702d674dde/components/libraries/timer/app_timer2.c:181
    PC at: 0x00029493
    <error> app: End of error report

  • try increasing APP_TIMER_CONFIG_OP_QUEUE_SIZE in your sdk_config.h file, seems like the app_timer2 is queueing too many events into the queue and the queue size needs to be increased

  • No it's not working, Even if i am removing the function from the timeout handler, the system stops exactly after 181 seconds with the following error.

    <debug> nrf_sdh_ble: BLE event: 0x26.
    <debug> app: pm_whitelist_get returns 0 addr in whitelist and 0 irk whitelist
    <info> app: Slow advertising
    <debug> ble_cts_c: BLE event handler called with event 0x26
    <debug> nrf_sdh_ble: BLE event: 0x26.

    this problem started happening when i initialised the SPI peripheral, rtc3, and lfclk() .

Reply
  • No it's not working, Even if i am removing the function from the timeout handler, the system stops exactly after 181 seconds with the following error.

    <debug> nrf_sdh_ble: BLE event: 0x26.
    <debug> app: pm_whitelist_get returns 0 addr in whitelist and 0 irk whitelist
    <info> app: Slow advertising
    <debug> ble_cts_c: BLE event handler called with event 0x26
    <debug> nrf_sdh_ble: BLE event: 0x26.

    this problem started happening when i initialised the SPI peripheral, rtc3, and lfclk() .

Children
  • Which SDK are you using? This is clearly an app error check failure. Can you please start your application in debugger and put a breakpoint at the app_timer2.c 181 and show me the function call stack so that i understand a bit better what is going on. Seems like you are seeing exactly same issue as mentioned here. Are you by anychance using UART with an older SDK?

  • I am using the SDK 17.2.

    this is the init function befor the main.

      bool erase_bonds = true;
      (*log_init)();
      getmac();
      // initF();       //init internal flash
      // initFConfig(); // check if flash has config
      (*timers_init)();
    
      buttons_leds_init(&erase_bonds);
      peripheralSPI_init(); //init SPI
    
      lfclk_config(); //low frequency init for rtc
      rtc_config();   //init rtc
    
      scheduler_init();
      power_management_init();
      ble_stack_init();
      gap_params_init();
      gatt_init();
      db_discovery_init();
      services_init();
      advertising_init();
      conn_params_init();
      peer_manager_init();

    I have used the Nordic tutorials to implement custom services and characteristics, but the tutorial was for the 15 SDK.
    When I pause the debugger when the clocks halt, i end up in the nrfx_uarte.c . it stops near line 25 in the following snippet of nrfx_uarte.c

    void nrfx_uarte_uninit(nrfx_uarte_t const * p_instance)
    {
        uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
        NRF_UARTE_Type * p_reg = p_instance->p_reg;
    
        if (p_cb->handler)
        {
            interrupts_disable(p_instance);
        }
        // Make sure all transfers are finished before UARTE is disabled
        // to achieve the lowest power consumption.
        nrf_uarte_shorts_disable(p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX);
    
        // Check if there is any ongoing reception.
        if (p_cb->rx_buffer_length)
        {
            nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_RXTO);
            nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPRX);
        }
    
        nrf_uarte_event_clear(p_reg, NRF_UARTE_EVENT_TXSTOPPED);
        nrf_uarte_task_trigger(p_reg, NRF_UARTE_TASK_STOPTX);
    
        // Wait for TXSTOPPED event and for RXTO event, provided that there was ongoing reception.
        while (!nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_TXSTOPPED) ||
               (p_cb->rx_buffer_length && !nrf_uarte_event_check(p_reg, NRF_UARTE_EVENT_RXTO)))
        {}
    
        nrf_uarte_disable(p_reg);
        pins_to_default(p_instance);
    
    #if NRFX_CHECK(NRFX_PRS_ENABLED)
        nrfx_prs_release(p_reg);
    #endif
    
        p_cb->state   = NRFX_DRV_STATE_UNINITIALIZED;
        p_cb->handler = NULL;
        NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
    }
    
    nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance,
                             uint8_t const *      p_data,
                             size_t               length)
    {
        uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
        NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
        NRFX_ASSERT(p_data);
        NRFX_ASSERT(length > 0);
        NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length));
    
        nrfx_err_t err_code;
    
        // EasyDMA requires that transfer buffers are placed in DataRAM,
        // signal error if the are not.
        if (!nrfx_is_in_ram(p_data))
        {
            err_code = NRFX_ERROR_INVALID_ADDR;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
    
        if (nrfx_uarte_tx_in_progress(p_instance))
        {
            err_code = NRFX_ERROR_BUSY;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
        p_cb->tx_buffer_length = length;
        p_cb->p_tx_buffer      = p_data;
    
        NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
        NRFX_LOG_DEBUG("Tx data:");
        NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
                               p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
    
        err_code = NRFX_SUCCESS;
    
        nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
        nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
        nrf_uarte_tx_buffer_set(p_instance->p_reg, p_cb->p_tx_buffer, p_cb->tx_buffer_length);
        nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTTX);
    
        if (p_cb->handler == NULL)
        {
            bool endtx;
            bool txstopped;
            do
            {
                endtx     = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX);
                txstopped = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED);
            }
            while ((!endtx) && (!txstopped));
    
            if (txstopped)
            {
                err_code = NRFX_ERROR_FORBIDDEN;
            }
            else
            {
                // Transmitter has to be stopped by triggering the STOPTX task to achieve
                // the lowest possible level of the UARTE power consumption.
                nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STOPTX);
    
                while (!nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED))
                {}
            }
            p_cb->tx_buffer_length = 0;
        }
    
        NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }

    Random error is coming, following is the latest error, i got.
    <debug> nrf_sdh_ble: BLE event: 0x26.
    <debug> app: pm_whitelist_get returns 0 addr in whitelist and 0 irk whitelist
    <info> app: Slow advertising
    <debug> ble_cts_c: BLE event handler called with event 0x26
    <error> app: SOFTDEVICE: ASSERTION FAILED

    The apptimer2.c code snippet is below this line, and line number 181 is line number 32 in the following snippet.

    /**
     * @brief Function called on timer expiration
     * If end value is not reached it is assumed that it was partial expiration and time is put back
     * into the list. Otherwise function calls user handler if timer was not stopped before. If timer
     * is in repeated mode then timer is rescheduled.
     *
     * @param p_timer Timer instance.
     *
     * @return True if reevaluation of sortlist needed (becasue it was updated).
     */
    static bool timer_expire(app_timer_t * p_timer)
    {
        ASSERT(p_timer->handler);
        bool ret = false;
    
        if ((m_global_active == true) && (p_timer != NULL) && (p_timer->active))
        {
            if (get_now() >= p_timer->end_val) {
                /* timer expired */
                if (p_timer->repeat_period == 0)
                {
                    p_timer->active = false;
                }
        #if APP_TIMER_CONFIG_USE_SCHEDULER
                app_timer_event_t timer_event;
    
                timer_event.timeout_handler = p_timer->handler;
                timer_event.p_context       = p_timer->p_context;
                uint32_t err_code = app_sched_event_put(&timer_event,
                                                        sizeof(timer_event),
                                                        scheduled_timeout_handler);
                APP_ERROR_CHECK(err_code);
        #else
                NRF_LOG_DEBUG("Timer expired (context: %d)", (uint32_t)p_timer->p_context)
                p_timer->handler(p_timer->p_context);
        #endif
                /* check active flag as it may have been stopped in the user handler */
                if ((p_timer->repeat_period) && (p_timer->active))
                {
                    p_timer->end_val += p_timer->repeat_period;
                    nrf_sortlist_add(&m_app_timer_sortlist, &p_timer->list_item);
                    ret = true;
                }
            }
            else
            {
                nrf_sortlist_add(&m_app_timer_sortlist, &p_timer->list_item);
                ret = true;
            }
        }
        return ret;
    }
    

    yes, ive seen the uart malfunctioning.
    Please help. 

  • RitD said:
    Random error is coming, following is the latest error, i got.

     This could be either a stack memory corruption or a hardfault from the inaccurate LFCLK if you are using crystal for it.

     

    RitD said:
    The apptimer2.c code snippet is below this line, and line number 181 is line number 32 in the following snippet.

     This is saying that there is no space in the scheduler fifo and I am not sure why you do not get away with this after increasing the queue fifo size? probably you are getting the same error even later as you might have been putting it faster than pulling from the FIFO?

Related