1 Reply Latest reply on Aug 28, 2017 6:07 AM by user_246598725

    USBUART component change suggestion.

    user_377070487

      Not sure if this is the correct forum for this. If not apologies.

       

      I have a suggestion for the USBUART to fix a bug / problem.

       

      I'm using the USBUART to spew text to a PC from a PSoC. The PSoC is running a manufacturing test rig, it must operate with or without the PC.

       

      The existing USBUART checks that a PC is connected before attempting to send data. That's great, no PC, no data sent and the PSoC simply carries on.

       

      If a PC is connected then the PSoC code will wait indefinitely for the PC's receive buffer to be empty before sending. Here lies the problem. If a PC is physically attached to the USBUART then this is enough to satisfy the PSoC that it should wait for the empty buffer, but unless there is a hyperterminal (Putty or other serial port S/W) running on the PC then that buffer in the PC is NEVER emptied and once the buffer is filled the PSoC stalls.

       

      My suggestion is to add a simple timeout to the USBUART functions. Take PutString in USBFS_cdc.c as an example...

       

           void `$INSTANCE_NAME`_PutString(const char8 string[]) `=ReentrantKeil($INSTANCE_NAME . "_PutString")`

      is amended to:

           uint8  `$INSTANCE_NAME`_PutString(const char8 string[] uint16 timeout) `=ReentrantKeil($INSTANCE_NAME . "_PutString")`

       

      and

       

           while (`$INSTANCE_NAME`_IN_BUFFER_FULL == `$INSTANCE_NAME`_EP[epNumber].apiEpState)

                  {

                  }

       

      is amended to:

       

           while (`$INSTANCE_NAME`_IN_BUFFER_FULL == `$INSTANCE_NAME`_EP[epNumber].apiEpState)

                  {

                      if (timeout==0)

                          {return 255;}                         //Return 255 to indicate timeout

                      CyDelay(1);

                     timeout--;

                  }

       

      and finally:

       

            }

            while (strLength > 0u);

      }

       

      is amended to

       

            }

            while (strLength > 0u);

            return 0;   

      }

       

      This allows the user to pass a timeout in ms to the function. If the host pc doesn't empty the buffer in time the function returns 255. If the message is sent we return 0.

        • 1. Re: USBUART component change suggestion.
          user_246598725

          Hi,

           

          I'm not sure if I understand your problem right. A transmitting UART doesn't care if the receiver takes the data or not - the transmitter simply transmits the data if available. The only way to signal a transmitter to stop/continue transmission is using handshake (soft- or hardware).

          The above is valid for a "real" COM port implementation, just as a basic description.

           

          You wrote about the UsbUART. Here, things are a bit more complicated. The UsbUART tries to make a virtual COM port over an interface with a totally different approach. The USB functions must be blocking, because USB communication is always initiated by the host. On a real COM port, there's no real host - both transmitters may send at any time.

          So, the USB host coordinates the communication, and to ensure that the previous data to send has been collected, the USB functions must be blocking.

           

          Additionally, your approach of introducing a delay(!) would make the whole system slow, because the delay() function is simply a loop, which blocks the MCU for any other things (the same seems to apply to the original while-loop, I assume that's why the API states that CDCIsReady() function should be called prior to USBUART_PutString() function. The while-loop itself seems to be a fallback if CDCIsReady() has not been called.

           

          So, I want to suggest the following: use the CDCIsReady() function to check if the last packet has been transmitted. If not (no space for a new packet), then decrement a local timeout variable (preferrably in a non-blocking way), and when the timeout expires, cancel any future communication - the actual packet can be kept IMHO, this enables you to detect if a terminal application has been started, so you can continue communication.

           

          Regards,

           

          Ralf