Hi all
We use the nRF51822 with the S130 V1.0.0. Our application initializes the TIMER2 (f = 16MHz) with a EVENTS_COMPARE interrupt on the CC channel 1 to monitor some timings.
Afterwards the SoftDevice is enabled with the LFCLK source "NRF_CLOCK_LFCLKSRC_XTAL_20_PPM". The TIMER2 stays running.
Later on, we want to reduce the power consumption. Therefore we disable the TIMER2 with the following code:
NRF_TIMER2->TASKS_STOP = 1;
NRF_TIMER2->TASKS_SHUTDOWN = 1;
NVIC_DisableIRQ(TIMER2_IRQn);
NVIC_ClearPendingIRQ(TIMER2_IRQn);
Afterwards we call the function sd_app_evt_wait() but the nRF51822 wakes up immediately. The strange thing is, that when I change the LFCLK source at the SoftDevice initialization to "NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION", the nRF51822 stays in the low power mode. Therefore there should be no event/interrupt in our application that awakes the chip.
Further observations are:
- When we disable the TIMER2 before initializing the SoftDevice (LFCLK source is the XTAL) everything works fine
- When we initialize the TIMER2 after initializing the SoftDevice (LFCLK source is the XTAL) everything works fine too
Is there a problem when the TIMER2 is running during the SD init in combination with the LF crystal? Does anyone know this behavior?
EDIT: I've added a stripped-down version of our application to reproduce this behavior:
Function to enable the query-timer:
static void query_timer_init(void)
{
// :NOTE:
// Currently the following capture/compare channels are used:
// - Channel 0: Used to capture the timer value
// - Channel 1: Used to handle the overflow of the 16bit timer
// Stop the timer before the configuration
NRF_TIMER2->TASKS_STOP = 1;
// Init module variables
gTIMER2_high_word = 0;
// Configure TIMER2 in timer mode with 16 bits
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
// Use 16 MHz (disable the prescaler)
// -> f = HFCLK / (2 ^ prescaler_value)
NRF_TIMER2->PRESCALER = 0;
// Clear the timer before using it
NRF_TIMER2->TASKS_CLEAR = 1;
// Setup capture/compare channel 1 for timer overflow
NRF_TIMER2->CC[1] = 0xFFFF;
NRF_TIMER2->EVENTS_COMPARE[1] = 0;
NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos);
// Enable interrupt for timer 2
NVIC_SetPriority(TIMER2_IRQn, APP_IRQ_PRIORITY_HIGH);
NVIC_ClearPendingIRQ(TIMER2_IRQn);
NVIC_EnableIRQ(TIMER2_IRQn);
// Start the timer
NRF_TIMER2->TASKS_START = 1;
}
Function to disable the query-timer:
static void query_timer_disable(void)
{
// Stop the timer
NRF_TIMER2->TASKS_STOP = 1;
// Shutdown the timer module
NRF_TIMER2->TASKS_SHUTDOWN = 1;
// Disable and clear the timer interrupt
NVIC_DisableIRQ(TIMER2_IRQn);
NVIC_ClearPendingIRQ(TIMER2_IRQn);
}
The main function:
int32_t main(void)
{
uint32_t sd_stat = NRF_SUCCESS;
ble_enable_params_t ble_enable_params;
// Initialize the query timer
query_timer_init();
// Init the SoftDevice
sd_stat = sd_softdevice_enable(
//NRF_CLOCK_LFCLKSRC_RC_250_PPM_TEMP_4000MS_CALIBRATION, NULL); // -> OK
NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); // -> NOK
if (sd_stat != NRF_SUCCESS) {goto exception;}
// Init the BLE stack
ble_enable_params.gatts_enable_params.service_changed = 0;
ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT;
sd_stat = sd_ble_enable(&ble_enable_params);
if (sd_stat != NRF_SUCCESS) {goto exception;}
// Disable the query timer
query_timer_disable();
// Activate the system ON low power mode
sd_stat = sd_app_evt_wait();
if (sd_stat != NRF_SUCCESS) {goto exception;}
// -> This point should not be reached since there is no enabled wakeup source!
// Re-enable the query timer
query_timer_init();
// the main loop
while (1) {}
// -> Should never reach this point!
exception:
while (sd_stat != NRF_SUCCESS) {}
return 0;
}
Kind regards