2022-06-30 07:59 AM
Hello!
I'm working this UART+DMA with idle detection and ring buffer. My STM32F4707VET6 receives data from a sensor and then sends it by USB, the data received by USB should look like this:
$1651500,-5,-228,-988,-3,-217,-976,-102
$1651510,-4,-228,-987,-3,-216,-975,-105
$1651520,-6,-229,-988,-5,-217,-976,-114
$1651530,-5,-229,-987,-4,-217,-975,-110
$1651540,-6,-227,-987,-5,-215,-975,-129
$1651550,-6,-229,-988,-4,-218,-976,-119
But I receive this:
$1651500,-5,-228,-988,-3,-217,-976,-102
$1651510,-4,-228,-987,-3,-216,-975,-105
$1651520,-6,-229,-988,-5,-217,-976,-114
-987,-3,-216,-975,-105
$1651520,-6,-229,-988,-5,-217,-976,-114
$1651530,-5,-229,-987,-4,-217,-975,-110
$1651510,-4,-228,-987,-3,-216,-975,-105
$1651520,-6,-229,-988,-5,-217,-976,-114
I truncated the data because every sample is around 250-300 characters(variable), 50 samples every second at 115200 baudrate. And I checked that the sensor sends its data properly.
I wonder what may be causing this problem. I think maybe is some type of data I'm using on my code but I can't find it.
This is my ring buffer or callback snippet. I post this code because this is how my STM32 receives(possible the problem is here) and sends data:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
// Timer and RX indicator LEDs
__HAL_TIM_SetCounter(&htim2, 0); // Reset Timer2
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); // Turn on LED 2 - UART Rx LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); // Turn off LED 3 - Timer LED
if(huart->Instance == USART1){ // In USART 1
static uint8_t old_pos1 = 0;
uint8_t *ptemp1;
uint32_t i;
// Ring buffer management
if (Size != old_pos1){ // If buffer changed
if (Size > old_pos1){
ReceivedChars1 = Size - old_pos1;
for (i = 0; i < ReceivedChars1; i++){
pBufferReadyForUser1[i] = RXBufferUser1[old_pos1 + i];
}
}else{ // Buffer overflows
ReceivedChars1 = RX_BUFFER_SIZE - old_pos1;
for (i = 0; i < ReceivedChars1; i++){
pBufferReadyForUser1[i] = RXBufferUser1[old_pos1 + i];
}
if (Size > 0){
for (i = 0; i < Size; i++){
pBufferReadyForUser1[ReceivedChars1 + i] = RXBufferUser1[i];
}
ReceivedChars1 += Size;
}
}
// User data process and buffer & pointers update
UserDataTreatment(huart, pBufferReadyForUser1, ReceivedChars1);
ptemp1 = pBufferReadyForUser1;
pBufferReadyForUser1 = pBufferReadyForReception1;
pBufferReadyForReception1 = ptemp1;
}
// Buffer position(pointer) update
old_pos1 = Size;
}
// Turn off Rx indicator LED
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); // Turn off LED 2 - UART Rx LED
}
And my user data treatment function, once the data is received it sends by USB:
void UserDataTreatment(UART_HandleTypeDef *huart, uint8_t* pData, uint16_t Size){
if(huart->Instance == USART1){ // If USART1
__HAL_TIM_SetCounter(&htim2, 0); // Reset Timer2
CDC_Transmit_FS(pData, Size); // Send USB data
}
}
I'm using the example from: https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM32446E-Nucleo/Examples/UART/UART_ReceptionToIdle_CircularDMA
I also added some features like activity LEDs and a timer to send a special message if no UART messages are received in a few seconds, but I think they are not relevant in the problem. Anyways, tell me to upload them If you think you need them.
Thank you!
2022-06-30 08:07 AM
You say Send, and then show Rx code. Not really looking to unpack the logic of others code/implementations.
For Tx, you'd need to be aware that the buffer can be changed whilst the DMA is active, so typically one uses a ping-pong buffer, or locks the active buffer, and release/reuse only when completed. DMA IRQs can service the HT (Half Transfer) and TC (Transfer Complete) interrupts.
For Rx, watch for the data being "volatile", as it is changed outside of program flow/execution, and beyond the view of the processor.
2022-06-30 08:24 AM
Sorry, because I'm echoing data maybe my choice of words wasn't good. I posted the Rx because possibly the problem is there in how I receive and prepare the data to be sent. The Tx part is very simple and relies on the Rx.
Thank you for your answer! I will try the volatile data and then lock the active buffer.