cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476 USB FIFO Settings

cmurp77
Associate III
Posted on October 31, 2015 at 22:43

Hopefully this question has a simple answer. 

Currently I am writing some USB firmware (driver) for this device. All I am trying to do is complete a GetDescriptor command from the USB host. I seem to have no problem getting the setup packet, reading it, and then outputting my device descriptor in the IN data stage when the host asks for it. All the data goes out the pipe and all is well. However, the issue lies when the host tries to complete the Data1 0 length status stage. The micro just seemed to NAK this no matter what.

After several hours of debugging, I seemed to have the endpoints for IN and OUT transactions enabled during the various stages. There was no reason why the micro would just NAK the status stage, but no matter what I tried, it kept sending a NAK.

I never thought something as simple as the data FIFOs could cause the issue. Surely, something as simple as the FIFOs could not cause the issue. I mean.. writing and reading them are easy. Well... I started messing with the RX FIFO size and TX start address for IN EP 0 and... what do you know, my GetDescriptor request completed as the micro sent an ACK response. 

I am incredibly baffled by this. I need clarification. In the manual it says GRXFSIZ is allocated in 32 bit words. Does this not mean that if I want a 64 byte packet size, I need to input 16 into this register? How about the TFSIZ registers for the RAM start address? The way I understand the manual, the start address is not word based but byte based. This means IN EP 0 RAM address should be 64, Correct? The TX FIFO bits should then be programmed with 16 again for a 64 byte packet size.

The above programming failed and kept sending the NAK on the zero length status stage of the setup transaction. I changed the above programming to 64 for GRXFSIZ and kept the TXF settings the same and the micro sent an ACK. 

The manual says that it is required to allocated some 'extra space' in the RX FIFO for setup packets and status information. Even running all the calculations, with GRXFSIZ set to 16 (64 byte), if the RXFIFO was to be overflowed, this would not happen in the GetDescriptor command.  Setup stage : 3 words + 1 for setup complete, then maybe 1 more for OUT complete. I mean... that just doesn't add up to 16 words let alone 64 bytes.

Can someone clarify the settings of the FIFO registers?

Also, for the sake of argument, let's say that GRXFSIZ is set to 16 and means 16 bytes, not words.. If I process each stage of the transaction, the maximum bytes to the RXFIFO on the GetDescriptor command is 12 (3 words). Those get popped off. The FIFO pointer should then be back to 0. Then I get an OUT complete at some point in the FIFO. That gets popped off; FIFO pointer back to 0. From where I am standing, I am popping the FIFO as I am getting the various stage interrupts. There should be no chance to overflow. However, if in fact it is 16 bytes for the RXFIFO, and my ''popping'' action is not really popping, then the FIFO would reach maximum and overflow after the status stage. That would explain why the NAK was sent on the zero length OUT stage. However... I also tried increasing the GRXFSIZ value in increments of 4. 32 did not work and the only one that seemed to work was a value of 64 or above. 

Just to be clear, I am following what I think the manual intends for the RXFIFO. When I get an RXFLVL interrupt, I read the STSP register to 'pop' the first word off the FIFO and get the status. I then look at the packet status and pop additional words off if the byte count is not 0. To pop additional words, I read from address 0x50001000 and do not use the STSP for subsequent words. 

Thanks
7 REPLIES 7
cmurp77
Associate III
Posted on November 01, 2015 at 19:37

Ok so... after more investigation, all the code I have seen in the example libraries and beyond seem to put the RXFIFO size to 128 words. There is no explanation besides what is already in the manual, which is that you need to set the RXFIFO to (max packet size / 4) + some fudge factor for additional words of status. From what I see, there is no way that the RXFIFO can be overflowed. There just are not enough data bytes being transferred. The GetDescriptor request is 3 words and then the OUT status stage is a few more words. 

Now.. I am just spitballing here, but what if I understand how the FIFO works incorrectly. In the manual it says that RX packets are buffered into the FIFO back to back. Packets... packets.. Is this an indication that an entire 64 byte packet is buffered, even if the packet was a few words.. say... 0.. or 2? So this means regardless of packet size, every time the RXFLVL is triggered, the RXFIFO internal pointer is incremented by the size of the packet (16 words) and not by how much data and status words are actually stored? For example, even though the OUT status stage is a single word, the internal RXFIFO pointer actually increments 16 words. This could explain why possibly 16 words does not work. However, it does not explain why, if I am handling every transaction the moment it comes in and popping the RXFIFO, then how is there a chance for overflow.

This is a fishy situation. The manual and example code does not explain why 16 words does not work, even though that is 64 bytes.. which is more than enough for the GetDescriptor transaction. 

The manual states that when the RXFIFO is full, the core will NAK incoming packets. It does this for the 0 length status stage as I have experienced. I then increase the RXFIFO size and... it ACKs them. This indicates this is in fact a FIFO issue and not the control code.

I really would like some clarification on why this is not working.

cmurp77
Associate III
Posted on November 02, 2015 at 21:58

So, when pushing to the FIFO you can clearly see the number of words left in the TXFIFO via the status registers. If I push 5 words to the TXFIFO when I allocate 10 words, I can see 5 words left. There would be no reason to not keep the same implementation with the RXFIFO. That would mean that the USB core is just stacking the next word in the next available slot. In this case, it makes absolutely no sense on how the FIFO would be full. There are only a handful of RX status update words, 4 or 5 maybe, and then 2 words of actual data. That does not sum to 16 words in any case.

The CubeMX generated code puts GRXFSIZ at 128 words regardless of the setting, so that is no help on figuring out how this works.

Since nobody on the forum seems to know how the setting works or if ST's core internally needs tons of extra space, I think at this point I might try and contact an FAE. 

Posted on November 02, 2015 at 22:15

I think at this point I might try and contact an FAE

Historically the FAEs haven't participate here, never quite understood why not. Any way they would be your most effective conduit to the engineers. The USB IP has been developed by a third-party, as I recall.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cmurp77
Associate III
Posted on November 02, 2015 at 22:57

I work for a certain company that can get in touch fairly easily with one of the ST FAE's. I am going to talk to them directly via email. I was just hoping that maybe somebody on the forums would have the answer without having to go through official channels first.

If I learn anything from the FAE, I will post it back here.

cmurp77
Associate III
Posted on November 03, 2015 at 15:09

Clive: 

What you said about ST getting the module from a 3rd party seems true.. because... after some simple digging, you can take a look at the EFM32 series of micros. Exact same USB module down to the register level. SiLabs and ST have the same module. 

So using this, I went into the RM of the EFM32 to see if it could shed some light on the GRXFSIZ value. I have no idea why the values are what they are, but the EFM32 manual gives some examples of what the RXFIFO size should be. The minimum I calculate the RXFIFO to be using their formulas is around 30 words or so. This makes much more sense. I cannot get the module to work correctly with anything less than about 40 words, so I am guessing there is some internal mismash happening in the module which requires the extra space for internal processing before the end firmware gets it. If you do not have at least that much space, then the module just sends out NAKs.

Posted on November 03, 2015 at 16:42

http://www.synopsys.com/IP/InterfaceIP/USB/Pages/default.aspx

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mleo
Senior II
Posted on November 05, 2015 at 16:38

Hello,

The information about Reception FIFO size is hidden in chapter 47.11.3 - FIFO RAM allocation. It describes all the parts that should be allocated inside the reception FIFO for correct functionality.

But unfortunately without final equation and example – definitely something to be improved.

To set the FIFO size use:

Device RxFIFO =

(4 * number of control endpoints + 6) + ((largest USB packet used / 4) + 1 for

status information) + (2 * number of OUT endpoints) + 1 for Global NAK

With default value of 128 words you are safe.

Best regards,

Milan