cancel
Showing results for 
Search instead for 
Did you mean: 

32F4 USB CDC - any way to tell if Host has retrieved the data sent to it?

PHolt.1
Senior III

The Cube IDE code flow is

CDC_Transmit_FS

USBD_CDC_TransmitPacket

USBD_LL_Transmit

HAL_PCD_EP_Transmit

USB_WritePacket

and the last one does 16 32 bit word transfers to the USB FIFO

HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma)
{
  uint32_t USBx_BASE = (uint32_t)USBx;
  uint32_t *pSrc = (uint32_t *)src;
  uint32_t count32b, i;
 
  if (dma == 0U)
  {
    count32b = ((uint32_t)len + 3U) / 4U;
    for (i = 0U; i < count32b; i++)
    {
      USBx_DFIFO((uint32_t)ch_ep_num) = *((__packed uint32_t *)pSrc);
      pSrc++;
    }
  }
 
  return HAL_OK;
}

My Q is whether there is any way to tell when that data has been consumed.

I have been doing tests and found

  • there is a ~10kHz rate limit on calling CDC_Transmit_FS
  • the max CDC_Transmit_FS packet size is 800 bytes

I am sure these are both system dependent, so I am rate limiting to 1kHz and size limiting to 256 bytes.

There are various return codes from various functions but none of these appear to relate to whether you can shove more data out.

Is USB really "open loop" like that? I know it is all polled by the PC, seemingly at ~10kHz

11 REPLIES 11
PHolt.1
Senior III

That depends on what the box is doing, how much buffering there is, what response time is needed, etc.

Much of my work is in comms and mostly one has buffers, so the whole box can run in IDLE. If one was doing 3 phase motor control at 10000rpm that would be different.

I have ETH RX as highest priority, then 2-3 lower ones, and all the rest is at IDLE. Timer tick is a 1kHz ISR, not an RTOS task.

Is TxState an int or a boolean?

Piranha
Chief II

A system tick (hardware with ISR) and the timer thread are related but different things. The timer thread manages all software timers. If the IDLE thread is not the only one at the lowest priority, it cannot be used to put the CPU into sleep mode, which is an unnecessary waste of energy and heating of the MCU without any gain. The ETH Rx thread typically doesn't need to be set at the highest priorities because typically it has several Rx buffers for packets and it's DMA can fill those completely autonomously. It could be that some thread processing UART or similar data has to be at a higher priority because that communication is more timing sensitive. But, of course, it depends on protocols, hardware buffers and the project specifics.

Running (almost) everything at a single priority is not an achievement. It's a deliberate crippling of the system for no reason. Except for a few bytes of RAM, you don't gain anything from that. That's true for up to 32 priority levels, which is plenty for almost anything. Going for more is indeed not recommended as it will loose more resources.

> Is TxState an int or a boolean?

It doesn't matter. What I mean is that this is enough:

while (hcdc->TxState)