2024-06-14 03:24 AM - edited 2024-06-14 03:44 AM
After setting configuration registers in HAL_DMA_Start_IT, DMA fails to fire back interrupt, HAL_DMA_IRQHandler(). The TransferComplete call back routine is not called but only once after reset since HAL_DMA_IRQHandler() is called only once after initialization. Flags CC1DE and CC1IE are set after initialization and never change there after. I am trying to read a parallel ADC through GPIO using DMA with interrupt and timer input capture. I am using STM32L496ZG ucontroller and used CUBEMX to generate code.
Also, I am using Timer2 with input capture mode to request DMA transfer. And using MCO to generate 2 MHz to feed to PA0 for timer2 ch1.
I searched the forum and checked almost everything. I used latest CUBEMX 6.11.1 version.
Your help is greatly appreciated.
Thanks
Here is my initzn part;
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_DMA_Init();
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART2_UART_Init();
if(DWT_Delay_Init())
HAL_UART_Transmit(&huart2, (uint8_t *)"\r\nClkTick started", 17, HAL_MAX_DELAY);
else
HAL_UART_Transmit(&huart2, (uint8_t *)"\r\nClkTicks fail to start", 4, HAL_MAX_DELAY);
/* USER CODE BEGIN 2 */
if (HAL_DMA_Start_IT(htim2.hdma[TIM_DMA_ID_CC1], &GPIOE->IDR, (uint32_t)&aDST_Buffer, BUFFER_SIZE) != HAL_OK)
{
/* Transfer Error */
Error_Handler();
}
// Attach DMA callback functions
htim2.hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = HalfTransferComplete;
htim2.hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TransferComplete;
htim2.hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TransferError;
// Enable timer to trigger DMA transfer - CC1DE bit
__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_CC1);
// Enable timer input capture
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
}
DMA Req setting: >Mode: Normal.
And this is the data transfer callback routines:
static void HalfTransferComplete(DMA_HandleTypeDef *hdma_tim2_ch1) {
int position = 0;
LastITHalfComplete = 1;
/*Copy the first part of the received buffer */
for (int i = 0; i < HALF_BUFFER_SIZE; i++) {
aFull_Buffer[FullDataIndex] = aDST_Buffer[i+position];
FullDataIndex++;
//HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
}
}
static void TransferComplete(DMA_HandleTypeDef *hdma_tim2_ch1)
{
int position = HALF_BUFFER_SIZE;
LastITHalfComplete = 0;
/* Copy the second part of the received buffer */
for (int i = 0; i < HALF_BUFFER_SIZE; i++) {
aFull_Buffer[FullDataIndex] = aDST_Buffer[i+position];
FullDataIndex++;
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
}
transferComplete = 1;
}
static void TransferError(DMA_HandleTypeDef *hdma_tim2_ch1) {
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_14);
}
2024-06-14 03:47 AM - edited 2024-06-14 03:52 AM
Hello,
As you need to transfer data from GPIO IDR to a memory, how did you configure the DMA? Peripheral to Memory? If yes this that's not the correct config.
You need to consider the GPIO register as a memory location so you need to configure it as Memory to Memory.
You can also refer to this application note AN4666.
Read also this post: https://community.st.com/t5/stm32-mcus-products/stm32f429-read-from-pin-to-dma/m-p/683278
2024-06-14 04:54 AM
Thanks SofLit,
As you know there's no Mem to Mem option available in recent cubeMx. Only Periph to Mem Or Mem to Periph. I read somewhere that Periph to Mem is same as Mem to Mem. plz correct me.
According to AN4666 doc, DMA1Ch5 was selected using Tim2Ch1. And I did the same.
For timer in Inp capture, I am using falling edge to trigger DMA.
Thanks
2024-06-14 05:39 AM
Hello,
How?
2024-06-14 06:22 AM
I was checking here.
Ok. But if I did be selecting DMA MEM to MEM directly without timer, then how to connect it to timer pulse trigger? I mean, what condition will trigger a DMA request? Which channel to choose along with DMA2?
Thanks
2024-06-14 07:06 AM
Is the DMA set to Circular? If not, how do you start it again?
JW
2024-06-18 10:52 PM
Hi jan,
Sorry for late reply. I was working to put changes suggested by SofLit and DMA setting to circular, but could not succeed. DMA is set to normal.
Also, I could not accommodate MEM to MEM DMA change, as I could not connect interrupt trigger by timer with DMA.
Still struggling to get it work.
Thanks