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);
}
Solved! Go to Solution.
2024-08-30 08:09 AM - edited 2024-08-30 08:12 AM
Seems like HAL libraries have still loop holes to be fixed. Jan, you are right.
I used LL library for Timer1 along with DMA and it worked. I can see the change in GPIO inputs during debug.
Thanks for supporting me.
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
2024-06-24 11:29 AM
Hi @SofLit
Tried DMA in MEM to MEM mode and triggered it thru software. And chose DMA2 for it. Still the DMA transfer happens only once during start up.
Also, the mode is set to Normal instead of circular , since, according to RM, it cannot be set to Circular in Mem to MEM mode.
2024-06-24 11:58 AM - edited 2024-06-26 03:06 AM
1. DMA M2M mode is not triggered by the usual requests from peripherals. Immediately after enabling it performs the number of transfers set in DMA Stream's NDTR, and ends. That's all.
2. Contrary to what @SofLit said above, P2M *is* the correct mode, if you want to trigger individual transfers from the timer. However, in 'F4, only DMA2 can access the AHB bus where GPIO is located, and only TIM1 and TIM8 can trigger DMA2 streams. [EDIT] Sorry, this is irrelevant to this thread, as the 'L496 is used here, I mis-read the STM32 model.[/EDIT]
3. Cube may or may not get into your way when setting up this, as Cube/CubeMX inevitably caters only for a fraction of actions what the hardware allows, whatever Cube's authors deemed "usual", and this sounds to be "not usual". Disclaimer: I don't use Cube.
JW
2024-06-26 12:54 AM
Thats true @waclawek.jan .
After compiling configuration register functions (HAL_DMA_Start_IT() ), the CNDTR is becoming zero as soon as Enable Bit in DMA_CCRx register is set during Mem to Mem transfer mode. After that, no dma transfer takes place.
The compiler never reaches HAL_DMA_IRQHandler routine.
And the program hangs around Default_Handler routine infinitely.
According to @KnarfB , If an IRQ handler is not defined in the code, a default implementation is used in the interrupt vector table, the DefaultHandler.
Can you elaborate this ?
only TIM1 and TIM8 can trigger DMA2 streams.
How to make TIM1 to trigger DMA2 transfer?
Thanks Jan for supportive effort.