-
Notifications
You must be signed in to change notification settings - Fork 413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to detect difference between Pico and Pico W? #849
Comments
|
That's an interesting question and one I've been wondering myself but not dug into. FWI, re: the universal binary UF2, I think they were talking about the flash and not something like this. The ROM bootloader is a very simple UF2 programmer and there's no logic in it to allow something like that. https://github.com/raspberrypi/pico-bootrom . What I think they meant was that every flash chip has its own BOOT2 bootloader that's called by the ROM to set up the flash interface. It seems every flash mfgr. has their own protocol for non-1-bit, 1-directional SPI, and there are also different timing requirements even in SPI mode. So AIUI a "universal" binary would just include the (very slow) SPI/4 boot2.S file and work everywhere. The Pico chip and flash themselves are absolutely identical W and non-W, so it's up to the cyw43_init() call to fail and report back up the stack. Right now I believe it hangs in the case of missing CYW43 chip, but I have not examined it in GDB to see if it's my code or the upstream wifi driver. Let me see if I can wire up a GDB session and see if there's a simple way to catch the failing init call... |
As I understand it, the data blocks in the .uf2 can have a "family_ID" field and the boot loader is supposed to ignore blocks that don't match its own family ID. That allows one to create multiplatform .uf2 files by merging the .uf2 files for different families. For that work, however, the bootloaders for the Pico and the Pico W would need to be filtering on different family ID's. Unfortunately, the master file at https://github.com/microsoft/uf2/blob/master/utils/uf2families.json only lists one entry for the RP2040 right now, so I'm guessing that the boot loader does not make any distinction between Pico W and other RP2040 boards.
Thanks! No rush; I have a temporary workaround (just ask the user), but I'm looking for a better long-term solution. If it is possible to catch the failing call, it would be great if there were a way to check if it succeeded (i.e. that the board is Pico W). That's needed in order to enable/disable the WiFi API and to handle the user LED correctly on the two boards. |
The ROM itself needs to do this filtering, and there is no "Pico W" ROM, it's just a standard RP2040 chip with an onboard peripheral that the ROM knows nothing about. So, even updating the UF2 family generator isn't going to help here. :( A quick check w/GDB shows the CYW43 low level driver (from the SDK) is stuck waiting for a DMA completion that will never happen in the case when you try to start WiFi on a board w/o the chip, so it looks like some low-level hacking to make this work. It's in the queue but not going to happen quickly, sorry! |
That's what I thought; thanks for confirming. That also also means that there's no way to tell the difference between a Pico W and any other RP2040 board by looking at files on the virtual Flash drive (RPI-RP2), a trick I've sometimes used for other boards. That just leaves the third option, have the program detect the presence or absence of the WiFI chip at power up and adapt.
No problem, and no rush! Thanks for considering it. Also, many thanks for adding support for the Pico W so quickly. I was surprised at how easy it was to get the WiFi code we had for ESP boards up and running on the Pico W. Everything I've tried has worked right away, including joining a network, making HTTP requests, and UDP. Kudos! |
|
Just found this (arguably old) issue and thought I maybe have a bit of a hacky solution to your problem that might still help you. On the "normal" Raspberry Pi Pico, GPIO_24 is used to detect the presence of a USB connection (digital 0 or 1). There are some other pins that are changed between the two versions, so something similar to this might be a solution too. It's pretty complicated, heck you'd need LittleFS or the "EEPROM" compatability lib just for this, but it's the only way you could differentiate it in hardware without looking for the wireless chip, I think. |
|
Any progress on this issue? |
|
Why not identify it by the manufacturer's USB PID? PICO W PICO USB_VID = 0x239A Regards |
|
Those USB IDs are stored in the actual code, so aren't useful here where the program is actually trying to find out which one of those IDs to use for the Sw USB interface (and whether or not to init WiFi)... |
You could still check it from the programmer side and choose which sketch to upload, couldn't you? I.e. one for the Pico and one for the Pico W. |
|
Thanks for your suggestions sabas1080 and Phoenix1747. Here's a bit more context, in case you are interested. This fix would help K-12 educators and students who are just getting started with microcontrollers. I'd like to have a single universal .uf2 file that they can install on either a Pico or a Pico W. That means the binary has to detect which board it is running on at power up. If it is on a Pico W, it should initialize the CYW43 chip, otherwise it should not. A binary for a plain Pico runs on a Pico W. You don't get WiFi, of course, and the default user LED pin is incorrect, but it runs. However, if you install a Pico W binary on a normal Pico then it hangs on power up trying to initialize the non-existent CYW43 chip. Earle understands this problem. As he suggested, one solution would be to modify cyw43_init() to return with an error rather than hanging, allowing the boot sequence to proceed. Another solution would be detect the board type and only call cyw43_init() if it is a Pico W. MicroBlocks is currently asking users to select the board type from a menu when installing firmware on Pico boards. That works if they make the right selection. Unfortunately, some users select Pico W when they don't actually have a Pico W, which doesn't work. It would be a better user experience if we didn't need to ask them to choose. We could always install the universal binary and it would work on either board. |
|
This is how I programmatically determine whether the code is running on a Pico or a Pico W. It is kind of ad-hoc and depends on the different way the Pico and Pico W hardware implement the VSYS monitoring input on the GP29 pin. In use, at startup, a call is made to the CheckPicoBoard() function which then sets the global PicoIsW variable to true or false for use anytime the program needs to determine which board it's running on. |
|
@jhmaloney have you given the above routine a test? If it's good I can include it in the PicoW variant and run it automatically on startup, and expose the boolean through a |
|
I'll give it a try next week and let you know. |
|
Another option. There's a (new?) PDF from The RPI folks with a section called "2.4: Which HW am I running on?" in a project directory gives this for Raspberry Pi Pico W, and this for an original Raspberry Pi Pico board, |
|
dlkeng's code did not work for me -- I got the same results on both Pico and Pico-W. I'm guessing that the voltage on pin 29 is in the indeterminate range for digital values so the current code might work on some boards but not others. Reading the analog value on that pin would probably fix the problem. In any case, the code from RPI folks in "2.4: Which HW am I running on?" gives very different analog values for the Pico and Pico-W so that looks like the way to go. I assume the test would need to be done before calling cyw43_init() since cyw43_init () hangs on Pico boards that don't have the CYW43 chip, right? |
|
My original code appeared to work on the two Pico's and the two Pico W's I have. However, I did note in a comment on reading the GPIO29 input that "read ADC value better". Therefore, based on the reported results, I have changed reading the GPIO29 value from digital to analog using the ADC. Note that saving and restoring the pins configuration and ADC reset states is possibly optional. |
|
@dlkeng why are you pulling GP25 high? Is that safe in the case the board is non-USB powered? The RPI code actually just reads it (so should be safe at all times) and if I understand the doc correctly the logic is: |
Use the RPi code to get a best-guess as to whether the board is a Pico or PicoW. Fixes #849
Use the RPi code to get a best-guess as to whether the board is a Pico or PicoW. Fixes #849
Use the RPi code to get a best-guess as to whether the board is a Pico or PicoW. Fixes #849
|
I just ran a binary built with #1204 on Pico and PicoW and it seems to report properly. It also adjusts the Can you please give it a go, @jhmaloney and @dlkeng ? (The new call, in the docs, is |
|
Here's a blink.ino which should work on either board (compiled for PicoW) |
|
This is perfect! Blink works on both pico and pico-W board and really nice that you made LED_DEFAULT work for both boards. This allow MicroBlocks (and others) to distribute a single binary that works on both Pico and Pico-W board. That's really nice! When will the fix become available in PlatformIO? No rush... |
Use the RPi code to get a best-guess as to whether the board is a Pico or PicoW. Fixes #849
|
Thanks for the feedback! I should have a release this weekend, so probably sometime middle of next week. You can also always point to the git repo directly to pull it in before then. |
|
Thanks @dlkeng for the code that led to a solution. |
|
popping in here to request that instead of LED_DEFAULT, please use LED_BUILTIN - its the 'official' name of the built in LED on arduino boards/cores https://github.com/search?q=org%3Aarduino%20LED_BUILTIN&type=code |
|
@earlephilhower, in response to "why are you pulling GP25 high? Is that safe in the case the board is non-USB powered?" GPIO25 on both the Pico and Pico W are generally used as a digital output to control things. On the Pico, GPIO25 drives the onboard LED via a resistor. On the Pico W, GPIO25 has two functions:
As such, it should be safe to drive GPIO25 as long as no WiFi communications are going on with the CYW43. In my case I was using it to ensure the Pico vs Pico W boards by driving GPIO25 high to sense the VSYS voltage and then drive GPIO25 low to disconnect monitoring of the VSYS voltage, to more actively determine the Pico vs the Pico W difference. In the case of a Pico, this will momentarily turn the onboard LED on and then off with the monitored voltage from GPIO29/ADC3 not changing. In the case of the Pico W, when GPIO25 is high, the voltage from GPIO29/ADC3 will be at a higher level (about VSYS / 3) and when GPIO25 is low, the voltage from GPIO29/ADC will be at a lower level (close to 0 volts). In the case of only monitoring the state of the GPIO25 signal, on the Pico, it should always be low due to the resistor and LED to ground. On the Pico W, it appears to be taking advantage of the defaultly-enabled pull-down on the signal, which will turn off the VSYS FET so that a low will also be seen (if it is a high, then something is wrong with the CYW43 somehow driving that signal). As to the board being non-USB powered (i.e. Pico board VSYS pin 39 powered or Pico board VBUS pin 40 powered), that should not have any relevance as in any case VSYS is common - USB or VSYS or VBUS pin. If the Pico board 3V3_EN pin 37 is externally pulled low, then the RP2040 will not be running. As to the supplied "blink.zip", I too can confirm that it appears to run correctly on the Pico's and Pico W's that I have. As an observation, the new P.S. I think instead of |
That's not possible w/o costing ~400KB of useless code (the WIFI FW and the TCP stuff) for all Pico projects, so it's not going to happen. The idea here is you build for the max, knowingly paying that price, but are able to also run on the minimum one (i.e. opposite idea). I'll do an emergency fix and move the LED pin change right into the custom digitalWrite for the PicoW. 2.7.4 here we cone. 😭 |
|
That's OK. I was not proposing to be able to utilize any of the Pico W enhancements - just recognize which board it was executing on. I can still do that with my routine without much extra code. |
|
The real pain is it takes 350KB of firmware to control the LED on the PicoW, even if you don't do any WiFi, since it's controlled by the 2nd ARM chip. If you're not using the WiFi at all, and no LED,. then you can just build for the Pico and be done with it, since the chip itself is 100% identical, only a few IO hookups being modified. @ladyada yes, it works (and will work) with LED_BUILTIN. I was looking at Blink.ino which, for some reason, uses the Arduino |
|
I've been thinking about what @dlkeng wrote and studying the Pico-W schematic: With the current implementation, it seems possible that, under certain unusual conditions, the voltage on pin 29 would be higher than the expected value on the Pico-W and the test might falsely report that the board was not a Pico-W. This scenario might occur if the test were done while pin 25 was outputting high (e.g. during communications with the CYW43). The test code makes pin 25 an input, but I don't believe that doing that automatically turns on the pull-down resistor. Thus, there could be enough residual voltage on the gate of the FET to turn it on. That would pull the value on pin 29 up to 1/3 of VSYS. In that scenario, a digital read of pin 25 would probably return "high", so the later code in the test function would assume that it was Pico-W. But there's a small chance that, due to leakage, the voltage could have dropped to "low" from the standpoint of the pin 25 yet still be high enough to turn on the FET. I admit, this scenario seems unlikely. Still, it might be more reliable to explicitly enable the pulldown on pin 25 with gpio_pull_down(25) before reading reading the analog value of pin 29. You'd also need to record the pulldown state with gpio_is_pulled_down( 25) and and restore that state when done, so this would add three lines of code to your current test. But, in compensation, the code wouldn't actually need to check the value of pin 25 since it would be in a known state. A variation would be to make pin 25 output low (briefly) while reading the value of pin 29. This is definitely not urgent and it may not be needed at all -- I just wanted to think it through for my own satisfaction. |



This is a question, not an issue.
Is there a way to detect the difference between a Pico (i.e. a generic RP2040 board) and a Pico W, either when the board is in BOOTSEL mode or at startup time? Alternatively, is it possible to create a "universal .uf2" file that can contain code for both variations?
I'm the lead developer for MicroBlocks, a blocks programming language aimed at students and teachers who are just getting started with microcontrollers. I'd like to make the installation process for the Pico/PicoW as simple and automatic as possible.
One way to do that would be to have the firmware installer detect the board type (in BOOTSEL mode) so it could copy the appropriate .uf2 file to the board.
An alternate solution would be to create a universal .uf2 file, as the Micro:bit Educational Foundation did to allow a single .uf2 file to include binaries for both the micro:bit v1 and the micro:bit v2 boards. That would require that the installer built into the boot ROM could read such universal .uf2 files. (some possibly useful info here: https://forums.raspberrypi.com/viewtopic.php?t=335280)
A third solution would be to always include to WiFi support code, but have the program detect the presence or absence of the WiFI chip and adapt at power up. While this solution would include unused WiFi code on non-WiFi boards it would be okay to "waste" Flash storage space for the sake of simplifying the installation process for beginners.
Suggestions?
The text was updated successfully, but these errors were encountered: