Beispiel #1
0
	/*
 	 *	Init TX and RX buffers, they are in EM but not in the retainable part
 	 *  so the pointers have to be programmed again	*
 	 */
	if(func_check_mem_flag)
	{
		if (func_check_mem_flag==2)
		{
	  //init TX/RX buffers after DEEPSLEEP	
		co_buf_init_deep_sleep();
		// Set the first RX descriptor pointer into the HW
        ble_currentrxdescptr_set(REG_BLE_EM_RX_ADDR_GET(co_buf_rx_current_get()));
		}   	
       //INIT NONE RET. HEAP after DEEPSLEEP	
       	ke_mem_init(KE_MEM_NON_RETENTION, (uint8_t*)(jump_table_struct[rwip_heap_non_ret_pos]), jump_table_struct[rwip_heap_non_ret_size]);

		func_check_mem_flag = 0;//false;
		
	}
 #endif //RW_BLE_SUPPORT
#endif //DEEP_SLEEP
}

#endif //0

// /*********************************************************************************
//  *** SLP_INT ISR
//  ***/
void BLE_SLP_Handler(void)
//void BLE_SLP_Handler_func(void)
{
	ble_regs_pop();
	//smpc_regs_pop();
    
//#if !DEEP_SLEEP_ENABLED
//# if  DEVELOPMENT__NO_OTP    
//	SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 1);
//# else
//  SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 0);   
//# endif	// DEVELOPMENT__NO_OTP
//#endif // !DEEP_SLEEP_ENABLED

	SetBits16(GP_CONTROL_REG, BLE_WAKEUP_REQ, 0);   //just to be sure    

    if(jump_table_struct[0] == TASK_GTL)	
	{
		// UART and pads have already been activated by periph_init() which is called
		// at initialization by main_func() and during wakeup by BLE_WAKEUP_LP_Handler().
		
		gtl_eif_init();
	}

	SetBits32(BLE_INTACK_REG, SLPINTACK, 1);

#if DEEP_SLEEP //Needed only for compilation. Remove when ROM code is ready.
#if RW_BLE_SUPPORT
	rwip_wakeup();
#endif //RW_BLE_SUPPORT
#endif //DEEP_SLEEP
    
    if (lp_clk_sel == LP_CLK_RCX20)
        calibrate_rcx20(20);
}
Beispiel #2
0
void BLE_SLP_Handler(void)
//void BLE_SLP_Handler_func(void)
{
	ble_regs_pop();
//	smpc_regs_pop();
    

//	SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 0);   

	SetBits16(GP_CONTROL_REG, BLE_WAKEUP_REQ, 0);   //just to be sure    

    if((jump_table_struct[0] == TASK_GTL) || (BLE_INTEGRATED_HOST_GTL == 1 ))
	{
		// UART and pads have already been activated by periph_init() which is called
		// at initialization by main_func() and during wakeup by BLE_WAKEUP_LP_Handler().
		
		gtl_eif_init();
	}

	SetBits32(BLE_INTACK_REG, SLPINTACK, 1);

#if DEEP_SLEEP //Needed only for compilation. Remove when ROM code is ready.
#if RW_BLE_SUPPORT
	rwip_wakeup();
#endif //RW_BLE_SUPPORT
#endif //DEEP_SLEEP
    
	/*
	* Radio Subsystem initialization. Execute here after making sure that BLE core is awake.
	*/
	rf_workaround_init();
	rf_reinit();	

    if (lp_clk_sel == LP_CLK_RCX20)
        calibrate_rcx20(20);
    
    rwble_last_event = BLE_EVT_SLP;
    
}
Beispiel #3
0
sleep_mode_t rwip_sleep(void)
{
    sleep_mode_t proc_sleep = mode_active;
    uint32_t twirq_set_value;
    uint32_t twirq_reset_value;
    uint32_t twext_value;
    #if (DEEP_SLEEP)
    uint32_t sleep_duration = jump_table_struct[max_sleep_duration_external_wakeup_pos];//MAX_SLEEP_DURATION_EXTERNAL_WAKEUP;
    #endif //DEEP_SLEEP
#ifndef DEVELOPMENT_DEBUG
    uint32_t sleep_lp_cycles;
#endif

    DBG_SWDIAG(SLEEP, ALGO, 0);

#if (BLE_APP_PRESENT)
    if ( app_ble_ext_wakeup_get() || (rwip_env.ext_wakeup_enable == 2) )  // sleep forever!
        sleep_duration = 0;
#else
# if (!EXTERNAL_WAKEUP) // sleep_duration will remain as it was set above....
    if (rwip_env.ext_wakeup_enable == 2)
        sleep_duration = 0;
# endif		
#endif    
    
    do
    {
        /************************************************************************
         **************            CHECK STARTUP FLAG             **************
         ************************************************************************/
        POWER_PROFILE_INIT;

        // Do not allow sleep if system is in startup period
        if (check_sys_startup_period())
            break;
        
        /************************************************************************
         **************            CHECK KERNEL EVENTS             **************
         ************************************************************************/
        // Check if some kernel processing is ongoing
        if (!ke_sleep_check())
            break;
        
        // Processor sleep can be enabled
        proc_sleep = mode_idle;

        DBG_SWDIAG(SLEEP, ALGO, 1);

        
#if (DEEP_SLEEP)
        /************************************************************************
         **************             CHECK ENABLE FLAG              **************
         ************************************************************************/
        // Check sleep enable flag
        if(!rwip_env.sleep_enable)
            break;

        
        /************************************************************************
         **************           CHECK RADIO POWER DOWN           **************
         ************************************************************************/
        // Check if BLE + Radio are still sleeping
        if(GetBits16(SYS_STAT_REG, RAD_IS_DOWN)) {
            // If BLE + Radio are in sleep return the appropriate mode for ARM
            proc_sleep = mode_sleeping;
            break;
        }

        /************************************************************************
         **************              CHECK RW FLAGS                **************
         ************************************************************************/
        // First check if no pending procedure prevents us from going to sleep
        if (rwip_prevent_sleep_get() != 0)
            break;

        DBG_SWDIAG(SLEEP, ALGO, 2);

        
        /************************************************************************
         **************           CHECK EXT WAKEUP FLAG            **************
         ************************************************************************/
        /* If external wakeup is enabled, sleep duration can be set to maximum, otherwise
         * the system must be woken-up periodically to poll incoming packets from HCI */
        if((BLE_APP_PRESENT == 0) || (BLE_INTEGRATED_HOST_GTL == 1 )) // No need for periodic wakeup if we have full-hosted system
        {
            if(!rwip_env.ext_wakeup_enable)
                sleep_duration = jump_table_struct[max_sleep_duration_periodic_wakeup_pos]; // MAX_SLEEP_DURATION_PERIODIC_WAKEUP;
        }

        
        
        /************************************************************************
         *                                                                      *
         *                   CHECK DURATION UNTIL NEXT EVENT                    *
         *                                                                      *
         ************************************************************************/
        // If there's any timer pending, compute the time to wake-up to serve it
        if (ke_env.queue_timer.first != NULL)
            sleep_duration = jump_table_struct[max_sleep_duration_external_wakeup_pos];
#ifdef USE_POWER_OPTIMIZATIONS
        // Store sleep_duration calculated so far. Check below if sleep would be allowed.
        // If not, there's no reason to verify / ensure the available time for SLP...
        uint32_t tmp_dur = sleep_duration;
#endif

        /************************************************************************
         **************            CHECK KERNEL TIMERS             **************
         ************************************************************************/
        // Compute the duration up to the next software timer expires
        if (!ke_timer_sleep_check(&sleep_duration, rwip_env.wakeup_delay))
            break;

        DBG_SWDIAG(SLEEP, ALGO, 3);

        #if (BLE_EMB_PRESENT)
        /************************************************************************
         **************                 CHECK BLE                  **************
         ************************************************************************/
        // Compute the duration up to the next BLE event
        if (!lld_sleep_check(&sleep_duration, rwip_env.wakeup_delay))
            break;
        #endif // BLE_EMB_PRESENT
        
        DBG_SWDIAG(SLEEP, ALGO, 4);

        #if (BT_EMB_PRESENT)
        /************************************************************************
         **************                 CHECK BT                   **************
         ************************************************************************/
        // Compute the duration up to the next BT active slot
        if (!ld_sleep_check(&sleep_duration, rwip_env.wakeup_delay))
            break;
        #endif // BT_EMB_PRESENT

        DBG_SWDIAG(SLEEP, ALGO, 5);

        #if (HCIC_ITF)
        /************************************************************************
         **************                 CHECK HCI                  **************
         ************************************************************************/
        if((BLE_APP_PRESENT == 0) || (BLE_INTEGRATED_HOST_GTL == 1 ))
        {       
            // Try to switch off HCI
            if (!hci_enter_sleep())
                break;
        }
        #endif // HCIC_ITF

        #if (GTL_ITF)
        /************************************************************************
         **************                 CHECK TL                   **************
         ************************************************************************/
        if((BLE_APP_PRESENT == 0) || (BLE_INTEGRATED_HOST_GTL == 1 ))
        {
            // Try to switch off Transport Layer
            if (!gtl_enter_sleep())
                break;
        }
        #endif // GTL_ITF

        DBG_SWDIAG(SLEEP, ALGO, 6);
        
#ifdef USE_POWER_OPTIMIZATIONS
        /************************************************************************
         ******      BLOCK UNTIL THERE'S TIME FOR sleep() AND SLP ISR      ******
         ************************************************************************/
        uint32_t xtal16m_settling_cycles;
        bool rcx_duration_corr = false;
        
        // Restore sleep_duration
        sleep_duration = tmp_dur;
        /*
         * Wait until there's enough time for SLP to restore clocks when the chip wakes up.
         * Then check again if sleep is possible.
         */
        if ( ((lp_clk_sel == LP_CLK_RCX20) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_RCX20) )
        {
            xtal16m_settling_cycles = lld_sleep_us_2_lpcycles_sel_func(XTAL16M_SETTLING_IN_USEC);
            
            while ( (ble_finetimecnt_get() < 550) && (ble_finetimecnt_get() > 200) ); 
            // If we are close to the end of this slot then the actual sleep entry will
            // occur during the next one. But the sleep_duration will have been calculated
            // based on the current slot...
            if (ble_finetimecnt_get() <= 200)
                rcx_duration_corr = true;
        }
        else if ( ((lp_clk_sel == LP_CLK_XTAL32) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_XTAL32) )
        {
            while (ble_finetimecnt_get() < 300);  
        }
        
        /************************************************************************
         *                                                                      *
         *                   CHECK DURATION UNTIL NEXT EVENT                    *
         *                       (this is the 2nd check)                        *
         *                                                                      *
         ************************************************************************/
        bool sleep_check = false;
        
        do
        {
            /************************************************************************
             **************            CHECK KERNEL TIMERS (2)         **************
             ************************************************************************/
            // Compute the duration up to the next software timer expires
            if (!ke_timer_sleep_check(&sleep_duration, rwip_env.wakeup_delay))
                break;

            DBG_SWDIAG(SLEEP, ALGO, 3);

            #if (BLE_EMB_PRESENT)
            /************************************************************************
             **************                 CHECK BLE (2)              **************
             ************************************************************************/
            // Compute the duration up to the next BLE event
            if (!lld_sleep_check(&sleep_duration, rwip_env.wakeup_delay))
                break;
            #endif // BLE_EMB_PRESENT
            
            sleep_check = true;
        } while(0);
        
        if (!sleep_check)
        {
            if((BLE_APP_PRESENT == 0) || (BLE_INTEGRATED_HOST_GTL == 1 ))
            {
#if BLE_HOST_PRESENT		
                gtl_eif_init();
#else
                hci_eif_init();
#endif		
            }
            // sleep is aborted and serial i/f communication is restored
            break;
        }
        
        if (sleep_duration && rcx_duration_corr)
            sleep_duration--;
        
        DBG_SWDIAG(SLEEP, ALGO, 4);
#endif

        POWER_PROFILE_CHECKS_COMPLETED;
        
        /************************************************************************
         **************          PROGRAM CORE DEEP SLEEP           **************
         ************************************************************************/
        if ( ((lp_clk_sel == LP_CLK_RCX20) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_RCX20) )
        {
#if !defined(USE_POWER_OPTIMIZATIONS)
            twirq_set_value = lld_sleep_us_2_lpcycles_sel_func(XTAL_TRIMMING_TIME_USEC);
            
            twirq_reset_value = TWIRQ_RESET_VALUE;
            
            // TWEXT setting
            twext_value = TWEXT_VALUE_RCX;
#else
            // Calculate the time we need to wake-up before "time 0" to do XTAL16 settling,
            // call periph_init() and power-up the BLE core.
            uint32_t lpcycles = lld_sleep_us_2_lpcycles_sel_func(LP_ISR_TIME_USEC);
            
            // Set TWIRQ_SET taking into account that some LP cycles are needed for the power up FSM.
            twirq_set_value = RCX_POWER_UP_TIME + lpcycles;
            if (sleep_env.slp_state == ARCH_DEEP_SLEEP_ON)
                twirq_set_value += RCX_OTP_COPY_OVERHEAD;
            
            // BOOST mode + RCX is not supported
            if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 1)
                ASSERT_WARNING(0);

            // Program LP deassertion to occur when the XTAL16M has settled
            twirq_reset_value = lpcycles - xtal16m_settling_cycles;
            
            // TWEXT setting
            twext_value = lpcycles;
#endif
        }
        else if ( ((lp_clk_sel == LP_CLK_XTAL32) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_XTAL32) )
        {
#if !defined(USE_POWER_OPTIMIZATIONS)
            twirq_set_value = XTAL_TRIMMING_TIME;
            twirq_reset_value = TWIRQ_RESET_VALUE;
            twext_value = TWEXT_VALUE_XTAL32;
#else       
            // The time we need to wake-up before "time 0" to do XTAL16 settling,
            // call periph_init() and power-up the BLE core is LP_ISR_TIME_XTAL32_CYCLES in this case.
            
            // Set TWIRQ_SET taking into account that some LP cycles are needed for the power up FSM.
            twirq_set_value = XTAL32_POWER_UP_TIME + LP_ISR_TIME_XTAL32_CYCLES;
            if (sleep_env.slp_state == ARCH_DEEP_SLEEP_ON)
                twirq_set_value += XTAL32_OTP_COPY_OVERHEAD;
            
            // Adjust TWIRQ_SET in case of BOOST mode, if needed
            if (set_boost_low_vbat1v_overhead == APPLY_OVERHEAD)
                twirq_set_value += BOOST_POWER_UP_OVERHEAD;
            set_boost_low_vbat1v_overhead = NOT_MEASURED;

            // Program LP deassertion to occur when the XTAL16M has settled
            twirq_reset_value = LP_ISR_TIME_XTAL32_CYCLES - XTAL16M_SETTLING_IN_XTAL32_CYCLES;
            
            // TWEXT setting
            twext_value = LP_ISR_TIME_XTAL32_CYCLES;
#endif
        }

       
        //Prepare BLE_ENBPRESET_REG for next sleep cycle
        SetBits32(BLE_ENBPRESET_REG, TWIRQ_RESET, twirq_reset_value);   // TWIRQ_RESET
        SetBits32(BLE_ENBPRESET_REG, TWIRQ_SET, twirq_set_value);       // TWIRQ_SET
        SetBits32(BLE_ENBPRESET_REG, TWEXT, twext_value);               // TWEXT

        //Everything ready for sleep!
        proc_sleep = mode_sleeping;
        
#ifdef USE_POWER_OPTIMIZATIONS
        // Eliminate any additional delays.
        if (sleep_duration) 
            sleep_duration += SLEEP_DURATION_CORR;
        
        POWER_PROFILE_SLEEP_TIMES;
#endif

        #if (BT_EMB_PRESENT)
        // Put BT core into deep sleep
        ld_sleep_enter(rwip_slot_2_lpcycles(sleep_duration), rwip_env.ext_wakeup_enable);
        #elif (BLE_EMB_PRESENT)
        // Put BT core into deep sleep
        if ( ((lp_clk_sel == LP_CLK_XTAL32) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_XTAL32) )
            sleep_lp_cycles = rwip_slot_2_lpcycles(sleep_duration);
        else if ( ((lp_clk_sel == LP_CLK_RCX20) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_RCX20) )
            sleep_lp_cycles = rwip_slot_2_lpcycles_rcx(sleep_duration);
        
        lld_sleep_enter(sleep_lp_cycles, rwip_env.ext_wakeup_enable);
        #endif //BT_EMB_PRESENT / BT_EMB_PRESENT
        

        DBG_SWDIAG(SLEEP, SLEEP, 1);

        /************************************************************************
         **************               SWITCH OFF RF                **************
         ************************************************************************/        
        POWER_PROFILE_REMAINING_TIME;
        
        rwip_rf.sleep();
        
#ifdef USE_POWER_OPTIMIZATIONS
        // We may lower the clock now while we are waiting the BLE to go to sleep...
        bool slow_system_clk = false;
#if (BLE_APP_PRESENT)            
        if ( app_use_lower_clocks_check() )
#endif
        {
            // It will save some power if you lower the clock while waiting for STAT...
            SetBits16(CLK_AMBA_REG, PCLK_DIV, 3);  // lowest is 2MHz (div 8, source is @16MHz)
            SetBits16(CLK_AMBA_REG, HCLK_DIV, 3);
            
            slow_system_clk = true;
        }
#endif
                
        while(!ble_deep_sleep_stat_getf());
                
        //check and wait till you may disable the radio. 32.768KHz XTAL must be running!
        //(debug note: use BLE_CNTL2_REG:MON_LP_CLK bit to check (write 0, should be set to 1 by the BLE))
        while ( !(GetWord32(BLE_CNTL2_REG) & RADIO_PWRDN_ALLOW) ) {};
        
#ifdef USE_POWER_OPTIMIZATIONS
        if (slow_system_clk)
        {
            // and restore clock rates (refer to a couple of lines above)
            use_highest_amba_clocks();
        }
#endif

        ble_regs_push();    // push the ble ret.vars to retention memory
//        smpc_regs_push();   // push smpc ble ret.vars to retention memory
        
        //BLE CLK must be turned off when DEEP_SLEEP_STAT is set
        SetBits16(CLK_RADIO_REG, BLE_ENABLE, 0);   												

        #endif // DEEP_SLEEP
    } while(0);

    return proc_sleep;
}