2350/2040 - strange I2C problem


#1

I’m trying to work with the Adafruit charlieplexed LED matrix driver as an extension, using Pimoroni Tiny 2350 and Tiny 2040 boards (the latter added to the same uLisp core sections as the Adafruit QtPy). The matrix driver board is connected to the I2C bus correctly and recognized. Initialization with .begin works flawlessly, as does, for example, .drawPixel(...) - all this from within uLisp, having defined commands led-matrix-begin and led-matrix-draw-pixel within the extension.

To sum up: Initialization and drawing a pixel works, using my extension file. I’ve defined the other GFX commands in the extension, too, for example led-matrix-draw-line etc. Now if I try to invoke that one, for example, the microcontroller crashes/does not return from the library function.

Please assume that I invoke all extension functions in the same, the usual and correct manner with correct argument conversion from uLisp to C, I’ve checked that to and fro. I also made sure there’s definitely no crash until I invoke the library function, and the function call matches the ones provided in the examples (and header files) coming with the charlieplex library/the GFX library.

Moreover, all the examples work flawlessly, so neither the microcontroller nor the led boards/driver boards are broken in any way or connected falsely.

I get the impression that from within the uLisp extension all simple library calls work (like .clear, .setRotation and so on), but as soon as I try to do something more complex/fast serial I2C access, something goes wrong. Could this be an I2C issue conflicting with something uLisp sets up internally? I tried to find hints, but couldn’t. Maybe I missed some 2040/2350 port specialties?
Again: The phenomenon occurs with both the 2350 and the 2040, so I shouldn’t have made any mistake setting up the 2040 for uLisp.

Any hints are greatly appreciated! (uLisp version 4.7b)

Edit: Here’s a short code example illustrating that something seems to be wrong deeply within the mysteries of the RPi Pico:

curmatrix->matrix.drawPixel(x, y, b); // works and is shown
curmatrix->matrix.drawPixel(x+1, y+1, b); // works and is shown
curmatrix->matrix.drawPixel(x+2, y+2, b); // works and is shown
delay(500);
curmatrix->matrix.drawCircle(8,4, 2, 32); // fails - not shown
return nil; //not returning to uLisp


#3

So that code example is inside the C definition of a uLisp function you’ve defined in an Extensions File?

Could there be something significant about the fact that the ones that work correctly reference Lisp variables, but the last one has constant parameters?


#4

Thanks for looking into this, David. Yes, the code snippet resides within the extension file - but no, sadly the constant parameters are probably not the problem; in fact I inserted this command just for testing puposes (to prove that using one library call works from within uLisp while the next one with more parameters – Edit: or rather writing/reading via I2C several times – fails immediately). I copied the call from the Adafruit example, so this is really supposed to work… very strange, currently I have no clue at all.


#5

You’re welcome to message me your Extensions File and I’ll see if I can spot something (or email me).


#6

In my experience debugging I2C is best done with a logic analyzer. I highly recommend getting your hands on one.


#7

Thank you David and hasn0life. I’ll do some more tests in the next days and get back then.


#8

On the RP2040/RP2350 uLisp just calls the Arduino I2C routines, so if it works from a C program but not from uLisp I doubt it’s an I2C problem.


#9

I’ve found the problem, and it’s neither tied to the I2C bus nor uLisp nor the 2040/2350 boards, but rather to my faulty dynamic creation of a linked list of matrix instances. This is quite embarrassing, of course, but at least the mystery is solved now.

What happened was that I implemented this extension using the same C/C++ code I used for a linked list of servos. This code probably works just because the “Servo”-Library itself stores each servo in a static pre-defined array. Since there was no such thing for the matrix objects, I should have instantiated each matrix on the heap using

matrixlist->matrix = new Adafruit_IS31FL3731();

as opposed to

matrixlist->matrix = Adafruit_IS31FL3731();

Instantiating it on the stack apparently led to a broken (partially deleted) structure/object storage that was abandoned immediately after creation, but also was accidentally still partially accessible, so calling one method using the pointer worked, calling another method led into nirvana.
Apparently, the objects need to either reside in a pre-defined array (in this case the simple solution, I guess) and can be instantiated on the stack - or in a list that’s implemented as a C++ class itself - or need to be instantiated on the heap.

Thanks a lot for offering help on this!


#10

Glad you found the solution!


#11