cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L051 UART Frame error

VNong
Associate II

Hi,

i have some troubles with UART receive, unfortunately I had no explanation. I am new with STM32 MCU. Here is the issue:

  • The communication was working fine after power on, until the MCU access the EEPROM or when I tried to pause in debug mode. After that's, the framing error status is set permanently. Reset the MCU then it works again.

Here are my initial uart and received ISR code

GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* Enable clock */
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /* Init TX, RX Pins alternate function */
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = IOL_RX_GPIO_AF;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = GPIO_PIN_6;    
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = IOL_TX_GPIO_AF;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    uint32_t tmpreg = 0;
    tmpreg = USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
    USART1->CR1 = tmpreg;
      
    uint16_t usartdiv = (uint16_t)(SystemCoreClock/230400);
    USART1->BRR = usartdiv;
 
    USART1->CR3 |= USART_CR3_OVRDIS | USART_CR3_ONEBIT;
    
    uint32_t status = USART1->ISR;
    USART1->ICR = status;
    status = USART1->RDR;
    USART1->CR1 |= USART_CR1_UE;
    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
void USART1_IRQHandler(void)
{
    uint32_t status = 0;  
    uint8_t ui8_usart_data = 0;
    if(USART1->ISR & USART_ISR_RXNE)
    {
        /* Framing error and parity error */    
        status = USART1->ISR & 0xF;
        ui8_usart_data = USART1->RDR; 
        if(status)
        {
            USART1->ICR = status;      
        }                       
        CallbackReceivedInterrupt(ui8_usart_data, (uint8_t)status);
    }
}

Can someone pls explain me this issue or maybe i forgot a uart settings?

I already read some threads. Someone say that the ISR callback function should not be long. I think my callback funtion is not long, cause it always work after power on. I only ported the software to this new MCU STM32L051. The software works fine with other MCUs (in 4 different MCUs) and I did not see this issue in other MCU. I also did not access the EEPROM inside the callback function.

I appreciate for any ideas and thanks in advance!

Best regards

5 REPLIES 5
TDK
Guru

A framing error indicates the signal coming in is not as expected. Verify the clock configuration. Look at signal on a scope and correlate FE bit to incoming data frame.

Internal HSI clocks are not terribly accurate. Use a crystal instead and verify your clock tolerance is sufficient on both sides.

It's unlikely to be directly related to EEPROM access.

If you feel a post has answered your question, please click "Accept as Solution".

>>After that's, the framing error status is set permanently. 

I'd imagine the Reference Manual specifically describes how you're supposed to clear this, and other conditions like parity or noise errors.

  if (USART1->ISR & USART_ISR_ORE) // Overrun Error
    USART1->ICR = USART_ICR_ORECF;
  if (USART1->ISR & USART_ISR_NE) // Noise Error
    USART1->ICR = USART_ICR_NCF;
  if (USART1->ISR & USART_ISR_FE) // Framing Error
    USART1->ICR = USART_ICR_FECF;

If these occur continuously, perhaps look at the quality of the signalling, if the baud rates match, that the signal is not inverted, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
VNong
Associate II

Sorry for the late reply and thanks for your advices.

Last day I tried with different settings of Clock and with external crystal 18.432MHz (PLL, without PLL), my board and nucleo board. But the same issue occurs.

Additional to my application: I am porting the IO-Link device application to my board STM32L051C8 and IO-Link driver L6362ATR. I also have the Nucleo-L053R8 board and the Steval-IOD003V1 board.

Background of IO-Link and IO-Link Driver: what we send on USART-TX pin, we will receive them on RX Pin. And the firmware use only receive interrupt. The IO-Link master sends cyclic messages to my device, to read the device identification, to change communication mode....The baudrate is 230.4kBaud.

Everything works fine at power on. The IO-Link master recognizes my devices, the communication is fine. At this moment if I read the parameter in IO-Link Master Tool or if I save paramter in EEPROM, the communication will be terminated cause frame error occurs. The IO-Link Master tries to build the communication again but unsuccessful. It's strange because in debug I see that not all receive bytes are error. The Master communicates with the device until frame error occurs and then try the master again from beginning.

