I'm working on a Communications Device Class (CDC) driver for an embedded device, a Full Speed implementation of USB 2.0. The COM port settings are 115200, 8-bit, no parity, 1 stop bit, no flow control. Our PC application (32-bit, Windows 7, .NET 2.0) communicates with the target device through a virtual COM port, which on the target device can connect to either a FTDI (USB-to-SCI bridge) chip or the integrated USB peripheral in the microcontroller, depending on which port is selected by the application.
Both virtual COM ports work without any problems using Realterm. However, while our desktop application works using the virtual COM port connected via the FTDI chip, it hangs when attempting to use the virtual COM connected via the microcontroller's integrated USB peripheral.
When connected via the virtual COM port using the integrated USB, the application consistently hangs on the second call to SerialPort.Write(...). Using Serial Monitor from HHD Software I can see that the data is transmitted on the first call to SerialPort.Write(...). However, that data is never received by the target device.
It's odd because the only time I have seen similar problems on previous projects was when the flow control settings on each side of the bus were mismatched.
Additional info...
Here is the data captured from various port monitoring tools while running our PC application connected to the target device via its integrated USB peripheral. Any insight would be appreciated.
Sysinternals Portmon
Advanced USB Port Monitor
Device Monitoring Studio - Request View
Device Monitoring Studio - Packet View
For those that are interested, I am using CodeWarrior 10.2 with the MCF51JM128 from Freescale.
Any ideas or suggestions would be appreciated. Thanks.
It is clear from the logs that you are making the classic mistake of not taking care of the hardware handshaking signals. That only ever works by accident, a terminal emulator like Realterm will never make that mistake.
You must set the DtrEnable property to true. That turns on the Data Terminal Ready signal. It is important because RS-232 is an unterminated bus so is subject to electrical noise when the cable is disconnected or the power turned off. DTR convinces the device that it is in fact connected to a powered device. This is emulated of course in your case but the driver or firmware will still typically implement the RS-232 behavior.
And the RtsEnable property is important, used to handshake with the device and prevent the receive buffer from overflowing when the app isn't emptying the buffer in a timely matter. You really should set the Handshake property to Handshake.RequestToSend, the most common way a device implements it. Which then also takes care of turning RTS on. If you have to use Handshake.None for some reason then you have to turn it on yourself by setting RtsEnable to true.
This ought to take of the problem. If you still have trouble then use PortMon to spy on the way Realterm initializes the driver. Compare the commands you see against the commands that the SerialPort class sends. Make sure they are the same. In value, not in sequence.
Related
I'm using atmega168 with AVRUSB. (yeah, old version of V-USB. already integrated and seems to work otherwise, so no hurry to change)
My hardware can be powered by USB or via other source. How can I detect if the host is actually connected? It would be also nice to init USB whenever it's connected, but not necessary. Most important is that I need to skip the blocking USB polling if there's no host.
The hardware I'm using doesn't have USB VBUS connected to any GPIO, so a software-based method is required. Maybe I could add some timeout to the USB init routine or something similar?
The dev boards for the ESP32 family of MCU use CP210x (or similar) "FTDI" chips to communicate with the MCU when flashing. CP210x presents a COM port to the host computer which runs esptool.py, a script which implements the Esressif communication protocol. Rather then use a CP210x, I would like to utilize a SAMD21 in its place.
I have managed to receive logs from my ESP32, to a serial monitor on my computer, via the SAMD21, over USB. The SAMD21 connects to the ESP32 via UART, with the standard ESP configuration of 115200 8N1. I can manually enter bootloader mode by holding the correct pins low at boot, and I get the log back confirming the correct bootloader mode.
When I run esptool.py, however, the connection fails, and I get a timeout. Likewise the esptool "monitor" fails to acknowledge the same logs which my terminal emulator easily detects.
What is the communication protocol between the host computer running esptool.py, the CP210x FTDI chip, and the ESP32, and how can I emulate the CP210x with a SAMD21? The definition of "FTDI", "TTL" and "RS232" are all a bit fuzzy, as far as I can determine with research online, so if anyone has experience in this arena, I would be very curious to hear your advice.
The code I have on my SAMD21 is just:
#include <Arduino.h>
void setup()
{
Serial.begin(115200);
Serial1.begin(115200);
}
void loop()
{
if(Serial.available())
{
Serial1.write(Serial.read());
}
if(Serial1.available())
{
Serial.write(Serial1.read());
}
}
Where Serial1 is the UART and Serial is the USB Serial connection.
esptool.py expects a serial port (known as COM port on Windows) to communicate with the ESP32. It doesn't care if the computer has an old-style serial port, is using a USB-to-serial bridge with a proprietary protocol (FTDI, CP210x and the like) or is using the standardized UBS protocol for serial communication (USB CDC ACM). This is left to the operating system and the installed drivers.
However, esptool.py modifies the baud rate and uses the RTS and DTR signals to reset the ESP32. It is also rather susceptible to timing issues with regards to the reset. If you set the ESP32 in boot mode manually, you should be able to get away without these.
However, the most likely cause is that the Arduino CDC implementation does not implement flow control. If esptool.py sends more data than fit into the internal buffer, it is likely discarded, instead of sending a NAK back so the host computer can retry later.
I don't fully understand the SAMD21 Arduino core to verify it. If so, I don't see how you can make it work with an Arduino program. You would need to resort to some other framework for programming the SAMD21.
Update
After more tests, it turns out the USB CDC implementation of the SAMD21 Arduino core correctly implements flow control. So no data will be lost.
In fact, I was able to successfully upload code to an ESP32 module. The setup was:
Arduino code built with PlatformIO. Instead of Serial, I've used SerialUSB as I'm unsure how to control the project settings available in the regular Arduino IDE.
For the ESP32, I've used a ESP32-WROOM-32 module on a minimal board (reset and boot button, 2 pull-up resistors).
I've connected the board via GND, 3.3V, TX, RX directly to the SAMD21 dev board.
I've verified that I can see the ESP32 log output in normal run mode and the "waiting for download" prompt in bootloader mode (after pressing BOOT and RESET).
Arduino has multiple boards where the esp32 is on-board as WiFi adapter. To flash the esp32, there is a tool sketch called SerialNINAPassthrough in examples of the WiFi library, which should be uploaded into the main MCU of the board (SAMD21 on two of the official boards).
The SerialNINAPassthrough sketch handles the DTR and RTS signals sent by the esptool to reset the board into the flashing mode.
I have a device connected to a USB and it periodically sends data to my PC. During the time it is not sending data, the USB cable needs to be removed, else, the device won't work (a fail-safe feature, if the USB cable is connected and attached to pc, the device is in communication mode, if the USB cable is disconnected from pc, it is in stand-alone operation mode).
I was thinking to use the Devcon so I font has to use another hardware, I'll just disable the USB port during an operation mode, then enable it during communication mode. However, the periodic transfer of data can be set to every 5,10,15,30 minutes depending on the settings.
My question is, will it be okay to disable/enable the USB port periodically? Say every 5 minutes? Won't it cause any problem in the long run? Or would it be more efficient for me to use external hardware, a switch to connect/disconnect the USB? Appreciate any advice or thoughts.
If devcon works for you, I don't see why it would cause any problems in the long run. There is no inherent reason why the hardware should get damaged when you run some commands in your software to disable a USB port.
Using external hardware to accomplish the same thing would not be more efficient because you'd have to pay for the hardware and maintain it.
I'm trying to implement UART over a USB interface on the STM324x9I-EVAL development board. The purpose is to send commands to a servo controller (or other hardware, for that matter) serially. I've successfully implemented the USB_Device_CDC example on the development board but am unsure exactly how this works without a PC with drivers on the other end. As far as other hardware is concerned, will the USB port now simply look like a serial port? Or is there still a need for a driver or some sort of interface on the other end?
I do want to point out that I'm aware of the following post:
Emulating UART over USB
but I don't believe my question is fully answered within the context of that answer.
A USB connection is not a peer-to-peer connection like a UART. It requires a host and a device in a master/slave relationship. The device cannot initiate data transfer; it must be continuously polled by the by the host.
A CDC/ACM class device presents a virtual COM port on a PC host, but that does not allow the device to communicate with a UART interface. It looks like a serial port at the software level, but does not implement a UART physical layer. There is an awful lot going on under the hood to make it look like a PC serial port, but none of it resembles UART communications at the physical level.
There are devices that act as UART/USB bridges (from FTDI and Prolific for example), and you could (somewhat expensively) build your own from a microcontroller that has a USB device controller and a UART, but the bridge is a USB device and must still connect to a USB host; these are normally used to connect a PC to a microcontroller that lacks a USB controller or where the software/CPU overhead of using a USB controller is too great.
In theory you could connect a microcontroller that has a USB host controller to one that has a USB device controller, but you need host and device software stacks on each respectively, and once you have the USB connection, implementing CDC/ACM is a somewhat inefficient use of the available bandwidth. The purpose of the CDC/ACM class is primarily to allow "legacy" software to work on a PC.
If you need to connect to a "real" serial port, you should use a real UART - which are far more ubiquitous than USB controllers on microcontrollers in any case.
You should learn a little bit about USB device classes. CDC is a USB device class, and ACM is a subclass that I assume you are using. The device you made could be called a "CDC ACM device" because it uses the CDC class and the ACM subclass.
These classes and subclasses are defined by the USB Implementers Forum in documents that you can find here:
http://www.usb.org/developers/docs/devclass_docs/
These documents specify things like what USB descriptors a CDC ACM device should have in order to describe itself to the host, and what kinds of interfaces and endpoints it should have, and how serial data will be represented in terms of USB transactions and transfers.
Note that CDC ACM only specifies some USB commands for transferring data between the host and the device. It does not specify what the device will actually do with that data. You can use CDC ACM to implement a USB-to-serial adapter, or you can just use it as a general purpose communication interface for whatever data you want to send.
Yes, you do need a driver on the PC side. The driver needs to be designed to run on your specific operating system. It needs to create some kind of virtual serial port device in your operating system that other software (which only knows about serial ports) can find and connect to. It needs to translate serial port operations performed by other software on the serial port (e.g. writing some bytes to the serial port) into low-level USB commands according to the CDC ACM specifications (e.g. sending some bytes out to the device on a particular endpoint in the form of USB packets). It needs to somehow know which USB devices it should operate on, since not every USB device is a CDC ACM device.
For Windows, you will probably use the usbser.sys driver which comes with Windows. For versions of Windows older than Windows 10, you will need to write an INF file to associate your device to usbser.sys and sign it. For Windows 10 and later, there is a new INF file called usbser.inf already included with Windows which will automatically match any valid CDC ACM device. This means you don't have to write or distribute a driver for CDC ACM devices if you only intend to support using the device on Windows 10 or later. The partnership between Microsoft and Arduino which began in 2015 gives me hope that Microsoft will continue supporting and improving usbser.sys in the future. In fact, they claim that in Windows 10 "the driver has been rewritten by using the Kernel-Mode Driver Framework that improves the overall stability of the driver", so that is good news.
For Linux, there is the cdc_acm kernel module, which has been a standard part of the kernel for a long time and should work automatically with any CDC ACM device you plug in.
For Mac OS X, there is the AppleUSBCDCACM driver, which should work automatically with any CDC ACM device you plug in.
Note that for any of these drivers to recognize your device and work with it, your device has to have certain values in its USB descriptors, and the requirements can vary depending on what exact driver version you are talking about.
Will the USB port now simply look like a serial port?
No, that's the wrong way to think about it. The USB port will still look like a USB port, but the various USB drivers provided by your operating system will recognize that a CDC ACM device is plugged into that port and create a new entry in your operating system's list of serial ports. Then if you run some software that only knows about serial ports, it can connect to that port.
In fact, if you make a composite device, you can have a single USB device plugged into a single USB port that actually has two or more virtual serial ports.
I want to communicate to halios system(hardware) through usb port. I have a code which shows that the device is attached. I used USBTrace which shows that how many bytes are going in and out from the device to the host. But I do not know how to implement this is vc++2008 and by using windows xp.
If this is an evaluation board for an Elmos optical sensor IC I would guess that a USB to serial converter is involved. You could confirm this by watching Windows Device Manager for a new COM port appearing when you attach the device.
If that's the case you can use Basic example of serial communication with Windows XP/win32 but you may need to contact Elmos for the command protocol.