Hello everybody
I am working with the Raytac BLE Module "MDBT40", which is based on nrf51822.
And I am testing example project "ble_app_uart" in the SDK6.1.0 now.
But there are some problems when I add a new timer.
In the project "ble_app_uart", It contain only RTC timer.
However, I can't understand how the RTC interrupt work in the demo code.
So I add a timer2 in the project as below.
I hope it turn on LED once 100ms.
void start_timer2(void)
{
// Start 16 MHz crystal oscillator.
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while(NRF_CLOCK->EVENTS_HFCLKSTARTED==0){}
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Counter Mode
NRF_TIMER2->TASKS_CLEAR = 1; // clear the task first to be usable for later
NRF_TIMER2->PRESCALER = 9; //Set prescaler. Higher number gives slower timer. Prescaler = 0 gives 16MHz timer. Prescaler = 9 gives 31250 Hz timer, 1tick 32us.
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution
NRF_TIMER2->CC[0] = 3125; //Set value for TIMER2 compare register 0. Period is 32us * 3125 = 100ms.
// Enable interrupt on Timer 2, for CC[0]
NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
NVIC_EnableIRQ(TIMER2_IRQn);
NRF_TIMER2->TASKS_START = 1; // Start TIMER2
}
/** TIMTER1 peripheral interrupt handler. This interrupt handler is called whenever there it a TIMER1 interrupt
*/
void TIMER2_IRQHandler(void)
{
if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
{
NRF_TIMER2->EVENTS_COMPARE[0] = 0; //Clear compare register 0 event
NRF_TIMER2->TASKS_CLEAR=1;
// turn on LED
nrf_gpio_pin_set(D03);
while(1){};
}
}
And I put "start_timer2();" after "timers_init();" in main function.
But it doesn't interrupt while running.
What I miss in the process?
Sorry for my poor English.
And thanks in advance!
More test information
this is my main function
int main(void)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint8_t index_backup = 0;
uint8_t newbyte;
int i=0;
// Initialize
gpio_init();
timers_init();
start_timer2();
uart_init();
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();
sec_params_init();
uart_putstring((const uint8_t *)START_STRING);
advertising_start();
// Enter main loop
for (;;)
{
/*Stop reading new data if there are no ble buffers available */
if(ble_buffer_available)
{
if(app_uart_get(&newbyte) == NRF_SUCCESS)
{
data_array[index] = newbyte;
if (data_array[index] == '\n')
{
ble_buffer_available = ble_attempt_to_send(&data_array[0],index);
index_backup = index;
if(ble_buffer_available) index = 0;
}
else if (index == (BLE_NUS_MAX_DATA_LEN-1))
{
ble_buffer_available = ble_attempt_to_send(&data_array[0],index+1);
index_backup = index+1;
if(ble_buffer_available) index = 0;
}
else
{
index++;
}
}
}
/* Re-transmission if ble_buffer_available was set to false*/
if(tx_complete)
{
tx_complete=false;
index = index_backup;
ble_buffer_available = ble_attempt_to_send(&data_array[0],index);
if(ble_buffer_available) index = 0;
}
power_manage();
}
}
For testing, I turn on LED to make sure when process get trouble.
And process stop between turnonLED1 and turnonLED2 which in ble_stack_init();
static void ble_stack_init(void)
{
uint32_t err_code;
nrf_gpio_cfg_input(EXT_XTAL_MODE,NRF_GPIO_PIN_PULLUP);
TurnonLED1();
if(nrf_gpio_pin_read(EXT_XTAL_MODE) == 1)
{
// Initialize SoftDevice.
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_1000MS_CALIBRATION, false);
}
else
{
// Initialize SoftDevice.
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
}
TurnonLED2();
// Enable BLE stack
ble_enable_params_t ble_enable_params;
memset(&ble_enable_params, 0, sizeof(ble_enable_params));
ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
err_code = sd_ble_enable(&ble_enable_params);
APP_ERROR_CHECK(err_code);
// Subscribe for BLE events.
err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
APP_ERROR_CHECK(err_code);
}
Then I change position of start_time2(); in main(); as below
int main(void)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint8_t index_backup = 0;
uint8_t newbyte;
int i=0;
// Initialize
//leds_init();
gpio_init();
timers_init();
nrf_gpio_pin_clear(DIG3);
//buttons_init();
uart_init();
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();
sec_params_init();
uart_putstring((const uint8_t *)START_STRING);
start_timer2();
advertising_start();
//skip...
}
Process stop between turnonLED3 and turnonLED4 which in start_timer2();
void start_timer2(void)
{
turnonLED3();
// Start 16 MHz crystal oscillator.
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
turnonLED4();
while(NRF_CLOCK->EVENTS_HFCLKSTARTED==0){}
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Counter Mode
NRF_TIMER2->TASKS_CLEAR = 1; // clear the task first to be usable for later
NRF_TIMER2->PRESCALER = 9; //Set prescaler. Higher number gives slower timer. Prescaler = 0 gives 16MHz timer. Prescaler = 9 gives 31250 Hz timer, 1tick 32us.
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution
NRF_TIMER2->CC[0] = 3125; //Set value for TIMER2 compare register 0. Period is 32us * 3125 = 100ms.
// Enable interrupt on Timer 2, both for CC[0] and CC[1] compare match events
NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
NVIC_EnableIRQ(TIMER2_IRQn);
NRF_TIMER2->TASKS_START = 1; // Start TIMER2
}
Maybe it helpful to find problem?
Just more testing
I use app_timer instead of timer2.
It's working but "TIMER_INTERVAL" didn't perform as expected.(It take longer than 1ms to trigger interrupt.)
Are there higher priority interrupt cause it?(Bluetooth or Uart?)
And why timer2 can't work fine?
#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
#define APP_TIMER_MAX_TIMERS 2 /**< Maximum number of simultaneously created timers. */
#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */
static app_timer_id_t m_app_timer_id;
#define TIMER_INTERVAL APP_TIMER_TICKS(1, APP_TIMER_PRESCALER) // Timer_interval is 1ms
static void start_timer(void)
{
uint32_t err_code;
err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
}
void display_timeout_handler(void * p_context)
{
DriveXDig7Segment();
}
int main(void)
{
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint8_t index = 0;
uint8_t index_backup = 0;
uint8_t newbyte;
// Initialize
//leds_init();
gpio_init();
timers_init();
//buttons_init();
uart_init();
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();
sec_params_init();
uart_putstring((const uint8_t *)START_STRING);
start_timer();
advertising_start();
skip...
}