Cyusbserial is is a Haskell wrapper for the Cypress cyusbserial
library for the USB bridging chips CY7C65211*, CY7C65213 and CY7C65215. The main references are
-
the home pages of the three chips CY7C65211*, CY7C65213 and CY7C65215,
-
the USB-Serial Software Development Kit, and
-
the USB-Serial Library API Guide Rev 1.0 (registration required)
Unfortunately the Cypress bridge chips are buggy, and Cypress haven't published any errata, yet. We therefore advise caution when planning to use this chip. Although Cypress doesn't admit it, the forum discussions indicate that there are several bugs in some of the bridge chips:
- Erroneous bytes are being read (I2C)
- Long pauses between reads and writes (probably a USB software issue
- TXLED and RXLED indicator have no relation to the actual USB transfer
- The USB connection hangs sometimes
The support provided on the forum "Developer Community 3.0" is rather bad. Unpleasant questions are ignored, solutions are often worked out behind closed doors. Hence we do not use Cypress' chips right now.
The wrapper works but is not as polished as it could be. Until Cypress sort out the issues we will stay away from Cypress' chips and therefore only invest minimally in maintaining this library.
Cyusbserial
has a basic, thin wrapper that very closely mirrors the C API. It is located in System.Cypress.USBSerial
.
There is also a 'safe' wrapper with proper error handling that also manages library initialization and orderly opening/closing of handles. It is located in System.Cypress.USBSerial.Safe
.
In most cases you'll want to use the safe wrapper,
import System.Cypress.Safe.USBSerial
This is what is covered here.
Let's go through a simple example:
- Find a device,
- open it, and then
- extract library and firmware version and the firmware 'signature'
(The signature is just a four letter string that is not explained anywhere and seems to have no particular use. Let's have it anyway.)
All functions in System.Cypress.Safe.USBSerial
return the type
Either ReturnStatus a
The (safe) USB functions have to be sequenced in the USB
monad and executed with runUSB
:
runUSB :: USB a -> IO (Either ReturnStatus a)
so our new funcyion getBasicInfos
begins with
getBasicInfos :: IO (Either ReturnStatus (LibraryVersion, FirmwareVersion, Signature))
getBasicInfos = runUSB $ do
...
First, you have to find the appropriate device in the device tree. The function findDeviceWithVidPidTypeClass
lets you search the device tree for devices identified by
- vendor ID (
0x04b4
), - product ID (
0x0002
, i.e. CY7C65211 in UART mode), - device type (
DeviceType'MFG
), and - device class (
DeviceClass'Vendor
).
findDeviceWithVidPidTypeClass
returns either an error ReturnStatus
or a non-empty list [(DeviceID, InterfaceID)]
:
devIfaceIds <- try $ findDeviceWithVidPidTypeClass 0x04b4 0x0002 DeviceType'MFG DeviceClass'Vendor
let (devID, ifaceID) = head devIfaceIds
System.Cypress.Safe.USBSerial
uses the Error Monad (a.k.a. Exception Monad) from Control.Monad.Except.
The prepended try
will extract the returned value or abort the whole do
block with a Left ReturnStatus
. Since findDeviceWithVidPidTypeClass
will return ('throw') a Left ReturnStatus
when nothing is found, or anything else goes wrong, it is safe to use head
on the returned list.
With DeviceID
and InterfaceID
obtained you can open the device
withOpen devID ifaceID $ do
...
withOpen
has the signature
withOpen :: DeviceID -> InterfaceID -> USBWithHandle a -> USB (Either ReturnStatus a)
it works with the USBWithHandle
monad - all functions that need a device handle act in this monad.
Now you can go ahead and extract all the required information:
libVer <- try getLibraryVersion
fwVer <- try getFirmwareVersion
sig <- try getSignature
return (libVer, fwVer, sig)
One last thing to do is to fix the return type of withOpen
. To avoid nested Either
s you have to prepend a try
. The final result is
getBasicInfos :: IO (Either ReturnStatus (LibraryVersion, FirmwareVersion, Signature))
getBasicInfos = runUSB $ do
devIfaceIds <- try $ findDeviceWithVidPidTypeClass 0x04b4 0x0002 DeviceType'MFG DeviceClass'Vendor
let (devID, ifaceID) = head devIfaceIds -- infos is guaranteed to be non-empty
try $ withOpen devID ifaceID $ do
libVer <- try getLibraryVersion
fwVer <- try getFirmwareVersion
sig <- try getSignature
return (libVer, fwVer, sig)
By default the CY7C6521x chips are configured as UART devices. If you want to use the SPI/I2C/SPI/JTAG/PHDC interfaces, or configure the GPIO pins, you have to reconfigure the chip. The safe way to do this is to use Cypress Configuration Utility (Windows only). It is part of the USB-Serial SDK for Windows.
The crude and unsafe way to do this (Linux and Mac) is to use the readConfigFlash
and progConfigFlash
functions in System.Cypress.Safe.USBSerial.Extras
. These two functions are not part of the original API, instead they are reverse-engineered. These functions are absolutely not guaranteed to work, in particular if Cypress does any firmware updates. Be careful with these two functions, you may well brick your chip.
The recommended (i.e. only) way to use readConfigFlash
and progConfigFlash
is to configure the chip on Windows with the Configuration Utility, then export the config flash content with readConfigFlash
, and then program the config flash contents again with progConfigFlash
whenever necessary. This seems to work. But again: Be careful, or you will brick your chip.
Todo
Cypress has a cheap (4$) evaluation board CY8CKIT-049 for one of their PSoC chips that also has a USB-serial converter with a CY7C65211 that can be broken off.
Note that the USB-Serial board has 5V logic levels. Most devices are not 5V tolerant, and you have to use a logic level converter.
Cypress has three USB bridging chips: CY7C65211, CY7C65213 and CY7C65215.
The main features are:
- USB 2.0-certified, Full-Speed (12 Mbps)
- Support for communication driver class (CDC), personal health care device class (PHDC), and vendor-specific drivers
- Battery charger detection (BCD)
- Configurable UART interface(s)
- Data rates up to 3 Mbps
- GPIO pins (CY'11: 10x, CY'13: 8x, CY'15: 17x)
- Operating voltage: 1.71 to 5.5 V
The CY7C65211 and CY7C65215 also have
- Configurable SPI interface
- Data rate up to 3 MHz for SPI master and 1 MHz for SPI slave
- Data width: 4 bits to 16 bits
- Support of Motorola, TI, and National SPI modes
- Configurable I2C interface
- Master/slave up to 400 kHz
- Support of multi-master I2C
- JTAG interface: JTAG master for code flashing at 400 kHz
Device | Datasheet | Price/$ @1000 | Remarks |
---|---|---|---|
CY7C65211 | datasheet | 1.60-1.70 | Single SCB; Cheap breakout board available as part of CY8CKIT-049 |
CY7C65213 | datasheet | 1.50-1.60 | One SCB, only UART capable |
CY7C65215 | datasheet | 1.70-1.80 | Two SCBs, more GPIOs |
SCB=Serial Communication Block
Mode | Protocol | PID |
---|---|---|
UART | CDC | 0x0002 |
UART/SPI/I2C | Vendor/PHDC | 0x0004 |
Mode | Protocol | PID |
---|---|---|
UART | CDC | 0x0003 |
UART | Vendor/PHDC | 0x0006 |
Mode SCB0 | Protocol SCB0 | Mode SCB1 | Protocol SCB1 | PID |
---|---|---|---|---|
UART | CDC | UART | CDC | 0x0005 |
UART | CDC | UART/SPI/I2C/JTAG | Vendor/PHDC | 0x0007 |
UART/SPI/I2C | Vendor/PHDC | UART | CDC | 0x0009 |
UART/SPI/I2C | Vendor/PHDC | I2C/JTAG/I2C/JTAG | Vendor/PHDC | 0x000A |
The CY8CKIT-049 is of interest here because it has a USB-setial module with a CY7C65211 that can be broken off. For more information see docs/CY8CKIT-049-42xx.md.
The CYUSBS234 is an inexpensive (25$) dev kit with which all features of the CY7C65211 chip can be explored.
There is also a nice little breakout board PCB by David Freitag on github.
See Internals.md.
Cypress' licensing information is messy. The exact terms had to be clarified in questions posted on the Cypress developer community forum. In a nutshell:
- On Linux and Mac the libraries in the SDK of CyUSBserial are opensource and licensed under the LGPL 2.1 (see here). LGPL 2.1 is basically inherited from the
libusb
license terms. - On Windows the libraries are covered under Cypress' own license agreement that seems to be a LGPL variant, effectively. See here, in particular §1.3 of the attached
license.txt
.
To keep it simple this cyusbserial
library carries the LGPL-2.1 license itself.