Introdução ao periférico DMA (Direct Memory Access)

Se o projetista compreender o periférico de DMA, pode otimizar os seus projetos e evitar custos desnecessários. Confira neste artigo como ele funciona.

DMA significa Direct Memory Access, e foi implementado primeiramente no computador IBM 709 em 1958: a função do periférico era de mover os dados de uma região da memória para I/O e vice-versa, tendo acesso direto a elas sem a intervenção da CPU. Explicado o contexto, o nome DMA faz sentido, mas é um tanto infeliz: ao aprender o significado do nome GPIO (General Purpose Input Output) pode-se relacionar à vantagem de um pino ser configurável como entrada ou saída. Porém, a vantagem de se usar DMA não está exatamente no fato dele ter acesso direto à memória, como o nome pode sugerir.

Eu já não tinha acesso direto à memória? Tem a ver com a Memory Protection Unit?

Se o projetista compreender este periférico, pode otimizar os seus projetos evitando, assim, a necessidade de investir em componentes mais robustos e caros. Por esse motivo, neste artigo vou tentar explicar como funciona e quais são as vantagens desse periférico.

O processamento com e sem DMA

Vamos demonstrar na escala de tempo o processamento de um microcontrolador nos dois modos. Como exemplo, vamos imaginar o seguinte processamento:

  1. Task A vai montar um pacote de mensagem para ser enviado via UART;
  2. Task B vai enviar a mensagem via UART;
  3. Task C vai montar um pacote de dados diferente para ser enviado via SPI;
  4. Task D vai enviar o pacote via SPI;
  5. Ao terminar a Task D, a CPU vai realizar a Task A novamente, continuando o ciclo.

Tanto faz se é uma task de RTOS ou uma função comum. Neste primeiro caso de processamento, a CPU do microcontrolador fará todas as tarefas. Na escala do tempo ficaria como na Figura 1.

CPU responsável por executar todas as Tasks - sem DMA.
Figura 1 – CPU responsável por executar todas as Tasks.

O DMA é como se fosse um coprocessador, porém tem somente a função de transportar as mensagens. No nosso exemplo seria encarregado em realizar as tasks/funções B e D, deixando o processamento do sistema como na Figura 2.

Divisão de Tasks entre a CPU e o DMA.
Figura 2 – Divisão de Tasks entre a CPU e o DMA.

Como visto as áreas hachuradas na figura anterior, percebe-se que a CPU ganhou mais tempo de processamento. O tempo ocioso pode ser usado para colocar outras tasks/funções (Task E de cálculo matemático, por exemplo), ou até mesmo antecipar a Task A (a que está em cima da Task D), se for possível na lógica do sistema.

Quando uma transferência é concluída pelo DMA, este envia um sinal de interrupção para a CPU. Na figura anterior, ao final da Task B o DMA enviou um sinal para a CPU, que ordenou o DMA a realizar o Task D imediatamente, já que a Task C estava concluída. Claro que espera-se que exista um pequeno espaço de tempo entre a Task B e D, aonde há o tratamento da dita interrupção, como também a preparação dos ponteiros para o envio da mensagem.

Neste exemplo fizemos a transferência de dados somente da memória para o periférico, mas o DMA consegue realizar o caminho contrário, como também da memória para memória. Transferências de periférico a periférico são incomuns em microcontroladores.

Entendi que assim fica eficiente, mas o quanto?

Vamos supor que eu queira mandar “Hello World!” via UART (120 bits: 12 caracteres, cada um tem 8 bits mais start e stop bits no envio) na velocidade de 115200 bps, e o microcontrolador X roda na velocidade de 80 MHz. A conta fica da seguinte maneira:

dma conta

Isso significa que a CPU pode rodar 83 mil ciclos de clock realizando outras tarefas paralelamente ao envio da mensagem “Hello World!”. Aqui, deve-se tomar cuidado em dizer que seriam 83 mil instruções Assembly, pois dependendo da arquitetura algumas instruções levam dois ciclos de clock para serem executadas. Modificando o cálculo anterior, você pode estimar a otimização por tempo em milissegundos, e avaliar se alguma tarefa pode caber naquele tempo, ou não. Podem caber várias outras tarefas, como pode não ser o suficiente para um cálculo matemático complexo. O projetista deve avaliar cada caso, mas, via de regra, o DMA é usado em comunicações de baixa velocidade, como a UART, ou em transporte maciço de dados em sinais mais rápidos como a SPI.

O problema do DMA e a coerência de cache

A memória cache se localiza próxima ao CPU e é mais rápida que a RAM. O acesso aos dados da memória RAM podem exigir múltiplos ciclos de clock, e nesse cenário a memória cache tem a função de acelerar o processo de leitura e escrita, deixando os dados e instruções disponíveis numa região aonde seja necessário menos ciclos de clock.

O principal problema que pode acontecer ao se implementar o DMA no sistema é a falta de coerência dele com o cache. Veja o problema ilustrado na Figura 3. Num primeiro momento a memória cache acessa o endereço X da memória RAM, armazenando o valor “15”. O DMA armazena o valor “10” no endereço X num segundo momento, e operações subsequentes na CPU serão feitas com o valor desatualizado “15”. Por isso, há a necessidade de sinalização entre o cache e o DMA para uma possível invalidação e atualização do valor.

Ilustração simples do problema da coerência de cache.
Figura 3 – Ilustração simples do problema da coerência de cache.

A memória cache não é somente “coisa de browser”, os desenvolvedores devem se atentar pois microcontroladores ARM Cortex-M7 já utilizam sistema de cache. Este Application Note da ST recomenda que se for utilizar o DMA, que seja feita a alocação dos dados relativos a este numa região da memória que não seja “cacheável”.

Considerações finais

Este artigo tem o caráter introdutório e teórico sobre o DMA, sendo que a implementação em código pode mudar entre diferentes fabricantes de microcontroladores. Eu implementei no Tiva TM4C e você pode conferir neste link. Evandro Teixeira fez também um artigo explicando e aplicando o DMA na FRDM-KL25Z.

O desenvolvedor deverá ter paciência para ler o datasheet com calma e analisar com cuidado as bibliotecas fornecidas pelos fabricantes. A depuração da execução do DMA é um tanto complicado, portanto, um analisador lógico nessas horas é um grande aliado. Se estiver analisando um sinal SPI de alta frequência, não precisará de um analisador caro que capte altas frequências: abaixe a frequência do sinal em firmware, e se o sinal estiver conforme na baixa velocidade, muito provavelmente estará certo nas altas.

Saiba mais

Biblioteca de Software de DMA para FRDM-KL25Z

Soft-SPI: Biblioteca para memória SPI-Flash em microcontroladores PSoC-4

Utilizando os periféricos do microcontrolador ARM Cortex-M0+ ATSAMC21, da Microchip

Referências

Understanding DMA – Hackaday

DMA – A Little Help From My Friends – embedded.fm

DMA – The Ganssle Group

Direct memory access – Wikipedia

Formado em Engenharia Elétrica na UNESP de Guaratinguetá. Curte animes, seriados, rock, esportes, tecnologia, etc. Um menino prendado.

Notificações
Notificar
guest
2 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Wellington Mateus
Wellington
20/07/2018 12:07

Não compreendi o cálculo!

WEBINAR

Visão Computacional para a redução de erros em processos manuais

DATA: 23/09 ÀS 17:00 H