cancel
Showing results for 
Search instead for 
Did you mean: 

Troubleshooting UART comms issue (I think I'm really close but I'm missing something obvious)

JBee.1
Associate II

Hello!

I'm creating a basic UART project (using an STM32WB55 development board) to communicate with an external piece of hardware where I'm trying to send 9 bytes of data across and receive data back with an interrupt. It would appear I AM receiving the interrupt when I have the UART TX and RX lines tied together (so, hardware wise, that seems to be working correctly). Below is the code I'm using to send the data:

Here's my init function (called in main)

static void MX_LPUART1_UART_Init(void)
{
 
  /* USER CODE BEGIN LPUART1_Init 0 */
 
  /* USER CODE END LPUART1_Init 0 */
 
  /* USER CODE BEGIN LPUART1_Init 1 */
 
  /* USER CODE END LPUART1_Init 1 */
  hlpuart1.Instance = LPUART1;
  hlpuart1.Init.BaudRate = 31250;
  hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart1.Init.StopBits = UART_STOPBITS_1;
  hlpuart1.Init.Parity = UART_PARITY_NONE;
  hlpuart1.Init.Mode = UART_MODE_TX_RX;
  hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
  if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LPUART1_Init 2 */
 
  /* USER CODE END LPUART1_Init 2 */
 
}

Here's my Tx function (called from another function):

uint8_t UART_txBuffer[10] = {0};
 
if(HAL_UART_Transmit_IT(&hlpuart1, &UART_txBuffer, 9)!= HAL_OK)
{
	Error_Handler();
}

Here is my RX interrupt (which is being triggered correctly):

uint8_t UART_rxBuffer[10] = {0};
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
  HAL_UART_Receive_IT(&hlpuart1, &UART_rxBuffer, 9);
}

So, it looks like my data is being sent correctly (it even triggered my external hardware, which I got no response from when my data was incorrect previously). Me now getting a response from the HW is good news and seems to suggest that I'm sending the correct data (I'll have to sort through if THAT data is correct later on but, for all intents and purposes, I'm just tying the TX and RX lines together for this test).

So, based on this, all signs (to me anyway) point to an issue with the way I'm receiving it.

To be fair, I am getting warnings, which might point to the issue:

warning: passing argument 2 of 'HAL_UART_Transmit_IT' from incompatible pointer type [-Wincompatible-pointer-types]
 
warning: passing argument 2 of 'HAL_UART_Receive_IT' from incompatible pointer type [-Wincompatible-pointer-types]

I can get rid of the warnings by sending it &UART_txBuffer[0] instead, but then I get the error handler (which is obviously less ideal).

I don't have a scope with me currently to check the signals are coming across as expected but, based on the test with the external hardware, it does appear that it's sending correctly. Based on that, I assume it has to do with the way I'm receiving or storing my data. I thought I'd throw a post up in case someone else can point me the right direction. I actually think I'm really close at this point.

Any help you can give me would be greatly appreciated. Thanks!

7 REPLIES 7
KnarfB
Principal III

Taking & is wrong in both transmit and revceive. &UART_txBuffer[0] and &UART_rxBuffer[0] looks okay. The length is 10, not 9. The indices run from 0 to 9 though.

JBee.1
Associate II

Yeah, I just have a few functions that need to send 9 and a few that need to send 10, so I setup a global array of 10. I did specify that both Tx and Rx are sending and receiving 9 bytes so, assuming I'm not trying to send sizeof(UART_txBuffer), I think that should be ok with me specifying 9 bytes (but maybe I'm wrong and that's the cause of the problem?). I believe I had 9 originally and it didn't make a difference, sadly.

I had tried to use &UART_txBuffer[0] though and got an error handler issue when I tried to do that. Any idea why that might be? The logic makes sense to me as well, didn't understand the error though.

Thanks for your help!

KnarfB
Principal III

Should work if the arrays are global variables. You might want to debug-step through the code or set a breakpoint oin the error handler to check how it came.

Ok, looks like I'm back with more info!

I went ahead and hooked up a scope and, as I suspected, the data was being sent out and received correctly (which is a fun bit of news!). Unfortunately, the microcontroller seems to be catching the interrupt but it's not reading the data in (it's reading all 0's . . .).

The blue signal is the transmit, the yellow signal is the receive. I did update the code again to start with the first position of the array (as discussed previously).

    uint8_t UART_txBuffer[10] = {0};
     
    if(HAL_UART_Transmit_IT(&hlpuart1, &UART_txBuffer[0], 9)!= HAL_OK)
    {
    	Error_Handler();
    }
