Eu estava fazendo um projeto recentemente com o mbed (LPC1768), usando o DAC para gerar várias ondas. Eu li partes da folha de dados e ele falou sobre como tinha DMA para muitos periféricos. Parecia que seria útil, mas, em leituras adicionais, descobri que o DMA usava o mesmo barramento de dados que a CPU (o que eu acho que é normal). Isso significa que a CPU não pode interagir com nenhuma das memórias enquanto o DAC está obtendo dados? Além disso, como o DAC não tinha um buffer (tanto quanto eu poderia dizer) e, portanto, precisa do DMA com muita frequência, qual é o objetivo do DMA? Se a CPU não pode fazer transações de memória, pode fazer alguma coisa?
microcontroller
mbed
dma
BeB00
fonte
fonte
Respostas:
A folha de dados do LPC1768 que encontrei possui as seguintes aspas (ênfase minha):
O diagrama de blocos na página 6 mostra SRAM com vários canais entre a matriz AHB e a seguinte citação confirma isso:
E isso é reforçado pela seguinte citação:
Portanto, você pode transmitir dados para o seu DAC a partir de um dos blocos SRAM separados ou de um periférico diferente, enquanto usa a SRAM principal para outras funções.
Esse tipo de DMA periférico-periférico é comum em partes menores, onde a interface de memória é bastante simples (em comparação com o processador Intel moderno).
fonte
O longo e o curto é que o DMA permite que a CPU se comporte efetivamente na velocidade nativa, enquanto os periféricos podem se comportar efetivamente na velocidade nativa. A maioria dos números no exemplo é composta.
Vamos comparar duas opções para coletar dados periodicamente de um ADC:
Vamos transferir 1000 amostras do ADC para a RAM.
Usando a opção 1: para cada amostra existe
Vamos fingir que essa função de interrupção tem 76 instruções, toda a rotina tem 100 instruções, assumindo a execução de ciclo único (melhor caso). Isso significa que a opção 1 gastará 100.000 ciclos de tempo de CPU em execução.
Opção 2: o DMA está configurado para coletar 1000 amostras de ADC. Vamos supor que o ADC tenha um gatilho de hardware a partir de um contador de timer.
Fingir que toda a interrupção (com sobrecarga de entrada e saída) é 100 instruções de ciclo único. Usando o DMA, você gasta apenas 100 ciclos para salvar as mesmas 1000 amostras.
Agora, toda vez que o DMA acessa o barramento, sim, pode haver uma disputa entre CPU e DMA. A CPU pode até ser forçada a aguardar a conclusão do DMA. Mas aguardar a conclusão do DMA é muito mais curto do que travar a CPU para atender o ADC. Se o clock do núcleo da CPU for 2x Bus clock, a CPU poderá desperdiçar alguns ciclos do core aguardando a conclusão do DMA. Isso significa que o tempo efetivo de execução da transferência está entre 1000 (supondo que a CPU nunca espere) e 9000 ciclos. Ainda muito melhor do que os 100.000 ciclos.
fonte
Se, em um determinado ciclo, o processador e um controlador DMA precisassem acessar o mesmo barramento, um ou outro teria que esperar. Muitos sistemas, no entanto, contêm várias áreas de memória com barramentos separados, juntamente com uma "ponte" de barramento que permitirá à CPU acessar uma memória enquanto o controlador DMA acessa outra.
Além disso, muitas CPUs podem não precisar acessar um dispositivo de memória a cada ciclo. Se uma CPU normalmente precisar acessar a memória apenas em dois de três ciclos, um dispositivo DMA de baixa prioridade poderá explorar ciclos quando o barramento de memória estiver inativo.
Mesmo nos casos em que todo ciclo de DMA faria com que a CPU fosse interrompida por um ciclo, no entanto, o DMA ainda pode ser muito útil se os dados chegarem a uma taxa lenta o suficiente para que a CPU possa fazer outras coisas entre os itens de dados recebidos. , mas rápido o suficiente para que a sobrecarga por item precise ser minimizada. Se uma porta SPI estivesse alimentando dados para um dispositivo a uma taxa de um byte a cada 16 ciclos de CPU, por exemplo, interromper a CPU para cada transferência provavelmente faria com que passasse quase todo o tempo entrando e retornando da rotina de serviço de interrupção e nenhum fazendo qualquer trabalho real. No entanto, usando o DMA, a sobrecarga poderia ser reduzida para 13%, mesmo que cada transferência de DMA causasse a paralisação da CPU por dois ciclos.
Por fim, algumas CPUs permitem que o DMA seja executado enquanto a CPU estiver em suspensão. O uso de uma transferência baseada em interrupção exigiria que o sistema fosse ativado completamente para cada unidade de dados transferida. No entanto, usando o DMA, pode ser possível que o controlador de suspensão alimente o controlador de memória alguns relógios sempre que um byte chegar, mas deixe todo o resto em sono, reduzindo assim o consumo de energia.
fonte
Como programador, o DMA é uma opção para transferir dados de e para os periféricos que os suportam. Para o exemplo clássico de mudar um buffer grande por um periférico serial como SPI ou UART ou coletar várias amostras de um ADC, você tem três métodos para mover esses dados:
Método de votação. É aqui que você espera nos sinalizadores de registro para permitir que você altere o próximo byte. O problema é que você está mantendo toda a execução da CPU enquanto aguarda por isso. Ou, se você precisar compartilhar o tempo da CPU em um sistema operacional, sua transferência será drasticamente mais lenta.
Método de interrupção. É aqui que você escreve uma rotina de serviço de interrupção (ISR) que é executada a cada transferência de bytes e o código no ISR que gerencia a transferência. Isso é mais eficiente da CPU, porque a CPU atenderá seu ISR somente quando necessário. É gratuito para uso em todos os outros momentos, exceto no ISR. O ISR também é uma das opções mais rápidas para fazer a transferência em termos de velocidade de transferência.
DMA. Você configura o DMA com ponteiros de origem / destino, número de transferências e assim por diante. Ele roubará ciclos de barramento e tempo da CPU para realizar a transferência, e a CPU está livre para fazer outras coisas nesse meio tempo. Você pode configurar um sinalizador ou interromper para indicar quando a transferência é concluída. Geralmente é um toque mais rápido que o ISR e geralmente é a sua opção de transferência mais rápida.
Como programador, prefiro o DMA, pois é o mais fácil de codificar e é essencialmente a técnica mais rápida para fazer a transferência. Normalmente, você só precisa configurar alguns registros para os ponteiros de origem / destino e o número de transferências para fazer e desativar. Passo muito mais horas trabalhando no código ISR do que no código acelerado por DMA porque o código ISR requer habilidades críticas de design e precisa ser codificado, testado, verificado etc. O código DMA é muito menor e o código que preciso escrever sozinho é relativamente trivial e estou obtendo velocidade máxima de transferência em troca.
Na minha experiência, ultimamente com os processadores Atmel SAM3 / 4, o DMA executa um toque mais rapidamente do que um ISR eficiente de minha própria criação. Eu tinha um aplicativo que leria uma pilha de bytes do SPI a cada 5 ms. Muita matemática de ponto flutuante estava ocorrendo em tarefas em segundo plano, então eu queria que a CPU fosse o mais livre possível para essas tarefas. A implementação inicial foi ISR, e então mudei para o DMA para comparar e tentar comprar um pouco mais de tempo de CPU entre as amostras. O ganho da velocidade de transferência foi ligeiramente melhorado, mas apenas um pouco. Mal era mensurável no escopo.
Isso porque nos microprocessadores recentes que eu vi, o ISR e o DMA estão operando quase da mesma maneira - eles executam ciclos de CPU conforme necessário e o DMA está fazendo essencialmente as mesmas operações com o CPU que eu teria codificado em um ISR eficiente .
Em casos raros, vi periféricos que possuem sua própria área de RAM que SÓ era acessível por DMA. Isso foi feito em Ethernet MACs ou USBs.
fonte
O DMA é provavelmente usado aqui para que o DAC possa ter um tempo regular, gerar uma forma de onda alterando a saída analógica em algum intervalo conhecido.
Sim, se for um barramento compartilhado, então ... você precisa compartilhar.
O processador nem sempre está usando o barramento, portanto, às vezes, é uma boa idéia compartilhar com um mecanismo dma. E é claro que isso significa que as prioridades se envolvem, às vezes é apenas quem chegou lá primeiro (por exemplo, tem um comando fifo na frente do recurso e solicitações fifo up, na ordem em que chegam, sim, isso não seria necessariamente determinístico ) Em um caso como esse, convém que o dma tenha prioridade sobre a CPU, para que coisas sensíveis ao tempo, como DACs ou ADCs, tenham um tempo determinístico. Depende de como eles escolheram implementá-lo.
As pessoas às vezes têm essa suposição frequentemente incorreta de que o dma é gratuito. Ainda não consome tempo de barramento, se compartilhado com a CPU (que eventualmente é quando fala com um recurso com o qual a CPU pode conversar), então a CPU e / ou o DMA são retidos, portanto, a CPU ainda precisa aguardar um pouco. tempo, em algumas implementações (provavelmente não no seu microcontrolador), a CPU é completamente adiada até que o dma seja concluído, a CPU é interrompida pelo período. Depende apenas da implementação. A parte livre disso é que a CPU não precisa ser constantemente interrompida ou sondar ou prender a respiração para algum evento alimentar dados. Pode levar algum tempo para criar o próximo buffer para o dma. Ele precisa observar a transferência dma para concluir e lidar com isso, mas em vez de dizer que cada byte agora é de vários bytes, algum bloco de dados.
Não existe uma resposta universal. "Depende" ... do design específico da coisa específica que você está usando. Mesmo dentro de um projeto de chip / placa / sistema, pode haver vários mecanismos dma e não há razão para supor que todos funcionem da mesma maneira. Para cada instância, você precisa descobrir e, infelizmente, eles geralmente não a documentam ou a documentam bem o suficiente. Portanto, talvez seja necessário criar algumas experiências, se for uma preocupação.
fonte
As respostas até agora falam sobre a "velocidade" que a CPU pode fazer e como o DMA beneficia isso. No entanto, há outra consideração, poder .
Se a CPU desejasse enviar um pacote de dados em um link lento, ela precisaria ficar acordada a maior parte do tempo se estiver usando sondagens ou interrupções; no entanto, a CPU principal pode estar no estado de suspensão enquanto o DMA está sendo executado .
fonte
Alguns processadores, como a série STM32H7, têm muitas opções de RAM e montes de RAM acoplada. Ter bancos de RAM separados permite que o DMA martele muita RAM enquanto o processador está processando dados no RAM de acoplamento fechado que não requer armazenamento em cache e não é martelado pelo DMA. Para mover dados, você pode usar o MDMA. Eu construí um radar FMCW usando um desses. Os ADC obtêm dados de QI de duas entradas em uma SRAM. Em seguida, dimensiono os dados e executo o ponto flutuante de 256 bin fft complexo em dtcm ram. FIFO o resultado em uma matriz 2D na ram AXI usando MDMA.
Eu peguei uma segunda caixa de fft 64 no outro lado do fifo para o vetor de velocidade. Eu, então, faço a magnitude dos dados complexos e envio os valores resultantes dos pontos flutuantes 128 e 64 para outro H7 usando SPI a 12,5 MHz para a detecção. Eu faço tudo isso em 4 ms.
A taxa de amostragem é do ADC é de 84 kHz e, usando super amostragem, estou obtendo uma resolução de cerca de 18 bits.
Nada mal para um processador de uso geral rodando apenas na faixa de MHz e sem RAM externa.
Além disso, os caches grandes deste dispositivo também melhoram o desempenho dos cálculos fora do dtcm.
fonte