Author Topic: Any tips on making a logic analyzer with STM32F446ZE  (Read 7126 times)

0 Members and 1 Guest are viewing this topic.

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #25 on: February 02, 2019, 02:59:04 pm »
I want to build a Z80 in-circuit emulator that supports call tracing, debugging/breakpoints and circuit manipulation (like writing to the memory in-circuit).
To know how the Z80 drives its pins I thought I would make a purpose built logic analyzer and stream execution of a special program (that simply issues 'all' instructions) to the PC over USB. On the PC I would record the USB data stream and convert that into one of the import formats PulseView supports to make pretty pictures. I might even write a wavedrom convertor. This information is the basis for writing the in-circuit emulator.

I would like to be able to get it to run in the 4-6 MHz range or higher if feasible. That would make it a general purpose Z80 in-circuit emulator usable for anyone with a homebrew project or to repair a vintage home computer. Concerns about timing alignment and skew are reasonable, although I have half a clock cycle (25ns at 20MHz or 125ns at 4MHz)  to (over?) sample the pins... True, some pins are a little slower than others but all triggered on pos- or neg-edges. Clearly this is the critical speed factor (for the in-circuit emulator): At what speed can I reliably read/write all pins and perform the (debugging)logic...?

My circuit can run at 1kHz (-tested- probably even slower) so I am not worried about slowing the clock.

I picked the F446 because I have that laying around (PSoC5 too) - I want to avoid having to setup an entire hardware project for this.
I did play with FPGA's a bit (my circuit uses a CPLD) but writing a Z80 softcore with these features is out of my league (yes I know there are existing Z80 softcores - still would require me to add features).

Also, it is a STM32 learning experience.
« Last Edit: February 02, 2019, 03:13:52 pm by obiwanjacobi »
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #26 on: February 02, 2019, 05:18:19 pm »
My circuit can run at 1kHz (-tested- probably even slower) so I am not worried about slowing the clock.

If speed is not a problem then you can do practically anything. To get 40 pins @1 kHz, even serial sampling at 40 kSa/s will work. The higher the speed, the tougher it gets.
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #27 on: February 09, 2019, 11:04:31 am »
I am trying to get a hello world over USB working:
Spew a counter value over USB to the PC where an app using libusb is picking that up.

Problem is I do not speak SMT32's HAL speak yet so I feel lost in the woods - remember this is my first SMT32 project.
I use CubeMX to generate the code and Atollic True Studio as IDE.

In CubeMX I've configured the USB as Device only (deselected SOF and VBUS) - kept all defaults.
The USB_DEVICE middleware I have set to HID because that is easiest to get working on Windows - also all defaults.

I also do not know the details on how USB works. Turns out that these are too many unknowns to be able to quickly get this going.
Hence I turn to you.

Found an USB sample in STM32Cube/Repository but that only shows basically the same code I get from CubeMX: it init's the USB but does not send anything (great sample guys!)

I don't know what calls to use to actually send some data over USB (and can't find a CubeMX/HAL example).
I have tried some (last one was USBD_CtlSendData), but they made getting the descriptors fail on the PC or returned error codes...

I would really appreciate some pointers:
- to CubeMX/HAL documentation
- an example of using USB with an F4 (or similar) that actually does something
- what type of USB config is simplest and fastest - and how to set that up?

I have seen lots of other (custom) libraries, but I really would like to keep the dependencies down and not involve other stuff.
Also, I hear everybody bash HAL - I would like to see for myself  ;D


Added to MX_USB_DEVICE_Init()
Code: [Select]
USBD_LL_OpenEP(&hUsbDeviceFS, 1, USBD_EP_TYPE_BULK, 64);

main.c
Code: [Select]
  ...
  MX_USB_DEVICE_Init();
  long counter = 0;
  while (1)
  {
  USBD_StatusTypeDef result = USBD_CtlSendData(&hUsbDeviceFS, (uint8_t*)&counter, sizeof(counter));
  if (result == USBD_OK)
  counter++;
  }
  ...
*) removed all the green code markers
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #28 on: February 09, 2019, 12:15:50 pm »
There is enough USB  examples already present in the library packages and enough application notes and other third party materials for this.

Just don't be lazy ;)

https://damogranlabs.com/2018/02/stm32-usb-cdc/

 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #29 on: February 10, 2019, 06:55:47 am »
There is enough USB  examples already present in the library packages and enough application notes and other third party materials for this.
With 'library packages' do you mean the 'STM32Cube/Repository' folder?
That is where I found a 'demonstration' of USB HID but without any actual data handling.
There are so many projects there that it is hard to find the right one.

