I'm a bit of a novice at programming, but I'm trying to develop an application that sends a continuous stream of data out of the USART using DMA, taking advantage of the DMA Transfer Half-Complete, and Transfer-Complete interrupts.
I've got a circular DMA USART transmission working, but when I enable either of the interrupts, my code goes into an InfiniteLoop: handler.
I'm using a BluePill (STM32F103C8) and writing in VSCode / PlatformIO with the Arduino-ststm32 framework.
I can't figure out how to tell the code where I want it to go when either of these interrupts fire.
I'm doing a lot of this programming "bare-metal" because I don't really know how to determine what core and/or library tools I have available to utilize. I see a lot of examples on the internet, but invariably they are using a different setup (framework etc) than I am, so their code doesn't really port to my IDE.
Help?!
Here is my code (couldn't figure out how to attach it)
#include <Arduino.h>
#include "HardwareSerial.h"
//This program sends a serial stream of data from an STM32F1 BluePill to an ESP32 MCU for display on a web page.
uint8_t to_esp32_buffer[4]; //
HardwareSerial Serial3(PB11,PB10);
void setup() {
Serial.begin(38400);
to_esp32_buffer[0] = 0x00;
to_esp32_buffer[1] = 0x01;
to_esp32_buffer[2] = 0x02;
to_esp32_buffer[3] = 0x03;
RCC->AHBENR |= RCC_AHBENR_DMA1EN; //enable clock for DMA1
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;//enable clock for USART3
NVIC_EnableIRQ(USART3_IRQn); //enable global interrupts from USART3
NVIC_EnableIRQ(DMA1_Channel2_IRQn); //enable global interrupts from DMA1 channel2 (which handles usart3 Tx)
Serial3.begin(600);
USART3->CR1 &= ~USART_CR1_UE; //Disable USART
USART3->CR1 |= USART_CR1_TE; //Transmit enable
USART3->CR1 |= USART_CR1_RE; //Receive enable
USART3->CR3 |= USART_CR3_DMAT; //Set for DMA transfer
//USART3->SR &= ~USART_SR_TC; //Clear the transmission complete bit in the status register
//Initially the CCR register is set to 0x0000 0000 so only non-zero values must be written
//DMA1_Channel1->CCR &= ~DMA_CCR_EN; //disable DMA channel before configuring
DMA1_Channel2->CPAR = (uint32_t) & USART3->DR; //Configure the address of the peripheral
//DMA1_Channel2->CMAR = (uint32_t)msg; //Configure the address of memory
DMA1_Channel2->CMAR = (uint32_t) & to_esp32_buffer; //Configure the address of memory
DMA1_Channel2->CCR &= ~(DMA_CCR_PL_Msk); //Low priority
DMA1_Channel2->CCR &= ~(DMA_CCR_MSIZE_Msk); //Configure "chunk" size 00=8bits, 01=16bits, 10=32bits, 11=reserved
DMA1_Channel2->CCR &= ~(DMA_CCR_PSIZE_Msk); //Configure Peripheral chunk size.
DMA1_Channel2->CCR |= DMA_CCR_MINC; //increment memory address after each byte tranferred
DMA1_Channel2->CCR |= DMA_CCR_DIR; //from memory to peripheral (USART Transmit)
//I don't know how to handle these interrupts (yet)
//DMA1_Channel2->CCR |= DMA_CCR_HTIE; //Enable interrupt when transfer half-complete
//DMA1_Channel2->CCR |= DMA_CCR_TCIE; //Enable interrupt when transfer complete
DMA1_Channel2->CCR |= DMA_CCR_CIRC; //Enable Circular mode (keep repeating)
DMA1_Channel2->CNDTR = 4; //Tell how many chunks (bytes) to transfer
DMA1_Channel2->CCR |= DMA_CCR_EN; //Enable the DMA channel
USART3->CR1 |= USART_CR1_UE; //Enable USART
}
void loop(){
//This is just to prove that the main loop is running
Serial.print("x");
delay(1);
}