Si bien DMA alivia la CPU y, por lo tanto, puede reducir la latencia de otras aplicaciones controladas por interrupciones que se ejecutan en el mismo núcleo, hay costos asociados con ella:
Solo hay una cantidad limitada de canales DMA y hay limitaciones sobre cómo esos canales pueden interactuar con los diferentes periféricos. Otro periférico en el mismo canal puede ser más adecuado para el uso de DMA.
Por ejemplo, si tiene una transferencia masiva de I2C cada 5 ms, este parece ser un mejor candidato para DMA que un comando de depuración ocasional que llega a UART2.
Configurar y mantener DMA es un costo en sí mismo. (Normalmente, la configuración de DMA se considera más compleja que la configuración de la transferencia controlada por interrupción normal por carácter, debido a la administración de memoria, a la mayor cantidad de periféricos involucrados, al uso de DMA en las interrupciones y a la posibilidad de que necesite analizar los primeros caracteres fuera de DMA de todos modos, ver más abajo)
DMA puede usar energía adicional , ya que es otro dominio del núcleo que necesita ser sincronizado. Por otro lado, puede suspender la CPU mientras la transferencia de DMA está en progreso, si el núcleo lo admite.
DMA requiere memorias intermedias para trabajar (a menos que esté haciendo DMA periférico a periférico), por lo que hay algunos costos de memoria asociados con él.
(El costo de la memoria también puede estar presente cuando se usan interrupciones por carácter, pero también puede ser mucho más pequeño o desaparecer si los mensajes se interpretan de inmediato dentro de la interrupción).
DMA produce una latencia porque la CPU solo recibe una notificación cuando la transferencia se completa / medio completa (consulte las otras respuestas).
Excepto cuando se transmiten datos hacia / desde un búfer en anillo, debe saber de antemano cuántos datos recibirá / enviará.
Esto puede significar que es necesario procesar los primeros caracteres de un mensaje usando interrupciones por carácter: por ejemplo, al interactuar con un XBee, primero debe leer el tipo y el tamaño del paquete y luego activar una transferencia DMA en un búfer asignado.
Para otros protocolos, esto puede no ser posible si solo usan delimitadores de fin de mensaje: por ejemplo, protocolos basados en texto que se usan '\n'
como delimitadores. (A menos que el periférico DMA admita la coincidencia en un personaje).
Como puede ver, hay muchas compensaciones a considerar aquí. Algunos están relacionados con limitaciones de hardware (número de canales, conflictos con otros periféricos, coincidencia de caracteres), algunos se basan en el protocolo utilizado (delimitadores, longitud conocida, memorias intermedias).
Para agregar alguna evidencia anecdótica, me enfrenté a todas estas compensaciones en un proyecto de pasatiempo que utilizaba muchos periféricos diferentes con protocolos muy diferentes. Hubo algunas compensaciones que hacer, principalmente basadas en la pregunta "¿cuántos datos estoy transfiriendo y con qué frecuencia voy a hacer eso?". Básicamente, esto le brinda una estimación aproximada del impacto de la transferencia simple impulsada por interrupción en la CPU. Por lo tanto, le di prioridad a la transferencia I2C antes mencionada cada 5 ms sobre la transferencia UART cada pocos segundos que usaba el mismo canal DMA. Otra transferencia UART que ocurre con más frecuencia y con más datos, por otro lado, tiene prioridad sobre otra transferencia I2C que ocurre con menos frecuencia. Todo es una compensación.
Por supuesto, usar DMA también tiene ventajas, pero eso no es lo que pediste.