I also saw the signal under scope, baudrate is fine, the scope can decode the USART signal and I saw the data were all correct.

The same issue occurs in nucleo board and my board, Nucleo Board does not have external crystal, but my board has 18.432MHz.

I don't know which settings I have to look at now.

Following are my code again for inital clock, usart and IRQ Handler. I used PLL to make a 24.576MHz clock, and USART1 use APB clock.

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enables the Clock Security System
  */
  HAL_RCC_EnableCSS();
}
void MX_USART1_UART_Init(void)
 
{
 
   GPIO_InitTypeDef GPIO_InitStruct = {0};   
 
  __HAL_RCC_USART1_CLK_ENABLE();
 
  IOL_RX_PORT_RCC_ENABLE();
 
  IOL_TX_PORT_RCC_ENABLE();
 
   /* Init TX, RX Pins alternate function */
 
  GPIO_InitStruct.Pin = IOL_RX_PIN;
 
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 
  GPIO_InitStruct.Pull = GPIO_PULLUP;
 
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
 
  GPIO_InitStruct.Alternate = IOL_RX_GPIO_AF;
 
  HAL_GPIO_Init(IOL_RX_PORT, &GPIO_InitStruct);
 
   
 
  GPIO_InitStruct.Pin = IOL_TX_PIN;   
 
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 
  GPIO_InitStruct.Pull = GPIO_PULLUP;
 
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
 
  GPIO_InitStruct.Alternate = IOL_TX_GPIO_AF;
 
  HAL_GPIO_Init(IOL_TX_PORT, &GPIO_InitStruct);
 
   
 
   uint32_t tmpreg = USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
 
  USART1->CR1 = tmpreg;
 
  USART1->CR2 = 0;  
 
  uint16_t usartdiv = (uint16_t)(24576000UL/230400UL);
 
  USART1->BRR = usartdiv; 
 
  USART1->CR3 = 0;
 
  USART1->CR3 |= USART_CR3_ONEBIT;
 
   
 
  HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
 
  HAL_NVIC_EnableIRQ(USART1_IRQn);
 
  USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF | USART_ICR_PECF;
 
  USART1->RQR = USART_RQR_RXFRQ;
 
  USART1->RQR = USART_RQR_TXFRQ;
 
  USART1->CR1 |= USART_CR1_UE;  
 
}
 
void USART1_IRQHandler(void)
{
    uint32_t isr_reg = USART1->ISR;
    uint32_t status = 0;   
    uint32_t ui8_usart_data = 0;
    status = isr_reg & 0xF;  
    if(isr_reg & USART_ISR_RXNE)
    {
          if(status)
          {    
               USART1->RQR = USART_RQR_RXFRQ;
//               USART1->ICR = status;
               idx = 0;
              if(isr_reg & USART_ISR_PE)
              {
                  USART1->ICR = USART_ICR_PECF;
                  _ParErr_Count++;
              }
              if(isr_reg & USART_ISR_FE)
              {
                  USART1->ICR = USART_ICR_FECF;
                  _frameErr_Count++;
              }
              if(isr_reg & USART_ISR_NE)
              {
                  USART1->ICR = USART_ICR_NCF;
                  _NoiseErr_Count++;
              }
              if(isr_reg & USART_ISR_ORE)
              {
                  USART1->ICR = USART_ICR_ORECF;
                  _OverFlowErr_Count++;
              }
          } 
          else
          {       
            ui8_usart_data = USART1->RDR; 
          }
        uart_buf[idx++] = ui8_usart_data;
        if(idx >= 256)
            idx = 0;
        ReceivebytesCallbackFunction((uint8_t)ui8_usart_data, (uint8_t)status);
    }
}

Aniket
Associate II

well i am no expert , but i guess clearing the fe flag using  __HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_FE); // Clear the error flag might work , 

in ur case huart1