0
\$\begingroup\$

I am writing a very simple program to validate that my board (STM32L4) can receive terminal (TeraTerm) characters via interrupt. The program runs as expected for the first few seconds (anywhere between 3 and 6 seconds). If I enter keystrokes into TeraTerm, the program prints both "yo" and "hi" after each second expires, until the 3 to 6 seconds are up. After this, it only prints "yo". Here is my code:

/*variable decl
volatile bool flag1 = false;
volatile bool flag2 = false;
volatile bool flag3 = false;
volatile static uint8_t c;
volatile static uint32_t isr_reg;

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  
  /* Configure the system clock to 80 MHz */
  SystemClock_Config();

  /* Initialize LED */
  BSP_LED_Init(LED2);
  Console_UART_Init();

  NVIC_SetPriority(USART1_IRQn, 0);
  NVIC_EnableIRQ(USART1_IRQn);

  SET_BIT(console_uart.Instance->CR1, USART_CR1_UESM);
  SET_BIT(console_uart.Instance->CR1, USART_CR1_PEIE);

  printf("\r\n");

  while (true) {
      printf("yo\r\n");

      BSP_LED_On(LED2);
      if (flag1 == true) {
          printf("hi\r\n");
          flag1 = false;
          BSP_LED_Off(LED2);
      }
      if (flag2 == true) {
          printf("hola\r\n");
          flag2 = false;
      }
      if (flag3 == true) {
          printf("error\r\n");
          flag3 = false;
      }
      HAL_Delay(1000);
  }
}

static void Console_UART_Init(void)
{
  console_uart.Instance = USART1;
  console_uart.Init.BaudRate = 115200;
  console_uart.Init.WordLength = UART_WORDLENGTH_8B;
  console_uart.Init.StopBits = UART_STOPBITS_2;
  console_uart.Init.Parity = UART_PARITY_NONE;
  console_uart.Init.Mode = UART_MODE_TX_RX;
  console_uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  console_uart.Init.OverSampling = UART_OVERSAMPLING_16;
#ifdef UART_ONE_BIT_SAMPLE_DISABLE
  console_uart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  console_uart.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

  #endif


  if (HAL_UART_Init(&console_uart) != HAL_OK)
  {
      while(1);
  }

}

void USART1_IRQHandler(void)  {    

    /* USER CODE END USART3_IRQn 0 */

  isr_reg = console_uart.Instance->ISR;

  if (isr_reg & USART_ISR_RXNE_Msk ) {
        flag1 = true;
        c = console_uart.Instance->RDR;
  }
  if (isr_reg & USART_ISR_ORE_Msk) {
      flag2 = true;
    console_uart.Instance->ICR |= USART_ICR_ORECF;

  }
  if (isr_reg & USART_ISR_PE_Msk) {
    flag3=true;
  }


  return;

    /* USER CODE BEGIN USART3_IRQn 1 */
    /* USER CODE END USART3_IRQn 1 */ 

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uint8_t c;
    if (huart == &console_uart)
    {
        flag2 = true;
    }
}

I have tried adjusting the loop interval to make sure that this issue is a function of time, not # of repetitions, and this has shown to be true. IE, when the HAL_Delay in my code is set to 100ms instead of 1000ms, the "hi" is printed 10x more during the first few seconds.

I have also tried observing the UART ISR flags in the debugger, and it looks like, after the first few seconds of ideal behavior, the RXNEIE bit stays set, but the RXNE flag never gets set (ISR doesn't get called either). This would lead me to believe that the issue lies with Teraterm, not my program, but I also know that observing interrupt-driven behavior on the debugger isn't always reliable.

Once more, the problem is that my program runs successfully for the first 3-6 seconds, then RX interrupts stop working. I am truly baffled as to what could be causing this problem. Any help/pointers would be appreciated!

\$\endgroup\$
10
  • \$\begingroup\$ I should also add that __HAL_UART_ENABLE_IT(&console_uart, UART_IT_RXNE); is called in HAL_UART_MspInit() \$\endgroup\$
    – will
    Commented Dec 31, 2020 at 10:20
  • \$\begingroup\$ You should check the first answer of electronics.stackexchange.com/questions/224714/… You might have a UART error that needs to be cleared. \$\endgroup\$
    – Damien
    Commented Dec 31, 2020 at 10:26
  • \$\begingroup\$ It makes no sense to enable parity error interrupts if parity is set to none. What else the code is doing? Any timers running in background, or any other interrupts? \$\endgroup\$
    – Justme
    Commented Dec 31, 2020 at 10:47
  • \$\begingroup\$ How exactly have you connected your STM32 board to whatever box is running Teraterm? \$\endgroup\$ Commented Dec 31, 2020 at 16:49
  • \$\begingroup\$ I'm not familiar with this processor, but you could be nesting interrupts to the point that your stack overflows. You might try disabling interrupts when you enter the UART ISR and re-enable just before exiting to reduce the possibility of reception of additional interrupts while you are servicing an earlier one. Some processors have a stack overflow interrupt that you could use to help troubleshoot. \$\endgroup\$ Commented Dec 31, 2020 at 17:13

1 Answer 1

1
\$\begingroup\$

Update: the problem was related to my PC turning off USB ports to conserve power. I fixed it by disabling this feature in Device Manager

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.