I have an ADC set up with DMA to fill a buffer in circular mode. I've verified with the debugger that this buffer is being filled with the expected data.
I am using a FreeRTOS task to send this data over UART based on the interrupts provided by the DMA functionality. When the buffer is half full, I send the first half; when the buffer is full, I send the second half.
I am using a Nucleo L476RG.
Here is my code:
#include "ADC.hpp"
#include <string.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "main.h"
#include "utils/print.hpp"
#include "stm32l4xx_hal.h"
extern ADC_HandleTypeDef hadc3;
extern UART_HandleTypeDef huart2;
extern volatile SemaphoreHandle_t print_lock;
namespace ADC
{
volatile SemaphoreHandle_t adc_lock;
volatile uint16_t adc_buf[ADC_BUF_SIZE];
volatile uint8_t buf[] = "abcdefg\r\n";
void task(void *arg)
{
adc_lock = xSemaphoreCreateBinary();
HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_buf, ADC_BUF_SIZE);
HAL_StatusTypeDef result;
uint16_t offset = ADC_BUF_SIZE >> 1;
while (1)
{
xSemaphoreTake(adc_lock, HAL_MAX_DELAY);
offset = (offset + (ADC_BUF_SIZE >> 1)) % ADC_BUF_SIZE;
xSemaphoreTake(print_lock, HAL_MAX_DELAY);
while ((result = HAL_UART_Transmit(&huart2, (uint8_t *)adc_buf+offset*2, ADC_BUF_SIZE, HAL_MAX_DELAY)) == HAL_BUSY) {}
xSemaphoreGive(print_lock);
}
vTaskDelete(nullptr);
}
} // namespace ADC
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
xSemaphoreGiveFromISR(ADC::adc_lock, nullptr);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
xSemaphoreGiveFromISR(ADC::adc_lock, nullptr);
}
Here is a screenshot from the debugger showing correct data in adc_buf
When looking at the received data using screen /dev/ttyACM0 115200, then converting to hex using vscode, this is what is received. I have already verified that the baudrate is correct.
I've tried adding a buffer with a long string message and sending that over and over, and it is sent and received correctly. Only data from the DMA buffer is being sent as 0xFD rather than the correct bytes. All other data is sent and received correctly.
Here are the settings for the UART and the ADC/DMA.





screen /dev/ttyACM0 115200, then converting to hex using vscode," -- If you instead used a better tool such as minicom (in hex display mode), then you can skip that conversion step. Since you're reading from "/dev/ttyACM0", then you are not reading from a "UART" on the PC end, but rather have a USB-to-USB connection using CDC ACM (which tries to emulate an RS-232 link). But if you're actually sending from USART2 on the Nucleo, then you're probably reading the wrong device on the PC. IOW a USB-to-UART adapter on the PC would be named /dev/ttyUSB0ttyACM0?