cancel
Showing results for 
Search instead for 
Did you mean: 

['F4 OTG] OTG_HFIR handling

1.

In RM0090 rev.17, OTG_FS chapter, there's a 34.9 Dynamic update of the OTG_FS_HFIR register subchapter saying, "The USB core embeds a dynamic trimming capability of SOF framing period in host mode allowing to synchronize an external device with the SOF frames." then showing on Fig.391 how does it exactly work. However, the OTG_FS Host frame interval register (OTG_FS_HFIR) register description says, " Do not change the value of this field after the initial configuration." So, can the frame interval be dynamically updated in OTG_FS, or not?

2.

In RM0090 rev.17. OTG_HS chapter, in description of OTG_HS Host frame interval register (OTG_HS_HFIR) register, while the narrative mentions microframes for HS, it would be nice if also the formula for HS - 125us microframes (after correction, see below) would be added, same as in RM0390

3.

In RM0390 rev.4, 31.15.19 OTG host frame interval register (OTG_HFIR) (btw. could you please in RM0390 remove numbering/subchaptering of individual registers, and do the a proper global/host/device subchaptering of the USB_OTG registers subchapter? thanks.) there is a remark, "Caution: RLDCTRL = 1 is not recommended." Why? Does setting RLDCTRL have any other effect than disabling the dynamic update of HFIR - which I believe is used only in some niche applications anyway? And what is the purpose of that bit at all, why wouldn't simply not touching FRIVL all the time suffice? Also, the narrative for both variants of the FRIVL fields says, " Do not change the value of this field after the initial configuration, unless the RLDCTRL bit is set."; however, RLDCLR bit's description says, "1: The HFIR cannot be reloaded dynamically". Shouldn't the above sentence say, " Do not change the value of this field after the initial configuration, if the RLDCTRL bit is set."?

4.

In both RMs (and both HS and FS in RM0090), the formula for OTG_HFIR.FRIVL is messy:

 Frame interval = 1 ms × (FRIVL - 1)

In RM0090, there's also some additional garbage:

frame duration × PHY clock frequency

which makes no sense whatsoever.

The proper formula (assuming the counter HFNUM.FTREM counts indeed from FRIVL down to 0) is

LS, FS: FRIVL=1ms x PHY clock frequency - 1

HS: FRIVL=125us x PHY clock frequency - 1

5.

In both RMs, in the "Host initialization" subchapters (in both the FS and HS chapters in RM0090), there's an item saying "10. Program the HFIR register with a value corresponding to the selected PHY clock 1" The last 1 is obviously spurious; could that be a footnote in the original?

ST, please comment, correct.

Thanks,

JW

1 REPLY 1

As ST or Synopsis did not care to comment and I had work to do, I resorted to what I like - experimenting - and what I hate - replacing proper documentation with results of the experiments.

And as ST and Synopsys most probably won't care to comment in the future either, here are some of my findings, for others to discuss and try to confirm/reject.

In the Synopsys OTG USB module in 'F4 (and also in 'F7/high-end 'L4/'F105/107), in host mode, after device is connected and reset is issued, a counter runs to determine the 1ms frame (for LS/FS) or 125us microframe (HS) duration. It is a 16-bit downcounter clocked by PHY clocks, and its current content can be read through OTG_HFNUM.FTREM. When it counts to 0, it is reloaded from OTG_HFIR.FRIVL, and a SOF frame (FS/HS) or keep-alive (LS) is issued on the bus (and frame counter in OTG_HFNUM.FRNUM is incremented, and SOF interrupt fired, and possibly some other events within the module may be bound to this moment, too).

The following is behaviour observed in the OTG_FS module of 'F407 and a 'F446, which is in contrast with the description in respective RM0090 rev.17 and RM0390 rev.4.

1. After application ends the bus reset by clearing OTG_HPRT.PRST, the module sets OTG_HPRT.PENA, and at the same time loads the frame counter by a value based on current state of OTG_HCFG.FSLSPCS - 60000 for 0b00 (which represents FS mode with HS PHY at 60MHz clock, although RM specifies this value as undefined), 48000 for 0b01 (for FS with 48MHz PHY clock) and 6000 for 0b10 (for LS with 6MHz PHY clock - RM says, LS mode with 48MHz PHY clock should be possible with OTG_HCFG.FSLSPCS=0b01, but in my experiments I could not get the module working in this way; I guess this option is crippled in hardware and the documentation does not reflect this fact).

