STM32F1 Bulk transfer size problem

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: barthess, RoccoMarco

rbarreiros
Posts: 27
Joined: Sat Mar 28, 2015 2:32 am

STM32F1 Bulk transfer size problem

Postby rbarreiros » Tue Apr 05, 2016 6:02 pm

Hello,

I'm having a problem that I can't pin point the reason.

From what I read, FS USB bulk transfers can be max 64 bytes, but I'm having issues sending and receiving bulk data with 64 bytes, 63 and below work pretty well.

My test project is here:
https://github.com/rbarreiros/STM32F1-usb-test

Any idea what am I doing wrong ? or if I'm doing anything wrong at all ! I tried to debug the issue with no success :/

Thanks.

User avatar
Giovanni
Site Admin
Posts: 13012
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 744 times
Been thanked: 620 times
Contact:

Re: STM32F1 Bulk transfer size problem

Postby Giovanni » Tue Apr 05, 2016 6:55 pm

Hi,

Hard to tell, my usual test writes blocks much larger than 64 bytes.

Just a note, when you get the event of input available then you need to keep reading from the endpoint until the returned length is zero or the queue will not be emptied. Use TIME_IMMEDIATE as timeout, you don't need to sleep.

Giovanni

rbarreiros
Posts: 27
Joined: Sat Mar 28, 2015 2:32 am

Re: STM32F1 Bulk transfer size problem

Postby rbarreiros » Wed Apr 06, 2016 10:41 am

I noticed something strange, I increased the size of the array holding the data read from 64 to 128, to make sure I would empty the buffer, then I proceeded to make sure all the data was read from the buffer by checking when the length returned was 0, but still had the same problem, the test.c was getting read timeouts from the device, but sending to the device was ok, only that the device would acknowledge a read only after every 4th send, 4 * 64 = 256 which is the SERIAL_USB_BUFFERS_SIZE so I decreased SERIAL_USB_BUFFERS_SIZE to 64, and lo and behold, the data flows.

Is this supposed to happen ? can't I have a SERIAL_USB_BUFFERS_SIZE of say 128, and still be able to read from queue before it's full, empty it, reply the host and repeat ? Is me doing something wrong ?

Thanks.

p.s. : I updated the repo above with this changes

skute
Posts: 64
Joined: Wed Aug 29, 2012 10:17 pm

Re: STM32F1 Bulk transfer size problem

Postby skute » Thu Apr 07, 2016 5:09 am

This sounds like a protocol issue. When sending data of max packet size the host/device need to 'terminate' the request with a short packet (zero-length packet). Without a short packet both the host/device don't know the transfer has ended if the length is equal to the max packet size.

To test you can try changing the max packet size to 16 and see if the problem occurs when attempting to transfer 16 bytes.

User avatar
Giovanni
Site Admin
Posts: 13012
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 744 times
Been thanked: 620 times
Contact:

Re: STM32F1 Bulk transfer size problem

Postby Giovanni » Thu Apr 07, 2016 8:10 am

The insertion of the zero packet should be performed by the driver, I need to test this, weekend job.

It would be interesting to test your application on a device with the OTG cell, it uses a different driver, and see if the result is the same or if it works. That would hint at a problem in the driver.

Giovanni

rbarreiros
Posts: 27
Joined: Sat Mar 28, 2015 2:32 am

Re: STM32F1 Bulk transfer size problem

Postby rbarreiros » Thu Apr 07, 2016 11:11 am

When debugging, I noticed in wireshark that libusb was sending the 0 length packet, so I would assume the problem is in ChibiOS, I'll try to test a bit further.

Off topic quick question, can I put a callback function inside a thread ? or I shouldn't ? Something like this:

Code: Select all

static THD_WORKING_AREA(waThread2, 1024);
static THD_FUNCTION(Thread2, arg)
{
    uint8_t buffer[513];

    void mycallback(UARTDriver *uart)
    {
        ...
        chSysLockFromISR();
        uartStartSendI(uart, sizeof(buffer), buffer);
        chSysUnlockFromISR();
    }

    thd_config_t cfg = (thd_config_t)arg;
    ...
    cfg.uartCfg.txend2_cb = &mycallback;

    while(true)
    {
        chThdMiliseconds(10); // Do I really need this or can be ignored ?
    }
}

