Aunque el DMA alivia a la CPU y, por tanto, puede reducir la latencia de otras aplicaciones basadas en interrupciones que se ejecutan en el mismo núcleo, hay costes asociados a él:
-
Sólo hay un cantidad limitada de canales DMA y hay limitaciones en la forma en que 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 tienes una transferencia I2C masiva cada 5ms, esto parece un mejor candidato para DMA que un comando de depuración ocasional que llega a UART2.
-
Configuración y mantener la AMD es un coste por sí mismo. (Normalmente, la configuración de DMA se considera más compleja que la configuración de una transferencia normal por carácter impulsada por interrupción, debido a la gestión de la memoria, a que hay más periféricos implicados, a que DMA utiliza interrupciones por sí mismo y a la posibilidad de que necesites analizar los primeros caracteres fuera de DMA de todos modos, ver más abajo).
-
La DMA puede utilizar energía adicional ya que se trata de otro dominio del núcleo que hay que cronometrar. Por otro lado, puedes suspender la CPU mientras la transferencia DMA está en progreso, si el núcleo lo soporta.
-
La DMA requiere búferes de memoria para trabajar (a menos que estés haciendo DMA de periférico a periférico), por lo que hay algún coste de memoria asociado.
(El coste de la memoria puede también estar ahí cuando se usan interrupciones por carácter, pero también puede yo mucho más pequeño o desaparecer del todo si los mensajes se interpretan enseguida dentro de la interrupción).
-
La DMA produce un latencia porque la CPU sólo recibe una notificación cuando la transferencia está completa/medio completa (ver las otras respuestas).
-
Excepto cuando se transmiten datos a/desde un búfer en anillo, se necesita saber de antemano cuántos datos que va a recibir/enviar.
-
Esto puede significar que es necesario procesar los primeros caracteres de un mensaje utilizando interrupciones por carácter: por ejemplo, cuando se interconecta con un XBee, primero se lee el tipo y el tamaño del paquete y luego se activa una transferencia DMA a un búfer asignado.
-
Para otros protocolos, esto puede no ser posible en absoluto, si sólo utilizan delimitadores de fin de mensaje: por ejemplo, los protocolos basados en texto que utilizan '\n'
como delimitador. (A menos que el periférico DMA admita la coincidencia con un carácter).
Como puedes ver, hay que tener en cuenta muchas compensaciones. Algunas están relacionadas con las limitaciones del hardware (número de canales, conflictos con otros periféricos, coincidencia de caracteres), otras se basan en el protocolo utilizado (delimitadores, longitud conocida, búferes de memoria).
Para añadir algunas pruebas anecdóticas, me he enfrentado a todas estas compensaciones en un proyecto de hobby que utilizaba muchos periféricos diferentes con protocolos muy distintos. Había que hacer algunas concesiones, sobre todo basadas en la pregunta "¿cuántos datos voy a transferir y con qué frecuencia voy a hacerlo?". Esto te da esencialmente una estimación aproximada del impacto de una simple transferencia basada en interrupciones en la CPU. Así, di prioridad a la mencionada transferencia I2C cada 5ms sobre la transferencia UART cada pocos segundos que utilizaba el mismo canal DMA. Otra transferencia UART que ocurre más a menudo y con más datos, por otro lado, tiene prioridad sobre otra transferencia I2C que ocurre más raramente. Todo son compensaciones.
Por supuesto, el uso de DMA también tiene ventajas, pero eso no es lo que has pedido.
0 votos
No todos los µC tienen DMA. Si usted puede usarlo, entonces genial, úsalo si necesito la velocidad.
0 votos
@HarrySvensson No sé si realmente necesito la velocidad, pero el DMA lo conseguí en pocas horas, mientras que las interrupciones las probé durante varias semanas (tiempo de pasatiempo libre). Pensé que lo mejor sería probar primero directamente (que funcionaba), que las interrupciones (no funcionaba bien), que el DMA (usando las interrupciones).
2 votos
¿Por qué no? Eso es una cuestión de opinión, que busca una conjetura en cuanto a la posible razón técnica, o de la misma manera demasiado amplia, y por lo tanto no es una pregunta que pertenece aquí. Por nombrar un ejemplo al azar, el DMA significará más latencia en la reclamación de los datos, sobre todo porque no se obtiene ningún beneficio real a menos que se permita recoger varios caracteres. A menudo eso puede estar bien, a veces no.
6 votos
Si conseguir que las interrupciones funcionen te ha llevado semanas, es porque has enfocado la tarea de forma equivocada; conseguir que el DMA funcione bien podría llevar más tiempo -en realidad es una tarea más compleja, así que la aparente facilidad de la tarea más compleja sobre la más sencilla presumiblemente se reduce a los recursos que has utilizado para guiarte con cada una, no al mecanismo en sí.
1 votos
@Michel Keijzers: nunca has dicho el bitrate de tu aplicación, o me lo he perdido. Me sorprende que las interrupciones no te hayan funcionado. A 72MHz y 115200 baudios tienes la friolera de 5000 relojes por carácter.
5 votos
Nunca asumas que dma libera la cpu, a veces sí, la cpu sigue funcionando, a veces no el procesador se congela para mantener el bus para el motor dma. Es trivial hacer esto con una implementación de un brazo, así que no se puede decir que todos los brazos son de esta manera y todos los x86 son de esa manera o lo que sea, no es tan simple, siempre hay que examinar el diseño del sistema y tal vez hacer un poco de hacking. El chip que tienes puede muy bien liberar el núcleo del brazo, esto es sólo un comentario sobre la dma. En cuanto a tu pregunta, no tiene sentido que no puedas mantener el ritmo y dma + int es probablemente la solución completa si no puedes simplemente sondear.
1 votos
Dado que está utilizando una HAL y/o una biblioteca proporcionada por el proveedor, el problema podría no estar en el chip sino en la HAL o la biblioteca proporcionada. ¿Examinaste cuidadosamente cada centímetro de la biblioteca para asegurarte de que el problema no estaba en el código o en una combinación de tu código y el suyo y el compilador?
2 votos
Tenga en cuenta que el MIDI es de 31250 baudios, por lo que es probable que el brazo no esté sudando en absoluto al tratar con esto.
0 votos
@old_timer ... ni siquiera si recibo 1 byte a la vez (¿que la configuración de la nueva intterrupción DMA lleva demasiado tiempo?)
5 votos
Las interrupciones son bastante triviales en el puerto serie del STM32F. ¿Por qué no publicas una pregunta con tu código para que algunos de nosotros podamos tratar de detectar dónde te estás equivocando? Nunca es una buena idea hackear el código hasta que funcione sin entender cuál era el problema subyacente.
0 votos
@Jon Totalmente cierto ... Lo haré esta noche (no en casa ahora). Bueno, teniendo en cuenta los muchos puestos de UART con interrupciones (no DMA) en STM no es realmente trivial.
7 votos
En mi (no tan) humilde opinión, esta es una de las desventajas de usar el horrible e hinchado Cube. Escribe el software desde cero, aprenderás exactamente cómo funciona la UART (porque tienes que hacerlo), entenderás mucho mejor el periférico y a la larga te ahorrará mucho tiempo.
0 votos
@Jon ... tal vez espere un poco ... primero quiero tener una versión de trabajo con DMA, después de que voy a volver a las interrupciones para ver si funciona o no ... entonces voy a hacer la pregunta (tengo muy poco tiempo lo siento).
0 votos
@DiBosco cierto ... sin embargo voy a seguir primero algunas comprobaciones con el DMA (ya que parece que funciona), que volver a las interrupciones, que probablemente utilizar la forma de 'bajo nivel'.