How can I resolve UART transmission errors on my STM32F407VGT6 MCU during rapid string transmission?

Good day everyone @Middleware & OS , I have an objective to transmit a string ("test123") 10 times as fast as possible through UART in interrupt mode utilizing an STM32F407VGT6 MCU on STM32CubeIDE, but I am facing problems. Despite the initial successful transmission, the code eventually encounters an unacceptable scenario where it falls into the Error_Handler(). Though implementing delays between each transmission guarantees that all strings are transferred successfully, I desire to comprehend why this accomplishment cannot be attained without incorporating any delay. What might be causing the issue with transmitting the strings without delays, and how can I fix it? Here's an attachment of my code.
6 Replies
UC GEE
UC GEE5mo ago
The issue seems to be that you're trying to start a new transmission before the previous one has completed, which is why adding a delay works. The key is to ensure that the transmission is complete before starting a new one. Your approach to wait for the transmission to complete is correct, but it might not be working as intended because the flagTxCmpltUsart flag is reset immediately after starting the transmission. Try modifying your code to only reset the flag within the callback function. This ensures the flag correctly reflects the completion status of the transmission. Here's the modified code:
uint8_t TxData[] = "test123\n";
bool flagTxCmpltUsart = true;

for(int i = 0; i < 10; i++) {
if(HAL_UART_Transmit_IT(&huart3, TxData, strlen(TxData)) != HAL_OK) {
Error_Handler();
}
Wait_Unit_Uart_Tx_Is_Complete();
}

void Wait_Unit_Uart_Tx_Is_Complete(void) {
while(!flagTxCmpltUsart) {}
flagTxCmpltUsart = false;
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if(huart->Instance == USART3) {
flagTxCmpltUsart = true;
}
}
uint8_t TxData[] = "test123\n";
bool flagTxCmpltUsart = true;

for(int i = 0; i < 10; i++) {
if(HAL_UART_Transmit_IT(&huart3, TxData, strlen(TxData)) != HAL_OK) {
Error_Handler();
}
Wait_Unit_Uart_Tx_Is_Complete();
}

void Wait_Unit_Uart_Tx_Is_Complete(void) {
while(!flagTxCmpltUsart) {}
flagTxCmpltUsart = false;
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if(huart->Instance == USART3) {
flagTxCmpltUsart = true;
}
}
@Sterling
Sterling
Sterling5mo ago
Hmmm, that makes sense. So, the flag should only be reset once the transmission is confirmed to be complete within the callback. I'll try this out.
Sterling
Sterling5mo ago
But what if I want to improve the efficiency further? Is there a way to handle this without busy-waiting in the Wait_Unit_Uart_Tx_Is_Complete() function? @UC GEE
UC GEE
UC GEE5mo ago
Yes @Sterling , you can further improve efficiency by using a more event-driven approach, such as implementing a queue for the strings you want to send and transmitting the next string in the callback function once the current transmission completes. This way, the MCU can perform other tasks while waiting for UART transmissions to complete. Here's an example modification:
uint8_t TxData[] = "test123\n";
int currentStringIndex = 0;
int totalStrings = 10;

void StartNextTransmission(void) {
if(currentStringIndex < totalStrings) {
if(HAL_UART_Transmit_IT(&huart3, TxData, strlen(TxData)) != HAL_OK) {
Error_Handler();
}
currentStringIndex++;
}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if(huart->Instance == USART3) {
StartNextTransmission();
}
}

int main(void) {
// Initial setup
StartNextTransmission();
while(1) {
// Other tasks can be performed here
}
}
uint8_t TxData[] = "test123\n";
int currentStringIndex = 0;
int totalStrings = 10;

void StartNextTransmission(void) {
if(currentStringIndex < totalStrings) {
if(HAL_UART_Transmit_IT(&huart3, TxData, strlen(TxData)) != HAL_OK) {
Error_Handler();
}
currentStringIndex++;
}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if(huart->Instance == USART3) {
StartNextTransmission();
}
}

int main(void) {
// Initial setup
StartNextTransmission();
while(1) {
// Other tasks can be performed here
}
}
In this approach, StartNextTransmission() is called in the main function to initiate the first transmission, and subsequent transmissions are triggered within the callback function.
Sterling
Sterling5mo ago
Oh wow, thanks very much @UC GEE 🙏
Want results from more Discord servers?
Add your server