Skip to main content
edited title
Link
Umberto D.
  • 335
  • 3
  • 11

Interrupt handling in microcontrollers and FSM example

added tags due to the update
Link
Umberto D.
  • 335
  • 3
  • 11
added 3676 characters in body
Source Link
Umberto D.
  • 335
  • 3
  • 11

Initial question

Update: interrupts and state charts

I will provide a specific situation. Let us assume we want to implement a state chart, which is composed by 4 blocks:

  1. Transitions/Effect.
  2. Exit conditions.
  3. Entry activity.
  4. Do activity.

This is what a professor taught us at university. Probably, not the best way of doing it is by following this scheme:

while(true) {

  /* Transitions/Effects */
  //----------------------------------------------------------------------
  next_state = current_state;

  switch (current_state)
  {
    case STATE_A:
      if(EVENT1) {next_state = STATE_C}
      if(d == THRESHOLD) {next_state = STATE_D; a++}
      break;
    case STATE_B:
      // transitions and effects
      break;
    (...)
  }

  /* Exit activity -> only performed if I leave the state for a new one */
  //----------------------------------------------------------------------
  if (next_state != current_state)
  {
    switch(current_state)
    {
      case STATE_A:
        // Exit activity of STATE_A
        break;
      case STATE_B:
        // Exit activity of STATE_B
        break;
        (...)
    }
  }

  /* Entry activity -> only performed the 1st time I enter a state */
  //----------------------------------------------------------------------
  if (next_state != current_state)
  {
    switch(next_state)
    {
      case STATE_A:
        // Entry activity of STATE_A
        break;
      case STATE_B:
        // Entry activity of STATE_B
        break;
      (...)
    }
  }

  current_state = next_state;

  /* Do activity */
  //----------------------------------------------------------------------
  switch (current_state)
  {
    case STATE_A:
      // Do activity of STATE_A
      break;
    case STATE_B:
      // Do activity of STATE_B
      break;
    (...)
  }
}

Let us also assume that from, say STATE_A, I want to be sensitive to a interrupt coming from a set of buttons (with debouce system, etc. etc.). When someone presses one of these buttons, an interrupt is generated and the flag related to the input port is copied into a variable buttonPressed. If the debounce is set to 200 ms in some way (watchdog timer, timer, counter, ...) we are sure that buttonPressed cannot be updated with a new value before 200 ms. This is what I am asking you (and myself :) of course)

Do I need to enable interrupt in the DO activity of STATE_A and disable before leaving?

/* Do activity */
//-------------------------------------
switch (current_state)
{
  case STATE_A:
    // Do activity of STATE_A
    Enable_ButtonsInterrupt(); // and clear flags before it
    // Do fancy stuff and ...
    // ... wait until a button is pressed (e.g. LPM3 of the MSP430)
    // Here I have my buttonPressed flag ready!
    Disable_ButtonsInterrupt();
    break;
  case STATE_B:
    // Do activity of STATE_B
    break;
  (...)
}

In a way that I am sure that the next time I execxute block 1 (transition/effects) at the next iteration I am sure that the conditions checked along the transitions are not coming from a subsequent interrupt that has overwritten the previous value of buttonPressed that I need (although it is impossible that this happens because 250 ms must elapse).

Initial question

Update: interrupts and state charts

I will provide a specific situation. Let us assume we want to implement a state chart, which is composed by 4 blocks:

  1. Transitions/Effect.
  2. Exit conditions.
  3. Entry activity.
  4. Do activity.

This is what a professor taught us at university. Probably, not the best way of doing it is by following this scheme:

while(true) {

  /* Transitions/Effects */
  //----------------------------------------------------------------------
  next_state = current_state;

  switch (current_state)
  {
    case STATE_A:
      if(EVENT1) {next_state = STATE_C}
      if(d == THRESHOLD) {next_state = STATE_D; a++}
      break;
    case STATE_B:
      // transitions and effects
      break;
    (...)
  }

  /* Exit activity -> only performed if I leave the state for a new one */
  //----------------------------------------------------------------------
  if (next_state != current_state)
  {
    switch(current_state)
    {
      case STATE_A:
        // Exit activity of STATE_A
        break;
      case STATE_B:
        // Exit activity of STATE_B
        break;
        (...)
    }
  }

  /* Entry activity -> only performed the 1st time I enter a state */
  //----------------------------------------------------------------------
  if (next_state != current_state)
  {
    switch(next_state)
    {
      case STATE_A:
        // Entry activity of STATE_A
        break;
      case STATE_B:
        // Entry activity of STATE_B
        break;
      (...)
    }
  }

  current_state = next_state;

  /* Do activity */
  //----------------------------------------------------------------------
  switch (current_state)
  {
    case STATE_A:
      // Do activity of STATE_A
      break;
    case STATE_B:
      // Do activity of STATE_B
      break;
    (...)
  }
}

Let us also assume that from, say STATE_A, I want to be sensitive to a interrupt coming from a set of buttons (with debouce system, etc. etc.). When someone presses one of these buttons, an interrupt is generated and the flag related to the input port is copied into a variable buttonPressed. If the debounce is set to 200 ms in some way (watchdog timer, timer, counter, ...) we are sure that buttonPressed cannot be updated with a new value before 200 ms. This is what I am asking you (and myself :) of course)

Do I need to enable interrupt in the DO activity of STATE_A and disable before leaving?

/* Do activity */
//-------------------------------------
switch (current_state)
{
  case STATE_A:
    // Do activity of STATE_A
    Enable_ButtonsInterrupt(); // and clear flags before it
    // Do fancy stuff and ...
    // ... wait until a button is pressed (e.g. LPM3 of the MSP430)
    // Here I have my buttonPressed flag ready!
    Disable_ButtonsInterrupt();
    break;
  case STATE_B:
    // Do activity of STATE_B
    break;
  (...)
}

In a way that I am sure that the next time I execxute block 1 (transition/effects) at the next iteration I am sure that the conditions checked along the transitions are not coming from a subsequent interrupt that has overwritten the previous value of buttonPressed that I need (although it is impossible that this happens because 250 ms must elapse).

Tweeted twitter.com/#!/StackElectronix/status/586629027630342144
added 1 character in body
Source Link
Umberto D.
  • 335
  • 3
  • 11
Loading
Source Link
Umberto D.
  • 335
  • 3
  • 11
Loading