DMA no Arduino Due - Acesse a memória diretamente - MakerHero

Acesso direto à memória (DMA) no Arduino Due 2

O Arduino Due foi o primeiro Arduino oficial a usar um microcontrolador fora da linha ATmega. O escolhido foi o AT91SAM3X8E,também da Atmel. Com um núcleo ARM Cortex M3 de 32 bits rodando a 84MHz, 96K de Ram e 512K de Flash, ele possui uma capacidade de processamento muito maior que o ATmega328 do Uno. Em termos de periféricos, ele também possui muitos recursos adicionais, como o DMA que veremos aqui. Infelizmente, o Due não alcançou muita popularidade, talvez por trabalhar a 3,3 V ao invés dos 5 V usados no Uno.

O DMA – Direct Memory Access – é um recurso que permite executar tarefas de movimentação de dados entre a memória e periféricos sem intervenção direta do processador. Para entender melhor, vejamos um exemplo, considerando um display ligado via I2C.

OLED com DMA

Material necessário

Para montar o nosso exemplo, vamos precisar de:

Como funciona o DMA

Na operação sem DMA (única forma disponível no Arduino UNO), o programa escreve os bytes a serem enviados ao display um a um no periférico de I2C. Antes de enviar um byte é preciso garantir que o byte anterior já foi enviado, o que é feito monitorando um registrador de status ou aguardando uma interrupção. O resultado é uma grande atividade do processador (se não usarmos interrupção ele ficará o tempo todo ocupado com esta atividade).

No Due, podemos programar o DMA para copiar os bytes de uma região da memória para o dispositivo de I2C. Uma vez feito o disparo, o processador só precisa intervir quando a transferência foi concluída. Durante a transferência em si o processador está livre. Isto pode fazer uma grande diferença quando desejamos atualizar continuamente o display todo. Sem DMA, o processador alterna entre gerar a próximo imagem e enviá-la ao display; com DMA a próxima imagem pode ser gerada enquanto a anterior está sendo enviada.

Um detalhe interessante é que o SAM3X possui vários DMAs. Vou usar aqui o Peripheral DMA (PDC) que é específico para uso com os periféricos seriais. A programação do PDC é mais simples e ele está integrado aos registradores dos periféricos seriais. O periférico que implementa o I2C é o TWI (Two Wire Interface).

Funcionamento DMA

Na figura acima podemos ver:

  • Os registradores TWI_RPR e TWI_RCR indicam o endereço e tamanho do buffer usado na recepção.
  • Os registradores TWI_TPR e TWI_TCR indicam o endereço e tamanho do buffer usado na transmissão.
  • Os status RX_READY e TX_READY (no periférico TWI) indicam para o PDC quando um byte foi recebido ou o TWI está pronto para transmitir um byte, Estes sinais são o que disparam a transferência de um byte entre o periférico e a memória.
  • Os status END_RX e END_TX no TWI são atualizados pelo PDC para indicar que todo o buffer foi recebido ou transmitido.

A biblioteca do Arduino não possui funções para manipulação do DMA, é necessário usar bibliotecas de mais baixo nível e acessar diretamente o hardware. A documentação básica para escrever o código é o datasheet do microcontrolador. A programação (sem DMA) do TWI pode ser vistas nos fontes da biblioteca do Arduino, que são instalados no seu micro quando você instala do suporte ao Arduino Due. São também instalados os fontes da Atmel com as definições das estruturas e rotinas de  baixo nível.

Programa para a comunicação usando DMA

Juntando tudo isso com um pouco de experimentação, cheguei ao exemplo abaixo:

Qualquer problema que você pode ter ao programar a placa Due, você pode checar o nosso post explicando como utilizá-la.

E aí, curtiu comunicar com o display usando DMA?  Você pode nos ajudar a melhorar o blog comentando abaixo.

Faça seu comentário

Acesse sua conta e participe

2 Comments

  1. Very interesting tutorial! Do you have an example of how also use the DMA read of I2C interface?

    1. No, so far I’ve only used DMA for I2C and SPI writing.