Skip to main content
CLeo.1
Senior II
June 30, 2021
Solved

STM32H753ZI DMA Handler stop working when switched from C to C++

  • June 30, 2021
  • 2 replies
  • 1454 views

Hi everyone, just a question about this DMA not triggering for unknown reasons.

The only thing I can deduced is the switch from C to C++ and how variables behave within an object maybe.

All I know is the peripheral is working and the DMA is setting the right flag. I also tried the C version of my code and it worked. Double check the buffer is in the right memory region as well the RAM_D1.

0693W00000BcUZfQAN.png0693W00000BcUZpQAN.png0693W00000BcUZuQAN.pngFor some reason it doesnt wanna hit the void DMA1_Stream3_IRQHandler(). Yes I used the

Main.cpp

int main () {
 
clock clock;
audioProcessor ap;
uart<uint8_t*> uart(ap.GET_UART4_RxBUFF(), 1);
 
while (1) {
 
	}
}
 
void DMA1_Stream3_IRQHandler() {
 
	if (((DMA1->LISR) & (DMA_LISR_TCIF3)) != 0) {
		 DMA1->LIFCR |= DMA_LIFCR_CTCIF3;
 
		 UART4_TC = OK;
	}
}

uart.h

/*
 * i2s.h
 *
 * Created on: Jun. 22, 2021
 * Author: Christopher
 */
 
#ifndef PERIPERHALS_HEADER_MIDCLASS_UART_H_
#define PERIPERHALS_HEADER_MIDCLASS_UART_H_
#include "peripheral.h"
 
 
template <class T>
class uart: public I_peripheral {
 
private:
		void SET_GPIO();
		void SET_Peripheral();
		void SET_Clock();
		void SET_DMA(T Rx_BUFF, uint32_t length);
		void SET_Interrupt();
		void SET_REG(T Rx_BUFF, uint32_t length);
 
public:
		 uart(T Rx_BUFF, uint32_t length) {
			SET_REG(Rx_BUFF, length);
		}
};
 
template <class T>
void uart<T>::SET_GPIO() {
 
	RCC->AHB4ENR &= ~(RCC_AHB4ENR_GPIODEN);
	RCC->AHB4ENR |= RCC_AHB4ENR_GPIODEN;
 
	GPIOD->MODER &= ~((GPIO_MODER_MODE0) |
				 (GPIO_MODER_MODE1));
 
	GPIOD->MODER |= (GPIO_MODER_MODE0_AF) |
				 (GPIO_MODER_MODE1_AF);
 
	GPIOD->OSPEEDR |= GPIO_OSPEEDR_OSPEED0_VERY_HIGH_SPEED |
				 GPIO_OSPEEDR_OSPEED1_VERY_HIGH_SPEED;
 
 
	GPIOD->AFR[0] &= ~((GPIO_AFRL_AFSEL0) |
				 (GPIO_AFRL_AFSEL1));
 
	GPIOD->AFR[0] |= (GPIO_AFRL_AFSEL0_UART4_RX) |
				 (GPIO_AFRL_AFSEL1_UART4_TX);
}
 
template <class T>
void uart<T>::SET_Peripheral() {
 
	UART4->BRR = 0x412;
	UART4->CR3 |= (USART_CR3_DMAT) | (USART_CR3_DMAR);
	UART4->CR1 |= (USART_CR1_M1_8BITS) | (USART_CR1_M0_8BITS) | (USART_CR1_RE) | (USART_CR1_TE);
	UART4->CR2 |= (USART_CR2_STOP_1BIT);
	UART4->CR1 |= USART_CR1_UE;
}
 
template <class T>
void uart<T>::SET_Clock() {
 
	RCC->APB1LENR |= RCC_APB1LENR_UART4EN;
	RCC->D2CCIP2R &= ~(RCC_D2CCIP2R_USART28SEL);
	RCC->D2CCIP2R |= RCC_D2CCIP2R_USART234578SEL_PLLCLK;
 
}
 
