Upgrade to v4.5.3 - rpc spi no longer working

Ah great to know. Will try to find out what’s going on and let you know.

Hello!

  1. I tested the firmware fix you provided issue #2173 with rpc.py from 4.5.2 and everything works as expected with my code!
  2. I tested the latest development release and not even the example code works for me. I suspect issue #2173 is yet to be pushed in the dev branch correct?
  3. I tried to debug rpc.py (from 4.5.3 release) with the firmware fix you provided here.
    a) I observe that sometimes, only 1 out of 10 requests, the function call is triggered by Arduino (sending a call over SPI every second). The loop() function is indeed looping every “recv_timeout”. I am not a programmer so I really don’t know where to put my hands in here. For sure it’s not working as intended with my code but the only difference between my code and example is that I’m loading more libraries and have many more variables defined (more memory occupied).

Something broke in rpc.py between 4.5.2 and 4.5.3 . More than happy to try to help to fix with some guidance.

Can you please push changes for issue #2173 into the dev branch and let me know if I can help finding the issue with rpc.py?

Hi, I’ve retested my fix: ports/stm32: Don’t control CS pin in slave mode. by kwagyeman · Pull Request #2180 · openmv/openmv (github.com)

And it should be fine to merge.

The code works fine running the popular features example on the Arduino and on the OpenMV Cam without issue using the SPI bus.

As mentioned, I can verify our example code works as expected. I don’t know what is wrong with your code.

Ok, understood.

The fact is that my code isn’t doing anything when the rpc is looping. I suspect some issue that only becomes evident when there is more than just the example loaded.

I’ll use the 4.5.2 rpc.py script with the newer firmware release from now on . Eventually the problem with 4.5.3 one may become evident by some other users which are able to debug properly .

In the future I’ll try to make some code that breaks the rpc that I can share.

Thanks.

Thanks!

Hi. I can manage to reproduce and show you at least one of the root causes of my problem. (SPI communication between Arduino and Openmv with RPC library.)

I have been using 4.5.2 rpc.py file on my flash with newer builds to continue to work but now I have more breaking changes with 4.5.8 that I am investigating so I would like to use the firmware as is without using the older rpc.py)

With this script if I dont import my config file I get a print “spi_ping” when expected.

import rpc, struct

from config import c

dyntag = 0

interface = rpc.rpc_spi_slave(cs_pin="P3", clk_polarity=1, clk_phase=0) 

def spi_ping(data): #no data from function, dummy
    global dyntag

    print("spi_ping: %s" % (dyntag))

    prev_dyntag = dyntag

    dyntag += 1

    return struct.pack('<H', prev_dyntag)

interface.register_callback(spi_ping)

interface.loop()

If I import config.py I randomly get a ping every 100 seconds or so.
Supposing the issue has to do with memory management.

# config.py

class c:
    # Define configuration parameters as class attributes
    variable_1 = 3
    variable_2 = 13
    variable_3 = 57
    variable_4 = 24
    variable_5 = 0
    variable_6 = 0
    variable_7 = 6
    variable_8 = 9
    variable_9 = 31
    variable_10 = 9
    variable_11 = 25
    variable_12 = 13
    variable_13 = 36
    variable_14 = 0
    variable_15 = 21
    variable_16 = 4
    variable_17 = 2
    variable_18 = 0
    variable_19 = 4
    variable_20 = 5
    variable_21 = 35
    variable_22 = 0
    variable_23 = 9
    variable_24 = 18
    variable_25 = 30
    variable_26 = 0
    variable_27 = 27
    variable_28 = 14
    variable_29 = 0
    variable_30 = 0
    variable_31 = 10
    variable_32 = 95
    variable_33 = 1
    variable_34 = 0
    variable_35 = 10000
    variable_36 = 18
    variable_37 = 4
    variable_38 = 5
    variable_39 = 20
    variable_40 = 2
    variable_41 = 4
    variable_42 = 8
    variable_43 = 140
    variable_44 = 0
    variable_45 = 162
    variable_46 = 255
    variable_47 = 128
    variable_48 = 100
    variable_49 = 200
    variable_50 = 192
    variable_51 = 99
    variable_52 = 2700
    variable_53 = 100

    # Derived parameters
    variable_54 = [variable_1 + variable_5, variable_2 + variable_6, variable_3, variable_4]
    variable_55 = [variable_7, variable_8, variable_11, variable_12]
    variable_56 = [variable_9, variable_10, variable_11, variable_12]
    variable_57 = [variable_13, variable_14, variable_15, variable_16]
    variable_58 = [variable_17, variable_18, variable_19, variable_20]
    variable_59 = [variable_21, variable_22, variable_23, variable_24]
    variable_60 = [variable_25, variable_26, variable_27, variable_28]
    variable_61 = [variable_29, variable_30, variable_11, variable_12]

    variable_62 = variable_31 / 100
    variable_63 = variable_32 / 100
    variable_64 = 666

