Skip to content
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

Support for Raspberry Pi RM2 wifi / ble module #9777

Open
anecdata opened this issue Oct 31, 2024 · 17 comments
Open

Support for Raspberry Pi RM2 wifi / ble module #9777

anecdata opened this issue Oct 31, 2024 · 17 comments

Comments

@anecdata
Copy link
Member

anecdata commented Oct 31, 2024

Would need CircuitPython API to select the MCU pins to use.

We also may want to consider adding ssl to boards with enough resources that would not ordinarily have it (this would also expand the set of boards that could use WIZnet ethernet as an SPI peripheral with ssl).

I don't see mention of this module on the Raspberry Pi site, but it is incorporated in 3rd-party products, for example @pimoroni RM2 breakout and Pico Plus 2 W.

Related:
CircuitPython Bump cyw43-driver module to v1.0.4 plus to match SDK 2.0.0. #9775
MicroPython Support for RM2 break out boards #16057

@eightycc
Copy link

The RM2 module incorporates the same mux'ing of its DI, DO, and IRQ pins as the Pico Plus 2 W so building a CP board port for a Pico Plus 2 board with the module SP/CE attached should be straightforward.

Of course that approach leads to a proliferation of board ports, so some means of separately supporting RM2 might be a good thing.

@eightycc
Copy link

eightycc commented Nov 24, 2024

Pico SDK 2.0.0 hard codes the pin numbers used for the CYW43439 gSPI interface, so changing CYW43_PIN_WL_... will have no effect. The develop branch of the SDK corrects this.

@dhalbert
Copy link
Collaborator

Are there boards that need the pin numbers to be changed? Or can we wait for the pico-sdk changes to be put in a release? We can move up the submodule commit if necessary.

@eightycc
Copy link

eightycc commented Nov 24, 2024

@dhalbert All of the RP2350 boards that include an RM2 that I've looked at follow the RP2040 Pico W pin assignments so they are not affected. It does become an issue with RM2 breakouts. For example, the Pimoroni Pico Plus 2 attaches an RM2 breakout with its SP/CE connector that utilizes pins 32, 33, 34, 35, and 36.

I do not recommend switching to the SDK develop branch at this time. I tried it and got stuck in build issues.

Release SDK 2.1 has no build issues.

@eightycc
Copy link

Pico SDK 2.1 corrects hard-coded CYW43 pin numbers in the SDK. #9831 picks up SDK 2.1.

supervisor/port.c hard codes CYW43 pin numbers guarded by CIRCUITPY_CYW43.

@eightycc
Copy link

eightycc commented Dec 20, 2024

I've worked through removing hard coded pins so that I can build CP for an RP2040 Pico with an RM2 attached to pins 10, 11, 12, and 13. It runs, but the RM2 fails to initialize. Hooking up a scope while reducing the SPI clock to 625kHz reveals something interesting.

The SPI clock phase for the RP2040 to RM2 is as expected, bits are output on the falling edge of the clock. However, the RM2 is outputting bits on the rising edge of the clock which is causing words read from the RM2 to be off by 1 bit. RM2 clock phase is controlled by the "High-speed mode" bit of the gSPI config register which should default to 1 (sample and output on rising edge of SPICLK), after reset, but instead is behaving as if it is defaulting to 0 (sample on SPICLK rising edge, output on falling edge). It appears that the RM2 default differs from the bare CYW43439 used on the Pico W.

Digging into the SDK's CYW43 driver code, I find that the order of operations to initialize the CYW43/RM2 is incorrect. The driver code first attempts to read the CYW43 test register, then it writes the config register. This worked with the CYW43439 default, but fails with RM2 default. According to the CYW43439 data sheet, the driver should be first writing the config register, then polling the test register.

@anecdata
Copy link
Member Author

I hadn't noticed until now that the tins were different between PicoW / Pico2W (both blank), and the RM2 (FCC labeling). MicroPython presumably would have also encountered this (?) but I don't spot a mention of SPI in their PR (16057).

@eightycc
Copy link

There could be different versions of the RM2 floating around? The one I'm testing with is from Pimoroni and does have FCC markings. An aspect of working with the CYW43439 and RM2 that adds difficulty is that the old Cypress Semi data sheet is incomplete and diverges from the actual parts. I read through 16057 again and there is mention of stability problems with an RM2 breakout. The closest the issue comes to pointing at gSPI is adjustment down of the CLK, presumably to compensate for signal degradation.

