void $Sub$$UART_Handler(void) #endif { uint32_t idd; idd = 0x0F & GetWord32(UART_IIR_FCR_REG); if(idd!=NO_INT_PEND) { switch(idd) { case UART_TIMEOUT: if ((uart_sps_env.errordetect == UART_ERROR_DETECT_ENABLED) && uart_fifo_err_getf()) { uart_sps_rec_error_isr(); } uart_sps_timeout_data_avail_isr(); break; case RECEIVED_AVAILABLE: uart_sps_rec_data_avail_isr(); break; case THR_EMPTY: uart_sps_thr_empty_isr(); break; default: break; } } }
bool uart_sps_flow_off(void) { bool flow_off = true; do { // First check if no transmission is ongoing if ((uart_temt_getf() == 0) || (uart_thre_getf() == 0) || !uart_sps_is_rx_fifo_empty()) { flow_off = false; break; } // Configure modem (HW flow control disable, 'RTS flow off') SetWord32(UART_MCR_REG, GetWord32(UART_MCR_REG) & (~UART_RTS)); //SetWord32(UART_MCR_REG, 0); // Wait for 1 character duration to ensure host has not started a transmission at the // same time for (int i=0;i<UART_WAIT_BYTE_COUNTER;i++); // Check if data has been received during wait time if(!uart_sps_is_rx_fifo_empty()) { // Re-enable UART flow uart_sps_flow_on(); // We failed stopping the flow flow_off = false; } } while(false); return (flow_off); }
void BLE_RF_DIAG_Handler(void) { uint32 irq_scr; uint16_t cn; cn = GetWord16(RF_BMCW_REG) & 0x003F; irq_scr = GetWord32(BLE_RF_DIAGIRQ_REG); // read BLE_RF_DIAGIRQ_REG so that you clear DIAGIRQ_STAT_0 (otherwise interrupt is activated again and again!) #if LUT_PATCH_ENABLED const volatile struct LUT_CFG_struct *pLUT_CFG; // = (const volatile struct LUT_CFG_struct *)(jump_table_struct[lut_cfg_pos]); pLUT_CFG = (const volatile struct LUT_CFG_struct *)(jump_table_struct[lut_cfg_pos]); if(!pLUT_CFG->HW_LUT_MODE) { set_rf_cal_cap(cn); } #endif #if MGCKMODA_PATCH_ENABLED if(GetBits16(RF_MGAIN_CTRL_REG, GAUSS_GAIN_SEL) && (irq_scr & DIAGIRQ_STAT_0)) // TODO: If GAUSS_GAIN_SEL==0x1 AND it is an TX_EN interrupt (for RX_EN int it is not necessary to run) { set_gauss_modgain(cn); } #endif #ifdef PRODUCTION_TEST if( irq_scr & DIAGIRQ_STAT_0)//check TXEN posedge { test_tx_packet_nr++; } if( irq_scr & DIAGIRQ_STAT_1)//check RXEN posedge { test_rx_irq_cnt++; } #endif }
/** **************************************************************************************** * @brief Used to calculate the boot image CRC * @param[in] length: Length of the image in 32-bit words * @return CRC checksum (1 byte) **************************************************************************************** */ uint8_t calc_crc(uint32_t length){ uint32_t i; uint32_t temp; uint8_t crc; crc=0xFF; for(i=0;i<length;i++) { temp=GetWord32(program_t+4*i); crc^=(0xFF&(temp>>24)); crc^=(0xFF&(temp>>16)); crc^=(0xFF&(temp>>8 )); crc^=(0xFF&(temp )); } return crc; }
void BLE_RF_DIAG_Handler(void) { uint16_t cn; cn = GetWord16(RF_BMCW_REG) & 0x003F; #if LUT_PATCH_ENABLED const volatile struct LUT_CFG_struct *pLUT_CFG; // = (const volatile struct LUT_CFG_struct *)(jump_table_struct[lut_cfg_pos]); pLUT_CFG = (const volatile struct LUT_CFG_struct *)(jump_table_struct[lut_cfg_pos]); if(!pLUT_CFG->HW_LUT_MODE) { set_rf_cal_cap(cn); } #endif #if MGCKMODA_PATCH_ENABLED if(GetBits16(RF_MGAIN_CTRL_REG, GAUSS_GAIN_SEL) && GetBits32(BLE_RF_DIAGIRQ_REG, DIAGIRQ_STAT_0)) // TODO: If GAUSS_GAIN_SEL==0x1 AND it is an TX_EN interrupt (for RX_EN int it is not necessary to run) { set_gauss_modgain(cn); } #endif GetWord32(BLE_RF_DIAGIRQ_REG); // read BLE_RF_DIAGIRQ_REG so that you clear DIAGIRQ_STAT_0 (otherwise interrupt is activated again and again!) }
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; }
void uart_sps_force_flow_off(void) { SetWord32(UART_MCR_REG, GetWord32(UART_MCR_REG) & (~UART_RTS)); }