2019-02-26 02:51 PM
Hi, I'm having a hard time understanding the HAL_PCDEx_SetTxFiFo() function that I should call inside the USBD_LL_Init() function for my Stm32L476. I have attach my descriptor results from USBTreeView. But here the highlight:
My composite device have multiple interface:
I did keep the IAD and CDC as the last into the descriptor since it seem to confuse some COM driver. But I still have a hard time with my endpoints and the call to init the TX buffer, I'm not sure I do the right thing.
Does HAL_PCDEx_SetTxFiFo() use for the fifo 2nd argument :
What is it represent exactly? Can I skip some? How much can be used, is 6 too much?
It seem like if I remove my application endpoints my CDC work normally and when I add them my write cannot be perform since the
CDC_Transmit_FS()
if (hcdc->TxState != 0){
return USBD_BUSY;
}
The TXState is always busy. This even if no driver and I do nothing with the other endpoints, the CDC stop working. I suspeect I don't do the rith thing with my tx buffer init with HAL_PCDEx_SetTxFiFo
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); /* Default control EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40); /* CDC bulk EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x10); /* CDC interrupt EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10); /* HID interrupt EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x40); /* App bulk EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x40); /* App interrupt EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 6, 0x40); /* App isochronous EP */
Maybe I got this wrong, I'm just not sure how this get link to the proper endpoint or if I overflow the RX space (I have read the F4 only support 0..5, not sure if this is true for the L4?).
Does the descriptor order and interface order and endpoint numbering have any requirements? like does the lowest interfaces should have the lowest endpoints numbers?
Solved! Go to Solution.
2019-02-27 07:59 AM
> yes we are using Stm32L476 as stated in the first message.
Sorry, I overlooked that information.
> since we are using small packet for 2 interrupts (0x10 for 16 multiples each) we could still have some RAM availables for a few endpoints with each (0x40).
Yes, but bear in mind that the sum of Rx FIFO and all Tx FIFOs is max. 1.25kB, i.e. max. 0x140 words).
> Where is this limitation [max. number of endpoints] documetend?
and also at several places in the OTG_FS chapter in RM.
> We though based on this presentation from ST that we were having 8 bi-directional endpoints (16 totals)
That presentation talks about the lower-end 'L4 range, see page 2. They contain an entirely different device-only USB module.
JW
2019-02-26 03:40 PM
I would rather recommend skipping these HAL calls, and configure the registers directly according to the reference manual. It will save you some time.
The HAL_PCDEx_SetTxFiFo() calls (and the Rx as well) are used in the examples as if they were allocating byte size in the FIFOs. Inside however they take the input as is, and write to the registers which are supposed to hold 32 bit word sizes. The reference manuals also contradict each other between devices with the same OTG IP: https://github.com/IntergatedCircuits/USBDevice4Cube/issues/1#issuecomment-439653127
2019-02-26 03:49 PM
humm, k, any offical documentation about those registers?
and why does the HAL_PCDEx_SetTxFiFo() have any issues or is buggy? I would rather not have to rewrite the whole HAL setup here if possible. I'm just trying to understand that function and known if I do the right thing. So I should use these formula how exactly?
L4:
(5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for status information) + (2 * number of OUT endpoints) + 1 for Global NAK
This is my stm32l4xx_hal_pcd_ex.c file for this functions. Not sure the equation match anything near that methode behavior.
HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
{
uint8_t index = 0;
uint32_t Tx_Offset = 0;
/* TXn min size = 16 words. (n : Transmit FIFO index)
When a TxFIFO is not used, the Configuration should be as follows:
case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
--> Txm can use the space allocated for Txn.
case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
--> Txn should be configured with the minimum space of 16 words
The FIFO is used optimally when used TxFIFOs are allocated in the top
of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
Tx_Offset = hpcd->Instance->GRXFSIZ;
if(fifo == 0)
{
hpcd->Instance->DIEPTXF0_HNPTXFSIZ = (size << 16) | Tx_Offset;
}
else
{
Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
for (index = 0; index < (fifo - 1); index++)
{
Tx_Offset += (hpcd->Instance->DIEPTXF[index] >> 16);
}
/* Multiply Tx_Size by 2 to get higher performance */
hpcd->Instance->DIEPTXF[fifo - 1] = (size << 16) | Tx_Offset;
}
return HAL_OK;
}
2019-02-26 04:10 PM
I don't use Cube so won't comment on usage of given function; you can look it up yourself, it's open source.
You didn't tell us which 'L4 are you talking about, so I assume it's 'L476 with respective RM0351; if it's not, look the respective details up in the RM for your particular model.
Also, the code snippet you gave us does not match the descriptor you attached, but that's not that important for the key points.
First of all, the 'L476 contains besides endpoints for EP0 only 5 IN and 5 Out endpoints, so that's probably your primary problem.
(Just a sidenote, in the mainstream 'F4xx there are two OTG modules and the OTG_HS has more endpoints).
The OTG module contains a certain amount of FIFO RAM (1.25kB for the 'L476), and you ought to tell the module how do you want to partition it, between one common Rx FIFO (common for all IN endpoints), and one FIFO for each Tx (OUT) endpoint. This is done by setting OTG_GRXFSIZ, OTG_DIEPTXF0 and OTG_DIEPTXFx registers, see description of these registers in OTG_FS registers subchapter of the OTG_FS chapter in RM. Note, all FIFO-related values are in words (how does this translate to the requirements of Cube/HAL functions, is up to you to find out). The Tx-FIFO registers generally contain not only the size of FIFO, but also its beginning, so the user can partition the FIFO in non-continuous chunks (even if this does not make much sense).
JW
2019-02-26 04:29 PM
> (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for status information) + (2 * number of OUT endpoints) + 1 for Global NAK
That's the recommendation for the Rx FIFO, i.e. the value to go to OTG_GRXFSIZ . See FIFO RAM allocation subchapter of the OTG_FS chapter in RM. I'm not going to comment on this formula nor the overall quality of documentation here.
JW
2019-02-27 07:27 AM
@Community member
yes we are using Stm32L476 as stated in the first message.
Thanks for the information. If the number of endpoints is limited to 5 IN and 5 OUT + the Control IN/OUT EP 0 if I understand well, that could explain the problems I see. I was not there when they did choose the hardware and I trying to add features into existing code.
I might need to revise my whole design. But I did not knew this limitation I knew it was 1.25 Kb RAM buffer was available, since we are using small packet for 2 interrupts (0x10 for 16 multiples each) we could still have some RAM availables for a few endpoints with each (0x40).
I did check that document:
Where is this limitation documetend? is it HAL limitation or the chip itself? I will add an assert so anybody who will try to do this on the chips will not compile anymore. We though based on this presentation from ST that we were having 8 bi-directional endpoints (16 totals) on page 3:
This is a bummer, since the CDC use 2 of them already, 1 for HID, that leave me with only 2 on the application control. I will go 1 bulk and 1 interrupt and remove the isochronous one. This is a rather complicated device that is used by 3 different drivers (1x HID driver, 1x VCOM for debug and production and 1x custom driver to control and operate the device).
Anyway thanks for the information, I will trim the design and see what I can do.
reagrds,
2019-02-27 07:59 AM
> yes we are using Stm32L476 as stated in the first message.
Sorry, I overlooked that information.
> since we are using small packet for 2 interrupts (0x10 for 16 multiples each) we could still have some RAM availables for a few endpoints with each (0x40).
Yes, but bear in mind that the sum of Rx FIFO and all Tx FIFOs is max. 1.25kB, i.e. max. 0x140 words).
> Where is this limitation [max. number of endpoints] documetend?
and also at several places in the OTG_FS chapter in RM.
> We though based on this presentation from ST that we were having 8 bi-directional endpoints (16 totals)
That presentation talks about the lower-end 'L4 range, see page 2. They contain an entirely different device-only USB module.
JW
2019-03-08 09:00 AM
Thanks for the information, I did remove the isochronous endpoint to reduce to 5 endpoints IN. Now I have the following descriptor. I have goes through the usbcdc110.pdf and reorder the interfaces and endpoints to be into an easier way to follow and make sure the descriptor is in order. Now I have
I still have issues with my COM port for some reason, I cannot write the bus is stick to busy, maybe something I do is totally wrong or my handling is wrong, but I have a hard time understanding why the VCOM is not working anymore (I have a setup where I only have the HID and VCOM and it work, if I add the app control interfaces with his 3 endpoints it stop working). So I guess I have declare something either impossible or badly that make the VCOM stop working. Any requirements in the interfaces orders and numbering?
Now my usbd_conf.c have the following lines:
/* RX buffer is a big as the biggest one */
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
/* Lower level can only support from 0 to 5 maximum for L4 series for IN endpoints */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); /* Default control EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x10); /* HID interrupt EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 0x40); /* App bulk EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x10); /* App interrupt EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 0x40); /* CDC bulk EP */
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 0x10); /* CDC interrupt EP */
I can read the VCOM data, the RX is working, but when I try to send the data through the USBWrite() from usbd_cdc_if.c, but the transfer doesn't succeed since the TxState is not IDLE (== 0) but busy but it never goes back to idle. I'm wondering why. I guess the CDC Communication interrupt is no more working properly, but I don't know why.
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY; // I end up here with the new config
...
}
The TxState is set to BUSY (1) during USBD_CDC_TransmitPacket() fonction only. And if should be clear with USBD_CDC_DataIn() set back to 0, but I don't get this call anymore.
I'm not sure why I don't get those IN communication anymore, I also have IN issue with the Application Control endpoints. I don't get what is going on. Any tips or info on how to debug this properly, would be welcome.
2019-03-08 01:51 PM
2019-03-09 03:51 AM
0x80 + 0x40 + 0x10 + 0x40 + 0x10 + 0x40 + 0x10 = 0x170 > 0x140
I don't say this is the only problem in your code.
I might've mentioned that I don't use Cube.
JW