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

Bus Fault after calling __get_FPSCR in FreeRTOS configPRE_SLEEP_PROCESSING(x)

I'm trying to set up a project with SDK 16.0.0 using FreeRTOS with the softdevice.  The device will be battery powered and therefore power management capabilities are required.

My freeRTOSConfig.h is the same as in the ble_app_hrs_freertos_pca10040_s132 with the following additions:

#if ( __FPU_PRESENT)
#define PWR_MGMT_FPU_SLEEP_PREPARE() pwr_mgmt_fpu_sleep_prepare()
extern void pwr_mgmt_fpu_sleep_prepare(void);
#else
#define PWR_MGMT_FPU_SLEEP_PREPARE()
#endif // NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED

#define configPRE_SLEEP_PROCESSING(x) PWR_MGMT_FPU_SLEEP_PREPARE()

#define configSUPPORT_STATIC_ALLOCATION

Based on this thread I tried to add pwr_mgmt_fpu_sleep_prepare in main.c, however my code gets a busfault any time I use the __get_FPSCR() or __set_FPSCR() macro.

My application works as expected except not sleeping when I comment out the FPSCR macros.

When I uncomment the macro's the busfault breakpoint triggers and the PC is stopped at address 0xA60.

Do I need to implement this sleep prepare step?

Why do these FPSCR macro's cause a bus fault?

Given:

1) I'm not even using the FPU.

2) This example only performs some I2C operations once per second

3) I have RTC2 enabled and operating at 32KHz with only overflow interrupt enabled ( for tracking time independent from freeRTOS )

4) I have an idle task hook that does NRF_LOG_FLUSH with NRF_LOG_ENABLED

Then will it be reasonable to expect the sd_app_evt_wait() call to sleep for some amount of time?  It seems at the moment it will never sleep despite every task being blocked/suspended.

Parents
  • Hi,

    Access to these registers should not be restricted. Are you not able to enter sleep with sd_app_evt_wait()? Are you experiencing immediate wakes, since it looks like you try to implement the workaround for FPU errata?

    Do you have a sample project that we can use to reproduce this behavior?

    Best regards,
    Jørgen

  • After modifying the freertos example to eliminate the vApplicationIdleHook and instead unblock the logger task from a hook in the logger library, I have been able to see the freertos port sleep as expected.

    The immediate wakes were caused by the idle hook resuming the logger task.  This causes freertos to always have a task to run and never sleep.  Nordic should remove this from the example, it doesn't work and causes customers to waste engineering time.  

    I will implement FPU interrupt to handle FPU errors next and I may still have some questions.

  • what exact change did you make to eliminate the vApplicationIdleHook and where exactly did you unblock the logger task?

    Did you understand why it was keeping your system awake if unblocking in idleHook? It is the safest way to run the logs when rest of the rtos tasks are not running. 

    The change that you said does not make sense unless you have changed the priority of the logger task so high that it is not allowing any other task to run. 

    Nordic should remove this from the example, it doesn't work and causes customers to waste engineering time.  

    The example is done correctly in terms of how logging is handled. It very much looks like this was caused due to choosing of wrong priorities of the tasks. 

Reply
  • what exact change did you make to eliminate the vApplicationIdleHook and where exactly did you unblock the logger task?

    Did you understand why it was keeping your system awake if unblocking in idleHook? It is the safest way to run the logs when rest of the rtos tasks are not running. 

    The change that you said does not make sense unless you have changed the priority of the logger task so high that it is not allowing any other task to run. 

    Nordic should remove this from the example, it doesn't work and causes customers to waste engineering time.  

    The example is done correctly in terms of how logging is handled. It very much looks like this was caused due to choosing of wrong priorities of the tasks. 

Children
  • I have not changed the priorities of any tasks.  I proved this problem on the example project with no modifications.  

    The logging task in the example uses simple suspend and resume.  The logger task is the lowest priority however since it is resumed every time the system is idle, the scheduler always has an unblocked task to run and therefore it can never sleep.  

    This is very easy to verify.  In port_cmdsis_systick.c, the vPortSuppressTicksAndSleep task calculates the time it was sleeping.  I added the calculated sleep time to a static variable m_sleep_time and could verify that no time was actually spent asleep in sd_app_evt_wait().

    Here is the code I added to track sleep time:

    //exisintg code

    diff = (exitTime - enterTime) & portNRF_RTC_MAXTICKS;

    //my code

    static uint32_t m_sleep_time=0;

    m_sleep_time+=diff;

    Then I monitor m_sleep_time from the debugger.

    To improve this situation, the logger task needs to block until logs need to be flushed.

    For this I modified nrf_log_frontend.c buf_prealloc static function.  I added a weakly defined function vLogPendingHook() 

    Then I override the vLogPendingHook() in my application to use direct to task notification to signal to the logger task that logs need to be flushed:

    void vLogPendingHook( void )
    {
    #if NRF_LOG_ENABLED
    BaseType_t result = pdFAIL;

    if ( __get_IPSR() != 0 )
    {
    BaseType_t higherPriorityTaskWoken = pdFALSE;
    result = xTaskNotifyFromISR( m_logger_thread, LOG_PENDING_EVT, eSetValueWithoutOverwrite, &higherPriorityTaskWoken );

    if ( pdFAIL != result )
    {
    portYIELD_FROM_ISR( higherPriorityTaskWoken );
    }
    }
    else
    {
    UNUSED_RETURN_VALUE(xTaskNotify( m_logger_thread, LOG_PENDING_EVT, eSetValueWithoutOverwrite ));
    }

    #endif //NRF_LOG_ENABLED
    }

Related