Just don't be lazy ;)
I try not to be - I have spend a good few hours trying out different USB configs and searching online for the relevant information.
But most experienced users (in any field) forget how many little bits of information you need to know to be sufficient in the object matter.
Some things that might be logical and self explanatory to you - can be a mystery to me (I'm a noob in this).
So asking for some pointers could just fill in that missing piece for me.

https://damogranlabs.com/2018/02/stm32-usb-cdc/
Yes CDC - that brings up the USB device as a COM port (on windows at least). I was not sure if that was the correct interface for the highest bandwidth.
Is that your recommendation - that I use CDC instead of HID? And if so, should I still use libusb on the PC or just fallback to the Windows COM API?
BTW I choose HID assuming it would be the easiest to get going...

Thanx.
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #30 on: February 10, 2019, 11:50:16 am »
CDC is definitely NOT for high data bandwidth! Sorry if I have confused you, I thought you were attempting that.

But definitely the easiest.  In theory, there is no limit, but in practice, the limit are fucking stupid windows USB drivers (USB host does not ask the device for data quick or often enough) and on linux the speed is bit better, but nearly not what USB is capable of.

If you need high bandwidth, make a completely custom protocol and use bulk transfer to move large amounts of data. However doing so requires in depth knowledge of USB which, guessing by your confusion with the libraries, you are lacking.

This will probably require writing custom drivers and/or working around with universal ones, like the libusb or others.  :-//

I am not sure how would you define a logic analyzer as an HID device.  HID would most than likely be ultra slow interface, due to transfer type it uses (interrupt?).

//yes, the standard COM Api is enough. If you can work with libusb, definitely use that instead over a custom protocol.
« Last Edit: February 10, 2019, 11:53:08 am by Yansi »
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #31 on: February 10, 2019, 03:45:12 pm »
No problem - I got a CDC echo working on a COM port (using putty) but as soon as I spew data in the main loop the PC does not recognize the USB device anymore.

Ok custom USB protocol: Is using Zadig custom enough?
When I replaced the standard Windows driver for the CDC sample (above) with winUSB I could pick up the connection with libusb in my PC program - did not check any data transfer, but I could open the USB with the vendor and product Ids.

Is there a CubeMX middelware usb device option for a custom protocol, or is that all hand coded? or- what CubeMX option would be a good starting point to copy from as a basis...?

Hmm, now I have the feeling I am the first one who tries to interface a STM32 to a PC with USB FS at 'Full Speed' - that can't be right, surely loads of other people have done this before me...?
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 2124
  • Country: us
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #32 on: February 10, 2019, 05:04:41 pm »
...
Hmm, now I have the feeling I am the first one who tries to interface a STM32 to a PC with USB FS at 'Full Speed' - that can't be right, surely loads of other people have done this before me...?
I've done it on a STM32F767 in FS mode, and using the HAL CDC driver.  It can sustain about 880kB/s (~7Mb/s) with a linux host.  I haven't looked at this for about a year, but take a look at a couple of things:

- In usbd_cdc_if.c APP_RX_DATA_SIZE should be 64 (not 4).

- After requesting a buffer to be sent via CDC_Transmit_FS(), you cannot change the data in the buffer until the transmit completes.

- And, while a buffer is being transmitted, you cannot call CDC_Transmit_FS() again until the interface is idle.

To address these last two, I used hcdc->TxState to check for idle, and set up a simple double buffer to handle newlib _write()'s to the USB interface to make sure CDC_Transmit_FS() has dedicated access to the transmit buffer.

Maybe ST has addressed these issues in more recent versions of CubeMX/HAL.  The version I made these fixes to is at least a year old (probably more).
 
The following users thanked this post: obiwanjacobi

Offline Yansi

  • Super Contributor
  • ***
  • Posts: 3893
  • Country: 00
  • STM32, STM8, AVR, 8051
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #33 on: February 11, 2019, 01:03:35 am »
I don't know, I am not too much of a windows programmer, I have only briefly encountered Zadig for the RTL-SDR dongle. And guess what - didn't work.

LibUSB could be likely installed manually (INF file is needed to be created  to assign the driver to your device).

Regarding the speed - we have tested also CDC at USB HS interface, the maximum speed (linux) was about 60mbps if I remember correctly. Which is "good enough", but nearly not the fulll USB potential there.

I should probably learn how to code GUI on PCs, especially to test out the libusb (I have quite some interesting applications for that too).
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #34 on: February 11, 2019, 06:54:13 am »
Good pointers @MarkL - thanks a lot.
I will code that up in my test program and see if I can transfer data to the PC with libusb.

We'll go from there.
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #35 on: February 12, 2019, 11:32:34 am »
- In usbd_cdc_if.c APP_RX_DATA_SIZE should be 64 (not 4).

- After requesting a buffer to be sent via CDC_Transmit_FS(), you cannot change the data in the buffer until the transmit completes.

- And, while a buffer is being transmitted, you cannot call CDC_Transmit_FS() again until the interface is idle.

To address these last two, I used hcdc->TxState to check for idle, and set up a simple double buffer to handle newlib _write()'s to the USB interface to make sure CDC_Transmit_FS() has dedicated access to the transmit buffer.

Seems like the current CubeMX code has these points pretty much covered. CDC_Transmit_FS() returns USB_BUSY if TxState != 0.
Stepping thru my STM32 code I can see the first call to CDC_Transmit_FS() is successful, after that it never works again.
I also have trouble receiving data on the PC. Do I need to flush anything?

main.c
Code: [Select]
  MX_USB_DEVICE_Init();

  const char* text = "-";
  while (1)
  {
  USBD_StatusTypeDef result = CDC_Transmit_FS((uint8_t*)text, 2);
  if (result == USBD_OK)
    HAL_Delay(200);
  }

Also been looking at the interface and endpoint numbers. Not sure which numbers I should use. Is there any way I can find this out?

On the PC side I do a
Code: [Select]
libusb_claim_interface -which takes an interface number and for receiving I start a transfer with
Code: [Select]
libusb_alloc_transfer and
Code: [Select]
libusb_submit_transfer which take an endpoint number (and is input | 0x80)...
I have used this type of code successfully with the PSoC5 USB...

Amazing how much time you can spend on something that looks simple enough...  :palm:
« Last Edit: February 12, 2019, 11:34:57 am by obiwanjacobi »
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #36 on: February 12, 2019, 04:39:02 pm »
I sniffed out the STM32 USB on the PC:
I'm using interface 3 and input EndPoint 5

Code: [Select]
descriptors[0] = "Configuration Descriptor"
bLength = 9
bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE (2)
wTotalLength = 67
bNumInterfaces = 2
bConfigurationValue = 1
iConfiguration = 0
Reserved = 0
SupportsRemoteWakeup = 0
SelfPowered = 0
PoweredByBus = 1
MaxPower = 0x96 -> 300 mA

descriptors[1] = "Interface Descriptor"
bLength = 9
bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE (4)
bInterfaceNumber = 2
bAlternateSetting = 0
bNumEndpoints = 1
bInterfaceClass = UsbCommunication (2)
bInterfaceSubClass = 2
bInterfaceProtocol = 1
iInterface = 6

descriptors[2] = "Class-Specific Interface Descriptor"
bLength = 5
bDescriptorType = CS_INTERFACE (36)
bDescriptorSubtype = 0
comm_interface = 
bcdCDC = 272

descriptors[3] = "Class-Specific Interface Descriptor"
bLength = 5
bDescriptorType = CS_INTERFACE (36)
bDescriptorSubtype = 1
comm_interface = 
call_capatibilities = 
controls = 
UseClassInterface = 0
SelfControl = 0
Reserved = 0
bmCapatibilities = 0
bDataInterface = 00000011

descriptors[4] = "Class-Specific Interface Descriptor"
bLength = 4
bDescriptorType = CS_INTERFACE (36)
bDescriptorSubtype = 2
comm_interface = 
abstract_control_capatibilities = 
controls = 
FeatureSupport = 0
LineStateSupport = 1
Send_Break_Support = 1
NotificationSupport = 0
Reserved = 0
bmCapatibilities = 00000110

descriptors[5] = "Class-Specific Interface Descriptor"
bLength = 5
bDescriptorType = CS_INTERFACE (36)
bDescriptorSubtype = 6
comm_interface = 
bMasterInterface = 2
bSlaveInterface =  3 

descriptors[6] = "Endpoint Descriptor"
bLength = 7
bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE (5)
bEndpointAddress = 4
Reserved = 0
Direction = Input
type = Interrupt (3)
reserved = 0
wMaxPacketSize = 2
bInterval = 255

descriptors[7] = "Interface Descriptor"
bLength = 9
bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE (4)
bInterfaceNumber = 3                                                                            <<==
bAlternateSetting = 0
bNumEndpoints = 2
bInterfaceClass = UsbCommData (10)
bInterfaceSubClass = 0
bInterfaceProtocol = 0
iInterface = 7

descriptors[8] = "Endpoint Descriptor"
bLength = 7
bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE (5)
bEndpointAddress = 5
Reserved = 0
Direction = Output
type = Bulk (2)
reserved = 0
wMaxPacketSize = 8
bInterval = 0

descriptors[9] = "Endpoint Descriptor"
bLength = 7
bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE (5)
bEndpointAddress = 5                                                                             <<==
Reserved = 0
Direction = Input    <<==
type = Bulk (2)
reserved = 0
wMaxPacketSize = 16
bInterval = 0
« Last Edit: February 12, 2019, 04:40:56 pm by obiwanjacobi »
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline obiwanjacobiTopic starter

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Any tips on making a logic analyzer with STM32F446ZE
« Reply #37 on: February 13, 2019, 04:57:13 pm »
Several things were wrong but the understanding that the Host initiates the USB communication with the device got me looking in the right place.
My basic test program now works. I can send data from the STM32 (CDC USB) to the PC and have libusb read that data.

When my order of connectors come in I can wire up a test setup and progress further.
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf