STM32F103 double buffered bulk IN endpoint. [SOLVED] - Page 1
Forum section: electronics / general

author: DELTA67
author_rank: Regular Contributor
timestamp: November 04, 2024, 08:10:23 pm
content: Hi all,I'm experimenting with USB on the STM32F103C8 as I've mentionned in this thread:https://www.eevblog.com/forum/microcontrollers/weird-stm32f103-usb-module!!/With your help (thanks ataradov, pcprogrammer, ... and others) I can now control a LED via control transfer or send/receive data via simple bulk transfer.The only problem however, is when the size of the config descriptor is EVEN, the device can't be enumerated!! I've to add an extra dummy byte in order to get things working. No problem with other descriptors if they are even.Now I'm struggling with double buffered IN endpoint. Only one buffer can be sent to the host.Here's how I do it:1- EP1 descriptor:Code:0x07, // bLength0x05, // bDescriptorType: Endpoint0x81, // bEndpointAddress: (1IN)0x02, // bmAttributes: Bulk0x08, // wMaxPacketSize: 8 bytes0x00,0x00, // bInterval:2- EP1 initialization:Code:...............Addr += 64;BTable.TX_ADDR = Addr;// TX0_ADDRBTable.TX_COUNT = 0;// TX0_COUNTAddr += 64;//BTable.RX_ADDR = Addr;// TX1_ADDRBTable.RX_COUNT = 0;// TX1_COUNT// at startup the Application owns TX1BUFUSB->EPR = EP_DTOG_RX | EP_KIND | EP_TX_VALID | 1;fill(tx0buf, BTable.TX_ADDR);// copy tx0buf[] to TX0_ADDR in PMAfill(tx1buf, BTable.RX_ADDR);// copy tx1buf[] to TX1_ADDR in PMABTable.TX_COUNT = 8;// TX0_COUNTBTable.RX_COUNT = 8;// TX1_COUNT3- EP1 transfer complete interrupt handler:to toggle the DTOG_RX bit I declared a pointer to it in the bitband region:Code:#define BITBAND_PERIPH(address, bit) ((uint32_t *)(0x42000000 + (((uint32_t)address) - 0x40000000) * 32 + (bit) * 4))volatile uint32_t* bb_DTOGRX = BITBAND_PERIPH(&(USB->EPR), 14);and the handler:Code:if(EP == 1){if(USB->EPR & EP_CTR_TX){USB->EPR = EP_BULK | EP_KIND | 1; //Reset the CTR TX bit*bb_DTOGRX = 1;//toggle DTOG_RX by bitbanding}}4- The host application:a 10 times for() loop doing usb_bulk_read() from the device.I expected to see tx0buf[] then tx1buf[] then tx0buf[] ...etc, but I get only the contents of tx0buf[] once then the device stops responding.

author: ataradov
author_rank: Super Contributor
timestamp: November 04, 2024, 10:16:15 pm
content: For the descriptor length - it is likely your size calculations are wrong when copying the data, so you are not copying the last byte. Although it is strange that it happens when it is even.For the other issue. I have never used double buffered endpoints, but I'm 99.9% sure USB controller will not work with bit-band region. It barely works with regular register access.Just toggle it manually. It is stupid complicated to figure out all combination of bits to not accidentally clear something else, but it is doable.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 06:38:25 am
content: Quote from: DELTA67 on November 04, 2024, 08:10:23 pmIf the intent is to actually toggle the bit, setting it to one won't work. Exor with 1 should work.Code:*bb_DTOGRX ^= 1; //toggle DTOG_RX by bitbandingOn a side not, there is a button in the editor to list code, which works better than using the quote button. It is the one marked with the # symbol, right next to the quote button.

author: ataradov
author_rank: Super Contributor
timestamp: November 05, 2024, 07:01:02 am
content: This bit is toggled by writing one to it. The issue is that this register is the stupidest thing I've seen in my entire life as far as registers concerned. It is a mine fiend of bits that are cleared by writing one, writing 0 or toggled by writing one. So, you have to come up with creative masks to not mess up the bits you don't want to mess up.If controller supported toggling from bit-band region, it would be cool. But given how shit the design is to begin with, I really doubt it.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 07:06:59 am
content: Thanks ataradov and pcprogrammer.Quote from: ataradov on November 04, 2024, 10:16:15 pmHere's how I copy RAM to PMA:Code:uint16_t*txbuf; // transmit buffer pointer.uint16_tl2tx; // bytes still need to be send.//=================================================void RAM2PMA(uint8_t EPn){uint32_t i;uint8_t count = l2tx <= 8 ? l2tx : 8;uint32_t* dest = (PMA_BASE + BTable.TX_ADDR * 2);BTable.TX_COUNT = count;for (i = 0; i<(count+1)/2; i++) *dest++ = *txbuf++;l2tx -= count;setValid(EPn, TX);}//=================================================void sendData(uint8_t EPn, uint16_t* data, uint16_t length){if(length > SETUPPACKET->wLength) l2tx = SETUPPACKET->wLength;else l2tx = length;txbuf = data;RAM2PMA(EPn);}Quote from: ataradov on November 04, 2024, 10:16:15 pmI tried it this way but it did'nt work:Code:void togl_DTOG_RX(uint8_t EPn){register uint16_t val = USB->EPR;// Read Current EP statUSB->EPR = (val ^1<<14) & 0xCF8F;// Toggle DTOG_RX}Have you a working code please?Quote from: pcprogrammer on November 05, 2024, 06:38:25 amDONE!

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 08:45:32 am
content: Frome here:https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/memory-model/optional-bit-bandingWe can read:QuoteThe USB periheral base address is 0x40005C00, so it's included in the 1-MB peripheral bit-band region, No?

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 12:20:54 pm
content: Quote from: DELTA67 on November 04, 2024, 08:10:23 pmYes, they are great, especially ataradov.Your question about double buffering doesn't make sense, because there is a system gap between packets, during which time you will take the buffer.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 12:39:48 pm
content: Quote from: Postal2 on November 05, 2024, 12:20:54 pmCan you explain please?

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 12:47:18 pm
content: Quote from: DELTA67 on November 05, 2024, 12:39:48 pmWe are dealing with a slow USB FS, the buffer size is 64 bytes. When transferring in any direction with any degree of buffering on the oscilloscope you will always see gaps, sufficient in time to rewrite 64 bytes 10 times anywhere, which negates the meaning of the buffering itself.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 02:58:57 pm
content: Quote from: Postal2 on November 05, 2024, 12:47:18 pmYou are dealing with a 1ms interval between packages, so indeed with bulk transfer on 12Mbit/s double buffering does not add anything useful. Only when the host ups the frequency of fetching packages does it help, and for this you need a dedicated host driver.I have done so for a project, but switched to isochronous mode to make it work.@DELTA67, I will search for the latest version of my code tomorrow. It is on another machine, and I have to dig it up.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 03:06:08 pm
content: Quote from: ataradov on November 05, 2024, 07:01:02 amAh yes, that is the "invariant value" thing. Forgot about that.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 03:27:59 pm
content: Quote from: pcprogrammer on November 05, 2024, 02:58:57 pmThis will work in point-to-point conditions. Any USB hub between devices will give a minimum 50 µS gap between FS packets, if we count on this gap, our device will work both directly and through the hub equally. Especially considering that many SBCs obviously have a hub, and laptops have a limited number of USB sockets.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 03:42:32 pm
content: Quote from: pcprogrammer on November 05, 2024, 02:58:57 pmOk, thanks in advance.Have you any solution for teh EVEN size of config desc problem? I've tried your code in the previous thread with no success.If you can, please, try the bulk double buffering transfer, just for learning purpose, this will help us all here.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 03:52:44 pm
content: Quote from: DELTA67 on November 05, 2024, 03:42:32 pmFor educational purposes, it is better to read how this is organized on the FX2 chip in descriptions from 20 years ago.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 03:59:14 pm
content: Quote from: Postal2 on November 05, 2024, 03:52:44 pmWe are working with the STM32F103. It's USB module it's a little bit complicated.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 04:04:42 pm
content: Quote from: DELTA67 on November 05, 2024, 03:59:14 pmIs FS harder than HS? OK.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 04:20:24 pm
content: Quote from: DELTA67 on November 05, 2024, 03:42:32 pmAbout the even size of the descriptor problem I have to look at my and your code and refresh my memory as to what is needed and why if might fail.For the bulk double buffering I'm not sure if I tried it with my own host driver. I did a lot of testing to get a continuous stream of data from the F103 into the host computer. With the CH340 host driver it did not work with bulk transfer, double buffered or not. The remaining bandwidth on the channel was never filled by the host. That is why I switched to isochronous mode.The host driver I wrote is only for Linux and I had to install it with modprobe, if I remember correctly, on every startup to be able to use it.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 04:25:58 pm
content: Quote from: pcprogrammer on November 05, 2024, 04:20:24 pmWhy a bulk double buffering needs a special driver?

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 04:36:37 pm
content: Quote from: DELTA67 on November 05, 2024, 04:25:58 pmNot per se for the double buffering, but to obtain full speed. The CH340 driver only polls the device every millisecond to see if there is data to fetch. This leaves a lot of bandwidth in the channel not used. In the USB specifications it is allowed to use the free bandwidth if no other device on the channel needs it, but this has to be incorporated in the driver.Another reason of why I switched to iso mode is that the buffer can be bigger. Full speed bulk transfer uses at max 64 byte buffers, which also means more overhead in transmissions.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 04:41:29 pm
content: Quote from: pcprogrammer on November 05, 2024, 04:36:37 pmOK!I've done some debugging:The initial status of EP1 is 0x4131 = 0b0100 0001 0011 0001 as expectedafter the first bulk read it changes to 0x0101 = 0b0000 0001 0000 0001we see that:- STAT_TX (bits[5:4]) = 00 disabled (expected 11) !- DTOG_TX (bit6) = 0 NOT toggled by the hardware (expected 1) !!- DTOG_RX (bit14) = 0 toggled (by bitbanding) from 1 to 0 as expected.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 05:01:51 pm
content: @pcprogrammer:If you've already tried double buffered bulk can you share your code please?

author: ataradov
author_rank: Super Contributor
timestamp: November 05, 2024, 05:04:49 pm
content: Quote from: DELTA67 on November 05, 2024, 07:06:59 amI don't see anything obviously wrong with this code. Having USB sniffer might help. Even my RP2040 one should be good enough here, since the issue happens during enumeration.Quote from: DELTA67 on November 05, 2024, 07:06:59 amHere is how I clear it in my code:Code:if (USB_EPnR(ep) & USB_EP_DTOG_RX)USB_EPnR(ep) |= (USB_EP_CTR_RX | USB_EP_CTR_TX | USB_EP_DTOG_RX);But this code from endpoint clear feature request, so I don't think it was actually tested. But I expect this to be correct, I tried to get it right at the time of writing.If you want to toggle, then you don't need the "if" part.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 05:14:17 pm
content: Quote from: ataradov on November 05, 2024, 05:04:49 pmA simple ORing with DTOG_RX mask?It seems that bitbanding works for USB too. As you said it's a cool feature! Alas it's usful for single bits only I think. for multi bit fields like STAT_TX we have to do it à la old school.

author: ataradov
author_rank: Super Contributor
timestamp: November 05, 2024, 05:22:00 pm
content: Yes, a simple OR. OR will preserve all already set bits and CTR are written to1, since they are cleared by writing 0, so writing 1 is always safe and should not affect their value if they are set by the hardware in the meantime.There is nothing special about START_xx field. There is absolutely no reason they are set by toggling. This is just bad design. But if bit-banding works, it should work for them too. Non-atomicity is not a problem since no matter what you do, you are transitioning from disabled to valid state via NAK or STALL. And this is not a problem.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 05:32:34 pm
content: Quote from: ataradov on November 05, 2024, 05:04:49 pmWhen I add a dummy byte at the end of the config desc, Wireshark complains from the format but it displays correctly the fields.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 05, 2024, 05:41:00 pm
content: Quote from: ataradov on November 05, 2024, 05:04:49 pmWhen I was looking for a description of the initialization of USB FS fields, the source code of the libraries for STM32F103 turned out to be the best. I especially liked the hid-device from STM32F103. Now I know who to thank for the excellent code of these libraries.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 05:43:51 pm
content: Quote from: ataradov on November 05, 2024, 05:22:00 pmIf they designed it this way it's surely for a GOOD reason! The EP control register contains bits for both In and Out and the whole register is written at once.

author: ataradov
author_rank: Super Contributor
timestamp: November 05, 2024, 06:12:30 pm
content: ST has notoriously poorly designed register sets. There is no good reason for this. The reason this happens is that hardware people make the peripherals and by the time it gets to the software people it is too late to change anything. And then you get locked in into the poor design and carry it forward. And hardware people have completely different mindset of what is a good register design. Many things that are easy in the hardware end up being super ugly in the firmware.Spending some time upfront designing stuff like this pays off in a long run, but nobody does it.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 06:27:21 pm
content: Quote from: ataradov on November 05, 2024, 05:22:00 pmWOOOOOOW, It works !!!Code:if(EPn == 1){if(USB->EPR & EP_CTR_TX){USB->EPR = 1<<14 | EP_BULK | 1<<8 | 1; // clear CTR_TX and toggle DTOG_RX in the same time!}}Now I get the two buffers alternatly as expected.THANKS for all for your help.If someone needs the full project PM me and I'll attach it here.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 05, 2024, 07:32:19 pm
content: @DELTA67, if you had analyzed my CH340 code you would have seen that it is done in a similar way. I use specific registers for the endpoints instead of using array addressing, but the flags are handled in the same way. The comment also mentions the invariant values being used.Code://Signal we are ready to receive more data by preparing for toggling the needed RX status bits//Keep the other bits unaltered, by using the previous data or the invariant valueUSB->EP2R = ((USB->EP2R ^ USB_EP_RX_VALID) & (USB_EPREG_MASK | USB_EPRX_STAT)) | USB_EP_CTR_RX | USB_EP_CTR_TX;This is not using the double buffering, but the principle is the same. Based on ataradov his way it seems it can be simplified and still work.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 05, 2024, 07:51:30 pm
content: Quote from: pcprogrammer on November 05, 2024, 07:32:19 pmYes, your code is great, it has inspired me a lot, very much thanks.I'm waiting for your isochronous and bulk codes to studdy them. It seems that the host side for iso transfers is more complicated than that for bulk ones.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 09:29:12 am
content: Here is the project for the Linux iso host driver for the STM32F103 device I made.It only supports reading data from the device, which is a continuous stream of samples. In the stuff directory there are scripts that show how the driver is used.It is work from 5 years back and I have not used it since a long time, so forgot a lot about it.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 09:32:59 am
content: Here is the project for the STM32F103 device.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 09:48:35 am
content: I did not find the old projects with the bulk transfer mode. For what I recall of it, it was based on my CH340 driver. The double buffering setup most likely was the same as in the iso transfer mode project.The whole setup was to use samples from a 16 bit 100kSa/s ADC to feed a FFT based spectrum analyzer and an oscilloscope. At the time I was not up to speed with Linux native GUI coding, so I used a database and webpages for displaying the signals on the screen. Never really finished the project.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 06, 2024, 10:07:01 am
content: THANKS pcprogrammer for sharing this interresting project !Hugs

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 10:15:29 am
content: I'm trying to figure out your problem with the size of the Config Descriptor, but fail to see the problem.The size depends on the number of endpoints described in it, and it will be even when an even number of endpoints is described. The number of endpoints is given in the Interface Descriptor, and needs to match the number of Endpoint Descriptors that follow.When there is a mismatch between these the host will not enumerate the device.So when changing the Config Descriptor to add or remove an endpoint make sure to correct the number in the Interface Descriptor.Code://USB Configuration Descriptorconst uint8_t ConfigDescriptor[] ={0x09, // bLength: Configuration Descriptor size0x02, // bDescriptorType: Configuration0x27, // wTotalLength:no of returned bytes0x00,0x01, // bNumInterfaces: 1 interface0x01, // bConfigurationValue: Configuration value0x00, // iConfiguration: Index of string descriptor describing the configuration0x80, // bmAttributes: self powered0x31, // MaxPower 98 mA//Interface Descriptor0x09, // bLength: Interface Descriptor size0x04, // bDescriptorType: Interface// Interface descriptor type0x00, // bInterfaceNumber: Number of Interface0x00, // bAlternateSetting: Alternate setting0x03, // bNumEndpoints: 3 endpoints used !!!!!!! This needs to be changed when the number of endpoints changes !!!!!!!!0xFF, // bInterfaceClass: Vendor Interface Class0x01, // bInterfaceSubClass0x02, // bInterfaceProtocol0x00, // iInterface://Endpoint 2 IN Descriptor0x07, // bLength: Endpoint Descriptor size0x05, // bDescriptorType: Endpoint0x82, // bEndpointAddress: (IN2)0x02, // bmAttributes: Bulk0x20, // wMaxPacketSize:0x00,0x00, // bInterval://Endpoint 2 OUT Descriptor0x07, // bLength: Endpoint Descriptor size0x05, // bDescriptorType: Endpoint0x02, // bEndpointAddress: (OUT2)0x02, // bmAttributes: Bulk0x20, // wMaxPacketSize:0x00,0x00, // bInterval: ignore for Bulk transfer//Endpoint 1 IN Descriptor0x07, // bLength: Endpoint Descriptor size0x05, // bDescriptorType: Endpoint0x81, // bEndpointAddress: (IN1)0x03, // bmAttributes: Interrupt0x08, // wMaxPacketSize:0x00,0x01 // bInterval};

author: Postal2
author_rank: Frequent Contributor
timestamp: November 06, 2024, 10:41:21 am
content: Quote from: pcprogrammer on November 06, 2024, 09:32:59 amIs it really possible to send a variable packet length to the host? I haven't done that for a long time, for FX2LP if I request more than the device will give - the Windows system crashes to a blue screen.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 11:18:24 am
content: Quote from: Postal2 on November 06, 2024, 10:41:21 amThat project worked with the driver I wrote for Linux, so if there is variable length packages in there, which I don't recall, it is possible. To talk to the Linux driver I wrote other projects that get the data, perform checks and the FFT and write the result to a database. If wanted I can add those too.Ah Windows, when does it not crash.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 06, 2024, 11:36:06 am
content: Quote from: pcprogrammer on November 06, 2024, 11:18:24 amWell, I don't know. It seems to me that requesting a packet larger than sent is bad in any case. The bus is still overloaded with requests for some time. Although for FS this is probably not very relevant.But I will still make equal packets. I solved variable length packets by pre-querying the length through another point, it looks stupid.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 06, 2024, 12:03:55 pm
content: Quote from: pcprogrammer on November 06, 2024, 10:15:29 amThanks for your effort to solve the problem.Here's my config desc:Code:const uint8_t ConfigDescriptor[] = {0x09, // bLength: Configuration Descriptor size0x02, // bDescriptorType: Configuration// +14 for EP1 IN/OUT descriptors and +1 to keep the length ODD(9+9+7+7+1), // wTotalLength:no of returned bytes0x00,0x01, // bNumInterfaces: 1 interface0x01, // bConfigurationValue: Configuration value0x00, // iConfiguration: Index of string descriptor describing the configuration0x80, // bmAttributes: D7 =1 ==> bus powered50,// MaxPower: 50x2 = 100mA//Interface Descriptor0x09, // bLength: Interface Descriptor size0x04, // bDescriptorType: Interface descriptor type0x00, // bInterfaceNumber: Number of Interface0x00, // bAlternateSetting: Alternate setting0x02, // bNumEndpoints: 2 EPs0xFF, // bInterfaceClass: Vendor Interface Class0x00, // bInterfaceSubClass0x00, // bInterfaceProtocol0x00, // iInterface:// EP1 OUT descriptor0x07, // bLength: Endpoint Descriptor size0x05, // bDescriptorType: Endpoint0x01, // bEndpointAddress: (1OUT)0x02, // bmAttributes: Bulk0x08, // wMaxPacketSize: 8 bytes0x00,0x00, // bInterval:// EP1 IN descriptor0x07, // bLength: Endpoint Descriptor size0x05, // bDescriptorType: Endpoint0x81, // bEndpointAddress: (1IN)0x02, // bmAttributes: Bulk0x08, // wMaxPacketSize: 8 bytes0x00,0x00, // bInterval:// Add this byte to get an ODD length !!!!0x00};And here's how I send it:Code:uint16_t*txbuf;uint16_tl2tx;// bytes still need to be send.//=================================================void RAM2PMA(uint8_t EPn){uint32_t i;uint8_t count = l2tx <= 8 ? l2tx : 8;uint32_t* dest = (PMA_BASE + BTable.TX_ADDR * 2);BTable.TX_COUNT = count;for (i = 0; i<(count+1)/2; i++) *dest++ = *txbuf++;l2tx -= count;//Signal ready to transmitsetValid(EPn, TX);}//=================================================void sendData(uint8_t EPn, uint16_t *data, uint16_t length){if(length > SETUPPACKET->wLength) l2tx = SETUPPACKET->wLength;else l2tx = length;txbuf = data;RAM2PMA(EPn);}//=================================================================void send_descriptor(){switch(SETUPPACKET->wValueH){case DEVICE_DESC_TYPE:sendData(0, (uint16_t *)DeviceDescriptor, sizeof(DeviceDescriptor));break;case CFG_DESC_TYPE:sendData(0, (uint16_t *)ConfigDescriptor, sizeof(ConfigDescriptor));break;...........................

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 12:35:45 pm
content: Ah yes, there is the total length that also needs to be set. As I wrote before, it has been way back that I worked on the USB stuff.And your issue remains even when you adjust all the needed values?In another project on another MCU I wrote a device driver for mass storage class and that has only two endpoints and thus an even length Config Descriptor. Works without problems, so it is a bit strange that it fails in your case.

author: pcprogrammer
author_rank: Super Contributor
timestamp: November 06, 2024, 12:49:27 pm
content: Quote from: Postal2 on November 06, 2024, 11:36:06 amFor as far as I know the host does not request a number of bytes when getting data from a device. The device is setup with a maximum length for the buffers in use and can setup packages up to that max buffer length. Take my CH340 emulation driver on the STM32F103, it tells the host the buffers in use are 32 bytes in size and when the process on the STM32F103 only wants to send a single byte to the host, it just does this. If the process wants to send 1000 bytes it will be chopped up by the USB handler in 32 byte chunks and the host will fetch the data until there is nothing more to fetch.In my iso transfer based project the buffers are 232 bytes long and the process sends as many samples as fit in this 232 bytes, provided they are available. If there are less it will send less. If there are more it will have to lag behind and hope that the host catches up again. (I looked at the code to check this)So I don't see what your problem with variable length packages is.

author: DELTA67
author_rank: Regular Contributor
timestamp: November 06, 2024, 12:50:26 pm
content: Quote from: pcprogrammer on November 06, 2024, 12:35:45 pmYES !!

author: Postal2
author_rank: Frequent Contributor
timestamp: November 06, 2024, 01:50:01 pm
content: Quote from: pcprogrammer on November 06, 2024, 12:49:27 pmI know how the host works, but I'm not going to write my own driver for FX2LP to implement features I can do without. The driver needs to be sent the exact number of bytes to receive via deviceiocontrol.Code:bool myCyReadPipe(){//rcv via ep 86//max size = 4096 (0x1000)if ( hCyDevice == INVALID_HANDLE_VALUE ) return false;//use endpoint 0x02 as OUT (from host to device)//use endpoint 0x86 as IN (from device to host)//bytesToSEND = myFtdiBBangRWbufCurPointer//bytesToReceive = myFtdiCurFlushRcvBytes;//this use bit-bang via mpsse or real mpsse//myFtdiBBangRWbuf EARLY USED FOR R-W, BUT NOW myFtdiBBangRWbuf FOR READULONG length = sizeof(SINGLE_TRANSFER) + myFtdiCurFlushRcvBytes;//ULONG lengthBuf = sizeof(SINGLE_TRANSFER) + myFtdiCurFlushRcvBytes + 4096;// PUCHAR buf = new UCHAR;PUCHAR buf = myGlobalBuf2;DWORD dwReturnBytes;DWORD dwBytesReturned = 0;DWORD dwBytesReturned2 = 0;overlapped_R.hEvent = INVALID_HANDLE_VALUE;overlapped_R.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf;UINT retryCounter = 0;while(retryCounter++ < 2048){ZeroMemory (buf, length);pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST;pSingleTransfer->SetupPacket.ulTimeOut = 25;//25 sec for transfer???pSingleTransfer->reserved = 0;pSingleTransfer->ucEndpointAddress = 0x86;pSingleTransfer->IsoPacketLength = 0;pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER);pSingleTransfer->BufferLength = myFtdiCurFlushRcvBytes;DeviceIoControl(hCyDevice, IOCTL_ADAPT_SEND_NON_EP0_TRANSFER,buf, length,buf, length,&dwReturnBytes, &overlapped_R);//old timeout 500L, with 2000L correct timeout for i2c (?)if(WaitForSingleObject(overlapped_R.hEvent, 2000L) == WAIT_OBJECT_0 ){ GetOverlappedResult(hCyDevice, &overlapped_R, &dwBytesReturned2, TRUE);}else{//ASSUME EVENT BROKEN, TRY LAST READGetOverlappedResult(hCyDevice, &overlapped_R, &dwBytesReturned2, TRUE);// Copy last received to bufif(0 != (dwBytesReturned2 - sizeof(SINGLE_TRANSFER))) memcpy(&myFtdiBBangRWbuf, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), (dwBytesReturned2 - sizeof(SINGLE_TRANSFER)));dwBytesReturned += (dwBytesReturned2 - sizeof(SINGLE_TRANSFER));myMesShow(_T("timeout pipe 86."));//delete[] buf;//CloseHandle(overlapped_R.hEvent);//overlapped_R.hEvent = INVALID_HANDLE_VALUE;//return false;break;}// Copy received to bufif(0 != (dwBytesReturned2 - sizeof(SINGLE_TRANSFER))) memcpy(&myFtdiBBangRWbuf, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), (dwBytesReturned2 - sizeof(SINGLE_TRANSFER)));dwBytesReturned += (dwBytesReturned2 - sizeof(SINGLE_TRANSFER));if(dwBytesReturned >= myFtdiCurFlushRcvBytes) break;dwBytesReturned2 = sizeof(SINGLE_TRANSFER);//=0;}static UINT r_countMax = 0;if(r_countMax < retryCounter){r_countMax = retryCounter;if(eMMC_showDebugInfo){CString strTemp;strTemp.Format( "r_count= %d", r_countMax);myMesShow(strTemp);}}CloseHandle(overlapped_R.hEvent);overlapped_R.hEvent = INVALID_HANDLE_VALUE;//if(dwReturnBytes >= length)// Copy received to buf//{if(0 != myFtdiCurFlushRcvBytes) memcpy(myFtdiBBangRWbuf, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), myFtdiCurFlushRcvBytes);//delete[] buf;//return true;}if(dwBytesReturned >= myFtdiCurFlushRcvBytes)return true;myMesShow(_T("err len pipe 86."));nt_status_show(pSingleTransfer->NtStatus);usbd_status_show(pSingleTransfer->UsbdStatus);//delete[] buf;return false;}//end myCyReadPipeQuote from: pcprogrammer on November 06, 2024, 12:49:27 pmCode://Tell the USB system how many bytes to send*cptr = (cnt * BYTES_PER_COUNT) + 2;Quote from: pcprogrammer on November 06, 2024, 12:49:27 pmIf you don't see a problem - it means there is no problem.

author: Postal2
author_rank: Frequent Contributor
timestamp: November 07, 2024, 10:29:46 am
content: Now I understand where the opinion about the FX2LP driver comes from.Quote from: SiliconWizard on June 29, 2024, 10:39:02 pmThe driver is great, has a signature for Windows 10x64, you just need to have a normal programming style.Or use the option:Quote