Respuesta no específica de AVR:
Saltar a un ISR desde un subproceso de ejecución normal generalmente requiere un cambio de contexto , donde el estado actual de la CPU se guarda en algún lugar (pila, registros ocultos) para que el ISR pueda usar la CPU como necesita, y cuando termina, el ISR restaura el contexto (de modo que para el programa principal, la CPU se encuentra en el estado exacto en que se encontraba antes del ISR) y continúa. Es un salto asíncrono desde la ejecución normal: el programa no decide deliberadamente bifurcarse, algún mecanismo externo (una señal, algún hardware, lo que sea) toma la decisión.
Una llamada de función ordinaria no requiere un cambio de contexto per se. El código está siguiendo una ruta conocida, por lo que no es necesario guardar / conservar todos los registros de la CPU. Dependiendo de la función, es posible que tenga que pasarle argumentos y volver a leer un valor de retorno, pero ya que no está adelantando la ejecución normal (es decir, el programa sabe a dónde va y cuándo va a ir allí) y no espera para volver con todo como estaba antes de la llamada, no estás haciendo un cambio de contexto.
Si no ve ningún cambio de contexto en su código ISR (podría ser push, pops, etc.) entonces tal vez el hardware se encarga de eso por usted. En otros dispositivos (muchas partes de Microchip, por ejemplo) necesita cuidar el cambio de contexto en el código. En general, espero que un salto de ISR requiera un código adicional para encargarse del cambio de contexto frente a una llamada de función XXX (anulación) sin efecto.
Llamar a una función desde un ISR no es tan diferente de llamar a una función en el espacio de usuario. El código se ramificará de la misma manera que antes, con los argumentos pasados y los valores devueltos devueltos. Sin embargo, si se encuentra en un dispositivo de pila limitada, tenga cuidado: la llamada a la función estará enviando y extrayendo cosas hacia y desde la pila que probablemente ya está manteniendo el contexto del código fuera del ISR. El desbordamiento de pila es siempre una posibilidad con llamadas de función anidadas (la recursión es realmente mala para esto).
Un contenedor ATOMIC_BLOCK bloquea las interrupciones de la activación mientras se está ejecutando un segmento de código. Si ya está en un ISR, supongo que esto evitaría que el ISR sea precedido por otro ISR de mayor prioridad. Puedo entender por qué puede querer hacer esto, por lo que me parece válido (nota: no soy un experto en ARM)