Hi, the RPC library goes garbage collection each inner loop to reduce the surprises of garbage cleanup breaking the link as the MCU goes off and does garbage collection for several milliseconds.

However, those aren’t a lot of variables you are importing. It shouldn’t affect anything. You are also not modifying them. I mean, you can stream images over SPI and it works which is a lot more allocations…

The issue is likely how tight the timing is between both devices.

In the RPC slave class you can modify this variable:

self._put_short_timeout_reset = 2
self._get_short_timeout_reset = 2

If you increase these, it will lower the link bandwidth but give more time for the remote side to request/respond. However, the RPC library uses an incrementing backoff strategy where it will slowly increase these timeouts anyway… so, you shouldn’t have to touch them as they increase each time the RPC loop tries to connect internally.

Do you have a protocol analyzer? I can tell the issue easily from that. However, I recently tested SPI performance with an Arduino and detecting faces and it works as expected without any issue.

Strange that it works with older rpc.py. Unfortunately I don’t have a protocol analyzer. I can try modifying those parameters and will let you know .

Also I can transmit a lot of information with no issue with the old library. I think the .loop remains in a blocking condition too long and is missing incoming messages , maybe due to GC.collect. Was GC.collect added at a certain point in rpc.py? Could there be issues with auto garbage collection. ?

Maybe GC takes longer now?

This is the only thing I can think of, we added a bunch of heap blocks so it has to iterate over more RAM now… this is probably the cause. If so, then I’d modify the library name and remove the GC calls from it and see if that helps. If this is the issue those lines can be removed:

openmv/scripts/libraries/rpc.py at master · openmv/openmv (github.com)

Change the name and remove all the gc calls from it and then import the new name after copying to your disk and see if it works again. If it does then the GC calls need to go.

Tried modifing

self._put_short_timeout_reset = 2
self._get_short_timeout_reset = 2

No effect.

Got rid of gc.collect()
The example made to demonstrate the bug works!

However my main does not work (tested only for ping)! There I have more memory allocated and certainly more callbacks and functions defined in various files . I also tried disabling gc all together and re enabling in my callbacks. Same behavior both example code and my actual project main.

Again, works with older RPC library and latest released firmware.

The main difference I see between the two rpc.py old vs new is “time” being used instead of “pyb” for timing. Also machine.SPI replacing pyb.SPI . I don’t know how that explains any of this really.

I will check it again. Added a github tracker.

Is being discussed also in another post about SPI and DMA.

Hello, I am not sure if my problem is related but maybe it is.
I bought OpenMV H7 Plus which came with version 4.5.1. It ask me in the IDE to update but I didn’t initially.
I prepared the RPC remote thru VCP connection, and set it default in the IDE. Running form IDE told me “You cannot use the USB VCP while the IDE is connected!”. That is fine.
I plugged the OpenMV device to a Raspberry PI 5, and I configure the Raspberry PI board to connect and get images thru RPC. I installed necessary dependencies, I run script and the images come thru the opened window. Everything was fine.
Later on, I update the OpenMV board to version 4.5.8, from the IDE. Then I could not get the images on the Raspberry PI machine. Going back to the IDE and try running the script on the IDE machine, I now get a different message: AttributeError: ‘module’ object has no attribute ‘rpc_usb_vcp_slave’.
Was the support for VCP removed from RPC library, in the 4.5.8, or why getting this error?

The class is still there but not valid for the RT1062.

I now get a different message: AttributeError: ‘module’ object has no attribute ‘rpc_usb_vcp_slave’.

This sounds odd… the class is in the library. Maybe something else is wrong. Can you provide the code you are running? Is it the example script?

It is the example script.
Just try to load image_transfer_jpg_as_the_remote_device_for_your_computer.py on version 4.5.8 on OpenMV H7 Plus from within the IDE

Will test.