cancel
Showing results for 
Search instead for 
Did you mean: 

Setting IFCR does not clear ISR

Beartama
Visitor

I'm using the STM32F103C8T6, and trying to blink my LED via the interrupt handler of a DMA with this code

#include <stdint.h>
// STM32F103C8 is a medium density device, hence we use the xB header
#include <stm32f103xb.h>

#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning                                                                       \
    "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif

int main(void) {
	uint32_t blinking[2] = { GPIO_BSRR_BR8, GPIO_BSRR_BS8 };
	uint32_t dest = 0;

	RCC->CR |= RCC_CR_HSION;
	while ((RCC->CR & RCC_CR_HSIRDY) == 0)
		;

	RCC->AHBENR |= RCC_AHBENR_DMA1EN;   // Enable clock for DMA1
	RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // Enable clock for TIM1
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Enable IO port A

	NVIC_EnableIRQ(DMA1_Channel2_IRQn);

	DMA1_Channel2->CCR |= DMA_CCR_MSIZE_1   // 32-bits memory size
	| DMA_CCR_PSIZE_1 // 32-bits peripheral size
			| DMA_CCR_MINC    // Memory increment
			| DMA_CCR_CIRC    // Circular mode
			| DMA_CCR_DIR     // Read from memory
			| DMA_CCR_HTIE    // Enable half transfer interrupt
			| DMA_CCR_TCIE    // Enable complete interrupt
			| DMA_CCR_MEM2MEM
	;

	DMA1_Channel2->CNDTR = 2;
//  DMA1_Channel2->CPAR = (uint32_t)&GPIOA->BSRR;
	DMA1_Channel2->CPAR = (uint32_t) &dest;
	DMA1_Channel2->CMAR = (uint32_t) blinking;

	TIM1->CCMR1 |= TIM_CCMR1_OC1M_0;
	TIM1->DIER |= TIM_DIER_CC1DE;
	TIM1->CCER |= TIM_CCER_CC1E; // Enable OC1 output
	TIM1->BDTR |= TIM_BDTR_MOE;

	TIM1->PSC = 512 - 1;
	TIM1->ARR = (15625 * 2) - 1;

	GPIOA->CRH &= ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8); // GPIO A: Clear pin 8 configuanaration
	GPIOA->CRH |=
	GPIO_CRH_MODE8; // GPIO A: Set pin 8 to output with 50 MHz and push-pull

	DMA1_Channel2->CCR |= DMA_CCR_EN;
	TIM1->CR1 |= TIM_CR1_CEN;

	/* Loop forever */
	for (;;) {
	}
}

void DMA1_Channel2_IRQHandler() {
	if ((DMA1->ISR & DMA_ISR_HTIF2) != 0) {
		GPIOA->BSRR = GPIO_BSRR_BR8;
	}
	if ((DMA1->ISR & DMA_ISR_TCIF2) != 0) {
		GPIOA->BSRR = GPIO_BSRR_BS8;
	}

	DMA1->IFCR = DMA_IFCR_CGIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTCIF2;
}

However, at 67, setting the IFCR register does not seem to clear the ISR flags and the handler keeps getting called. How do I handle this?

 

7 REPLIES 7
TDK
Super User

> DMA_CCR_CIRC // Circular mode

> the handler keeps getting called

Seems like correct behavior to me.

Use normal (non-circular) mode if you only want it to happen once.

If you feel a post has answered your question, please click "Accept as Solution".

I mean the handler is called immediately without the delay expected.

waclawek.jan
Super User

How do you know?

[EDIT]

DMA_CCR_MEM2MEM

Don't. This does not do what you may think it does. The M2M mode means "ignore trigger from TIM, do autotrigger the given channel so that transfers run as quick as possible".

JW

My setup has an LED connected to GPIO A8, if there’s a delay between two interruption invocations, i would see the LED blinking. However, I see the LED stays bright without being turned off.

Can your eyes detect if it's blinking at 1 MHz? Unlikely.

The flag is getting cleared here, it's just getting set again immediately afterwards because the transfer happens so fast.

If you feel a post has answered your question, please click "Accept as Solution".

I’m confused now, I believe I set the prescaler to 512 and the auto reload register to 31250, since the HSI clock ticks at 8MHz, this should make the DMA tick every 2s, am i make a mistake here?

waclawek.jan
Super User

Yes, I repeat, don't use MEM2MEM in DMA, as it ignores the triggers from timer and autotriggers at maximum rate.

JW