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 i2cperipheral on RP2040 #4536

Closed
tannewt opened this issue Apr 1, 2021 · 42 comments
Closed

Support i2cperipheral on RP2040 #4536

tannewt opened this issue Apr 1, 2021 · 42 comments
Labels
Milestone

Comments

@tannewt
Copy link
Member

tannewt commented Apr 1, 2021

https://forums.adafruit.com/posting.php?mode=quote&f=60&p=864733#pr864799

@tannewt tannewt added enhancement rp2 Raspberry Pi RP2 Micros labels Apr 1, 2021
@tannewt tannewt added this to the Long term milestone Apr 1, 2021
@billmania
Copy link

I'm eager to have i2cperipheral supported on the Teensy 4.X with CircuitPython, so I can use two Teensy 4.1 units as I2C Responders on a very short I2C bus. I'd like to know more about how I and my organization can increase the priority or this issue and/or support someone working on it.

Just for background I'd also like to understand if it's not currently supported only because it's low priority or if it's because of issues with I2C in general on the Teensy 4.X.

@ladyada
Copy link
Member

ladyada commented Apr 13, 2021

you can subscribe to #2470
its our low priority, but if someone implements and submits a PR, we'd help get it merged!

@dhalbert
Copy link
Collaborator

dhalbert commented Jan 9, 2022

Copied from #5410:

from @domdfcoding:

Hi,

Would it be possible to add the i2cperipheral module to RP2040-based boards like the Pico? It looks like the Pico SDK has an i2c_set_slave_mode function so set one of the i2c ports into slave mode. Presumably that could be used as the basis of an implementation?

@dhalbert
Copy link
Collaborator

dhalbert commented Jan 9, 2022

@ifurusato suggests looking at https://github.com/adamgreen/i2cperipheral, which is a MicroPython implementation of I2CPeripheral.

@wattsie
Copy link

wattsie commented May 2, 2022

Hi all, any success getting i2cperipheral to work with an RP2040?
I have a project where I would like to use an RP2040 as an I2C slave (ahem.. peripheral/target)
If not, I can try to look into it (if time permits), don't want to duplicate effort if others are working on it.
(PS: checked latest 7.3.0b2, not supported)
Cheers.

@kstillson
Copy link

kstillson commented May 2, 2022 via email

@ifurusato
Copy link

So far as I know Adam has managed to get his i2cperipheral library to at least a working state, but I myself haven't had the time to check into it at all, focused on an entirely different project right now, sorry.

@im-redactd
Copy link

Hi all, any success getting i2cperipheral to work with an RP2040? I have a project where I would like to use an RP2040 as an I2C slave (ahem.. peripheral/target) If not, I can try to look into it (if time permits), don't want to duplicate effort if others are working on it. (PS: checked latest 7.3.0b2, not supported) Cheers.

Would you be interested in collaborating on this? I could REALLY use the functionality but I'm not familiar enough with the circuitpython environment enough to tackle this myself.

@billmania
Copy link

billmania commented Jun 17, 2022 via email

@kstillson
Copy link

kstillson commented Jun 17, 2022 via email

@tannewt
Copy link
Member Author

tannewt commented Jun 17, 2022

We're happy to give pointers on the Discord: https://adafru.it/discord That's the best place for fast replies.

Generally you'll want to start by copying ports/atmel-samd/common-hal/i2cperipheral/ into ports/raspberrypi/common-hal. Then, delete all of the implementation in the C functions and the samd specific headers. Once you have this, turn on CIRCUITPY_I2CPERIPHERAL in ports/raspberrypi/mpconfigport.mk. At this point you should be able to build a CP binary and import i2cperipheral. Lastly, you'll need to implement each common_hal function. Any port-specific state you need to keep goes in the i2cperipheral_i2c_peripheral_obj_t struct in the I2CPeripheral.h file in common-hal. All of the common_hal functions take this object in.

@gamblor21
Copy link
Member

