/** **************************************************************************************** * @brief SPI 439 Read * @param[in] address: 12 bits register address on 439 * @param[in] data: * * To read one data word from the SPI, 3 transactions are needed. * - First transaction: send command&address * - Second transaction: send dummy 0 * - Third transacation: read returned data * This functions uses POLLING to check if SPI transaction has completed. * * @return data read from the 439 **************************************************************************************** */ uint32_t spi_getword(uint32_t address) // IZP named changed { uint32_t dataRead = 0; spi_cs_low(); uint32_t dataToSend = ((SC14439_MEM_RD<<13) | (address&0x1FFF )); SetWord16(SPI_RX_TX_REG0, (uint16_t)dataToSend); // write (low part of) dataToSend while (!GetBits16(SPI_CTRL_REG, SPI_INT_BIT)); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag dataToSend = 0; SetWord16(SPI_RX_TX_REG0, (uint16_t)dataToSend); // write (low part of) dataToSend while (!GetBits16(SPI_CTRL_REG, SPI_INT_BIT)); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag SetWord16(SPI_RX_TX_REG0, (uint16_t)dataToSend); // write (low part of) dataToSend while (!GetBits16(SPI_CTRL_REG, SPI_INT_BIT)); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag dataRead = GetWord16(SPI_RX_TX_REG0); //read (low part of) data from spi slave spi_cs_high(); return dataRead; // return data read from spi slave }
/** **************************************************************************************** * @brief Read from 3-wire SPI * @param[in] registerIndex: Target address (A6..A0) * * @return byte read **************************************************************************************** */ uint8_t read_from_3wire_SPI_register(uint8_t registerIndex, uint8_t is_last_transaction) { static uint8_t i, dataRead; GPIO_SetInactive(cs.port, cs.pin); // pull CS low GPIO_SetPinFunction( sdio.port, sdio.pin, OUTPUT, PID_SPI_DO); // configure SDIO as output SetWord16(SPI_RX_TX_REG0, (uint16_t)(registerIndex) ); // MSB set to HIGH - A6..A0 Address of register to write to do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); //Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt GPIO_SetPinFunction( sdio.port, sdio.pin, INPUT, PID_SPI_DI); // configure SDIO as input for (i=0; i<TsradCounter; i++); // {DEV.NOTE#: For Mouse sensor Delay > Tsrad = 4us <-- suitable counter is 6} SetWord16(SPI_RX_TX_REG0, (uint16_t)0x00 ); // dummy write data - read data do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); //Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt dataRead = GetWord16(SPI_RX_TX_REG0); // read received byte SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag if(is_last_transaction) GPIO_SetActive(cs.port, cs.pin); // set CS high return dataRead; }
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 Read a single item from serial flash via SPI * @param[in] x: buffer to read the data **************************************************************************************** */ inline void getByte_SPI(uint8* x ) { SetWord16(SPI_RX_TX_REG0, (uint16) DUMMY); while (GetBits16(SPI_CTRL_REG, SPI_INT_BIT==0)); SetWord16(SPI_CLEAR_INT_REG, 0x01); *(uint8*)x=(uint8)GetWord16(SPI_RX_TX_REG0); }
/** **************************************************************************************** * @brief SPI 439 Write * @param[in] address: 12 bits address on 439 * @param[in] data: 16 bits value for the register * * To write one data word to 439 with the SPI, 2 transactions are needed. * - First transaction: send command&address * - Second transaction: write data * This functions uses POLLING to check if SPI transaction has completed. * * @return data read **************************************************************************************** */ void spi_setword(uint32_t address, uint32_t data) // IZP named changed { spi_cs_low(); uint32_t dataToSend = ((SC14439_MEM_WR<<13) | (address&0x1FFF )); SetWord16(SPI_RX_TX_REG0, (uint16_t)dataToSend); // write address while (!GetBits16(SPI_CTRL_REG, SPI_INT_BIT)); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag SetWord16(SPI_RX_TX_REG0, (uint16_t)data); // write (low part of) dataToSend while (!GetBits16(SPI_CTRL_REG, SPI_INT_BIT)); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag spi_cs_high(); }
/** **************************************************************************************** * @brief Handler of the Green LED Timer * * @param[in] msgid * @param[in] param * @param[in] dest_id * @param[in] src_id * * @return KE_MSG_CONSUMED **************************************************************************************** */ int app_green_led_timer_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (!dbg_uses_led_pins() || !((GetWord16(SYS_STAT_REG) & DBG_IS_UP) == DBG_IS_UP)) { // GPIOs are not being used by the debugger switch(green_led_st) { case LED_OFF: green_led_off(); break; case BLINK_LED_IS_ON__TURN_OFF: GPIO_SetActive(KBD_GREEN_LED_PORT, KBD_GREEN_LED_PIN); // high - off app_timer_set(APP_GREEN_LED_TIMER, TASK_APP, BLINK_GREEN_OFF); green_led_st = BLINK_LED_IS_OFF__TURN_ON; if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((red_led_st == LED_OFF) || (red_led_st == BLINK_LED_IS_OFF__TURN_ON))) { app_restore_sleep_mode(); // restore sleep } break; case BLINK_LED_IS_OFF__TURN_ON: green_led_blink(); app_timer_set(APP_GREEN_LED_TIMER, TASK_APP, BLINK_GREEN_ON); leds_block_sleep(); break; case LED_ON: green_led_off(); if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((red_led_st == LED_OFF) || (red_led_st == BLINK_LED_IS_OFF__TURN_ON))) { app_restore_sleep_mode(); // restore sleep } break; default: break; } } return (KE_MSG_CONSUMED); }
/** **************************************************************************************** * @brief Write a single item to serial flash via SPI * @param[in] x: data to send **************************************************************************************** */ void putByte_SPI(uint32 x) { uint16 tmp; SetWord16(SPI_RX_TX_REG0, (uint16_t)x); // write (low part of) dataToSend do { } while (GetBits16(SPI_CTRL_REG, SPI_INT_BIT) == 0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag tmp = GetWord16(SPI_RX_TX_REG0); }
/** **************************************************************************************** * @brief Write to 3-wire SPI * @param[in] registerIndex: Target address (A6..A0) * @param[in] valueToWrite: Value to write * * @return Number of read bytes **************************************************************************************** */ void write_to_3wire_SPI_register(uint8_t registerIndex, uint8_t valueToWrite) { GPIO_SetInactive(cs.port, cs.pin); // pull CS low GPIO_SetPinFunction( sdio.port, sdio.pin, OUTPUT, PID_SPI_DO); // configure SDIO as output SetWord16(SPI_RX_TX_REG0, (uint16_t)(registerIndex | 0x80) ); // MSB set to HIGH - A6..A0 Address of register to write to do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); //Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt SetWord16(SPI_RX_TX_REG0, (uint16_t)valueToWrite ); // write data do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); // Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt GPIO_SetActive(cs.port, cs.pin); // set CS high }
void burst_write_to_3wire_SPI_register(uint8_t registerIndex) { GPIO_SetPinFunction( sdio.port, sdio.pin, OUTPUT, PID_SPI_DO); // configure SDIO as output SetWord16(SPI_RX_TX_REG0, (uint16_t)(registerIndex) ); // MSB set to HIGH - A6..A0 Address of register to write to do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); // Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt GPIO_SetPinFunction( sdio.port, sdio.pin, INPUT, PID_SPI_DI); // configure SDIO as input }
uint16_t $Sub$$get_rc16m_count_func(void) { uint16_t count; uint16_t trim = GetBits16(CLK_16M_REG, RC16M_TRIM); count = $Super$$get_rc16m_count_func(); SetBits16(CLK_16M_REG, RC16M_TRIM, trim); return count; }
uint16_t __wrap_get_rc16m_count_func(void) { uint16_t count; uint16_t trim = GetBits16(CLK_16M_REG, RC16M_TRIM); count = __real_get_rc16m_count_func(); SetBits16(CLK_16M_REG, RC16M_TRIM, trim); return count; }
/** **************************************************************************************** * @brief Callback function, called when external wakeup function is triggered. * * @return void. **************************************************************************************** */ void ext_wakeup_cb(void) { if (GetBits16(SYS_STAT_REG, PER_IS_DOWN)) { // Return GPIO functionality from external wakeup GPIO #if DEVELOPMENT_DEBUG GPIO_reservations(); #endif set_pad_functions(); } SetBits32(GP_CONTROL_REG, BLE_WAKEUP_REQ, 1); }
uint8_t burst_read_from_3wire_SPI_register(void) { static uint8_t dataRead; SetWord16(SPI_RX_TX_REG0, (uint16_t)0x00 ); // dummy write data - read data do { } while (GetBits16(SPI_CTRL_REG,SPI_INT_BIT)==0); // polling to wait for spi transmission SetWord16(SPI_CLEAR_INT_REG, 0); // Clear SPI_CTRL_REG[SPI_INT_BIT] interrupt dataRead = GetWord16(SPI_RX_TX_REG0); // read received byte SetWord16(SPI_CLEAR_INT_REG, 0x01); // clear pending flag return dataRead; }
/** **************************************************************************************** * @brief Enable pad's and peripheral clocks assuming that peripherals' power domain is down. * * * @return void **************************************************************************************** */ void periph_init(void) { // Power up peripherals' power domain SetBits16(PMU_CTRL_REG, PERIPH_SLEEP, 0); while (!(GetWord16(SYS_STAT_REG) & PER_IS_UP)) ; SetBits16(CLK_16M_REG, XTAL16_BIAS_SH_DISABLE, 1); // Initialize UART component #ifdef PROGRAM_ENABLE_UART if (GetBits16(CLK_CTRL_REG, RUNNING_AT_XTAL16M)) { SetBits16(CLK_PER_REG, UART1_ENABLE, 1); // enable clock - always @16MHz // mode=3-> no parity, 1 stop bit 8 data length #ifdef UART_MEGABIT uart_init(UART_BAUDRATE_1M, 3); #else uart_init(UART_BAUDRATE_115K2, 3); #endif // UART_MEGABIT } #endif // PROGRAM_ENABLE_UART //FPGA #ifdef FPGA_USED SetBits16(CLK_PER_REG, SPI_ENABLE, 1); // enable clock SetBits16(CLK_PER_REG, SPI_DIV, 1); // set divider to 1 SetBits16(CLK_PER_REG, WAKEUPCT_ENABLE, 1); // enable clock of Wakeup Controller #endif //rom patch patch_func(); //Init pads set_pad_functions(); #ifndef FPGA_USED // SetBits16(CLK_PER_REG, WAKEUPCT_ENABLE, 1); // enable clock of Wakeup Controller #endif //SetWord16(P01_PADPWR_CTRL_REG,0xFF); // Enable the pads SetBits16(SYS_CTRL_REG, PAD_LATCH_EN, 1); }
/** **************************************************************************************** * @brief Send an HCI message over the SPI * @param[in] size: size of data to send in bytes * @param[in] *msg_ptr: pointer to the first byte to be sent **************************************************************************************** */ void spi_send_hci_msg(uint16_t size, uint8_t *msg_ptr) { uint16_t i; NVIC_DisableIRQ(GPIO0_IRQn); while(GetBits16(SPI_DATA_REG,1<<SPI_DREADY_PIN)==1); // Polling DREADY to detect if data is being received spi_cs_high(); // Close CS spi_cs_low(); // Open CS spi_access(0x05); for (i=0; i<size; i++) { spi_access(*msg_ptr++); } spi_cs_high(); // Close CS NVIC_EnableIRQ(GPIO0_IRQn); }
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!) }
void rf_reinit_func(void) { uint32 tmp32 = 0; SetBits32(&tmp32, RTRIP_DELAY, 7); SetBits32(&tmp32, TXPWRDN, 0x5); SetBits32(&tmp32, RXPWRUP, RXPWRUP_VAL); SetBits32(&tmp32, TXPWRUP, TXPWRUP_VAL); SetWord32(BLE_RADIOPWRUPDN_REG, tmp32); SetBits32(BLE_RADIOCNTL1_REG, XRFSEL, 3); SetBits32(BLE_RWBTLECNTL_REG, SYNCERR, 0); //this must be always '0' SetBits16(CLK_RADIO_REG, RFCU_DIV, 1); //RFCU clock must always be 8MHz! SetBits16(CLK_RADIO_REG, RFCU_ENABLE, 1); SetBits16(PMU_CTRL_REG, RETENTION_MODE, 0xF); if (lp_clk_sel == LP_CLK_XTAL32) { //If LP clock is XTAL32 in Boost mode set XTAL32K_CUR to 1. if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) SetBits16(CLK_32K_REG, XTAL32K_CUR, 1); } rf_regs(); #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) { SetWord16(RF_VCOCAL_CTRL_REG, vcocal_ctrl_reg_val); } #endif //LUT_PATCH_ENABLED enable_rf_diag_irq(RF_DIAG_IRQ_MODE_RXTX); // This just enables the TX_EN int. RX_EN int enable status remains as it was }
/** **************************************************************************************** * @brief Calculates RCX20 frequency. * * @param[in] cal_time. Calibration time in RCX20 cycles. * * @return void **************************************************************************************** */ void read_rcx_freq(uint16_t cal_time) { if ( (cal_enable) && ((CFG_LP_CLK == LP_CLK_FROM_OTP) || (CFG_LP_CLK == LP_CLK_RCX20)) ) { while(GetBits16(CLK_REF_SEL_REG, REF_CAL_START) == 1); volatile uint32_t high = GetWord16(CLK_REF_VAL_H_REG); volatile uint32_t low = GetWord16(CLK_REF_VAL_L_REG); volatile uint32_t value = ( high << 16 ) + low; volatile uint32_t f = (16000000 * cal_time) / value; cal_enable = 0; rcx_freq = f; rcx_period = ((float) 1000000/f) * 1024; rcx_slot_duration = 0.000625 * (float)rcx_freq; #ifdef RCX_MEASURE if (rcx_period_last) { volatile int diff = rcx_period_last - rcx_period; if (abs(diff) > rcx_period_diff) rcx_period_diff = abs(diff); } rcx_period_last = rcx_period; if (rcx_freq_min == 0) { rcx_freq_min = rcx_freq; rcx_freq_max = rcx_freq; } if (rcx_freq < rcx_freq_min) rcx_freq_min = rcx_freq; else if (rcx_freq > rcx_freq_max) rcx_freq_max = rcx_freq; #endif } }
/** **************************************************************************************** * @brief Initialisation of ble core, pwr and clk * * The Hclk and Pclk are set **************************************************************************************** */ void init_pwr_and_clk_ble(void) { SetBits16(CLK_RADIO_REG, BLE_DIV, 0); SetBits16(CLK_RADIO_REG, BLE_ENABLE, 1); SetBits16(CLK_RADIO_REG, RFCU_DIV, 1); SetBits16(CLK_RADIO_REG, RFCU_ENABLE, 1); /* * Power up BLE core & reset BLE Timers */ SetBits16(CLK_32K_REG, RC32K_ENABLE, 1); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 0); SetBits16(CLK_RADIO_REG, BLE_LP_RESET, 1); SetBits16(PMU_CTRL_REG, RADIO_SLEEP, 0); while (!(GetWord16(SYS_STAT_REG) & RAD_IS_UP)); // Just wait for radio to truely wake up select_lp_clk(); if ( ((lp_clk_sel == LP_CLK_XTAL32) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_XTAL32) ) { SetBits16(CLK_32K_REG, XTAL32K_ENABLE, 1); // Enable XTAL32KHz // Disable XTAL32 amplitude regulation in BOOST mode if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) SetBits16(CLK_32K_REG, XTAL32K_DISABLE_AMPREG, 1); else SetBits16(CLK_32K_REG, XTAL32K_DISABLE_AMPREG, 0); SetBits16(CLK_32K_REG, XTAL32K_CUR, 5); SetBits16(CLK_32K_REG, XTAL32K_RBIAS, 3); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 1); // Select XTAL32K as LP clock } else if ( ((lp_clk_sel == LP_CLK_RCX20) && (CFG_LP_CLK == LP_CLK_FROM_OTP)) || (CFG_LP_CLK == LP_CLK_RCX20) ) { SetBits16(CLK_RCX20K_REG, RCX20K_NTC, 0xB); SetBits16(CLK_RCX20K_REG, RCX20K_BIAS, 1); SetBits16(CLK_RCX20K_REG, RCX20K_TRIM, 0); SetBits16(CLK_RCX20K_REG, RCX20K_LOWF, 1); SetBits16(CLK_RCX20K_REG, RCX20K_ENABLE, 1); SetBits16(CLK_RCX20K_REG, RCX20K_SELECT, 1); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 0); SetBits16(CLK_32K_REG, XTAL32K_ENABLE, 0); // Disable Xtal32KHz } else ASSERT_WARNING(0); SetBits16(CLK_32K_REG, RC32K_ENABLE, 0); // Disable RC32KHz SetBits16(CLK_RADIO_REG, BLE_LP_RESET, 0); if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) SetWord16(DCDC_CTRL3_REG, 0x5); /* * Just make sure that BLE core is stopped (if already running) */ SetBits32(BLE_RWBTLECNTL_REG, RWBLE_EN, 0); /* * Since BLE is stopped (and powered), set CLK_SEL */ SetBits32(BLE_CNTL2_REG, BLE_CLK_SEL, 16); SetBits32(BLE_CNTL2_REG, BLE_RSSI_SEL, 1); }
/** **************************************************************************************** * @brief Initialisation of ble core, pwr and clk * * The Hclk and Pclk are set **************************************************************************************** */ void init_pwr_and_clk_ble(void) { SetBits16(CLK_RADIO_REG, BLE_DIV, 0); SetBits16(CLK_RADIO_REG, BLE_ENABLE, 1); SetBits16(CLK_RADIO_REG, RFCU_DIV, 1); SetBits16(CLK_RADIO_REG, RFCU_ENABLE, 1); /* * Power up BLE core & reset BLE Timers */ SetBits16(CLK_32K_REG, RC32K_ENABLE, 1); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 0); SetBits16(CLK_RADIO_REG, BLE_LP_RESET, 1); SetBits16(PMU_CTRL_REG, RADIO_SLEEP, 0); while (!(GetWord16(SYS_STAT_REG) & RAD_IS_UP)); // Just wait for radio to truely wake up select_lp_clk(); if (lp_clk_sel == LP_CLK_XTAL32) { SetBits16(CLK_32K_REG, XTAL32K_ENABLE, 1); // Enable XTAL32KHz // Disable XTAL32 amplitude regulation in BOOST mode if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) SetBits16(CLK_32K_REG, XTAL32K_DISABLE_AMPREG, 1); else SetBits16(CLK_32K_REG, XTAL32K_DISABLE_AMPREG, 0); SetBits16(CLK_32K_REG, XTAL32K_CUR, 5); SetBits16(CLK_32K_REG, XTAL32K_RBIAS, 3); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 1); // Select XTAL32K as LP clock } else if (lp_clk_sel == LP_CLK_RCX20) { SetBits16(CLK_RCX20K_REG, RCX20K_NTC, 0xB); SetBits16(CLK_RCX20K_REG, RCX20K_BIAS, 1); SetBits16(CLK_RCX20K_REG, RCX20K_TRIM, 0); SetBits16(CLK_RCX20K_REG, RCX20K_LOWF, 1); SetBits16(CLK_RCX20K_REG, RCX20K_ENABLE, 1); SetBits16(CLK_RCX20K_REG, RCX20K_SELECT, 1); SetBits16(SYS_CTRL_REG, CLK32_SOURCE, 0); } SetBits16(CLK_32K_REG, RC32K_ENABLE, 0); // Disable RC32KHz SetBits16(CLK_RADIO_REG, BLE_LP_RESET, 0); if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) SetWord16(DCDC_CTRL3_REG, 0x5); /* * Just make sure that BLE core is stopped (if already running) */ SetBits32(BLE_RWBTLECNTL_REG, RWBLE_EN, 0); /* * Since BLE is stopped (and powered), set CLK_SEL */ SetBits32(BLE_CNTL2_REG, BLE_CLK_SEL, 16); SetBits32(BLE_CNTL2_REG, BLE_RSSI_SEL, 1); /* * Set spi interface to software */ #ifdef FPGA_USED // the following 2 lines are for FPGA implementation SetBits32(BLE_CNTL2_REG, SW_RPL_SPI, 0); SetBits32(BLE_CNTL2_REG, BB_ONLY, 1); #endif }
/** **************************************************************************************** * @brief Handler of the Red LED Timer * * @param[in] msgid * @param[in] param * @param[in] dest_id * @param[in] src_id * * @return KE_MSG_CONSUMED **************************************************************************************** */ int app_red_led_timer_handler(ke_msg_id_t const msgid, void const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id) { if (!dbg_uses_led_pins() || !((GetWord16(SYS_STAT_REG) & DBG_IS_UP) == DBG_IS_UP)) { // GPIOs are not being used by the debugger switch(red_led_st) { case LED_OFF: red_led_off(); break; case DOUBLE_BLINK_LED_IS_ON__TURN_OFF_A: red_led_off(); app_timer_set(APP_RED_LED_TIMER, TASK_APP, DOUBLE_BLINK_RED_OFF_A); red_led_st = DOUBLE_BLINK_LED_IS_OFF__TURN_ON_B; if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((green_led_st == LED_OFF) || (green_led_st == BLINK_LED_IS_OFF__TURN_ON))) { app_restore_sleep_mode(); } break; case DOUBLE_BLINK_LED_IS_OFF__TURN_ON_B: red_led_blink(); app_timer_set(APP_RED_LED_TIMER, TASK_APP, DOUBLE_BLINK_RED_ON_B); red_led_st = DOUBLE_BLINK_LED_IS_ON__TURN_OFF_B; leds_block_sleep(); break; case DOUBLE_BLINK_LED_IS_ON__TURN_OFF_B: red_led_off(); app_timer_set(APP_RED_LED_TIMER, TASK_APP, DOUBLE_BLINK_RED_OFF_B); red_led_st = LED_OFF; if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((green_led_st == LED_OFF) || (green_led_st == BLINK_LED_IS_OFF__TURN_ON))) { app_restore_sleep_mode(); } break; case BLINK_LED_IS_ON__TURN_OFF: red_led_off(); app_timer_set(APP_RED_LED_TIMER, TASK_APP, BLINK_RED_OFF); red_led_st = BLINK_LED_IS_OFF__TURN_ON; if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((green_led_st == LED_OFF) || (green_led_st == BLINK_LED_IS_OFF__TURN_ON))){ app_restore_sleep_mode(); // restore sleep } break; case BLINK_LED_IS_OFF__TURN_ON: red_led_blink(); app_timer_set(APP_RED_LED_TIMER, TASK_APP, BLINK_RED_ON); leds_block_sleep(); break; case LED_ON: red_led_off(); if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && ((green_led_st == LED_OFF) || (green_led_st == BLINK_LED_IS_OFF__TURN_ON))) { app_restore_sleep_mode(); // restore sleep } high_priority_indications_active = false; break; default: break; } } return (KE_MSG_CONSUMED); }
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; }
/* * LOCAL FUNCTIONS DEFINITIONS **************************************************************************************** */ // ============================================================================================ // ==================== DEEP SLEEP PATCH - THIS CODE MUST STAY IN RAM ========================= // ============================================================================================ extern void rf_workaround_init(void); extern void rf_reinit(void); // /********************************************************************************* // *** WAKEUP_LP_INT ISR // ***/ void BLE_WAKEUP_LP_Handler(void) { volatile long t=0; #if !(USE_WDOG) SetWord16(SET_FREEZE_REG, FRZ_WDOG); //Prepare WDOG, i.e. stop #endif // // Gives 1dB higher sensitivity - UNTESTED // if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) // { // // Boost-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x8); // 80mA // } // else // { // // Buck-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x4); // 40mA // } /* * Wait and Switch to XTAL 16MHz * (default after each wake-up is RC 16MHz, but XTAL initialization sequence has been already initiated by PMU) * NOTE: * 1. If app does not need XTAL16MHz but RC16MHz is enough then skip this section! * 2. Wait-loop BEFORE activating PERIPH_PD in order to save some power... */ // It will save some power if you lower the clock while waiting for XTAL16 to settle. // Could also switch to 32KHz, but then processing power is dramatically reduced (e.g. patching() routine may be too slow). SetBits16(CLK_AMBA_REG, PCLK_DIV, 3); // lowest is 2MHz (div 8, source is RC @16MHz) SetBits16(CLK_AMBA_REG, HCLK_DIV, 3); while ( !GetBits16(SYS_STAT_REG, XTAL16_SETTLED) ) // this takes some mili seconds __NOP(), __NOP(), __NOP(); // reduce some APB activity SetBits16(CLK_CTRL_REG, SYS_CLK_SEL, 0); // select XTAL 16MHz SetBits16(CLK_16M_REG, RC16M_ENABLE, 0); // save power from RC 16MHz // and restore clock rates (refer to a couple of lines above) SetBits16(CLK_AMBA_REG, PCLK_DIV, 0); SetBits16(CLK_AMBA_REG, HCLK_DIV, 0); /* * Init System Power Domain blocks: GPIO, WD Timer, Sys Timer, etc. * Power up and init Peripheral Power Domain blocks, * and finally release the pad latches. */ if(GetBits16(SYS_STAT_REG, PER_IS_DOWN)) periph_init(); /* * Since XTAL 16MHz is activated, power-up the Radio Subsystem (including BLE) * * Note that BLE core clock is masked in order to handle the case where RADIO_PD does not get into power down state. * The BLE clock should be active only as long as system is running at XTAL 16MHz (not at RC16 or 32KHz). * Also BLE clock should be enabled before powering up the RADIO Power Domain ! */ SetBits16(CLK_RADIO_REG, BLE_ENABLE, 1); // BLE clock enable SetBits16(PMU_CTRL_REG, RADIO_SLEEP, 0); // Power up! Note: System must run at 16MHz when powering up RADIO_PD. while (!(GetWord16(SYS_STAT_REG) & RAD_IS_UP)) {}; // this may take up to 1/2 of the 32KHz clock period /* * Wait for at least one Low Power clock edge after the power up of the Radio Power Domain *e.g. with ble_wait_lp_clk_posedge() ) * or even better check the BLE_CNTL2_REG[WAKEUPLPSTAT] ! * Thus you assure that BLE_WAKEUP_LP_IRQ is deasserted and BLE_SLP_IRQ is asserted. * After this check exit this ISE in order to proceed with BLE_SLP_Handler(). */ while ( GetBits32(BLE_CNTL2_REG, WAKEUPLPSTAT) || !GetBits32(BLE_INTSTAT_REG, SLPINTSTAT)) if (t) break; // Now BLE_WAKEUP_LP_IRQ is deasserted and BLE_SLP_IRQ is asserted, so exit in order to proceed with BLE_SLP_Handler(). // NOTE: If returning from BLE_WAKEUP_LP_Handler() will not cause BLE_SLP_Handler() to start, // but the code after __WFI() is executed, then THERE WAS A SW SETUP PROBLEM !!! // so it is recommended to place a check after __WFI(). }
int main_func(void) { volatile unsigned i; sleep_mode_t sleep_mode; // keep at system RAM. On each while loop it will get a new value. sys_startup_flag = true; /* ************************************************************************************ * Platform initialization ************************************************************************************ */ #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // 200 * 10.24ms = ~2sec active time! SetWord16(WATCHDOG_CTRL_REG, 0); // Generate an NMI when counter reaches 0 and a WDOG (SYS) Reset when it reaches -16! // WDOG can be frozen by SW! SetWord16(RESET_FREEZE_REG, FRZ_WDOG); // Start WDOG #else SetWord16(SET_FREEZE_REG, FRZ_WDOG); #endif set_system_clocks(); GPIO_init(); periph_init(); /* Don't remove next line otherwhise dummy[0] could be optimized away * The dummy array is intended to reserve the needed Exch.Memory space in retention memory */ dummy[0] = dummy[0]; descript[0] = descript[0]; #if (BLE_CONNECTION_MAX_USER > 4) cs_table[0] = cs_table[0]; #endif /* Don't remove next line otherwhise data__1 is optimized away. * The address 0x9010 is used by the ROM code (rand.o) and cannot be used by the * application code! */ //GZ data__1 = 0; // Initialize unloaded RAM area //unloaded_area_init(); // Initialize random process srand(1); // Initialize the exchange memory interface, emi in RAM for the time being, so no init necessary #if 0 emi_init(); #endif // Initialize NVDS module nvds_init((uint8_t *)NVDS_FLASH_ADDRESS, NVDS_FLASH_SIZE); //check and read BDADDR from OTP nvds_read_bdaddr_from_otp(); #ifdef RADIO_580 iq_trim_from_otp(); #endif /* ************************************************************************************ * BLE initialization ************************************************************************************ */ init_pwr_and_clk_ble(); //diagnostic(); // rf_init(&rwip_rf); // SetBits32(BLE_RADIOCNTL1_REG, XRFSEL, 3); #if UNCALIBRATED_AT_FAB SetBits16(BANDGAP_REG, BGR_TRIM, 0x0); // trim RET Bandgap SetBits16(BANDGAP_REG, LDO_RET_TRIM, 0xA); // trim RET LDO SetWord16(RF_LNA_CTRL1_REG, 0x24E); SetWord16(RF_LNA_CTRL2_REG, 0x26); SetWord16(RF_LNA_CTRL3_REG, 0x7); SetWord16(RF_RSSI_COMP_CTRL_REG, 0x7777); SetWord16(RF_VCO_CTRL_REG, 0x1); SetBits16(CLK_16M_REG, RC16M_TRIM, 0xA); #endif // Initialize BLE stack NVIC_ClearPendingIRQ(BLE_SLP_IRQn); NVIC_ClearPendingIRQ(BLE_EVENT_IRQn); NVIC_ClearPendingIRQ(BLE_RF_DIAG_IRQn); NVIC_ClearPendingIRQ(BLE_RX_IRQn); NVIC_ClearPendingIRQ(BLE_CRYPT_IRQn); NVIC_ClearPendingIRQ(BLE_FINETGTIM_IRQn); NVIC_ClearPendingIRQ(BLE_GROSSTGTIM_IRQn); NVIC_ClearPendingIRQ(BLE_WAKEUP_LP_IRQn); rwip_init(error); /* Set spi to HW (Ble) * Necessary: So from this point the BLE HW can generate spi burst iso SW * SPI BURSTS are necessary for the radio TX and RX burst, done by hardware * beause of the accurate desired timing */ //FPGA #ifdef FPGA_USED SetBits32(BLE_CNTL2_REG,SW_RPL_SPI ,1); #endif //Enable BLE core SetBits32(BLE_RWBTLECNTL_REG,RWBLE_EN ,1); #if RW_BLE_SUPPORT && HCIC_ITF // If FW initializes due to FW reset, send the message to Host if(error != RESET_NO_ERROR) { rwble_send_message(error); } #endif /* ************************************************************************************ * Sleep mode initializations (especially for full embedded) ************************************************************************************ */ #if (EXT_SLEEP_ENABLED) app_set_extended_sleep(); #elif (DEEP_SLEEP_ENABLED) app_set_deep_sleep(); #else app_disable_sleep(); #endif if (lp_clk_sel == LP_CLK_RCX20) { calibrate_rcx20(20); read_rcx_freq(20); } /* ************************************************************************************ * Application initializations ************************************************************************************ */ #if (BLE_APP_PRESENT) { app_init(); // Initialize APP } #endif /* #if (BLE_APP_PRESENT) */ /* ************************************************************************************ * Main loop ************************************************************************************ */ lld_sleep_init_func(); SetWord16(TRIM_CTRL_REG, 0xA2); SetBits16(CLK_16M_REG, XTAL16_CUR_SET, 0x5); // // Gives 1dB higher sensitivity - UNTESTED // if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) // { // // Boost-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x8); // 80mA // } // else // { // // Buck-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x4); // 40mA // } // Now enable the TX_EN/RX_EN interrupts, depending on the RF mode of operation (PLL-LUT and MGC_KMODALPHA combinations) #if LUT_PATCH_ENABLED const volatile struct LUT_CFG_struct *pLUT_CFG; pLUT_CFG = (const volatile struct LUT_CFG_struct *)(jump_table_struct[lut_cfg_pos]); if (!pLUT_CFG->HW_LUT_MODE) { enable_rf_diag_irq(RF_DIAG_IRQ_MODE_RXTX); } else { #if MGCKMODA_PATCH_ENABLED enable_rf_diag_irq(RF_DIAG_IRQ_MODE_TXONLY); // This just enables the TX_EN int. RX_EN int enable status remains as it was #endif //MGCKMODA_PATCH_ENABLED } #else //LUT_PATCH_ENABLED #if MGCKMODA_PATCH_ENABLED enable_rf_diag_irq(RF_DIAG_IRQ_MODE_TXONLY); // This just enables the TX_EN int. RX_EN int enable status remains as it was #endif //MGCKMODA_PATCH_ENABLED #endif //LUT_PATCH_ENABLED #if BLE_APP_SPOTAR //app_spotar_exec_patch(); #endif if ( (app_get_sleep_mode() == 2) || (app_get_sleep_mode() == 1) ) { SetWord16(SET_FREEZE_REG, FRZ_WDOG); // Stop WDOG until debugger is removed if ((GetWord16(SYS_STAT_REG) & DBG_IS_UP) == DBG_IS_UP) SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 1); // close debugger } /* ************************************************************************************ * Watchdog ************************************************************************************ */ #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // 200 * 10.24ms active time for initialization! SetWord16(RESET_FREEZE_REG, FRZ_WDOG); // Start WDOG #endif /* ************************************************************************************ * Main loop ************************************************************************************ */ while(1) { // schedule all pending events if(GetBits16(CLK_RADIO_REG, BLE_ENABLE) == 1) { // BLE clock is enabled if(GetBits32(BLE_DEEPSLCNTL_REG, DEEP_SLEEP_STAT) == 0 && !(rwip_prevent_sleep_get() & RW_WAKE_UP_ONGOING)) { // BLE is running #ifndef FPGA_USED uint8_t ble_evt_end_set = ke_event_get(KE_EVENT_BLE_EVT_END); // BLE event end is set. conditional RF calibration can run. #endif rwip_schedule(); #ifndef FPGA_USED if (ble_evt_end_set) { uint32_t sleep_duration = 0; if (lp_clk_sel == LP_CLK_RCX20) read_rcx_freq(20); if (lld_sleep_check(&sleep_duration, 4)) //6 slots -> 3.750 ms conditionally_run_radio_cals(); // check time and temperature to run radio calibrations. } #endif #if (BLE_APP_PRESENT) if ( app_asynch_trm() ) continue; // so that rwip_schedule() is called again #endif } } #if (BLE_APP_PRESENT) // asynchronous events processing if (app_asynch_proc()) continue; // so that rwip_schedule() is called again #endif GLOBAL_INT_STOP(); #if (BLE_APP_PRESENT) app_asynch_sleep_proc(); #endif // if app has turned sleep off, rwip_sleep() will act accordingly // time from rwip_sleep() to WFI() must be kept as short as possible! sleep_mode = rwip_sleep(); // BLE is sleeping ==> app defines the mode if (sleep_mode == mode_sleeping) { if (sleep_env.slp_state == ARCH_EXT_SLEEP_ON) { sleep_mode = mode_ext_sleep; } else { sleep_mode = mode_deep_sleep; } } if (sleep_mode == mode_ext_sleep || sleep_mode == mode_deep_sleep) { SetBits16(PMU_CTRL_REG, RADIO_SLEEP, 1); // turn off radio if (jump_table_struct[nb_links_user] > 1) { if( (sleep_mode == mode_deep_sleep) && func_check_mem() && test_rxdone() && ke_mem_is_empty(KE_MEM_NON_RETENTION) ) { func_check_mem_flag = 2;//true; } else sleep_mode = mode_ext_sleep; } else { if( (sleep_mode == mode_deep_sleep) && ke_mem_is_empty(KE_MEM_NON_RETENTION) ) { func_check_mem_flag = 1;//true; } else sleep_mode = mode_ext_sleep; } #if (BLE_APP_PRESENT) // hook for app specific tasks when preparing sleeping app_sleep_prepare_proc(&sleep_mode); #endif if (sleep_mode == mode_ext_sleep || sleep_mode == mode_deep_sleep) { SCB->SCR |= 1<<2; // enable sleepdeep mode bit in System Control Register (SCR[2]=SLEEPDEEP) SetBits16(SYS_CTRL_REG, PAD_LATCH_EN, 0); // activate PAD latches SetBits16(PMU_CTRL_REG, PERIPH_SLEEP, 1); // turn off peripheral power domain if (sleep_mode == mode_ext_sleep) { SetBits16(SYS_CTRL_REG, RET_SYSRAM, 1); // retain System RAM SetBits16(SYS_CTRL_REG, OTP_COPY, 0); // disable OTP copy } else { // mode_deep_sleep #if DEVELOPMENT__NO_OTP SetBits16(SYS_CTRL_REG, RET_SYSRAM, 1); // retain System RAM #else SetBits16(SYS_CTRL_REG, RET_SYSRAM, 0); // turn System RAM off => all data will be lost! #endif otp_prepare(0x1FC0); // this is 0x1FC0 32 bits words, so 0x7F00 bytes } } SetBits16(CLK_16M_REG, XTAL16_BIAS_SH_DISABLE, 0); #if (BLE_APP_PRESENT) // hook for app specific tasks just before sleeping app_sleep_entry_proc(&sleep_mode); #endif WFI(); #if (BLE_APP_PRESENT) // hook for app specific tasks just after waking up app_sleep_exit_proc(sleep_mode); #endif // reset SCR[2]=SLEEPDEEP bit else the mode=idle WFI will cause a deep sleep // instead of a processor halt SCB->SCR &= ~(1<<2); } else if (sleep_mode == mode_idle) { #if (!BLE_APP_PRESENT) if (check_gtl_state()) { #endif WFI(); #if (!BLE_APP_PRESENT) } #endif } // restore interrupts GLOBAL_INT_START(); #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // Reset WDOG! 200 * 10.24ms active time for normal mode! #endif } }
/** **************************************************************************************** * @brief WKUPCT IRQ Handler * * @return void **************************************************************************************** */ void WKUP_QUADEC_Handler(void) { #ifdef WKUP_ENABLED wakeup_handler_function_t wakeupHandlerFunction; #endif //WKUP_ENABLED #ifdef QUADEC_ENABLED quad_encoder_handler_function_t quadEncoderHandlerFunction; #endif //QUADEC_ENABLED uint8_t source = 0; /* * The system operates with RC16 clk */ /* * Restore clock */ SetBits16(CLK_AMBA_REG, PCLK_DIV, 0); SetBits16(CLK_AMBA_REG, HCLK_DIV, 0); #ifdef QUADEC_ENABLED if ((GetBits16(CLK_PER_REG, QUAD_ENABLE) != 0) && (GetBits16(QDEC_CTRL_REG,QD_IRQ_STATUS) !=0 )) { // Quadrature Decoder clock is enabled & Quadrature Decoder interrupt has triggered source = SRC_QUAD_IRQ; SetBits16(QDEC_CTRL_REG, QD_IRQ_CLR, 1); // write 1 to clear Quadrature Decoder interrupt SetBits16(QDEC_CTRL_REG, QD_IRQ_MASK, 0); // write 0 to mask the Quadrature Decoder interrupt } else #endif //QUADEC_ENABLED { #ifdef WKUP_ENABLED if ((GetBits16(CLK_PER_REG, WAKEUPCT_ENABLE) != 0)) { // since the interrupt does not come from the Quadrature controller, it is from the wakeup timer source = SRC_WKUP_IRQ; SetWord16(WKUP_RESET_IRQ_REG, 1); //Acknowledge it SetBits16(WKUP_CTRL_REG, WKUP_ENABLE_IRQ, 0); //No more interrupts of this kind } #endif //WKUP_ENABLED } /* Note: in case of simultaneous triggering of quadrature decoder and wakeup timer, quadrature decoder interrupt will be handled. The */ ///To check SetBits16(CLK_PER_REG, WAKEUPCT_ENABLE, 1); // enable clock of Wakeup Controller //NVIC_DisableIRQ(WKUP_QUADEC_IRQn); /* * Init System Power Domain blocks: GPIO, WD Timer, Sys Timer, etc. * Power up and init Peripheral Power Domain blocks, * and finally release the pad latches. */ //if(GetBits16(SYS_STAT_REG, PER_IS_DOWN)) //periph_init(); /* * run callback functions */ #ifdef QUADEC_ENABLED if (source == SRC_QUAD_IRQ) { if (QUADDEC_callback != NULL) // Quadrature Decoder callback has been set-up by the application clock is enabled { int16_t x,y,z; x = quad_decoder_get_x_counter(); y = quad_decoder_get_y_counter(); z = quad_decoder_get_z_counter(); quadEncoderHandlerFunction = (quad_encoder_handler_function_t)(QUADDEC_callback); quadEncoderHandlerFunction(x,y,z); } } else #endif //QUADEC_ENABLED { #ifdef WKUP_ENABLED if (source == SRC_WKUP_IRQ) { if (WKUPCT_callback != NULL) { wakeupHandlerFunction = (wakeup_handler_function_t)(WKUPCT_callback); wakeupHandlerFunction(); } } #endif //WKUP_ENABLED } return; }
int main_func(void) { volatile unsigned i; sleep_mode_t sleep_mode; // keep at system RAM. On each while loop it will get a new value. sys_startup_flag = true; /* ************************************************************************************ * Platform initialization ************************************************************************************ */ #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // 200 * 10.24ms = ~2sec active time! SetWord16(WATCHDOG_CTRL_REG, 0); // Generate an NMI when counter reaches 0 and a WDOG (SYS) Reset when it reaches -16! // WDOG can be frozen by SW! SetWord16(RESET_FREEZE_REG, FRZ_WDOG); // Start WDOG #else SetWord16(SET_FREEZE_REG, FRZ_WDOG); #endif #if defined(CFG_USE_DEFAULT_XTAL16M_TRIM_VALUE_IF_NOT_CALIBRATED) #define DEFAULT_XTAL16M_TRIM_VALUE (1302) // Apply the default XTAL16 trim value if a trim value has not been programmed in OTP if ( 0 == GetWord16(CLK_FREQ_TRIM_REG) ) { SetBits16(CLK_16M_REG, RC16M_ENABLE, 1); // enable RC 16MHz for (volatile int i = 0; i < 20; i++); SetBits16(CLK_CTRL_REG, SYS_CLK_SEL, 1); // switch to RC16 while( (GetWord16(CLK_CTRL_REG) & RUNNING_AT_RC16M) == 0 ); // wait for actual switch SetBits16(CLK_CTRL_REG, XTAL16M_DISABLE, 1); // disable XTAL16 SetWord16(CLK_FREQ_TRIM_REG, DEFAULT_XTAL16M_TRIM_VALUE); // set default trim value SetBits16(CLK_CTRL_REG, XTAL16M_DISABLE, 0); // enable XTAL16 while( (GetWord16(SYS_STAT_REG) & XTAL16_SETTLED) == 0 ); // wait for XTAL16 settle SetBits16(CLK_CTRL_REG , SYS_CLK_SEL ,0); // switch to XTAL16 while( (GetWord16(CLK_CTRL_REG) & RUNNING_AT_XTAL16M) == 0 ); // wait for actual switch } #endif set_system_clocks(); GPIO_init(); periph_init(); /* Don't remove next line otherwhise dummy[0] could be optimized away * The dummy array is intended to reserve the needed Exch.Memory space in retention memory */ dummy[0] = dummy[0]; descript[0] = descript[0]; #ifndef __DA14581__ #if (BLE_CONNECTION_MAX_USER > 4) cs_table[0] = cs_table[0]; #endif #else #if (BLE_CONNECTION_MAX_USER > 1) cs_table[0] = cs_table[0]; #endif #endif /* Don't remove next line otherwhise data__1 is optimized away. * The address 0x9010 is used by the ROM code (rand.o) and cannot be used by the * application code! */ //GZ data__1 = 0; // Initialize unloaded RAM area //unloaded_area_init(); // Initialize random process srand(1); // Initialize the exchange memory interface, emi in RAM for the time being, so no init necessary #if 0 emi_init(); #endif // Initialize NVDS module // 初始化非易失性存储器 nvds_init((uint8_t *)NVDS_FLASH_ADDRESS, NVDS_FLASH_SIZE); //check and read BDADDR from OTP nvds_read_bdaddr_from_otp(); #ifdef RADIO_580 iq_trim_from_otp(); #endif /* ************************************************************************************ * BLE initialization ************************************************************************************ */ init_pwr_and_clk_ble(); //diagnostic(); // rf_init(&rwip_rf); // SetBits32(BLE_RADIOCNTL1_REG, XRFSEL, 3); #if UNCALIBRATED_AT_FAB SetBits16(BANDGAP_REG, BGR_TRIM, 0x0); // trim RET Bandgap SetBits16(BANDGAP_REG, LDO_RET_TRIM, 0xA); // trim RET LDO SetWord16(RF_LNA_CTRL1_REG, 0x24E); SetWord16(RF_LNA_CTRL2_REG, 0x26); SetWord16(RF_LNA_CTRL3_REG, 0x7); SetWord16(RF_VCO_CTRL_REG, 0x1); SetBits16(CLK_16M_REG, RC16M_TRIM, 0xA); #endif // Initialize BLE stack NVIC_ClearPendingIRQ(BLE_SLP_IRQn); NVIC_ClearPendingIRQ(BLE_EVENT_IRQn); NVIC_ClearPendingIRQ(BLE_RF_DIAG_IRQn); NVIC_ClearPendingIRQ(BLE_RX_IRQn); NVIC_ClearPendingIRQ(BLE_CRYPT_IRQn); NVIC_ClearPendingIRQ(BLE_FINETGTIM_IRQn); NVIC_ClearPendingIRQ(BLE_GROSSTGTIM_IRQn); NVIC_ClearPendingIRQ(BLE_WAKEUP_LP_IRQn); rwip_init(error); #if ((BLE_APP_PRESENT == 0 || BLE_INTEGRATED_HOST_GTL == 1) && BLE_HOST_PRESENT ) patch_gtl_task(); #endif // #if (BLE_APP_PRESENT == 0 || BLE_INTEGRATED_HOST_GTL == 1) /* Set spi to HW (Ble) * Necessary: So from this point the BLE HW can generate spi burst iso SW * SPI BURSTS are necessary for the radio TX and RX burst, done by hardware * beause of the accurate desired timing */ //FPGA #ifdef FPGA_USED SetBits32(BLE_CNTL2_REG,SW_RPL_SPI ,1); #endif //Enable BLE core SetBits32(BLE_RWBTLECNTL_REG,RWBLE_EN ,1); #if RW_BLE_SUPPORT && HCIC_ITF // If FW initializes due to FW reset, send the message to Host if(error != RESET_NO_ERROR) { rwble_send_message(error); } #endif /* ************************************************************************************ * Sleep mode initializations (especially for full embedded) ************************************************************************************ */ #if (EXT_SLEEP_ENABLED) app_set_extended_sleep(); #elif (DEEP_SLEEP_ENABLED) app_set_deep_sleep(); #else app_disable_sleep(); #endif if (lp_clk_sel == LP_CLK_RCX20) { calibrate_rcx20(20); read_rcx_freq(20); } /* ************************************************************************************ * Application initializations ************************************************************************************ */ #if (BLE_APP_PRESENT) { app_init(); // Initialize APP // 初始化应用程序 } #endif /* #if (BLE_APP_PRESENT) */ /* ************************************************************************************ * Main loop ************************************************************************************ */ lld_sleep_init_func(); SetWord16(TRIM_CTRL_REG, 0xA2); SetBits16(CLK_16M_REG, XTAL16_CUR_SET, 0x5); // // Gives 1dB higher sensitivity - UNTESTED // if (GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) // { // // Boost-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x8); // 80mA // } // else // { // // Buck-mode // SetBits16(DCDC_CTRL2_REG, DCDC_CUR_LIM, 0x4); // 40mA // } // Now enable the TX_EN/RX_EN interrupts, depending on the RF mode of operation (PLL-LUT and MGC_KMODALPHA combinations) enable_rf_diag_irq(RF_DIAG_IRQ_MODE_RXTX); #if BLE_APP_SPOTAR // 打补丁 //app_spotar_exec_patch(); #endif if ( (app_get_sleep_mode() == 2) || (app_get_sleep_mode() == 1) ) { SetWord16(SET_FREEZE_REG, FRZ_WDOG); // Stop WDOG until debugger is removed while ((GetWord16(SYS_STAT_REG) & DBG_IS_UP) == DBG_IS_UP) {}; SetBits16(SYS_CTRL_REG, DEBUGGER_ENABLE, 0); // close debugger } /* ************************************************************************************ * Watchdog ************************************************************************************ */ #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // 200 * 10.24ms active time for initialization! SetWord16(RESET_FREEZE_REG, FRZ_WDOG); // Start WDOG #endif #if (STREAMDATA_QUEUE) stream_fifo_init (); #endif /* ************************************************************************************ * Main loop ************************************************************************************ */ // 设置LED电亮 SetWord16(P10_MODE_REG,0x310); SetWord16(P11_MODE_REG,0x300); //SetWord16(P1_DATA_REG,~(GetWord16(P1_DATA_REG)) | 0xfd); //SetWord16(P10_MODE_REG,0x300); // // 定时器时钟使能 // SetWord16(CLK_PER_REG, 0x0008); // // // SetWord16(TIMER0_CTRL_REG, 0x0e); // SetWord16(TIMER0_ON_REG, 65535); // SetWord16(TIMER0_RELOAD_M_REG, 10000); // SetWord16(TIMER0_RELOAD_N_REG, 5000); // SetWord16(TIMER0_CTRL_REG, TIMER0_CTRL_REG | 0x01); // NVIC_SetPriority(SWTIM_IRQn,254); // NVIC_EnableIRQ(SWTIM_IRQn); while(1) { // schedule all pending events if(GetBits16(CLK_RADIO_REG, BLE_ENABLE) == 1) { // BLE clock is enabled if(GetBits32(BLE_DEEPSLCNTL_REG, DEEP_SLEEP_STAT) == 0 && !(rwip_prevent_sleep_get() & RW_WAKE_UP_ONGOING)) { // BLE is running #ifndef FPGA_USED uint8_t ble_evt_end_set = ke_event_get(KE_EVENT_BLE_EVT_END); // BLE event end is set. conditional RF calibration can run. #endif rwip_schedule(); // 调度 aiwesky 20101003 #ifndef FPGA_USED if (ble_evt_end_set) { uint32_t sleep_duration = 0; if (lp_clk_sel == LP_CLK_RCX20) read_rcx_freq(20); if (lld_sleep_check(&sleep_duration, 4)) //6 slots -> 3.750 ms conditionally_run_radio_cals(); // check time and temperature to run radio calibrations. } #endif #if (BLE_APP_PRESENT) if ( app_asynch_trm() ) continue; // so that rwip_schedule() is called again #endif #ifdef CFG_PRINTF { arch_printf_process(); } #endif } } #if (BLE_APP_PRESENT) // asynchronous events processing if (app_asynch_proc()) continue; // so that rwip_schedule() is called again #endif #if (STREAMDATA_QUEUE) if (stream_queue_more_data( )) continue; #endif #if (!BLE_APP_PRESENT) if (check_gtl_state()) #endif { GLOBAL_INT_STOP(); #if (BLE_APP_PRESENT) app_asynch_sleep_proc(); #endif // // set wake-up delay only for RCX (to cover small frequency shifts due to temerature variation) // if (lp_clk_sel == LP_CLK_RCX20) // set_sleep_delay(); // if app has turned sleep off, rwip_sleep() will act accordingly // time from rwip_sleep() to WFI() must be kept as short as possible! sleep_mode = rwip_sleep(); // 读取休眠模式 // BLE is sleeping ==> app defines the mode if (sleep_mode == mode_sleeping) { if (sleep_env.slp_state == ARCH_EXT_SLEEP_ON) { sleep_mode = mode_ext_sleep; } else { sleep_mode = mode_deep_sleep; } } if (sleep_mode == mode_ext_sleep || sleep_mode == mode_deep_sleep) { SetBits16(PMU_CTRL_REG, RADIO_SLEEP, 1); // turn off radio if (jump_table_struct[nb_links_user] > 1) { if( (sleep_mode == mode_deep_sleep) && func_check_mem() && test_rxdone() && ke_mem_is_empty(KE_MEM_NON_RETENTION) ) { func_check_mem_flag = 2;//true; } else sleep_mode = mode_ext_sleep; } else { if( (sleep_mode == mode_deep_sleep) && ke_mem_is_empty(KE_MEM_NON_RETENTION) ) { func_check_mem_flag = 1;//true; } else sleep_mode = mode_ext_sleep; } #if (BLE_APP_PRESENT) // hook for app specific tasks when preparing sleeping app_sleep_prepare_proc(&sleep_mode); #endif if (sleep_mode == mode_ext_sleep || sleep_mode == mode_deep_sleep) { SCB->SCR |= 1<<2; // enable sleepdeep mode bit in System Control Register (SCR[2]=SLEEPDEEP) SetBits16(SYS_CTRL_REG, PAD_LATCH_EN, 0); // activate PAD latches SetBits16(PMU_CTRL_REG, PERIPH_SLEEP, 1); // turn off peripheral power domain if (sleep_mode == mode_ext_sleep) { SetBits16(SYS_CTRL_REG, RET_SYSRAM, 1); // retain System RAM SetBits16(SYS_CTRL_REG, OTP_COPY, 0); // disable OTP copy } else { // mode_deep_sleep #if DEVELOPMENT_DEBUG SetBits16(SYS_CTRL_REG, RET_SYSRAM, 1); // retain System RAM #else SetBits16(SYS_CTRL_REG, RET_SYSRAM, 0); // turn System RAM off => all data will be lost! #endif otp_prepare(0x1FC0); // this is 0x1FC0 32 bits words, so 0x7F00 bytes } } SetBits16(CLK_16M_REG, XTAL16_BIAS_SH_DISABLE, 0); #if (BLE_APP_PRESENT) // hook for app specific tasks just before sleeping app_sleep_entry_proc(&sleep_mode); #endif #if ((EXTERNAL_WAKEUP) && (!BLE_APP_PRESENT)) // external wake up, only in external processor designs ext_wakeup_enable(EXTERNAL_WAKEUP_GPIO_PORT, EXTERNAL_WAKEUP_GPIO_PIN, EXTERNAL_WAKEUP_GPIO_POLARITY); #endif WFI(); // 暂停执行直到事件发生 aiwesky 20151003 #if (BLE_APP_PRESENT) // hook for app specific tasks just after waking up app_sleep_exit_proc(sleep_mode); #endif #if ((EXTERNAL_WAKEUP) && (!BLE_APP_PRESENT)) // external wake up, only in external processor designs // Disable external wakeup interrupt ext_wakeup_disable(); #endif // reset SCR[2]=SLEEPDEEP bit else the mode=idle WFI will cause a deep sleep // instead of a processor halt SCB->SCR &= ~(1<<2); } else if (sleep_mode == mode_idle) { #if (!BLE_APP_PRESENT) if (check_gtl_state()) #endif { WFI(); } } // restore interrupts GLOBAL_INT_START(); } #if (USE_WDOG) SetWord16(WATCHDOG_REG, 0xC8); // Reset WDOG! 200 * 10.24ms active time for normal mode! #endif } }
/** **************************************************************************************** * @brief Block sleep when a LED is up in BOOST mode for the period a LED is on. * * @param None * * @return void **************************************************************************************** */ void leds_block_sleep() { if ((GetBits16(ANA_STATUS_REG, BOOST_SELECTED) == 0x1) && app_get_sleep_mode()) { app_force_active_mode(); // in BOOST mode, prevent sleep only if enabled } }