cancel
Showing results for 
Search instead for 
Did you mean: 

Transmit and Receive "parallel" on UARTs

RockfordC64
Associate II

Hello,

we have a custom board with a STM32L051R6T6 MCU.

And we try to to receive and to transmit on an UART.

The telegrams have 40bytes lenght and the UART works on 9600 baud. The remote station sends one every 50ms.

If processing of the rx telegram was successful, we want to answer with a 40byte ackknowledge telegram.

Receiving and transmitting are done via interrupt in 40byte blocks.

If I comment out transmit, everything works. every telegram is received and processed.

But when I uncomment transmitting, a lot of rx telegramms are lost.

I also added a timer to debug the amount of time, which the uart needs to transmit (from HAL_UART_Transmit_IT to the HAL_UART_TxCpltCallback). This time is not as long as the time, where no are telegrams received.

I think that its not possible to send and receive parallel. But if tx is finished, should rx not run immediately again? It looks as the UART makes a break after sending.

I think, since rx telegram and tx telegram have the same length, I should maximum miss one rx telegram, not ~ten of them.

Can someone explain this behavior?

Thank you.

17 REPLIES 17
RockfordC64
Associate II

Logging with commented out transmit : nice behavior at rx side

*: 1:51 2:198 //Processing of the rx telegrams

*: t:52964 rxc1:51 rxc2:198 //maincycle timer log

*: t:55355 rxc1:51 rxc2:198 //we have actually no new telegram

*: t:57511 rxc1:52 rxc2:198 //we have one in UART1 but none on UART2

*: 1:52 2:199 //Processing of the rx telegrams

*: t:59807 rxc1:52 rxc2:199 //Now both UARTs have new telegrams in theyr queues

*: t:62199 rxc1:53 rxc2:199 // and so on

*: 1:53 2:200

*: t:64494 rxc1:53 rxc2:200

*: t:1350 rxc1:54 rxc2:200

*: 1:54 2:201

*: t:3646 rxc1:54 rxc2:201

*: t:6037 rxc1:55 rxc2:201

*: 1:55 2:202

*: t:8334 rxc1:55 rxc2:202

*: t:10725 rxc1:56 rxc2:202

*: 1:56 2:203

*: t:13022 rxc1:56 rxc2:203

*: t:15412 rxc1:57 rxc2:203

*: 1:57 2:204

*: t:17708 rxc1:57 rxc2:204

*: t:20100 rxc1:58 rxc2:204

*: 1:58 2:205

*: t:22397 rxc1:58 rxc2:205

*: t:24788 rxc1:59 rxc2:205

*: 1:59 2:206

*: t:27084 rxc1:59 rxc2:206

*: t:29475 rxc1:60 rxc2:206

Karl Yamashita
Lead III

I'm assuming when you wrote //called from RxInterrupt

that you've meant from HAL_UART_RxCpltCallback()?

Never process data from an interrupt.

  • Instead since it's only 40 bytes, save the 40 bytes to another array and set a flag to indicate you have new data.
  • Then call HAL_UART_Receive_IT() to re-enable UART receive interrupt. Exit from HAL_UART_RxCpltCallback()
  • Then in your main loop check for that flag. Process that data hopefully before the next interrupt. But as the 40 bytes is coming in, the driver is writing to your primary array each byte. But since you've copied the last data to a secondary array, it isn't overwriting your secondary array.

You also need to post your function that has HAL_UART_Receive_IT() and HAL_UART_Transmit_IT() that might show a whole new perspective.

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.
RockfordC64
Associate II

@. (Community Member)

> Try transmit by polling,...

This is the same code except tx by polling:

*: 1:189 2:17 //Processing of the rx telegrams

*: t:35456 rxc1:189 rxc2:17 //maincycle timer log

*: t:35888 tx1:23 tst:24851 tsp:28760 ok //send blocking (look at the tx1 tst and tsp of next tx t:5790)

*: t:40189 tx2:23 tst:29152 tsp:33061 ok//send blocking (look at the tx1 tst and tsp of next tx t:10082)

*: t:46378 rxc1:189 rxc2:17 //latest here all tx is done, rx should be possible

*: t:48534 rxc1:189 rxc2:17

*: t:50690 rxc1:189 rxc2:17

*: t:52860 rxc1:189 rxc2:17

*: t:55109 rxc1:189 rxc2:17

*: t:57359 rxc1:189 rxc2:17

*: t:59609 rxc1:193 rxc2:17 //but only here we do recognize the first new rx telegram UART1

*: t:61859 rxc1:193 rxc2:17 //we missed 4 of them

*: t:64107 rxc1:194 rxc2:21 //And here the first telegram on UART2

*: t:821 rxc1:194 rxc2:21

*: t:2978 rxc1:194 rxc2:22

*: 1:195 2:22

*: t:5358 rxc1:195 rxc2:22

*: t:5790 tx1:24 tst:35913 tsp:39823 ok

*: t:10082 tx2:24 tst:40214 tsp:44124 ok

Yes I thougth about checking rxCount and CRC in main cycle and will try this immediately.

