Closed ThirteenFish closed 10 years ago
I committed a fix for this. It works like this:
In ChibiOS/os/hal/src/serial_usb.c, sduObjectInit(), the caller-supplied SerialUSBDriver's vmt (virtual method table) member is set to point at a file-static method table named "vmt". vmt in turn points at 8 I/O functions, the first four of which (write, read, put, get) are hard-coded to pass TIME_INFINITE as the time parameter of the underlying queue output functions. This is what causes writing to the serial port to block if the data is not being drained.
In common/util/usbserial.c, when PSAS_NONBLOCKING_SERIAL is defined to be true, then a new file-static vmt is defined, along with replacements for the write, read, put, and get functions. These replacements are identical, except that they pass TIME_IMMEDIATE for the time parameter, and thus will not block. The other 4 functions in the vmt, which do not have a hard-coded timeout policy, are left unchanged from the vmt set up by serial_usb.c. The new vmt is installed in place of the old one at the end of usbSerialDriverStart().
The change can be tested using the project e407_printf. This is a simple modification to e407_led, which outputs a string in the led-blinking while loop. If PSAS_NONBLOCKING_SERIAL is not defined true, and the serial port is not being drained, then the serial queue will fill up and the led will stop blinking. Draining the queue will start it blinking again, and letting it fill back up will stop it once more. With PSAS_NONBLOCKING_SERIAL defined, the led will never stop blinking, but if the serial port is monitored, it can be seen that output continues to be generated on every loop iteration. Output written to the queue when it is full is lost in this case.
As it turns out, when using chprintf with the USB serial driver, if the host computer doesn't read the ACM device, chprintf will block. This is bad, we should do something about it, like make it not block.