Embora o DMA libere a CPU e, portanto, possa reduzir a latência de outros aplicativos acionados por interrupção em execução no mesmo núcleo, há custos associados:
Há apenas uma quantidade limitada de canais DMA e existem limitações sobre como esses canais podem interagir com os diferentes periféricos. Outro periférico no mesmo canal pode ser mais adequado para uso de DMA.
Por exemplo, se você tem uma transferência I2C em massa a cada 5ms, isso parece ser um candidato melhor para DMA do que um comando de depuração ocasional que chega no UART2.
Configurar e manter o DMA é um custo por si só. (Normalmente, configurar o DMA é considerado mais complexo do que configurar a transferência acionada por interrupção normal por caractere, devido ao gerenciamento de memória, mais periféricos envolvidos, o uso do DMA interrompe-se e a possibilidade de você precisar analisar os primeiros caracteres fora do DMA de qualquer forma, veja abaixo.)
O DMA pode usar energia adicional , uma vez que é outro domínio do núcleo que precisa ser cronometrado. Por outro lado, você pode suspender a CPU enquanto a transferência do DMA estiver em andamento, se o núcleo suportar isso.
O DMA exige que os buffers de memória funcionem (a menos que você esteja usando DMA periférico a periférico), para que haja algum custo de memória associado a ele.
(O custo da memória também pode estar presente ao usar interrupções por caractere, mas também pode ser muito menor ou desaparecer se as mensagens forem interpretadas imediatamente dentro da interrupção.)
O DMA produz uma latência porque a CPU é notificada apenas quando a transferência é concluída / metade da conclusão (consulte as outras respostas).
Exceto ao transmitir dados para / de um buffer de anel, você precisa saber com antecedência quantos dados você receberá / enviará.
Isso pode significar que é necessário processar os primeiros caracteres de uma mensagem usando interrupções por caractere: por exemplo, ao fazer interface com um XBee, você primeiro lê o tipo e tamanho do pacote e, em seguida, aciona uma transferência de DMA para um buffer alocado.
Para outros protocolos, isso pode não ser possível, se eles usam apenas delimitadores de final de mensagem: por exemplo, protocolos baseados em texto que usam '\n'
como delimitador. (A menos que o periférico DMA suporte a correspondência em um caractere.)
Como você pode ver, há muitas compensações a serem consideradas aqui. Alguns estão relacionados a limitações de hardware (número de canais, conflitos com outros periféricos, correspondência de caracteres), outros são baseados no protocolo usado (delimitadores, comprimento conhecido, buffers de memória).
Para adicionar alguma evidência anedótica, eu enfrentei todas essas compensações em um projeto de hobby que usava muitos periféricos diferentes com protocolos muito diferentes. Havia algumas compensações a serem feitas, principalmente com base na pergunta "quantos dados estou transferindo e com que frequência vou fazer isso?". Isso essencialmente fornece uma estimativa aproximada do impacto de uma simples transferência acionada por interrupção na CPU. Assim, dei prioridade à transferência I2C acima mencionada a cada 5ms na transferência UART a cada poucos segundos que usava o mesmo canal DMA. Outra transferência UART acontecendo com mais frequência e com mais dados, por outro lado, tem prioridade sobre outra transferência I2C, o que ocorre mais raramente. É tudo uma troca.
Obviamente, usar o DMA também tem vantagens, mas não foi isso que você pediu.