Duración de una interrupción

2

Sé que una interrupción debe ser lo más corta posible, sin embargo, ¿qué es breve?

Mi rutina es bastante larga, pero tiene algunas instrucciones if, por lo que el tiempo de ejecución es corto. Pero tal vez todavía se considera (demasiado) largo.

¿Mi código causará problemas (en el futuro)? Actualmente solo tengo una interrupción, pero quiero agregar más adelante (por ejemplo, para el control DMX). Este es para manejar la entrada MIDI.

Está diseñado para un STM32F103C8T6 (72 MHz) y posteriormente STM32F446ZET6 (168 MHz). La declaración de depuración es temporal.

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__);
      }
   }
}

Actualización:

Después de solucionar algunos problemas en otra parte del código y rangos ligeramente diferentes en algunas sentencias if, funciona bastante bien. Solo muchos y grandes mensajes de sysex lo hacen un poco lento, pero eso no está relacionado con el ISR.

    
pregunta Michel Keijzers

2 respuestas

6

Cuando la CPU maneja una interrupción, deja de ejecutar el programa principal. En microprocesadores pequeños y simples que carecen de anidación de interrupciones, tampoco servirá para otras interrupciones.

La rutina de servicio de interrupción puede ejecutarse mientras su programa principal pueda tolerarlo. Puede intentar calcular la cantidad de ciclos requeridos si esto realmente le importa, pero su código me parece bastante corto.

El tamaño del código no es un problema éter. MicroP usa vectores para saltar al código de rutina de servicio, por lo que puede ser tan grande como sea necesario.

    
respondido por el pserra
2

La ejecución del ISR debe ser corta. Al mismo tiempo, la cantidad de código en el ISR puede ser apreciable.

Imagina un caso en el que tienes un switch en tu ISR. El switch tiene cien sucursales, aunque cada rama del switch se ejecuta rápidamente. Eso debería estar bien.

    
respondido por el Nick Alexeev

Lea otras preguntas en las etiquetas