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.

  • 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