template <class T>
void uart<T>::SET_DMA(T Rx_BUFF, uint32_t length) {
 
	RCC->AHB1ENR &= ~(RCC_AHB1ENR_DMA1EN);
	RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
 
		//Setup DMA
		DMAMUX1_Channel3->CCR &= ~(DMAMUX_CxCR_DMAREQ_ID);
		DMAMUX1_Channel3->CCR |= (DMAMUX_CxCR_DMAREQ_ID_UART4_Rx);
 
		DMA1_Stream3->CR &= ~((DMA_SxCR_CT) |
				 (DMA_SxCR_PL) |
							 (DMA_SxCR_MSIZE) |
							 (DMA_SxCR_PSIZE) |
							 (DMA_SxCR_MINC) |
							 (DMA_SxCR_CIRC) |
							 (DMA_SxCR_DIR) |
							 (DMA_SxCR_PFCTRL)|
							 (DMA_SxCR_TCIE) |
							 (DMA_SxCR_HTIE));
 
		DMA1_Stream3->CR |= (DMA_SxCR_CT_MEM0) |
				 (DMA_SxCR_PL_HIGH) |
							 (DMA_SxCR_MSIZE_8BIT) |
							 (DMA_SxCR_PSIZE_8BIT) |
							 (DMA_SxCR_CIRC) |
							 (DMA_SxCR_DIR_PERI_TO_MEM) |
							 (DMA_SxCR_PFCTRL_DMA_FLOW) |
							 (DMA_SxCR_TCIE);
 
		DMA1_Stream3->NDTR = length;
 
		DMA1_Stream3->PAR = (uint32_t)&UART4->RDR;
		DMA1_Stream3->M0AR = (uint32_t)Rx_BUFF;
 
		DMA1_Stream3->CR |= DMA_SxCR_EN;
}
 
template <class T>
void uart<T>::SET_Interrupt() {
 
	NVIC_EnableIRQ(DMA1_Stream3_IRQn);
	NVIC_SetPriority(DMA1_Stream3_IRQn,1);
}
 
template <class T>
void uart<T>::SET_REG(T Rx_BUFF, uint32_t length) {
 
	SET_Clock();
	SET_GPIO();
	SET_DMA(Rx_BUFF, length);
	SET_Peripheral();
 SET_Interrupt();
}
 
#endif /* PERIPERHALS_HEADER_MIDCLASS_UART_H_ */

 Some function to get the pointer to the buffer

/*
 * audioProcessor.cpp
 *
 * Created on: Jun. 22, 2021
 * Author: Christopher
 */
#include "audioProcessor.h"
 
 	 int audioProcessor::SAI1_A_RxBUFF[4096] = {0};
	 int audioProcessor::SAI1_B_TxBUFF[4096] = {0};
	 int audioProcessor::SAI2_A_TxBUFF[4096] = {0};
	 uint16_t audioProcessor::WS2812B_TxBUFF[1] = {0};
	 uint8_t audioProcessor::UART4_RxBUFF[1] = {0};
 
 	 int * audioProcessor::GET_SAI1_A_RxBUFF() {
		 return SAI1_A_RxBUFF;
	 }
 
	 int * audioProcessor::GET_SAI1_B_TxBUFF() {
	 		 return SAI1_B_TxBUFF;
	 }
 
	 int * audioProcessor::GET_SAI2_A_TxBUFF() {
	 	 return SAI2_A_TxBUFF;
	 }
 
	 uint16_t * audioProcessor::GET_WS2812B_TxBUFF() {
	 	 	 	 return WS2812B_TxBUFF;
	 	 }
 
	 uint8_t * audioProcessor::GET_UART4_RxBUFF() {
	 	 	 return UART4_RxBUFF;
	 }
 
	 uint8_t audioProcessor::GET_volume() {
		 return volume;
	 }
 
	 uint8_t audioProcessor::GET_subVolume() {
	 		 return subVolume;
	 	 }
 
	 double audioProcessor::GET_inputCompensator() {
	 		 return inputCompensator;
	 }
 
 

This topic has been closed for replies.
Best answer by TDK

The linker is looking for "DMA1_Stream3_IRQHandler", but if this function is with in a C++ file, the name it is mangled and so the linker doesn't find it. (It still compiles because there is a weakly defined default handler that it falls back to.)

Enclose the function in extern "C" brackets.

extern "C" {
 
void DMA1_Stream3_IRQHandler() {
 ...
}
 
}

2 replies

TDK
TDKBest answer
June 30, 2021

The linker is looking for "DMA1_Stream3_IRQHandler", but if this function is with in a C++ file, the name it is mangled and so the linker doesn't find it. (It still compiles because there is a weakly defined default handler that it falls back to.)

Enclose the function in extern "C" brackets.

extern "C" {
 
void DMA1_Stream3_IRQHandler() {
 ...
}
 
}

"If you feel a post has answered your question, please click ""Accept as Solution""."
CLeo.1
CLeo.1Author
Senior II
June 30, 2021

YUP! Just found this solution as well and that exact reasoning as to why using it. Thank you