here come the function which calls HAL_UART_Transmit_IT()

bool UartAcuTransmit(struct UartAcu* uartAcu, struct TelegramAcuTo* telegram){
	//dequeueing and sending the actual telegram from outboundQueue
	bool success = false;
 
	UartAcuTxInProgress(uartAcu, true);
	if ( HAL_UART_Transmit_IT( uartAcu->baseUart.handle, TelegramData(&telegram->baseTelegram) , TelegramLength(&telegram->baseTelegram)) == HAL_OK ){
		success = true;
	}
 
	return success;
}

and HAL_UART_Receive_IT()

void UartAcuStartInterrupt(struct UartAcu* uartAcu){
 
	UartStartInterrupt( &uartAcu->baseUart, uartAcu->syncForeward);
}
 
void UartStartInterrupt(struct Uart* uart, uint32_t countRx){
 
	HAL_UART_Receive_IT (uart->handle, uart->rxData, countRx);//initiate receiving via interrupt
}

I'm not sure what StatusSetInternalFault() does but if HAL_UART_Transmit_IT() does not return HAL_OK, it's more than likely it is returning HAL_BUSY. All you have to do is retry sending that data again later in main loop.

Just a heads up, your HAL_UART_Receive_IT() doesn't return any HAL status so you don't know if you need to retry enabling UART Receive interrupt again. So if by chance you get HAL_BUSY, your rx interrupt is no longer going to work until you reset the microcontroller.

for "But when I uncomment transmitting, a lot of rx telegramms are lost." are you missing some bytes in the beginning of the telegram or the whole telegram?

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.
RockfordC64
Associate II

@Community member​ 

Now the preprocessing (Counter + CRC) are done in maincycle, But no improvement. Tx works with interrupt again.

*: t:15459 tx1:72 tst:51770 tsp:55678 ok //tx on UART1 (dont care about tst and tsp, they are from last tx)

*: t:15854 tx2:72 tst:52165 tsp:56074 ok //tx on UART2 (dont care about tst and tsp, they are from last tx)

*: 1:247 2:104 //Processing of 2 rx telegrams

*: t:18328 rx1:247 rx2:104 rxp1:247 rxp2:104 //Maincycle time telegram have been enqueed(rx) and processed(rxp)

*: t:18925 ntx1:0 //tx1 of telegrams is denied because of TxCompleteInterrupt has still not triggered and tx from t:15459 still running (this is ok)

*: t:19108 ntx2:0 //tx1 of telegrams is denied because of TxCompleteInterrupt has still not triggered and tx from t:15854 still running (this is ok)

*: t:21261 rx1:-1 rx2:-1 rxp1:247 rxp2:104 //look at next tx, there we find the start and

*: t:23605 rx1:-1 rx2:-1 rxp1:247 rxp2:104 //stop timers of the actual running tx operation

*: t:25949 rx1:-1 rx2:-1 rxp1:247 rxp2:104 //tst:15484 tsp:19392 and tst:15880 tsp:19789

*: t:28305 rx1:-1 rx2:-1 rxp1:247 rxp2:104 //why cant I receive until t:44712

*: t:30649 rx1:-1 rx2:-1 rxp1:247 rxp2:104

*: t:32993 rx1:-1 rx2:-1 rxp1:247 rxp2:104

*: t:35336 rx1:-1 rx2:-1 rxp1:247 rxp2:104

*: t:37680 rx1:-1 rx2:-1 rxp1:247 rxp2:104

*: t:40024 rx1:-1 rx2:-1 rxp1:247 rxp2:104

*: t:42397 rx1:-1 rx2:-1 rxp1:251 rxp2:108 //but this i strange (nothing enqueued, but telegrams dequeued)

*: t:44712 rx1:-1 rx2:-1 rxp1:251 rxp2:108

*: t:47059 rx1:252 rx2:-1 rxp1:252 rxp2:108

*: 1:252 2:109

*: t:49541 rx1:-1 rx2:109 rxp1:252 rxp2:109

*: t:50147 tx1:73 tst:15484 tsp:19392 ok

*: t:50542 tx2:73 tst:15880 tsp:19789 ok

I need to check first, where the telegrams in the inboundqueue come from.

hope I'm back soon

I will include some more debugging code, to understand, what really happend in the RxInterruptRoutine.

As I wrote further below, I can dequeue a telegram but nothing is enqueued.

Thank you so far...

RockfordC64
Associate II

I have a complete new idea from whats happening.

First of all: receiving works, also while and after tx-ing.

I built some logging of the received telegramnumbers directly into RxCompleteIR.

It seems, that I receive full telegrams (no parts, or nothing).

But the telegram numbers are not in sequence. Without tx-ing, they are.

That's why my telegram rx count check discards them and does not enqueue them.

So I suspect, that the remote station somehow reacts to my tx telegrams.

I'm so sorry that this is a complete other view to the problem and I didin't got this sooner.

Someone told me, that the remote station will send its telegrams in sequence, no matter what happens.

For me, its a good realisation, and I know, that UARTs are working as expected.

You have brought me there, Thanks a lot.