RM say, at OTG_HFIR.FRIVL (i.e. the reload value) description, that "If no value is programmed, the core calculates the value based on the PHY clock specified in the FS/LS PHY clock select field of the host configuration register (FSLSPCS in OTG_HCFG)." This suggests, that OTG_HFIR.FRIVL is changed at that moment, but this is not the case - only the counter itself is loaded by the module, the reload value in FRIVL does not change and the counter is loaded by this unchanged value from FRIVL at the first SOF.

2. Writing OTG_HFIR.FRIVL may have two forms:

A) only OTG_HFIR.FRIVL, i.e. the reload value register, is written, and the counter loads the new value only when it finished downcounting from the old value i.e. at the next SOF; or

B) the new value is written to *both* OTG_HFIR.FRIVL and the counter, immediately; i.e. the length of the frame ongoing at the time when the write happens, is disturbed.

From the description in RMs, I have no idea, which of these corresponds to "dynamic".

In RM0090 in Dynamic update of the OTG_xx_HFIR register subchapter for both xx=FS and HS, the narrative indicates A) behaviour, while the figure in that subchapter indicates B) behaviour. The observed behaviour for 'F407 is A), i.e. matches narrative but is opposite of what the figure indicates.

In RM0360 there is an additional bit in OTG_HFIR register, OTG_HFIR.RLDCTRL, which functions exactly as switch between A) and B) behaviour. The narrative in Dynamic update of the OTG_HFIR register subchapter does not really explain, which setting of OTG_HFIR.RLDCTRL is related to which behaviour, nor does the narrative at the OTG_HFIR.RLDCTRL bit description (as "dynamic" is not explained properly); the figure in that subchapter displays A) behaviour with caption indicating RLDCTRL=0. The observed behaviour is the opposite to the figure, i.e. with OTG_HFIR.RLDCTRL = 0 the behaviour is B).

---

But why would this matter at all - frame length can be changed at the end of the day, as needed; and the only visible effect would be the first SOF or first two SOFs arriving in a slightly different time than expected. And, in both the 'F407 and 'F446 the "safe" A) behaviour is available (in 'F446 if OTG_HFIR.RLDCTRL = 1 but that's trivial to achieve), so what.

This is true, but there is at least one little devil lurking in the details. The sequence in "Host initialization" subchapter states, that OTG_HCFG.FSLSPCS ought to be set according to the detected speed *after* reset/enable. So, if a LS device is attached after either a FS device or after system reset (when OTG_HCFG.FSLSPCS = 0b00 by default), the counter is loaded according to this *previous* value of OTG_HCFG.FSLSPCS to either 48000 or 60000, and given in LS mode PHY clock is 6MHz, this results in the first keep-alive arriving after 8ms or 10ms. That means inactivity on the bus, and 3ms inactivity in USB world means Suspend, so some LS devices go to Suspend; and even if most of them wake up upon subsequent activity (but not on keep-alives alone) even without a proper Resume signalling, some tend to miss the first transaction.

Now, it's true, that the "Host initialization" subchapter calls for a "port reset" when OTG_HCFG.FSLSPCS value changes - this would result in two successive resets, but devices should be OK with that; and that would solve the problem, as the second reset would end with OTG_HCFG.FSLSPCS already set properly, so the module would start the frame counter with the appropriate value. But this needs to be implemented in the software.

This is not implemented in Cube, making the stack fail to start communication with some LS devices.

In 'F446, as Cube does not use the "safe" write to reload register (i.e. does not set OTG_HFIR.RLDCTRL), in the abovementioned case of LS starting with an excessively set counter, as Cube writes the expected (albeit one-off, see https://community.st.com/s/question/0D50X00009yEQY0SAO/cube-otg-incorrectly-set-hfirfrivl ) value corresponding to 6MHz PHY clock into OTG_HFIR.FRIVL and thanks to B) behaviour it immediately changes the frame counter, resulting in only a slightly longer than 1ms time until the first keep-alive. Thus, a basically incorrect procedure by lucky accident results in a nearly correct net effect...