int __attribute__((noreturn)) main(void)
{
    halInit();
    chSysInit();

    thd_config_t cfg1, cfg2, cfg3;

    ... fill cfg structs ...

    chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, cfg1);
    chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, cfg2);
    chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, cfg3);

    while(true)
    {
        chThdMiliseconds(10); // Do I really need this or can be ignored ?
    }
}


Is this OK ? will each thread call each own callback instead of the same callback since they share the same name ?

User avatar
Giovanni
Site Admin
Posts: 13012
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 744 times
Been thanked: 620 times
Contact:

Re: STM32F1 Bulk transfer size problem

Postby Giovanni » Thu Apr 07, 2016 11:16 am

Each thread should call its own but it is not standard C, it is a GNU extension.

BTW, I am not sure it would work with callbacks, try to avoid it. Writing into the configuration structure after the driver is started is also a bad idea, it is meant to be constant.

Giovanni

rbarreiros
Posts: 27
Joined: Sat Mar 28, 2015 2:32 am

Re: STM32F1 Bulk transfer size problem

Postby rbarreiros » Thu Apr 07, 2016 11:37 am

Giovanni wrote:Writing into the configuration structure after the driver is started is also a bad idea, it is meant to be constant.

Giovanni


The callback change in the config struct in that code was just an example to make the point, I do change it's config, but only the BRR, to send the break signal in a DMX stream, I tried the 'proper' approach, uartStop, change cfg, uartStart but the time this takes is too much, makes the break too long, so, I opted for the following, which works:

Code: Select all

void txend2_cb(UARTDriver uart)
{
  switch(dmxStatus)
  {
    case BREAK: // Break finished, send DMX Stream
      dmxStatus = IDLE;

      uart->usart->BRR = dmxBRR;
      chSysLockFromISR();
      uartStartSendI(uart, DMX_BUFFER_SIZE, dmxStream);
      chSysUnlockFromISR();

      break;
    case IDLE:  // Finished sending stream, send break
      dmxStatus = BREAK;

      uart->usart->BRR = brkBRR;
      uint8_t tmp[1] = {0};
      chSysLockFromISR();
      uartStartSendI(uart, 1, &tmp);
      chSysUnlockFromISR();
      break;
  };
}


BRR value is saved in brkBRR and dmxBRR after I set the correct baudrate in the cfg struct in order to avoid having to recalculate the BRR every time I change it:

Code: Select all

...

UARTConfig uartCfg = { NULL, NULL, NULL, NULL, NULL, DMX_BAUDRATE, 0, USART_CR2_STOP_1, 0 };
uartStart(UART1, &uartCfg);
dmxBRR = uartCfg.BRR;
uartStop(UART1);
uartCfg.speed = BREAK_BAUDRATE;
uartStart(UART1, &uartCfg);
brkBRR = uartCfg.BRR;
uartStop(UART1);

...


I would guess that is ok ?

rbarreiros
Posts: 27
Joined: Sat Mar 28, 2015 2:32 am

Re: STM32F1 Bulk transfer size problem

Postby rbarreiros » Tue Apr 12, 2016 11:20 am

Hello Giovanni,

Any news on your weekend test ?

I got my code running right now using a max packet size of 63, but I'd love to have it standard on 64 ! :D

Another small issue, while debug is on (specially asserts) if I connect/disconnect/connect the device it hits an assert because it calls usbInitEndpointI twice (1 each connect) because of osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); shouldn't it be de-init when disconnecting ? or, removed the assert ?

Other small issue, I don't need to set configuration on libusb when opening the device, but, some other applications might, and, right now, when calling set_configuration after running the test application which does a libusb open/set_configuration/claim_interface/bulk_transfer/release_interface/close twice, the third time, I get a -99 (LIBUSB_ERROR_OTHER) error when I run the test app again when calling set_configuration, and a -1 (LIBUSB_ERROR_IO) when trying to bulk write/read to the device. The device doesn't 'crash' as everything else keeps running, just stops talking USB, debug shows nothing wrong !

Best regards.

User avatar
Giovanni
Site Admin
Posts: 13012
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 744 times
Been thanked: 620 times
Contact:

Re: STM32F1 Bulk transfer size problem

Postby Giovanni » Tue Apr 12, 2016 12:42 pm

No news yet, I am in a busy month so little is going on with ChibiOS. I would appreciate if somebody could run a test about this else I will try again in next weekend.

Giovanni


Return to “STM32 Support”

Who is online

Users browsing this forum: No registered users and 2 guests