2022-09-01 03:04 AM
Hello. I'm struggling with DMA on that specific MCU. I'm using MEM2MEM to transfer data from RAM to GPIOD, triggered by TIM3 interrupt. Here's my init code:
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* Configure DMA request hdma_memtomem_dma2_channel1 on DMA2_Channel1 */
hdma_memtomem_dma2_channel1.Instance = DMA2_Channel1;
hdma_memtomem_dma2_channel1.Init.Request = DMA_REQUEST_MEM2MEM;
hdma_memtomem_dma2_channel1.Init.Direction = DMA_MEMORY_TO_MEMORY;
hdma_memtomem_dma2_channel1.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_memtomem_dma2_channel1.Init.MemInc = DMA_MINC_DISABLE;
hdma_memtomem_dma2_channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_memtomem_dma2_channel1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_memtomem_dma2_channel1.Init.Mode = DMA_NORMAL;
hdma_memtomem_dma2_channel1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_memtomem_dma2_channel1) != HAL_OK)
{
Error_Handler();
}
/* */
if (HAL_DMA_ConfigChannelAttributes(&hdma_memtomem_dma2_channel1, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* DMA interrupt init */
/* DMA2_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn);
}
And app code:
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
PCB.matrix.next();
}
}
void onDmaCompleted(DMA_HandleTypeDef*) {
HAL_GPIO_TogglePin(LAT_GPIO_Port, LAT_Pin);
}
void Matrix::next() {
if (currentRow == 0) {
currentFrame = frameBuffer.getFrame();
}
HAL_DMA_Start(&dma, (uint32_t) currentFrame, (uint32_t) &GPIOD->ODR, frameBuffer.getSize());
setAddress(currentRow++);
currentRow %= ROWS;
}
void Matrix::setAddress(uint8_t row) {
GPIOE->ODR = (row << 2);
}
void Matrix::begin() {
HAL_DMA_RegisterCallback(&dma, HAL_DMA_XFER_CPLT_CB_ID, onDmaCompleted);
HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);
}
This code works perfectly fine on F407, but on L562 I'm observing weird behavior.
On image lines are: yellow - TIM3 PWM, green - one pin of GPIOD, basically 010101..., blue line is LAT_Pin. Violet arrows point to complete interrupt generated by last DMA transfer. On F407 this specific interrupt was called immediately, here on L562 it obviously isn't. From my observation, in this case time differences between LAT_Pin state changes are quite regular (908-910us). I also wrote this code directly on registers, but the outcome was the same as this HAL code. ICACHE and TZ are off. This is only DMA channel in use. Data send by DMA is also correct, just this interrupt doesn't fire when expected.
So, is there a way for this interrupt to fire immediately? Any hints appreciated.
2022-09-01 05:32 AM
> blue line is LAT_Pin
Toggle it directly in the interrupt i.e. in DMA2_Channel1_IRQHandler(), upon the transfer complete flag is set, not in any callback etc.
JW