DMA - Kasimashi/Systemes-embarques GitHub Wiki

Le DMA

L'accès direct à la mémoire (en anglais DMA pour Direct Memory Access) est un procédé informatique où des données circulant de, ou vers, un périphérique sont transférées directement par un contrôleur adapté vers la mémoire principale de la machine, sans intervention du microprocesseur si ce n'est pour lancer et conclure le transfert. La conclusion du transfert ou la disponibilité du périphérique peuvent être signalés par interruption. Son objectif est de décharger le processeur des transferts de données. Le contrôleur de DMA est un module matériel capable de réaliser des transferts entre les périphériques et la mémoire. L'avantage d'une telle technologie est que le processeur peut faire autre chose. Le transfert des données peut être plus rapide.

DMA

La configuration minimale du DMA est la suivante :

- Adresse de source du transfert
- Adresse de destination du transfert
- Nombre de données à transférer
- Taille des données (octets, mots...)

Le déclenchement du DMA peut se faire par 2 voies :

  • Déclenchement par logiciel (notamment dans le cas de transferts mémoire vers mémoire)
  • Déclenchement sur événement d’un périphérique (exemple : données reçues par la carte réseau)

Contrôleur du DMA:

  • Plusieurs canaux (channels) pour effectuer plusieurs transferts en même temps (en provenance de plusieurs périphériques par exemple)
  • Registres de configuration par canaux
  • Transferts • Périphérique vers mémoire • Mémoire vers périphérique • Périphérique vers périphérique • Mémoire vers mémoire - Possibilité de remplir une zone mémoire avec un motif

Il y a différents mode d'opérations possibles pour le transfert des données :

  • Rafale (Burst) : Le bloc de données est transféré en une seule fois. Une fois que le contrôleur de DMA a accès au bus, il le conserve pendant tout le transfert. Le processeur ne peut pas faire d’accès mémoire pendant ce temps
  • Vol de cycle (Cycle Stealing) : Le processeur et le contrôleur de DMA se partagent alternativement le bus (un cycle pour le processeur, un pour le contrôleur de DMA)
  • Transparent : Le contrôleur de DMA n’a accès au bus que lorsque le processeur n’en a pas besoin.

Exemples

Example d'API de Silabs et de ST :

Silabs :

ST :

DMA_InitTypeDef  DMA_InitStruct;

//Clock for DMA2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);

//Stream_7 initializing(Each stream can do the job and you can choose one arbitrary)
DMA_InitStruct.DMA_Channel            = DMA_Channel_0;//In Memory to Memory mode channel number isn't important and has no effect
DMA_InitStruct.DMA_Priority           = DMA_Priority_High;
DMA_InitStruct.DMA_DIR                = DMA_DIR_MemoryToMemory;

/* Be very careful that in Memory to Memory mode Peripheral is the SOURCE 
memory*/
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)Config_Buffer;    
DMA_InitStruct.DMA_Memory0BaseAddr    = (uint32_t)(GPIOD_BASE);

DMA_InitStruct.DMA_BufferSize         = sizeof(Config_Buffer)/4;//"sizeof()"function determines the size of array in (bytes) But we need To know the number of int(4bytes) in array
                                                                // so we must to devide sizeof(Config_Buffer) result by 4                                                             
DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_Word;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Enable;
DMA_InitStruct.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
DMA_InitStruct.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
DMA_InitStruct.DMA_FIFOMode           = DMA_FIFOMode_Enable;
DMA_InitStruct.DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStruct.DMA_Mode               = DMA_Mode_Normal;

DMA_Cmd(DMA2_Stream7,DISABLE);
while(DMA_GetCmdStatus(DMA2_Stream7));/**Before calling DMA_Init() function,it is recommended to check that the Stream  is actually disabled using the function DMA_GetCmdStatus().*/                                                                                    

/**All the stream dedicated bits set in the status register (DMA_LISR and 
DMA_HISR) from the previous data block DMA transfer should be cleared before the 
stream could be re-enabled. *For More informations refer to Reference manual Page 324*/
DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7|DMA_FLAG_HTIF7|DMA_FLAG_TEIF7|DMA_FLAG_DMEIF7|DMA_FLAG_FEIF7);

DMA_Init(DMA2_Stream7,&DMA_InitStruct);
DMA_Cmd(DMA2_Stream7,ENABLE);
⚠️ **GitHub.com Fallback** ⚠️