Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting the CY7C65215 #3

Open
runger1101001 opened this issue Nov 5, 2024 · 5 comments
Open

Supporting the CY7C65215 #3

runger1101001 opened this issue Nov 5, 2024 · 5 comments

Comments

@runger1101001
Copy link

Thank you for your excellent work on this library.
In your readme you write:

However, in my experience so far, they are easier to work with and simpler to design your circuit board around. In particular, they do not need an external EEPROM, and they are much better documented on the electrical side. Why the industry still prefers the FTDI chips is... something of a mystery to me at this point.

I agree very much with this statement. I think perhaps the reason the FT2232H is still widely used, is that is has better software support. Your library may go a long way to change that.

I'm trying to add support for the CY7C65215 chips, the dual channel versions of these chips. Compared to the FT2232H this chip also offers 2 serial channels configurable as either UART, SPI or I2C, but needs far fewer external components to support it, and comes in a smaller package at half the price.

In terms of the code, at the moment it does not work to connect to these chips. To get my local version to connect, I needed to change the list_devices function in cy_scb_context.py.

There are significant differences to the USB device for the 2-channel version:

  1. The PID is a different one. It seems to be 0x0005 or 0x0007
  2. the CY7C65215 has 4 USB Interfaces when configured with 1 CDC UART and 1 SPI. I have to check different configurations, but presumably there is always one extra interface since it has 2 SCBs.
  3. the interface order seems to be: 0 - control, 1 - SCB1, 2 - SCB2, 3 - MGR
  4. the interfaces have the same classes and subclasses, but the endpoints are a little different: the endpoints for the SCBs in Vendor mode have different addresses. Instead of 0x01, 0x82 and 0x83 it is 0x04, 0x85 and 0x86.
  5. After modifying the checks in list_devices accordingly, it connects to my CY7C65215 successfully.

I'm happy to submit these changes as a PR, but I am uncertain regarding the best way to proceed.

What is the purpose of all these checks? Are you trying to recognise the device based on its interface and endpoint configuration? Why not trust the user-supplied PID values?

How to deal with the fact that there could be 2x UART or 2x SPI, etc? The CLI has the --scb option, but the SCBContext does not seem to take it into account?

@multiplemonomials
Copy link

Yeah frankly I'm shocked at how bad everything about the FT232H is. The example circuit uses a bajillion additional components and the datasheet is awful -- low res screenshots of example circuits, super unclear pin descriptions, you name it! Plus, when I tried it on my custom PCB I wasn't able to get it booting after like a month of on and off debugging. So I switched to Cypress parts, never to look back.

Yeah, unfortunately this driver isn't totally set up for the dual channel devices yet. I realized that when I was writing it but didn't really have time to go back and add support. At present I don't actually have a dual channel device to test with, though I might pick one up at some point.

The first thing we need to fix is the USB device scanning code in cy_scb_context.py, as you discovered. This code exists because these chips can have arbitrary VID/PID values, and I wanted a way to reliably detect them just based on their USB structure.

So that I can update the detection code, could you run this detection script on your PC with the CY7C65215 attached? I will probably need one run with it in I2C, SPI, and UART modes. That should give me enough info to update the detection code. Alternately you're welcome to submit a patch if you are confident making the needed mods.

After we fix that, the next step will be to update the driver code to properly distinguish SCB1 and SCB2. Currently some places are aware of the difference but other places aren't. We will probably need to add some new command line options as well. Last but not least, we will have to update the configuration code to be dual channel aware. I think the dual channel devices must use a somewhat different configuration format, so that will probably require some reverse engineering of the "set settings with USCU, then dump the config block" variety.

@runger1101001
Copy link
Author

I've actually made a bit of progress which I need to clean up and add to my PR...

I've also started working on a flash.py CLI tool, since I think writing to flash memories or FPGAs will be a primary use case. The current SPI code in the cy_serial_cli is good for testing but not enough to properly interact with flash memories. So I'm trying to add a small tool that will speak to CFI-conformant devices and allow the user to read/write/erase the chips.

