STM32 UART receive not functioning as normal

9.2k views Asked by At

I've spent the whole day and tonight trying to work out why my receive functions aren't working. When I started the project initially it was fine (this was a couple days ago). I've since worked on it more and now it will not work.

I've even now created a new project on CubeMX with only jtag and uart5 set up and still no receive functions work. I can confirm the board works fine with much older projects I have worked on.

I believe something is happening during the build process but I can't figure it out.

I'm using an STM32F207 chip.

Below is the very basic program I've put together to test the UART functionality. I can transmit perfectly fine, its just that no receive functions work.

I've even added the simple "HAL_UART_Receive()" in my main loop with a long timeout and it completely skips the whole function!

I've forced the activation of the UART interrupts too and that hasn't done anything.

I restored this project earlier today with a previous commit and the build ran fine for a bit. Then it stopped working again after a compile. I tried to restore it again and the second time it did nothing to solve the issue.

When sending data to the MCU the RXNE flag is triggered and the data register gets changed, not to anything remotely that is being sent however.

I'm running out of ideas!

Main.c:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f2xx_hal.h"
#include "usart.h"
#include "gpio.h"
#include "string.h"

/* Private variables ---------------------------------------------------------*/

extern uint8_t pc_uart_receive_flag;
extern char pc_buff[8];

char sys_ready[] = "UART Transmit test\r\n";

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/**
  * @brief  The application entry point.
  *
  * @retval None
  */
int main(void)
{

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();


  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_UART5_Init();

  /*
   * FORCING THESE ACTIVE AND STILL NOTHING
   */
  /* UART5 interrupt Init */
  HAL_NVIC_SetPriority(UART5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(UART5_IRQn);

  HAL_UART_Transmit_IT(&huart5, (uint8_t*)sys_ready, strlen(sys_ready));

  /* Infinite loop */
  while (1)
  {


      /*
       * NOT EVEN THIS WORKS!
       */
      HAL_UART_Receive(&huart5, (uint8_t*)pc_buff, strlen(pc_buff), 100000);

      //PC receive flag
      if(pc_uart_receive_flag==1){

            /*
             * BEGIN DEBUG
             */

            HAL_UART_Transmit_IT(&huart5, (uint8_t*)pc_buff, strlen(pc_buff)); // Return value that is saved

            /*
             * END DEBUG
             */

            pc_uart_receive_flag=0; // Reset flag

        }

  }

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  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_0) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}


/**
  * @brief  This function is executed in case of error occurrence.
  * @param  file: The file name as string.
  * @param  line: The line in file as a number.
  * @retval None
  */
void _Error_Handler(char *file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

usart.c:

/* Includes ------------------------------------------------------------------*/
#include "usart.h"

#include "gpio.h"

UART_HandleTypeDef huart5;

/* UART5 init function */
void MX_UART5_Init(void)
{

  huart5.Instance = UART5;
  huart5.Init.BaudRate = 115200;
  huart5.Init.WordLength = UART_WORDLENGTH_8B;
  huart5.Init.StopBits = UART_STOPBITS_1;
  huart5.Init.Parity = UART_PARITY_NONE;
  huart5.Init.Mode = UART_MODE_TX_RX;
  huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart5.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart5) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(uartHandle->Instance==UART5)
  {
    /* UART5 clock enable */
    __HAL_RCC_UART5_CLK_ENABLE();

    /**UART5 GPIO Configuration    
    PC12     ------> UART5_TX
    PD2     ------> UART5_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* UART5 interrupt Init */
    HAL_NVIC_SetPriority(UART5_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(UART5_IRQn);
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==UART5)
  {
    /* Peripheral clock disable */
    __HAL_RCC_UART5_CLK_DISABLE();

    /**UART5 GPIO Configuration    
    PC12     ------> UART5_TX
    PD2     ------> UART5_RX 
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12);

    HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);

    /* UART5 interrupt Deinit */
    HAL_NVIC_DisableIRQ(UART5_IRQn);
  }
}

stm32f2xx_it.c (interrupts):

/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx_hal.h"
#include "stm32f2xx.h"
#include "stm32f2xx_it.h"
#include "string.h"

/* External variables --------------------------------------------------------*/
extern UART_HandleTypeDef huart5;


uint16_t pc_uart_receive_flag=0;
char pc_buff[8];

/******************************************************************************/
/*            Cortex-M3 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
}

/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
  while (1)
  {
  }
}

/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
  while (1)
  {
  }
}

/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
  while (1)
  {
  }
}

/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
  while (1)
  {
  }
}

/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
}

/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
}

/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
}

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
}

/******************************************************************************/
/* STM32F2xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f2xx.s).                    */
/******************************************************************************/

/**
* @brief This function handles UART5 global interrupt.
*/
void UART5_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart5);

  HAL_UART_Receive_IT(&huart5, (uint8_t*) pc_buff, strlen(pc_buff));

}


/**
* @brief This function handles the callback for the UART channels.
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){


    // Callback triggered by UART5
    if (huart->Instance == UART5){
        pc_uart_receive_flag=1;
    }
}
1

There are 1 answers

1
Alex_embedded On

So! After much head scratching I have found a solution that works! It may not be the "best" way but it is a way that works and that I'm sure should be fine for the project I am doing. In my ISR file (stm32f2xx_it.c") I now have:

/**
* @brief This function handles UART5 global interrupt.
*/
void UART5_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart5);


  if(HAL_UART_Receive_IT(&huart5, (uint8_t*) pc_buff, PC_BUFF_LENGTH)==HAL_BUSY){

      // Add some sort of flag in this process for errors
  }

}


/**
* @brief This function handles the callback for the UART channels.
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){


    // Callback triggered by UART5
    if (huart->Instance == UART5){
        pc_uart_receive_flag=1;
    }
}

This is assuming that data is coming in by checking for "HAL_BUSY" in the if statement. I feel like as I great more confident with embedded programming I can better implement UART ISR's. Until then I will work with what I know.