0

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

enter image description here

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.

enter image description here

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.

enter image description here enter image description here enter image description here

2
  • 2
    "... the received data using 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/ttyUSB0 Commented Jul 9, 2022 at 23:02
  • Switching to minicom fixed it! Post this as an answer and I'll accept ;). It's being sent from the USB-A port on the nucleo, so maybe that's why it's ttyACM0? Commented Jul 9, 2022 at 23:32

1 Answer 1

2

When looking at the received data using screen /dev/ttyACM0 115200, then converting to hex using vscode, this is what is received.

Rather than perform an extra conversion step, suggest that you use a better tool such as minicom, which has a built-in hex display mode.


Addendum

Switching to minicom fixed it!

So apparently there's an issue when you perform the conversion "using vscode".

This result is consistent with your other testing of "adding a buffer with a long string message and sending that over and over, and it is sent and received correctly."
In hindsight, the next step in your testing could have been to perform the same conversion "using vscode" on this text data. Presumably you would not get the expected ASCII code values, and would then suspect that this conversion step was faulty.

It's being sent from the USB-A port on the Nucleo, so maybe that's why it's ttyACM0?

Yes. That is a USB-to-USB connection using CDC ACM, a protocol that can be used for emulating serial ports over USB. The PC is the USB host (as always), and the Nucleo board is a USB gadget implementing a virtual COM port.

There is no (actual) UART or USART involved with such a USB connection, so you are not "send[ing] this data over UART", nor is the USART2 Mode and Configuration relevant.
When your Nucleo program uses the HAL to access the huart2 pseudo-device, apparently this third "UART" is the virtual COM port using the USB connection. Assuming that the huart2 pseudo-device refers to the third USART device, USART2, is incorrect.

Sign up to request clarification or add additional context in comments.

3 Comments

I did in fact perform the same conversion on the received ASCII values "using vscode" before posting this and got the expected result. You can also see ASCII values in the vscode screenshot which I saw using screen but not using minicom.
Please try to be more respectful in your answers on here. I do not appreciate the condescension.
@alexanderd5398 -- No disrespect or condescension is/was intended. It's a blunt writing style. Sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.