Hello, I have been working with a STM32F4 where I use two channels of TIM8 to trigger data transfers from two GPIO ports to memory using two DMA2 streams. I would like to have these DMA streams write 16-bit data interleaved to 32-bit memory addresse
I have gotten the 16-bit data transfers individually working where each DMA stream would write to memory in half-world fashion. For this application it would make more sense to write 16-bit data from GPIO port I to the lower half of a 32-bit word and the data from GPIO port J to the higher half of that same 32-bit word.
My idea to implement this was to set up the DMA streams to have the peripheral data size to half-words and the memory size to worlds and have the memory base address aligned to respectively the address of a common data buffer and the address of the data buffer + 2.
The results however do not make sense to me. For testing purposes, using only 1 DMA stream the 16-bit data is written subsequently in the memory, not with a 16-bit gap of zeros between the individual DMA transfers.
When changing the size of the peripheral data size to words and testing with only 1 DMA stream the results is 16-bit data, 16-bit zeros, 16-bit data, ... When testing this with the other DMA stream the result is the same which I guess is due to data alignment being either half-word or word. (As specified in chapter 9.3.7 in the STM32F4 reference manual).
For reference I included the DMA setup code, the data buffers pointers are respectively pointing to the same address with p_data_buffer_2 pointing to the next half-word:
void Config_TIM8_CH2 (void){
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_7;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)p_data_buffer_1;
DMA_InitStructure.DMA_BufferSize = ACQ_TRANSFER_SIZE_HW;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(GPIOJ->IDR);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream3, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream3, DISABLE);
}
void Config_TIM8_CH3 (void){
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_7;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)p_data_buffer_2;
DMA_InitStructure.DMA_BufferSize = ACQ_TRANSFER_SIZE_HW;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(GPIOI->IDR);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream4, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream4, DISABLE);
}Does anyone happen to know how I could achieve this using the DMA settings or is this there another way to do increment the DMA memory pointer with an extra offset?