uint8_t UART_rxBuffer[10] = {0};
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
	/* Set transmission flag: transfer complete */
	HAL_UART_Receive_IT(&hlpuart1, &UART_rxBuffer[0], 9);
}

What's interesting is my code works fine when I have my Tx and Rx lines tied together, so I assume it has something to do with the way the hardware is sending the data across. One thing worth noting is that the interrupt fires from the external hardware the first time, but not any additional times (though if I restart the firmware, it will receive the interrupt again, so something is getting reinitialized).

I assume, based on the above, there's data left in the register that's not being grabbed and the reason it works when restarting the firmware is it's clearing the UART register or a flag of sorts. So, I guess this leaves me with 2 questions:

1) How do I get the firmware to collect the data? Do I need a for loop to grab it byte by byte?

2) What is causing it to hang? Do I need to clear a flag or something to that effect to allow it to retrigger?

I assume these errors are related but I'm not 100% sure what's going on.

Thanks for your help!

Read out and check/post content of UART and relevant GPIO registers.

JW

0693W000005CEFiQAO.jpgI went ahead and went back through the datasheet and came across the ORE flag, which I remembered I had cleared in another application I had (as well as the NE flag, for whatever reason). I added them both and the code appears to send the data across. That said, I'm not 100% sure this is what resolved the issue as I tried to reproduce the issue by unplugging the board from the PC and running the code with the cleared flags removed and I now can't seem to recreate the error I had last night. Not sure if I knocked it into a weird state or if something I did resolved the issue.

That said, my code was essentially changed to this:

void run_main()
{
	if(!HAL_GPIO_ReadPin (GPIOC, GPIO_PIN_4))
	{
		XOR_Checksum_Calc(&UART_txBuffer[0]);
		//if(HAL_UART_Transmit_IT(&hlpuart1, &UART_txBuffer[0], sizeof(UART_txBuffer))!= HAL_OK)
		tempReceiveCount = 0;
 
		//Clear Overrun Error Flag
	    __HAL_UART_CLEAR_OREFLAG(&hlpuart1);
 
		//Clear Noise Error Flag
	    __HAL_UART_CLEAR_NEFLAG(&hlpuart1);
		if(HAL_UART_Transmit_IT(&hlpuart1, &UART_txBuffer[0], 9)!= HAL_OK)
		{
			Error_Handler();
		}
	}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
	/* Set transmission flag: transfer complete */
	//HAL_UART_Receive_IT(&hlpuart1, &UART_rxBuffer[0], sizeof(UART_rxBuffer));
	HAL_UART_Receive_IT(&hlpuart1, &UART_rxBuffer[0], 9);
 
	//HAL_UART_Receive_IT(&hlpuart1, &UART_rxBuffer[tempReceiveCount], 1);
	//tempReceiveCount = (tempReceiveCount + 1) % 9;
}

However, I now, of course, have a different issue. It seems to be missing the first byte. I am receiving all the data as expected (00 01 74 10 0C CH CS F7), but I'm missing the F0 at the beginning. When I run it a second time, it would appear the first byte of the new command is in the final byte (8) of the previous command and that first byte is missing in the next set of values as well (see screenshot attached).

I tried reading the data one byte at a time (shown by the commented out section in the interrupt function) but got a similar result.

I was trying to do a while loop around the RXNE flag but can't seem to find a way to actually poll it (started going through the stm32wbxx_hal_uart.h and such files but can't seem to find a way to read a flag status that isn't already a macro, like with the ORE and NE commands). Was going to try and read bytes until that flag goes low (not sure if that would work anyway).

I tried going through the forums but haven't had much luck. I can technically work with what I have since the first byte isn't actually essential (it's always the same value, assuming the data is correct, obviously) but I would like to figure out the source of the issue and see if I can resolve it.

Any chance there's a forum post/topic/link suggestion you can point me to to determine the source of this problem? Once again, feels like I'm close but I'm kinda grasping at straws at this time.

Thanks for your help!

ORE = overrun, so the UART was not read fast enough when the (first?) char arrived. Are you calling HAL_UART_Receive_IT before HAL_UART_Transmit_IT? You can safely do so if the other side waits with the response for your request. Does enabling the FIFOs help? If you know the length of the answer, you can easily go with DMA which is less CPU intensive.