Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 5352

General • Re: High speed ADC interfacing

$
0
0
I don't think Mike was meaning that you should use the USB clock for your purposes - rather, that if you want to use something other than a 12MHz xtal as the main clock (which might be desirable to get your clock right) then you have to give up use of the USB at least in bootrom mode.

To get the right frequency for a clock you generate from PIO, there are various levels of effort you can take:
  1. Run the system clock at whatever rate you like (125MHz default, or 133MHz max permitted without overclocking), and just use the PIO's clock divider to get the frequency you want. However, unless this is an integer division of the system clock then the output will be jittery - and hugely, unusably jittery if trying to run close to full speed as you are. The way the PIO divider works for non-integer dividers is to use the integer values either side of what you want and alternate between them in the right proportion to give the average frequency you asked for: this works well enough for things like moderate-speed UARTs where the divider might be flipping between 1154 and 1155 so only a 0.1% wobble and UARTs don't care about that. But for higher frequencies and applications that care about jitter it's a disaster - so for your example of trying to get 50MHz from a 133MHz system clock you need a 100MHz PIO clock (to do high and low output on alternate cycles) and so a divider of 1.33. it will be flipping between divide-by-1 and divide-by-2, so your "100MHz" will comprise two cycles of 133MHz and one cycle of 66MHz!
  2. You can pick the system clock to be an integer multiple of the output clock you want, and then the PIO divider can just be an integer and not add any jitter. However, you have thrown away a bit of performance and you are also constrained by what the PLL can do - it has a limited set of multiply/divide options so it may not be able to generate exactly the frequency you ask for - so here instead of huge jitter but an accurate average rate, you've now got a pure but maybe not quite accurate rate. You also aren't entirely free from jitter as the PLL (like all PLLs) will have some analogue jitter in it, but for most applications that's small enough not to care.
  3. You can replace the external 12MHz crystal by a crystal or external oscillator that has a useful numerical relationship to your desired output frequency. Now the PLL is multiplying by an integer (or simple fraction) that it can do accurately, the PIO divider is at an integer value (or most likely at '1' for max performance), and you can probably pick a number for the system clock that's under 133MHz but not giving up too much CPU performance. In the extreme case where you can't tolerate even PLL jitter, you can use an external clock at exactly the frequency you want and not use the PLL (but that limits you to 50MHz max so you are giving up a lot of CPU performance). The snag with the different clock approach is that the bootrom assumes a 12MHz crystal clock, so if you use anything else then you won't be able to use USB in the bootrom (eg. for initial software load - you'll have to use SWD instead). There is a separate PLL for the USB clock, so you can probably generate a close-enough 48MHz for the USB from whatever other frequency you have chosen, in which case you can use USB in your application, just not at boot.
As I understand it, Mike's speciality is audio, and audio does often need very particular clock rates that aren't convenient multiples of 12MHz, so the option-3 approach may well be needed there; I've run into it myself in a radio application where we needed a particular clock for the radio and wanted the RP2040 synchronous with that. However, your initially stated requirement was for 50MHz, which is not so bad. I've done something extremely similar - Ethernet RMII, which is a 50MHz clock and 2-bit parallel data in each direction where I generate the clock in PIO as well as capturing the data. Here I went for option 2 and a 100MHz system clock - so giving up a 25% off max non-overclocked performance but not too bad, and then having two cycles per clock in my PIO programs. I ended up using three PIO SMs - one for Tx, one for Rx data moving and one to count the amount of data. Clock was generated by side-set - arbitrarily, I put this in the Tx SM, but it could have gone in any of them as they are all having to have the number of instructions in the loop carefully counted.

There is another approach for 50MHz that I discounted in that application because it required a mild overclock of RP2040, but it comes back into play for RP2350 with the 150MHz system clock permitted there (and also would almost certainly work in fact on RP2040). If you use 150MHz, that means you now have 3 PIO instructions per cycle, which means PIO can't generate a symmetric 50MHz clock. Possibly your application might not mind an asymmetric clock, but the RMII spec does not so I couldn't do that. However, on RP2040 a couple of pins can be CLK_GPOUTn (on RP2040 that's GPIOs 21, 23, 24, 25). These can be set up via the clock system to be a 1.5 divide of the system clock (ie. the output changes on both edges of the system clock, so it's not going to be perfectly symmetric but not bad). PIO can still use that GPIO as an input when it's configured as an output clock, so it should be possible to synchronize a PIO program to it (so long as you pick the right edge- the one that's aligned with clk_sys, not the one in the middle of it!). I haven't tried this yet, but on my design I picked GPIO22 as the pin that I currently toggle with PIO with a view to experimenting with the CLK_GPOUT approach).

When taking the option 3 approach, it's a great shame that on RP2xxx the CLK_GPINx inputs can't feed the PLL (so that you could have a basic 12MHz crystal on XIN for boot, then switch to CLK_GPIN later at a different frequency). You can still do it, but then you are limited to max 50MHz because that's the max permitted external clock and you can't use the PLL to multiply it. May be worth it for some applications, but you are giving up a lot of performance (both CPU performance and PIO performance) to do so.

Statistics: Posted by arg001 — Sat Nov 30, 2024 10:49 am



Viewing all articles
Browse latest Browse all 5352

Trending Articles