USB- using SOF packeys as time reference

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any usb experts around here? (I'm sure there are)

I am playing around with a micro with usb support that was intended to be used with a crystal when using usb. However, I wanted to see if I could make it work with the internal frc ('everyone' is doing it now, so why not me). The system clock uses a pll , and a clock can be routed out to a pin in various ways, and into the clkin pin which will only be used for the usb pll input (4Mhz).

I can adjust the frc via an osctun register, and be in the range of 3.94Mhz-4.066Mhz (sysclk/10) in 64 steps. I have tested the whole range, and the usb (cdc) doesn't hiccup at all (for some reason), so I think it is workable. I have about 10 steps in osctun that keep the clock in the 0.25% range.

I currently am using polling in the usb stack, and simply use the SOF callback to get average times between callbacks (1000 per second).

My question-
is there a way to 'delay' the initial usb communication after coming out of the usb reset state, so I can get some SOF packets coming in to tune the clock? (so I can tune the clock before important comms take place just in case the pc doesn't like the initial clock)

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There a few timing requirements in USB for enumeration, like 50ms or so response times for setup packets. I don't how quickly a typical PC starts the enumeration process after it detects device attachment.

If the PC does not like the clock there likely will be no communication at all, so you get a device error on the PC.

So, I'm fairly sure you cannot delay the enumeration process after attaching the device long enough to get many SOF packets.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It does seem usb wants to do its thing, no waiting around.

Maybe I can get enough initial ballpark timing from the first packets. Or maybe I can read the temperature (somehow) to initially compensate the clock before usb starts, then do the extra fine tuning as it runs. Or maybe I'll add a watch crystal (if the rtc will be used).

I'm not sure why, but I can't get usb to fail in the full range of the frc tuning (on several pc's). That's good I guess, but I was expecting the sky to fall or lightning bolts to appear (could still be on their way, though).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe store the last used calibration value in EEPROM and use that on startup? Maybe even store multiple of them in several temperature bins.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem with using a stored value from the last time, is it may not be close enough for the next time. Most often will be fine, but I want to do this as reliably as possible.

That 50ms you referred to is actually a long time. I don't have a great understanding of usb, but it appears I can ignore things for a little while and still get sof packets.

This is what I have tested so far- in the process of going to 'default state' (bus goes to reset state), I wait for the first sof flag, start a counter, go in a loop of waiting for 10 sof flags, get the counter again, and let the process continue (putting in initial clock tuning here).

The count I got was 200150 (which computes to a 4.003Mhz clkin), so it appears sof packets were coming in. Now I have to find out if that is allowable to do- one OS may tolerate it, but then next may not, unless it conforms to the usb specs (a little over my head, but I'm learning).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could force a dual enumeration by controlling the pull-up on the D line. Use the initial set of enumeration packets to generate timing, then re-enumerate once timing is achieved. Not ideal or pretty, but should work.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am now doing what I described previously- after usb reset, I get times of 10 sof packets (no responses), and adjust the osctun inside that loop. I can get real close after about 6 of them (could tweak more). Since Windows does the reset a second time, it gets done twice (and is tuned enough already that no adjusting is done). I can start osctun at either end, and it will be easily tuned in that first 10 sof packets.

I'm looking at the usb specs, and really can't figure out what applies to what I'm doing. I assume I am ignoring setup packets (no response appears to be the correct way to not acknowledge the packet), and I see 50ms in the device timing table which I think applies, but am not sure.

(I am probably getting some usb terms wrong, as I am getting confused by the terminology used)

If it turns out that what I do is acceptable, then it appears I will be on my way to a successful result.

update-
it appears that the 5 second limit applies here, as I can delay responding to the initial Get Descriptor request for about 5 seconds (and also after the subsequent reset where Set Address is first done). So a total of 10 seconds can pass before Windows will show the device. Any longer and I get the Windows usb device error.

I think the 50ms (and 500ms) response times do not apply as the setup packets are not ACKed (specs word it as - 'within XXms of receipt of the request'). Which means the upper limit applies- 5 seconds.

IF that is correct, me waiting out 10 SOF packets to sync the clock seems like it is not even close to being a problem.