2

I am having a strange problem. I have a board with 2 UART interfaces (STM32F217) and I am using DMA to receive the data on both UARTs (USART1 and USART2).

USART2 works perfectly. I can send and receive data through it no problem, but I am having a problem with USART1. It only works properly the first transfer. If it just worked once and then stopped then I'd be ok, since it probably means that I just need to add the function for USART1 interruption and call its IRQHandler But my problem is that the next times it receives the data, but it drops the first few bytes (randomly ... sometimes drops 2 sometimes drops up to 6 bytes and it's not like it's a fast protocol, it has a 1s timeout).

Here is my workflow: - Initialize UART;

  • Call Receive_DMA;

  • Protocol has variable size, it depends on the first bytes so I configured a fixed 256 circular receive transfer (maximum size for header + data) and check how many bytes have been received so far, if the amount matches the first byte then it's ok.

  • After error (did not receive entire packet, wrong CRC or timeout) or success then call

    HAL_UART_DMAStop(&huart1);

and then

if(HAL_UART_Receive_DMA(&huart1, rx232buffer, 256) != HAL_OK) {
    while(1);
}

This is done for both UARTs and one works perfectly and the other works well the first time and then starts dropping bytes.

Any idea of what could be the problem?

EDIT

Here's a version of my code. I wrote the functionality just now (inside main loop ... it's not exactly that but it works similar to that ... my code is kinda big and with many things not related to the communication so I just rewrote it like this ... as stated huart1 only works properly once and then drops bytes ... huart2 works fine .. huart1 is RS232 ... huart2 i RS485)

static void rxbuffer[256] = {0};
static void rx232buffer[256] = {0};

struct header {
    int startWord;
    int command;
    int size;
};

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;

static void MX_DMA_Init(void)
{
    /* DMA controller clock enable */
    __HAL_RCC_DMA2_CLK_ENABLE();
    __HAL_RCC_DMA1_CLK_ENABLE();

    /* DMA interrupt init */
    /* DMA1_Stream5_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
    /* DMA1_Stream6_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
    /* DMA2_Stream2_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
    /* DMA2_Stream7_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}

static void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 57600;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

}

static void MX_USART2_UART_Init(void)
{
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 57600;
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
    huart2.Init.StopBits = UART_STOPBITS_1;
    huart2.Init.Parity = UART_PARITY_NONE;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    if (HAL_UART_Init(&huart2) != HAL_OK)
     {
      _Error_Handler(__FILE__, __LINE__);
     }

}

int main(void)
{
    int bytecount;
    int bytecount232;

    int rxlen485;
    int rxlen232;
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();
    MX_USART2_UART_Init();

    if(HAL_UART_Receive_DMA(&huart2, rxbuffer, 256) != HAL_OK) {
        while(1);
    }

    if(HAL_UART_Receive_DMA(&huart1, rx232buffer, 256) != HAL_OK) {
        while(1);
    }

    while(1) {
        bytecount = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
        rxlen485 = 256 - bytecount;
        bytecount232 = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
        rxlen232 = 256 - bytecount232;

        if(rxlen485 >= sizeof(struct header)) {
            //start timer
            struct header *pHeader = rxbuffer;
            if(pHeader->size == rxlen485 - sizeof(struct header)) {
                //do something
                HAL_UART_DMAStop(&huart2);
                if(HAL_UART_Receive_DMA(&huart2, rxbuffer, 256) != HAL_OK) {
                    while(1);
            }

            if(timeout) { // purely demonstrative ... the timeout part
                //do something
                HAL_UART_DMAStop(&huart2);
                if(HAL_UART_Receive_DMA(&huart2, rxbuffer, 256) != HAL_OK) {
                    while(1);
                }
            }
        }

        if(rxlen232 >= sizeof(struct header)) {
            struct header *pHeader = rxbuffer;
            if(pHeader->size == rxlen232 - sizeof(struct header)) {
                //do something
                HAL_UART_DMAStop(&huart1);
                if(HAL_UART_Receive_DMA(&huart1, rx232buffer, 256) != HAL_OK) {
                    while(1);
                }

                if(timeout) { // purely demonstrative ... the timeout part
                    //do something
                    HAL_UART_DMAStop(&huart1);
                    if(HAL_UART_Receive_DMA(&huart1, rx232buffer, 256) != HAL_OK) {
                        while(1);
                    }
                }
            }
        }
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    __NOP();
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    __NOP();
}

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}






//----- in another file--------
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    PA11     ------> USART1_CTS
    PA12     ------> USART1_RTS 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA2_Stream2;
    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);

    /* USART1_TX Init */
    hdma_usart1_tx.Instance = DMA2_Stream7;
    hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);

  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
  else if(huart->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */

  /* USER CODE END USART2_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();

    /**USART2 GPIO Configuration    
    PD5     ------> USART2_TX
    PD6     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* USART2 DMA Init */
    /* USART2_RX Init */
    hdma_usart2_rx.Instance = DMA1_Stream5;
    hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(huart,hdmarx,hdma_usart2_rx);

    /* USART2_TX Init */
    hdma_usart2_tx.Instance = DMA1_Stream6;
    hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart2_tx.Init.Mode = DMA_NORMAL;
    hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_usart2_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(huart,hdmatx,hdma_usart2_tx);

    HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART2_IRQn);
  }

}
morcillo
  • 1,091
  • 5
  • 19
  • 51
  • 1
    please share more code. – BitShift Mar 13 '19 at 02:50
  • @Medicineman25 At the moment I don't have my code in front of me. But there is nothing special about it and what bothers me is that one UARt works and the other one doesn't. The one that works is via 485 and the other one 232 via SP3232EBEY-L. As soon as I'm in front of my PC I'll post the code – morcillo Mar 13 '19 at 03:00
  • @Medicineman25 Ok, Fortunately I've donde this so many times that I was able to rewrite the important right now and got the configurations I've been using from cubeMx – morcillo Mar 13 '19 at 03:27
  • Awesome!! Just for future, mentioning that one is doing 485 and the other 232 is vital information. – BitShift Mar 13 '19 at 04:30
  • So the only thing 'glaring' issue I can see there is that you have set the NVIC priority for the 2nd USART, but not the 1st. This might be causing you issues. Also, not sure what modem you are talking to, does it require assertion on RTS or CTS that aren't being made? What about your oversampling rate? Have you adjusted that? – BitShift Mar 13 '19 at 06:05
  • Also is it dropping bits at the USART or DMA? Might be good to pipe directly out again to a serial modem and print the output for a quick sanity check. – BitShift Mar 13 '19 at 06:06
  • @Medicineman25 Nice catch ... I'll try fixing that. And the DMA is dropping bits and not the UART. – morcillo Mar 13 '19 at 10:17
  • @Medicineman25 Went to the msp init function, added the priority and same problem. – morcillo Mar 13 '19 at 10:34
  • "if(HAL_UART_Receive_DMA(&huart1, rxbuffer, 256) != HAL_OK)" should that be rx232buffer? It could be timing out and diverting bits to another buffer. – BitShift Mar 13 '19 at 10:40
  • @Medicineman25 Nope. That was a typo, I'm fixing it now. I can see that I'm getting the frame in the correct buffer ... my problem really is that it randomly drops the first byte(s) ... First time -> full packet ... next time times ... packet - 1 byte .... packet - 4 bytes .. etc .. I'll keep on working on it but I think I'll have to change my approach – morcillo Mar 13 '19 at 10:49
  • Did you find any solution to this? I have a similar issue and searching for a solution. – Guray Gurkan May 09 '21 at 20:16

0 Answers0