You run into issues if you try to implement something like RMII, which requires an incoming 50MHz clock.
There's an implementation out there which feeds the clock to a GPIO clock input - but because it can't feed the PLL from it and the PIO is driven from the system clock that means your entire chip runs at 50MHz. This has some nasty implications, such as being unable to transmit at 100meg and having to do a lot of postprocessing.
There's another implementation which oversamples the signal instead. This requires overclocking the Pico to 250MHz. That's nearly double the design speed, and close to some peripherals no longer working.
A third implementation feeds the 50MHz clock into the XIN input, allowing the PLL to generate the right clock. This works, except that you've now completely broken the bootloader as it assumes a 12MHz clock when setting up USB. It's also not complete, as the 10meg half duplex mode is broken due to there not being enough space for the necessary PIO instructions.
Almost correct - the third implementation does generate the clock, but it isn't necessary to drive the clock directly from the system clock, as there are m/n clock dividers available. I use a 300 MHz system clock, and divide down to 50 MHz which works well. (I've also addressed a few other shortcomings of this library, but am not done yet...) Haven't looked at the 10 MHz half duplex mode, though.
Do you have your code publicly available? I was just discussing with a friend it would be nice to add an optional Ethernet mode to my motor controller, but the limitations of this library or other approaches limit the appeal.
Also, are there any other approaches that might be better and would offer 100meg or even gigabit links with the RP2350? Thanks!
I'm still working on it - hopefully will be on the DECstation2040 github soon. The interface uses the LAN8720/8740 MAC chips, which provide 10/100 Mbit. (I haven't tried 10 Mbit, so no idea if it works or not). FYI, here's a test result:
ping -q -i 0.005 192.168.1.6
PING 192.168.1.6 (192.168.1.6) 56(84) bytes of data.
229501/229501 packets, 0% loss, min/avg/ewma/max = 0.063/76.725/88.698/160.145 ms
295393/295987 packets, 0% loss, min/avg/ewma/max = 0.063/76.792/37.003/160.171 ms
295393/296278 packets, 0% loss, min/avg/ewma/max = 0.063/76.792/37.003/160.171 ms
(Above is with killall -s QUIT ping)
As you can see, it eventually hangs, and CMSIS reports:
target halted due to breakpoint, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x200001c4 msp: 0x20040f40
As far as I understood the explanation, the incoming ("external") 50Mhz clock signal is a core requirement of the spec: all of those workarounds are just what is required to meet that spec, and be able to TX/RX using the protocol at all.
PIO is surprisingly flexible, even more so in RP2350.