This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Suggestion needed for handling button interrupt in nRF51822

I have a nRF51822 program in which a button triggered event doesn't work as expected and crashes the program. The program may have potential race condition problem. Here is the problem description.

The program measures some sensor values and send them out in advertising packets. The measurement is made up of a chain of single-shot timer event handlers as illustrated in the pseudo code as follows:

volatile uint8_t data_update_ongoing = 0;

void measurement_start(void)
{
  data_update_ongoing = 1;
  
  // Signal LED1
  nrf_gpio_pin_set(LED_1);
  nrf_delay_ms(100);
  nrf_gpio_pin_clear(LED_1);
  
// Some init code here

  uint32_t err_code = app_timer_start(m_app_timer1, APP_TIMER1_TICKS, NULL);
  APP_ERROR_CHECK(err_code);
}

void app_timer1_handler(void * p_context)
{
  // Process something here 

  // Start app_timer2 
  uint32_t err_code = app_timer_start(m_app_timer2, APP_TIMER1_TICKS, NULL);
  APP_ERROR_CHECK(err_code);
}

...

void app_timer4_handler(void * p_context)
{
  // Process something

  // Finishing measurement
  data_update_ongoing = 0;
  
  // Signal LED2
  nrf_gpio_pin_set(LED_2);
  nrf_delay_ms(100);
  nrf_gpio_pin_clear(LED_2);
}

There are two places that measurement_start() can be called. One is the handler of a periodic timer "m_du_timer", and the other is a button handler. But there should be only a single active measurement, either triggered by the periodic timer or button. If the button is pressed when the measurement is active (triggered by the periodic timer), the program should just let the measurement finish and do data processing after that. Or the button handler will call measurement_start(). Similarly, if the periodic timer times out when the measurement is still active (triggered by the button press), then it should just let it finish and do nothing. Or the periodic timer handler will call measurement_start(). The pseudo code for this part is as follows:

void app_periodic_timer_handler(void * p_context)
{
  if (data_update_ongoing == 0) measurement_start();
  // If measurement is active, then do nothing
}

void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
 if (button_action==APP_BUTTON_PUSH)
	{	
    switch (pin_no)
      {
        case BUTTON1:		
					if (data_update_ongoing==0) measurement_start();
					while (data_update_ongoing) {}  // wait till the measurement finishes
					// Some data processing code here
          break;

        default:
            APP_ERROR_HANDLER(pin_no);
            break;
      }
	}
}

I can see the data updated correctly if I don't touch the button, and both LED1 and LED2 blink. However, if I press the button, only LED1 blinks and after that the program freezes. After some time the program resets itself because I see initialization values in ADV packets. If I remove the line "if (data_update_ongoing==0) measurement_start();", the program will not freeze. I can confirm the button and GPIOTE are initialized correctly by replacing some other test code (such blinking some LEDs) in the button_event_handler() and seeing them behaving correctly.

I will appreciate if anyone points out what I get wrong here. Suggestions are also need to handle this potential race condition in a better way.

Parents
  • I figure it out on my own. It may be the line "while (data_update_ongoing) {}" in button interrupt handler causing the problem. I guess it was blocking the other timer handlers from being executed by occupying the CPU. I remove this blocking line and do it in another way.

Reply
  • I figure it out on my own. It may be the line "while (data_update_ongoing) {}" in button interrupt handler causing the problem. I guess it was blocking the other timer handlers from being executed by occupying the CPU. I remove this blocking line and do it in another way.

Children
No Data
Related