My next testing step is to modify the driver to try both falling and rising clock edge phasing while reading the test register. If that works, then I can dump the RM2 gSPI registers to see the actual defaults.

@eightycc
Copy link

eightycc commented Dec 20, 2024

Here is a screenshot illustrating the phase error for an RM2 response to a read of the gSPI test register:

grab-o-scope

Yellow: CLK
Cyan: DO
Magenta: CS

@eightycc
Copy link

Clearly someone else has been here before. By changing the PIO program to spi_gap0_sample1 the RM2 functions as expected. I think the comment "for lower cpu speed" should read "for lower gSPI clock rate". It appears that the CYW43439 and RM2 have some sort of gSPI clock speed detection that governs the selection of clock/data phasing. Looks like I've got a Pico SDK issue in my future.

https://github.com/raspberrypi/pico-sdk/blob/95ea6acad131124694cda1c162c52cd30e0aece0/src/rp2_common/pico_cyw43_driver/cyw43_bus_pio_spi.c#L33-L42

@eightycc
Copy link

eightycc commented Dec 22, 2024

I've done some more testing with both the CYW43439 on the Pico W boards and the RM2 module.

The older CYW43439 operates as described in the Cypress Semi datasheet. It does not change gSPI data phasing at lower clock rates.

The newer RM2 modules change gSPI data phasing somewhere between 21.429MHz and 23.077MHz on the two RM2 modules I tested.

Assuming a 150MHz processor clock, a divisor of 3 results in a 25MHz gSPI clock. Depending on the accuracy of the RM2's gSPI clock measurement, a divisor of 3 could conceivably fail intermittently. At 23.077MHz (divisor 3, fraction 64) with a debug build I'm seeing instability.which leads me to think that there's a range of gSPI clock frequencies centered around 22MHz that are unusable.

Back to stable operation at 18.75MHz (divisor 4, fraction 0), but need to specify CYW43_SPI_PROGRAM_NAME="spi_gap0_sample1" to accommodate the change in phasing.

@anecdata
Copy link
Member Author

Thanks for digging so deep into this @eightycc!

@eightycc
Copy link

Support for an RM2 module on the new Fruit Jam would be so nice. Let me see what I can do to make that happen.

@eightycc
Copy link

Support for the CYW43 increases the CP firmware image from 1020KB to 1532KB. Most of the additional 512KB accommodates the CYW43's firmware, with the remainder taken up by the CYW43 driver, the lwIP stack, and mbedtls. To avoid increasing the CP image size for all RP2 boards, some or all of the additional 512KB could be stored in and loaded from the filesystem when RM2 module support is desired.

@anecdata
Copy link
Member Author

Probably not a big issue on 8MB flash or more, but a substantial trade-off for smaller flash boards (could wreak havoc with current partition maps though).

A generic ability to offload code into the user partition could potentially benefit many flash space issues.

@eightycc
Copy link

Loading the CYW43 firmware from a conventional binary file stored in the filesystem would be straightforward.

Executable code presents additional difficulties. Here are some initial thoughts:

The RP2 maps the entire flash memory into the 16MB XIP address space, so code can be executed directly from the FAT filesystem area of the flash.

It's unpredictable where a file will be stored in the filesystem, making it necessary to compile the executable code as position independent.

There would also need to be a means of dynamically linking the executable into the CP image when it is loaded. A method for solving this problem is to create an array of transfer vectors at a fixed location in RAM. When the executable is loaded, the transfer vectors are filled in. Calls from the CP image to functions in the loaded executable would be compiled to call the corresponding transfer vector. The transfer vector itself would be a machine language branch into the function in the loaded executable. Initially, transfer vectors contain a branch into an error handler.

When a file is larger than a FAT filesystem cluster, it cannot be guaranteed that the file's clusters will be contiguous in flash. As a consequence, a function's object code may not cross a cluster boundary. This will require processing at build time to arrange the executable's compiled functions appropriately.

@tannewt
Copy link
Member

tannewt commented Feb 13, 2025

Support for an RM2 module on the new Fruit Jam would be so nice. Let me see what I can do to make that happen.

Don't spend too much time on this. We're more likely to use an ESP32-CX for a wifi coprocessor. RM2 aren't very available yet from what I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants