2021-06-30 01:23 PM
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.
For 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;
}
Solved! Go to Solution.
2021-06-30 01:35 PM
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() {
...
}
}
2021-06-30 01:35 PM
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() {
...
}
}
2021-06-30 01:39 PM
YUP! Just found this solution as well and that exact reasoning as to why using it. Thank you