I'm willing to try to help if I can. I've been playing a bunch with Circuit Python, although thus far primarily as a developer using circ-py, not of circ-py. I do know C/C++, although my experience is from a while ago, and I'm not super-current on all the latest fancy auto-build systems and the like. one thing I was able to do a while ago was recompile a qtpy_m0 (atmel-samd) uf2 file to include the i2c client code, and as I recall, I was actually able to get this to work.

Discord is a great resource and feel free to ping me (there or here). My first real contribution was adding a module like this so willing to help you along if you need. I hopefully remember some of the pitfalls I ran into in the past. I've added some features to the RP2040 port before too so somewhat familiar with how it works.

@kstillson
Copy link

kstillson commented Jun 19, 2022 via email

@tannewt
Copy link
Member Author

tannewt commented Jun 21, 2022

@kstillson I'd recommend starting with: https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/busio/I2C.c It already interfaces with the I2C peripheral in the RP2040.

SERCOMs on SAMD21 are generic serial communication peripherals. They do SPI, I2C and UART. Modelling after that code may be more confusing than clear.

@kstillson
Copy link

kstillson commented Jun 22, 2022 via email

@tannewt
Copy link
Member Author

tannewt commented Jun 22, 2022

I'm glad you are making progress. Don't worry about getting laughed out of town. We appreciate contributions to CircuitPython and are happy to help refine things to get them merged in.

@kstillson
Copy link

kstillson commented Jun 24, 2022 via email

@dglaude
Copy link

dglaude commented Jun 24, 2022

Dear Ken,

Some ideas for your project:

pull-up resistors built into the pcb

You could put any stemma sensor with two connectors, and put it in between your QT RP2040. My guess is that the pull-up present will help, also you will have a sensor and your i2cperipheral so you could test one or the other and compare.

a chain of 2040 boards powering each other and communicating through their stemma/qt connectors with no other soldering / wiring required.

Not exactly your project, more like my project but very similar...
You could do UART between two QT Py but turning your Stemma QT cable into a serial cable.
Just take the cable and swap SDA and SCL on the connect (raise the plastic holder and pull the cable, then swap position).

On most board the pin choosen for SDA/SCL are also capable of RX/TX and what you do is a Stemma QT cable that put RX on TX.
I have done that cable modification a few time (just make sure you identify that cable as special) and one QT power the other.
What I did not try is to do serial communication yet.
But one idea would be to use the BluefruitConnect library that define protocol for various kind of data (colour, pin, ...) => https://github.com/adafruit/Adafruit_CircuitPython_BluefruitConnect

Not really helping for i2cperipheral, but maybe interesting alternative.

Don't hesitate to ping me on Discord.

@tannewt
Copy link
Member Author

tannewt commented Jun 24, 2022

Hey, @kstillson do you have a logic analyzer that you can put on the I2C lines? That'll really help you understand what is happening.

@kstillson
Copy link

kstillson commented Jun 25, 2022 via email

@dhalbert
Copy link
Collaborator

@kstillson Download the latest software for the Saleae: they've made a lot of improvements.

@Billy-Bogardus
Copy link

@kstillson I would be interested in helping test. I have an oscilloscope at my disposal, and possibly a little free time.
does your fork have all your changes?

@kstillson
Copy link

@Billy-Bogardus well, any help would be most appreciated. yup- I keep my github repos up-to-date. https://github.com/kstillson/circuitpython has the modifications to try to get i2cperipheral working on 2040, and https://github.com/kstillson/circuitpython-i2c-notes has working notes and the code I've been using on both the host and the peripheral to try to make it go. Thanks-in-advance! :-D

@Billy-Bogardus
Copy link

Billy-Bogardus commented Jun 26, 2022

@kstillson Just had a little time to build for my RP2040 and it looks like something is being inverted on the reading address. Reading 0x3D 0b0011 1101 instead of 0x42 0b0100 0010 attached below are the scope plot and screen shot.

Client_Transmission
Client_Transmission.txt
Client_Transmission.csv

