cancel
Showing results for 
Search instead for 
Did you mean: 

huart2 died on reception and needs repower

ICohe.1
Associate III

F4 board (Master) with huart1 & huart2 identically configured, talking to 2 identical boards(Slaves) with the same program. huart1 works perfectly, huart2 dies after receiving from slave.

Sequence:

Master sends 6 chars ( 9600) using HAL_UART_Transmit_IT() and slave answer with 20 chars repeatedly. Works fine when tested with huart1(on PB6,PB7).

Connecting the same slave to huart2(on PA2,PA3) instead, Master sends, slave received, slave answer with 20 chars, then Master try to send again but nothing coming out on the wire.

HAL_UART_Transmit_IT() still generate a call to HAL_UART_TxCpltCallback() but nothing is out.

The only way to get this single transaction again is to repower the Master.

The program do not even try to receive. No call to any IRQ or polling reception function. If I disconnect the Master's RX wire, it can transmit again (but useless without the slaves answer) .

Settings are identical for both huarts and done with QubeIDE.

Here is the simple program I use

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	__NOP();
}
 
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
	__NOP();
}
 
 
 
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
	__NOP();
}
 
UART_HandleTypeDef *uartUsed;
 
int main(void)
{
  HAL_Init();
 
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  MX_RTC_Init();
  MX_USART2_UART_Init();
  MX_USART6_UART_Init();
  MX_TIM1_Init();
 
  uartUsed=&huart2;
 
  while (1)
  {
		  HAL_Delay(1000);
		 HAL_UART_Transmit_IT(uartUsed,txBuffCmd,6); 
 }
 
static void MX_USART1_UART_Init(void)
{
 
  /* USER CODE BEGIN USART1_Init 0 */
 
  /* USER CODE END USART1_Init 0 */
 
  /* USER CODE BEGIN USART1_Init 1 */
 
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  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();
  }
  /* USER CODE BEGIN USART1_Init 2 */
 
  /* USER CODE END USART1_Init 2 */
 
}
 
/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{
 
  /* USER CODE BEGIN USART2_Init 0 */
 
  /* USER CODE END USART2_Init 0 */
 
  /* USER CODE BEGIN USART2_Init 1 */
 
  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 9600;
  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();
  }
  /* USER CODE BEGIN USART2_Init 2 */
 
  /* USER CODE END USART2_Init 2 */
 
}

11 REPLIES 11

> F4 board

What board is it? Is it a Nucleo or Disco? Isn't PA2/PA3 connected to something else on the board, e.g. STLink's VCP pins?

JW

ICohe.1
Associate III

it is a custom board. PA2/PA3 on Master are connected to PA10/PA9 on slave (F042) through 2X100R resistors. and a 30 cm flat cable

PIN ---- 100R----Cable-----100R----PIN

I don't use Cube/HAL, but you always can read out the USART (and maybe relevant GPIO) registers and check/compare to working case.

JW

ICohe.1
Associate III

Right. I could not see any different in the uart registers. It is not the same as there is no diff. Wondering if it is electric latch up. Because the only way to get it send again is turning it off and on again. Is there any constructural different between uart1 and uart2 ?

Piranha
Chief II

> Wondering if it is electric latch up. Because the only way to get it send again is turning it off and on again.

Stop wondering and write normal register based code at least for a test. Basic USART implementation takes only a few lines of code! There is a 99% chance that you'll see that the hardware works and the problem is caused by HAL/Cube non-working bloatware.

I don't think there are differences in hardware. There's one minor, i.e. that USART1 is on APB2 whereas USART2 is on APB1 (you did not tell us which F4 exactly do you use, but most if not all of them have this); but I don't see any possible mechanism where this would make any significant difference.

You've observed the Tx line using oscilloscope, I presume, and you've have verified that the code went through the instructions which actually write to USART data register.

If you use interrupts, I presume you've checked they stay enabled both in USART and NVIC.

If you can't see anything obvious in the UART and GPIO registers (which you might've posted for us to check), I'd say the problem may quite well be in Cube/HAL. You can try to debug Cube/HAL, observing its variables and states; or you can get rid of it and rewrite your code with direct register access.

JW

ICohe.1
Associate III

It is an STM32F401RET6. Didn't use scope but USB-Serial adapter connected to the Rx/Tx lines of the cable and terminal software on the PC.

When cable is connected to uart1 , I can see Master to slave transmission. then slave to master transmission and again -never stop.

When changing the code to use uart2 (I also moved the cable to the uart2 connector) I can see: Master to slave, then slave to master and then eveything stopps.

Master still execute HAL_UART_Transmit_IT(uartUsed,txBuffCmd,6); and even the HAL_UART_TxCpltCallback() is being called but the terminal dose not show anything.

Except of course the first transmission. The salve also report when receiving from master on another slave's uart.

I assume (might be wrong) that my setup is valid because for the first it works with uart1 and secondly, with uart2 I can detect the first Master transmission.

Somehow the slave transmission upset the output stage of the uart in a none recoverable fashion, As you can see in the program snippet above, apart from the configuration the software consist of selecting the uart in line 32 and then a while loop with a delay line and a HAL_UART_Transmit_IT.

I will first check again the hardware and then a low level uart programming as both of you sugested.

ICohe.1
Associate III

I want to inform you and others that might be reading this thread. I had a hardware issue. After fixing it everything works perfect. Yes with HAL functions, which in my case simplify fixed data length communication. The hardware issue was another mcu (TM32F070F6P6) on the master board hooked up to the same 4 communication lines. The other mcu was never programmed so in theory should not be an issue because all I/Os are inputs on powerup. Since I am not going to use this mcu, just removing it solved the problem.

Piranha
Chief II

So the second MCU's pin capacitance changed some minor timing and the HAL bugware failed. It's not a hardware, but a software issue. Change the power supply, temperature, put it in a box or add another unrelated code and it will fail again... Because it's broken!

> fixed data length communication

There is no such a thing with USART. USART is a stream (not message) based protocol. If you threat it like message based, your software will inevitably fail some day. You can implement messaging protocol over USART yourself and it's not so hard. Use some header, checksum and/or timing to separate frames.

As for USART driver code, this is pretty good guide:

https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx