UART with handshake enabled can lock mainboard

I am testing COM2 port. I am using Cobra II and the latest SDK, handshake is enabled (RequestToSend). If I pull CTS pin on my mainboard to 3V3 and continue to sent data to an external device mainborad locks up (every single running thread is stopped). If I pull CTS pin back to GND everything comes back to normal.

This means that if an external devices malfunctions and indefinitely indicates that it is not ready to accept incoming data your whole solution will became unusable.

Is the code were you write to the port in separate thread? I think it is normal that the thread from were you write to the port is blocked when the buffers are full.

@ RoSchmi - Yes, it is in a separate thread.
Mainboard locks-up and hence all the running threads are stopped. In other words, InternalCall does not return and all the managed code is blocked.

@ iamin - of course one blocking thread should not block the other threads. It’s hard to believe that this really occurs. As far as I know hardware flowcontrol does not work on the raptor board, did not hear about this from Cobra.
Maybe it would help to see your code.

@ RoSchmi - Well I can provide you a sample code, but you will not see anything special in there. One thread is constantly writing data to SerialPort and one thread that is blinking LED.

Write method of SerialPort is:


public override void Write(byte[] buffer, int offset, int count);

This call will not return (and hence block all the managed code) until I pull CTS to GND.

@ iamin -

InfiniteTimeout is the default.

Sorry, it’ s late now here in Germany so I cannot continue actually.
But if this is not a known issue the only way is to look at your code or create an example were one blocking thread is not blocking all the others.

Ok. Will give it to you in 5 minutes.

Took me 5 minutes to realize I was using COM1 instead of COM2.


Private ReadOnly _uart As New SerialPort("COM2", 115200, Parity.None, 8, StopBits.One) With {.Handshake = Handshake.RequestToSend}
Private ReadOnly _thWrite As New Thread(AddressOf Write)
Private ReadOnly _thLed As New Thread(AddressOf Led)

Sub Main()
	_uart.WriteTimeout = 0

	_uart.Open()
	Debug.Print("Ready to start")
	_thLed.Start()
	_thWrite.Start()
	Thread.Sleep(-1)
End Sub

Private Sub Write()
	Do
		_uart.WriteByte(49)
		Thread.Sleep(100)
	Loop
End Sub

Private Sub Led()
	Dim output As New OutputPort(DirectCast(47, Cpu.Pin), False)

	Do
		output.Write(True)
		Thread.Sleep(300)
		output.Write(False)
		Thread.Sleep(300)
	Loop
End Sub

@ iamin -
strange…
as far as I see and understand VB there are two different threads.
I do not understand why the Led Loop is blocked.

@ RoSchmi - Well, the simple answer is - Write method calls unmanaged code and this call is not returned until CTS is pulled down. The more in-depth answer could be provided after looking at Write implementation, which is written in C++, but that is not the language I familiar with.

@ iamin - I have not looked much at the uart code in .netmf, but my guess would be that there is a loop in the native code that waits forCTS to go low and while in this loop the .NETMF interrupts are disabled and therefore blocking the threads.

Just a guess, but probably a good place to start looking in the firmware.

@ taylorza - Very plausible.
In some cases like this MS is using a technique that is calling back to manged code and this way prevents your mainboard from locking.

@ iamin - A quick scan of the code shows that the function ‘CPU_USART_TxHandshakeEnabledState’ returns the state of the CTS pin. There are a few occurrences of a tight loop checking this state wrapped in a global lock. So it is very likely that this is indeed the issue.

@ taylorza - Are you looking inside usart.cpp?

At one place they do the following:

while(!CPU_USART_TxBufferEmpty( ComPortNum ))
{
	// The TxBuffer will never be empty as long as the handshake is preventing
	// the character from being sent
	if(!CPU_USART_TxHandshakeEnabledState(ComPortNum))
		return FALSE;

At another:

// wait for the holding register to empty
while(!CPU_USART_TxBufferEmpty( ComPortNum ) && CPU_USART_TxHandshakeEnabledState(ComPortNum));

// also wait for shift register to empty
while(!CPU_USART_TxShiftRegisterEmpty( ComPortNum ) && CPU_USART_TxHandshakeEnabledState(ComPortNum));
// now, all characters have been transmitted

@ iamin -

I made 2 threads, one for writing to PC, the other one for blinking LED,

  • pull CTS to low, LED is blinking, PC received data fine
  • pull CTS to high, LED is still blinking, data is hold so PC can not received data.

it looks like work correctly, can you put small code that we can reproduce it, please?

@ Dat - I have posted it in the 7th post: https://www.ghielectronics.com/community/forum/topic?id=18327&page=1#msg182037

I also tried your code in post 7#, exactly in VB. it doesn’t matter the CTS pin high or low, the LED 47 still blinking and I also can ping tiny CLR during CTS is high.
:think:

Oh, sorry, I tried in newest firmware while it happens in 4.3.6.0. :)). That is why I can not reproduce. This bug is already fixed. I think.

@ Dat - You are correct. With 4.3.7.0 I do not experience this issue.

Hi, I have the same problem with the handshake in the COM2 with the Cobra II. I try it with the firmware versions 4.3.7.9 and 4.3.7.10 and the problem still locking the mainboard. did you know some solution for this??