2
\$\begingroup\$

I know that an interrupt should be as short as possible, however, what is short?

My routine is quite long, but has quite some if-statements, so the execution time is short. But maybe it still is considered (way too) long.

Will my code cause problems (in the future)? Currently I have only one interrupt, but I want to add later more (for DMX control for example). This one is to handle MIDI input.

It is meant for an STM32F103C8T6 (72 MHz) and later STM32F446ZET6 (168 MHz). The debug statement are temporarily.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == huart1.Instance)
  {
      // Don't overwrite existing data.
      if (((_RxHead + 1) % BUFFER_SIZE) != _RxTail)
      {
          // Check for sysex.
          if (_SysexReceived == 0)
          {
              if (_RxByte == 0xF0)
              {
                  _RxBuffer[_RxHead] = _RxByte;
                  _RxHead = (_RxHead + 1) % BUFFER_SIZE;
                  _SysexReceived = 1;
              }

              // No sysex, skip active sensing/timing.
              else if ((_RxByte != 0xF8) && (_RxByte != 0xFE))
              {
                  // Add byte.
                  _RxBuffer[_RxHead] = _RxByte;
                  _RxHead = (_RxHead + 1) % BUFFER_SIZE;
              }
          }
          else if (_SysexReceived < MAX_SYSEX_LENGTH)
          {
              // Sysex: add byte.
              _RxBuffer[_RxHead] = _RxByte;
              _RxHead = (_RxHead + 1) % BUFFER_SIZE;
              _SysexReceived = (_RxByte == 0xF7) ? 0 : _SysexReceived + 1;
          }
          else // SysexReceived >= (or ==) MAX_SYSEX_LENGTH
          {
              // Too long message, only write last 0x7F.
              if (_RxByte == 0xF7)
              {
                  _RxBuffer[_RxHead] = _RxByte;
                  _RxHead = (_RxHead + 1) % BUFFER_SIZE;
                  _SysexReceived = 0;
              }
          }

#ifdef __BUFFER_DEBUG
          __ReceivedBufferData[__ReceivedIndex] = _RxByte;
          __ReceivedBufferHead[__ReceivedIndex] = _RxHead;
          __ReceivedBufferTail[__ReceivedIndex] = _RxTail;
          __ReceivedBufferSysex[__ReceivedIndex] = _SysexReceived;
          __ReceivedIndex++;
          if (__ReceivedIndex == __RECEIVED_BUFFER_SIZE)
          {
              __ReceivedIndex = 0;
              __ReceivedRounds++;
          }
#endif
      }
      else
      {
          _Error_Handler(__FILE__, __LINE__);
      }
   }
}

Update:

After fixing some problems somewhere else in the code and slightly different ranges in some if statements, it works quite well. Only many and big sysex-messages makes it a bit sluggish but that's not related to the ISR.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ It should be as long as it needs to be and no longer. If there is code you must run in an ISR, then the length of it is irrelevant. If however you can just set a flag and service it in your main loop however, then that is a good option to reduce time spent in irq land. \$\endgroup\$
    – Colin
    Commented Nov 22, 2017 at 8:28
  • 2
    \$\begingroup\$ In your case, handling MIDI the baud rate is pretty low, so it shouldn't be a problem, but you could just add the UART Rx data to a buffer and do the processing of it in your main loop. \$\endgroup\$
    – Colin
    Commented Nov 22, 2017 at 8:30
  • \$\begingroup\$ @Colin__s Thanks for the remarks... I think I cannot just copy it to a buffer, since I want to prevent very long buffers. In some cases MIDI system exclusive data can be like 10's of KB, which is too much to create a buffer. So the processing inside the ISR is mostly to 'ignore' too long (sysex) messages. \$\endgroup\$ Commented Nov 22, 2017 at 9:53

2 Answers 2

6
\$\begingroup\$

When the CPU handles an interrupt, it stops executing the main program. On small, simple microprocessors that lack interrupt nesting, it will also not serve other interrupts.

The interrupt service routine can execute for as long as your main program can tolerate it. You can try to estimate the number of cycles required if this really matter to you, but your code seems quite short to me.

The size of the code is not an issue ether. MicroP uses vectors to jump to the service routine code, so it can be as large as needed.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the clear explanation (later my main program will do a lot but it should withstand an even longer ISR probably). \$\endgroup\$ Commented Nov 22, 2017 at 2:16
2
\$\begingroup\$

Execution of the ISR should be short. At the same time, the amount of code in the ISR can be appreciable.

Imagine a case where you have a switch in your ISR. The switch has got a hundred branches, although each branch of the switch executes quickly. That should be fine.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks, than my guess was right (since I assume execution time is short for my ISR). \$\endgroup\$ Commented Nov 22, 2017 at 2:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.