2023-11-27 10:24 PM
Controller:STM32G473RET6
IDE:STM32CubeMX+Keil(LL library)
Using DMA1 channel 1, copy the data collected by the ADC during half transfer interrupts and transfer complete interrupts.Discovered that half transmission interrupts and full transmission interrupts cannot be used independently.
Specifically reflected in:
Solved! Go to Solution.
2023-11-28 07:13 PM
The HT flag still gets set even if it doesn't trigger the IRQ. So when your program runs, this happens:
In your IRQ, you should check for HT being enabled AND being set. And only then act upon it. HAL does this.
You should also set the interrupts you want before enabling the stream, to avoid calling them when you don't want to. Seems like you're using a timer to trigger the ADC here, so shouldn't be the case.
2023-11-28 06:44 AM - edited 2023-11-28 06:44 AM
> When DMA1 is initialized, if the half transfer interrupt is turned on and the transfer complete interrupt is turned off, the full transfer interrupt can still be triggered
How are you seeing this behavior exactly? Are you using your own IRQ handler or HAL's? Showing code would be informative.
Likely to be a software program bug, not a silicon hardware issue.
2023-11-28 05:34 PM
Yeah! I used DMA IRQ handler.I think that interrupt should not be triggered if it is not enabled.
/****************************part 1*****************************/
*DisableIT_TC,
*EnableIT_HT
****************************************************************/
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC3_Init();
MX_OPAMP3_Init();
MX_TIM1_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
LL_ADC_REG_SetDMATransfer(ADC3,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
LL_ADC_REG_StartConversion(ADC3);
Activate_ADC(ADC3);
Activate_OPAMP(OPAMP3);
LL_DMA_DisableIT_TC(DMA1,LL_DMA_CHANNEL_1);
LL_DMA_EnableIT_HT(DMA1,LL_DMA_CHANNEL_1);
LL_TIM_EnableCounter(TIM1);
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if((DMA1->ISR & DMA_ISR_TCIF1_Msk) == DMA_ISR_TCIF1_Msk)
{
LL_DMA_ClearFlag_TC1(DMA1);//The program can run here!!!why?TC interrupt was disable
LL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
if((DMA1->ISR & DMA_ISR_HTIF1_Msk) == DMA_ISR_HTIF1_Msk)
{
LL_DMA_ClearFlag_HT1(DMA1);
}
}
/****************************part 2*****************************/
*DisableIT_HT,
*EnableIT_TC
****************************************************************/
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC3_Init();
MX_OPAMP3_Init();
MX_TIM1_Init();
MX_UART4_Init();
/* USER CODE BEGIN 2 */
LL_ADC_REG_SetDMATransfer(ADC3,LL_ADC_REG_DMA_TRANSFER_UNLIMITED);
LL_ADC_REG_StartConversion(ADC3);
Activate_ADC(ADC3);
Activate_OPAMP(OPAMP3);
LL_DMA_EnableIT_TC(DMA1,LL_DMA_CHANNEL_1);
LL_DMA_DisableIT_HT(DMA1,LL_DMA_CHANNEL_1);
LL_TIM_EnableCounter(TIM1);
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if((DMA1->ISR & DMA_ISR_TCIF1_Msk) == DMA_ISR_TCIF1_Msk)
{
LL_DMA_ClearFlag_TC1(DMA1);
}
if((DMA1->ISR & DMA_ISR_HTIF1_Msk) == DMA_ISR_HTIF1_Msk)
{
LL_DMA_ClearFlag_HT1(DMA1);//The program can run here!!!why?HT interrupt was disable
LL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
}
2023-11-28 06:43 PM
Probably those interrupts were enabled and triggered before your code disabled them.
2023-11-28 07:13 PM
The HT flag still gets set even if it doesn't trigger the IRQ. So when your program runs, this happens:
In your IRQ, you should check for HT being enabled AND being set. And only then act upon it. HAL does this.
You should also set the interrupts you want before enabling the stream, to avoid calling them when you don't want to. Seems like you're using a timer to trigger the ADC here, so shouldn't be the case.
2023-11-28 10:22 PM
Yes,you are right.I used a timer to trigger the ADC.And in IRQ,check for HT being enabled & being set has been resolved this bug.
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if((DMA1->ISR & DMA_ISR_TCIF1_Msk) == DMA_ISR_TCIF1_Msk && LL_DMA_IsEnabledIT_TC(DMA1,LL_DMA_CHANNEL_1))
{
LL_DMA_ClearFlag_TC1(DMA1);
LL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
if((DMA1->ISR & DMA_ISR_HTIF1_Msk) == DMA_ISR_HTIF1_Msk && LL_DMA_IsEnabledIT_HT(DMA1,LL_DMA_CHANNEL_1))
{
LL_DMA_ClearFlag_HT1(DMA1);
}
}
But I cannot understand why check for HTIE being set in IRQ。Obviously HTIE was disabled.
LL_DMA_DisableIT_HT(DMA1,LL_DMA_CHANNEL_1);
Also simulated by Keil,I see HTIE was disabled.
2023-11-28 11:44 PM
As TDK said above, DMA sets the Half-Transfer flag regardless of whether interrupt is enabled or not. This flag is then input to an AND gate, other input of that gate is the HT-enable bit, and output of that gate is ORed together with other DMA interrupt sources and the result is fed to NVIC.
This solution allows to use software polling of the DMA flags, i.e. working without interrupts.
JW
2023-11-29 12:11 AM
Oh, I see now!:grinning_face:Thank you and TDK!