I'll try to run the detection later today, or latest by end of week - I'm killer busy at the moment :-/

@multiplemonomials
Copy link

That would be awesome, thank you!

@runger1101001
Copy link
Author

runger1101001 commented Nov 27, 2024

Sorry for the delay... very busy at the moment, it took a while to fit this in. But I've finally done some more work on my PR and have checked the USB device infos for you now...

For the screenshot and device scan below I had things configured with one CDC UART interface and one SPI interface on the two SCBs:

USBProber Screengrab:

image

Output of scan_device_tree.py:

- Device: 04b4:0007, Cypress Semiconductor USB-Serial (Dual Channel), SerNo: None
---> Cfg: Num Interfaces: 4, Identifier: 1, Attributes: 0xa0
    ---> Interface 0
        ---> Alternate settings 0: Num Endpoints: 1, Class and SubClass: (0x02, 0x02), Protocol: 1
            ---> Endpoint 0x83: Direction: Dev-To-Host, Type: Interrupt
    ---> Interface 1
        ---> Alternate settings 0: Num Endpoints: 2, Class and SubClass: (0x0a, 0x00), Protocol: 0
            ---> Endpoint 0x01: Direction: Host-To-Dev, Type: Bulk
            ---> Endpoint 0x82: Direction: Dev-To-Host, Type: Bulk
    ---> Interface 2
        ---> Alternate settings 0: Num Endpoints: 3, Class and SubClass: (0xff, 0x02), Protocol: 0
            ---> Endpoint 0x04: Direction: Host-To-Dev, Type: Bulk
            ---> Endpoint 0x85: Direction: Dev-To-Host, Type: Bulk
            ---> Endpoint 0x86: Direction: Dev-To-Host, Type: Interrupt
    ---> Interface 3
        ---> Alternate settings 0: Num Endpoints: 0, Class and SubClass: (0xff, 0x05), Protocol: 0

I have committed the changes you requested to my fork, and the PR has updated.
I've also committed changes to the cy_scb_context regarding the device identification. Of course, my problem is that I don't have the other devices to compare :-) but hopefully together we will get there.

I think I'm part of the way towards a solution.

The changes I have made are fundamentally this:

  • the detection code was too geared towards the single SBC chips. With the dual channel chips, you can have multiple serial/spi/i2c devices, with CDC or vendor mode, etc.
  • so the approach I took is to categorise each interface as one of the types: CDC, VENDOR UART, SPI, I2C, MFG, CDC_DATA, JTAG
  • after checking each interface type, we assign the ones we identified to the DiscoveredDevice. If the combination of stuff we found doesn't make sense, we skip the device

What's not yet working?

  • multiple interfaces of the same type (e.g. 2x SPI, 2x CDC). but its ok if you have for example 1xSPI and 1xCDC
  • the DiscoveredDevice.curr_cy_type assignment of the device. Since we have multiple interfaces we can be MFG, SPI and CDC all at the same time on the CY7C65215 and CY7C65215A

My proposal:

  • further refactor the code to allow the cli.py also to be more flexible and support multiple interfaces at the same time. DiscoveredDevice.curr_cy_type becomes a set of values rather than a single value.
  • In most situations it will be clear based on the desired operation which USB interface has to be used.
  • In some situations the -s parameter will be needed to distinguish which of two SBC interfaces you want to use, if you have 2x SPI and are trying to do a SPI read, for example

Furthermore:

  • we disable any kind of auto-configuration of the device type for the dual channel devices. The semantics are far too complex from my point of view, and user support will be a nightmare.
  • So instead if the type of interface isn't available for the operation you want, you get an error.
  • You can still read/write the configurations, so the user can manage type changes themselves by preparing the configs they need in advance using the GUI tool, and loading them explicitly when needed.

@multiplemonomials
Copy link

Nice work on this refactoring! I definitely agree that the current code needs a lot of work for dual channel devices. I might suggest simply having one DiscoveredDevice object map to one SCB, so you would just return two DiscoveredDevices (one with scb = 0, one with scb = 1) when you encounter a dual channel device.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants