Author Topic: STM32F103 double buffered bulk IN endpoint. [SOLVED]  (Read 2710 times)

0 Members and 1 Guest are viewing this topic.

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
STM32F103 double buffered bulk IN endpoint. [SOLVED]
« on: November 04, 2024, 08:10:23 pm »
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: [Select]
  0x07,   // bLength
  0x05,   // bDescriptorType: Endpoint
  0x81,   // bEndpointAddress: (1IN)
  0x02,   // bmAttributes: Bulk
  0x08,   // wMaxPacketSize: 8 bytes
  0x00,
  0x00,    // bInterval:

2- EP1 initialization:
Code: [Select]
...............
Addr += 64;
BTable[1].TX_ADDR = Addr; // TX0_ADDR
BTable[1].TX_COUNT = 0; // TX0_COUNT
Addr += 64; //
BTable[1].RX_ADDR = Addr; // TX1_ADDR
BTable[1].RX_COUNT = 0; // TX1_COUNT

// at startup the Application owns TX1BUF
USB->EPR[1] = EP_DTOG_RX | EP_KIND | EP_TX_VALID | 1;

fill(tx0buf, BTable[1].TX_ADDR);  // copy  tx0buf[] to TX0_ADDR in PMA
fill(tx1buf, BTable[1].RX_ADDR);  // copy  tx1buf[] to TX1_ADDR in PMA
BTable[1].TX_COUNT = 8; // TX0_COUNT  
BTable[1].RX_COUNT = 8; // TX1_COUNT
3- EP1 transfer complete interrupt handler:
to toggle the DTOG_RX bit I declared a pointer to it in the bitband region:
Code: [Select]
#define BITBAND_PERIPH(address, bit) ((uint32_t *)(0x42000000 + (((uint32_t)address) - 0x40000000) * 32 + (bit) * 4))
volatile uint32_t* bb_DTOGRX = BITBAND_PERIPH(&(USB->EPR[1]), 14);

and the handler:
Code: [Select]
if(EP == 1){
if(USB->EPR[1] & EP_CTR_TX){
USB->EPR[1] = 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.
« Last Edit: November 05, 2024, 07:24:58 pm by DELTA67 »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11911
  • Country: us
    • Personal site
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #1 on: November 04, 2024, 10:16:15 pm »
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.
Alex
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4676
  • Country: nl
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #2 on: November 05, 2024, 06:38:25 am »
and the handler:
Code: [Select]
  if(EP == 1)
  {
    if(USB->EPR[1] & EP_CTR_TX)
    {
      USB->EPR[1] = EP_BULK | EP_KIND |  1;   //Reset the CTR TX bit
      *bb_DTOGRX = 1;                         //toggle DTOG_RX  by bitbanding
    }
  }

If the intent is to actually toggle the bit, setting it  to one won't work. Exor with 1 should work.

Code: [Select]
  *bb_DTOGRX ^= 1;  //toggle DTOG_RX  by bitbanding

On 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.

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11911
  • Country: us
    • Personal site
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #3 on: November 05, 2024, 07:01:02 am »
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.
Alex
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #4 on: November 05, 2024, 07:06:59 am »
Thanks ataradov and pcprogrammer.
For the descriptor length - it is likely your size calculations are wrong when copying the data, so you are not copying the last byte.
Here's how I copy RAM to PMA:
Code: [Select]
uint16_t* txbuf;    // transmit buffer pointer.
uint16_t l2tx;              // 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[EPn].TX_ADDR * 2);
BTable[EPn].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);
}

Just toggle it manually.

I tried it this way but it did'nt work:
Code: [Select]
void togl_DTOG_RX(uint8_t EPn){
register uint16_t val = USB->EPR[EPn];         // Read Current EP stat
USB->EPR[EPn] = (val ^1<<14) & 0xCF8F; // Toggle DTOG_RX
}
Have you a working code please?

there is a button in the editor to list code, which works better than using the quote button.

DONE!
« Last Edit: November 05, 2024, 03:31:19 pm by DELTA67 »
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #5 on: November 05, 2024, 08:45:32 am »
Frome here:
https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/memory-model/optional-bit-banding
We can read:
Quote
The memory map has two 32-MB alias regions that map to two 1-MB bit-band regions:
    * Accesses to the 32-MB SRAM alias region map to the 1-MB SRAM bit-band region.
    * Accesses to the 32-MB peripheral alias region map to the 1-MB peripheral bit-band region.

The USB periheral base address is 0x40005C00, so it's included in the 1-MB peripheral bit-band region, No?
« Last Edit: November 05, 2024, 01:06:53 pm by DELTA67 »
 

Offline Postal2

  • Frequent Contributor
  • **
  • !
  • Posts: 826
  • Country: 00
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #6 on: November 05, 2024, 12:20:54 pm »
.... With your help (thanks ataradov, pcprogrammer, ... and others) I can now control a LED ....
Yes, 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.
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #7 on: November 05, 2024, 12:39:48 pm »
there is a system gap between packets, during which time you will take the buffer.
Can you explain please?
 

Offline Postal2

  • Frequent Contributor
  • **
  • !
  • Posts: 826
  • Country: 00
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #8 on: November 05, 2024, 12:47:18 pm »
Can you explain please?
We 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.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4676
  • Country: nl
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #9 on: November 05, 2024, 02:58:57 pm »
Can you explain please?
We 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.

You 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.


Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4676
  • Country: nl
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #10 on: November 05, 2024, 03:06:08 pm »
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.

Ah yes, that is the "invariant value" thing. Forgot about that.

Offline Postal2

  • Frequent Contributor
  • **
  • !
  • Posts: 826
  • Country: 00
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #11 on: November 05, 2024, 03:27:59 pm »
... I have done so for a project, but switched to isochronous mode to make it work. ...
This 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.
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #12 on: November 05, 2024, 03:42:32 pm »
I will search for the latest version of my code tomorrow. It is on another machine, and I have to dig it up.
Ok, 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.
« Last Edit: November 05, 2024, 03:52:30 pm by DELTA67 »
 

Offline Postal2

  • Frequent Contributor
  • **
  • !
  • Posts: 826
  • Country: 00
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #13 on: November 05, 2024, 03:52:44 pm »
.... If you can, please,  try the bulk double buffering transfer, just for learning purpose, this will help us all here.
For educational purposes, it is better to read how this is organized on the FX2 chip in descriptions from 20 years ago.
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #14 on: November 05, 2024, 03:59:14 pm »
it is better to read how this is organized on the FX2 chip in descriptions from 20 years ago.
We are working with the STM32F103. It's USB module it's a little bit complicated.
 

Offline Postal2

  • Frequent Contributor
  • **
  • !
  • Posts: 826
  • Country: 00
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #15 on: November 05, 2024, 04:04:42 pm »
We are working with the STM32F103. It's USB module it's a little bit complicated.
Is FS harder than HS? OK.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4676
  • Country: nl
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #16 on: November 05, 2024, 04:20:24 pm »
I will search for the latest version of my code tomorrow. It is on another machine, and I have to dig it up.
Ok, 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.

About 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.

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #17 on: November 05, 2024, 04:25:58 pm »
For the bulk double buffering I'm not sure if I tried it with my own host driver.
Why a bulk double buffering needs a special driver?
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4676
  • Country: nl
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #18 on: November 05, 2024, 04:36:37 pm »
For the bulk double buffering I'm not sure if I tried it with my own host driver.
Why a bulk double buffering needs a special driver?

Not 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.

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #19 on: November 05, 2024, 04:41:29 pm »
Not per se for the double buffering, but to obtain full speed.
OK!
I've done some debugging:
The initial status of EP1 is 0x4131 = 0b0100 0001 0011 0001 as expected
after the first bulk read it changes to 0x0101 = 0b0000 0001 0000 0001
we 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.
« Last Edit: November 05, 2024, 04:47:37 pm by DELTA67 »
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #20 on: November 05, 2024, 05:01:51 pm »
@pcprogrammer:
If you've already tried double buffered bulk can you share your code please?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11911
  • Country: us
    • Personal site
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #21 on: November 05, 2024, 05:04:49 pm »
Here's how I copy RAM to PMA:
I 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.

Have you a working code please?

Here is how I clear it in my code:
Code: [Select]
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.
Alex
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #22 on: November 05, 2024, 05:14:17 pm »
  USB_EPnR(ep) |= (USB_EP_CTR_RX | USB_EP_CTR_TX | USB_EP_DTOG_RX);

A 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.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11911
  • Country: us
    • Personal site
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #23 on: November 05, 2024, 05:22:00 pm »
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.
Alex
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 104
  • Country: fr
Re: STM32F103 double buffered bulk IN endpoint.
« Reply #24 on: November 05, 2024, 05:32:34 pm »
Having USB sniffer might help.
When I add a dummy byte at the end of the config desc, Wireshark complains from the format but it displays correctly the fields.
« Last Edit: November 05, 2024, 05:52:39 pm by DELTA67 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf