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

For errata 87, why is there an Assert() if the it could never happen?

I'm using the recommended code for handling errata 87 on the nRF52840.

 __STATIC_INLINE void pwr_mgmt_fpu_sleep_prepare(void)
     {
        uint32_t fpscr;
        CRITICAL_REGION_ENTER();
        fpscr = __get_FPSCR();
        __set_FPSCR(fpscr & ~0x9Fu);
        __DMB();
        NVIC_ClearPendingIRQ(FPU_IRQn);
        CRITICAL_REGION_EXIT();
        ASSERT((fpscr & 0x07) == 0);
     }

Why is the Assert() necessary if this code works around errata 87?

Is there anything that could cause the Assert() condition to be true? (other than an a higher priority interrupt or process using the FPU that executes as soon as the critical region exits)

Parents
  • Hi,

    The assert is related to previous FPU operations, and the intention is to inform the user that an FPU error (for example division by 0) occured. Please see this post.

    In the latest SDK, several comments have been added to the code to make this clear:

         __STATIC_INLINE void pwr_mgmt_fpu_sleep_prepare(void)
         {
            uint32_t original_fpscr;
    
            CRITICAL_REGION_ENTER();
            original_fpscr = __get_FPSCR();
            /*
             * Clear FPU exceptions.
             * Without this step, the FPU interrupt is marked as pending,
             * preventing system from sleeping. Exceptions cleared:
             * - IOC - Invalid Operation cumulative exception bit.
             * - DZC - Division by Zero cumulative exception bit.
             * - OFC - Overflow cumulative exception bit.
             * - UFC - Underflow cumulative exception bit.
             * - IXC - Inexact cumulative exception bit.
             * - IDC - Input Denormal cumulative exception bit.
             */
            __set_FPSCR(original_fpscr & ~0x9Fu);
            __DMB();
            NVIC_ClearPendingIRQ(FPU_IRQn);
            CRITICAL_REGION_EXIT();
    
            /*
             * The last chance to indicate an error in FPU to the user 
             * as the FPSCR is now cleared
             *
             * This assert is related to previous FPU operations 
             * and not power management.
             *
             * Critical FPU exceptions signaled:
             * - IOC - Invalid Operation cumulative exception bit.
             * - DZC - Division by Zero cumulative exception bit.
             * - OFC - Overflow cumulative exception bit.
             */
            ASSERT((original_fpscr & 0x7) == 0);
         }

Reply
  • Hi,

    The assert is related to previous FPU operations, and the intention is to inform the user that an FPU error (for example division by 0) occured. Please see this post.

    In the latest SDK, several comments have been added to the code to make this clear:

         __STATIC_INLINE void pwr_mgmt_fpu_sleep_prepare(void)
         {
            uint32_t original_fpscr;
    
            CRITICAL_REGION_ENTER();
            original_fpscr = __get_FPSCR();
            /*
             * Clear FPU exceptions.
             * Without this step, the FPU interrupt is marked as pending,
             * preventing system from sleeping. Exceptions cleared:
             * - IOC - Invalid Operation cumulative exception bit.
             * - DZC - Division by Zero cumulative exception bit.
             * - OFC - Overflow cumulative exception bit.
             * - UFC - Underflow cumulative exception bit.
             * - IXC - Inexact cumulative exception bit.
             * - IDC - Input Denormal cumulative exception bit.
             */
            __set_FPSCR(original_fpscr & ~0x9Fu);
            __DMB();
            NVIC_ClearPendingIRQ(FPU_IRQn);
            CRITICAL_REGION_EXIT();
    
            /*
             * The last chance to indicate an error in FPU to the user 
             * as the FPSCR is now cleared
             *
             * This assert is related to previous FPU operations 
             * and not power management.
             *
             * Critical FPU exceptions signaled:
             * - IOC - Invalid Operation cumulative exception bit.
             * - DZC - Division by Zero cumulative exception bit.
             * - OFC - Overflow cumulative exception bit.
             */
            ASSERT((original_fpscr & 0x7) == 0);
         }

Children
No Data
Related