I only have one 2040 processor right now so I will have to work up another test script for the opposing device.

@tannewt
Copy link
Member Author

tannewt commented Jun 27, 2022

@kstillson I use a Saleae so feel free to ping me on Discord if you need help getting it going.

@kstillson
Copy link

kstillson commented Jun 27, 2022 via email

@kstillson
Copy link

kstillson commented Jun 29, 2022 via email

@tannewt
Copy link
Member Author

tannewt commented Jun 29, 2022

and made the guess that "sar" (slave address register) is what we want.

Just wanted to make sure you know that that struct is allowing direct access to the peripheral registers. The data sheet is a very good resource about what they all do. I tend to use registers directly because the datasheets are generally the best documentation.

@Billy-Bogardus
Copy link

Billy-Bogardus commented Jul 1, 2022

Haven't had much time this week, but was able to read some of the datasheet today https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf I2C details start on page 439. there is also some sample code on page 359.
There is also a note that external pull ups should be used since the internal ones may not be strong enough.

@Billy-Bogardus
Copy link

Billy-Bogardus commented Jul 20, 2022

Tried to do a little bit of debugging today. I am struggling to understand how all the different files and libraries link together.
Does anyone have any recommendations on a good way to navigate the circuit python code base?
I am using VS Code.

@tannewt
Copy link
Member Author

tannewt commented Jul 25, 2022

@Billy-Bogardus I don't use a particularly fancy editor. We're happy to answer more specific questions on the Discord (https://adafru.it/discord) in #circuitpython-dev.

@kstillson
Copy link

kstillson commented Jul 25, 2022 via email

@manbehindthemadness
Copy link

Hmm I am also interested in creating an i2c slave using a seeed Xaio rp2040, I compiled and loaded @kstillson 's Fork. I have noticed when running the example code: https://docs.circuitpython.org/en/latest/shared-bindings/i2cperipheral/index.html#module-i2cperipheral The loop terminates because device.request is returning an address of 0x40 in the absence of an actual request (empty body).

@gamblor21
Copy link
Member

I started taking a look at this myself this weekend. I think it may be close. Please let me know if anyone has any updates they haven't posted. The datasheet does have a lot of good information. I hope to take a further look tomorrow and get my logic analyzer hooked up to get a better picture of what is being sent.

@manbehindthemadness
Copy link

I will most likely be dusting off my logic analyzer as well. Might we tweak the code to allow for a null address (just read everything going down the wire)? I feel this would prove advantageous for future diagnostics.

@manbehindthemadness
Copy link

I will most likely be dusting off my logic analyzer as well. Might we tweak the code to allow for a null address (just read everything going down the wire)? I feel this would prove advantageous for future diagnostics.

Now that I think about it, it would also allow us to emulate multiple slaves with a little python support logic.

@gamblor21
Copy link
Member

For anyone looking at this be aware of #6721 that will affect any changes. I did make some small progress and I'll post a more detailed update later.

@gamblor21
Copy link
Member

I think I have it working, probably needs a bit of cleanup.
@kstillson or @im-redactd would you like me to push into your repo so you can create a PR to the core? Or else I can create a PR myself to the core.

The basics of what I did:

  • in the is_addressed method found the correct status bytes to check if we have a read or write request (or nothing)
  • in read and write, address the hw->data_cmd register directly. The API does not really have good methods.
  • Some general cleanup in the constructor and deinit functions.

With #6721 there is probably a bunch of renaming work to do as well.

Good job to everyone who helped contribute to this, I think it is close.

@manbehindthemadness
Copy link

manbehindthemadness commented Aug 10, 2022 via email

@gamblor21
Copy link
Member

Closing this issue as support has been merged with the core now. If there are issues with it please open up a new issue and tag me on it.

@ladyada
Copy link
Member

ladyada commented Aug 17, 2022

thanks @gamblor21 !

@kstillson
Copy link

kstillson commented Oct 11, 2022 via email

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

No branches or pull requests