Skip to content

OpenAMP support. #12961

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

Merged
merged 16 commits into from
Mar 15, 2024
Merged

OpenAMP support. #12961

merged 16 commits into from
Mar 15, 2024

Conversation

iabdalkader
Copy link
Contributor

@iabdalkader iabdalkader commented Nov 13, 2023

This PR adds support for OpenAMP in MicroPython, with the goal of standardizing asymmetric multi-core support across different hardware running MicroPython. There are 3 major components to OpenAMP, libmetal, remoteproc and RPMsg. libmetal provides abstraction of the low-level underlying hardware, remoteproc is used for processor Life Cycle Management (LCM) (i.e loading firmware, starting, stopping a core etc..), and RPMsg is a bus infrastructure that enables Inter Processor Communications (IPC) between different cores. These components are implemented in this PR as follows:

  • OpenAMP's libmetal submodule is added in this PR (see note about this submodule), and a generic MicroPython system port is implemented, one that uses some sane defaults and common mp_hal functions, and also allows for MicroPython's ports to override defaults and config libmetal.

  • OpenAMP's remoteproc component is implemented in extmod/modremoteproc.c module which provides an API to load firmware and control remote processors. Port-specific ops must be implemented for this module (similar to mpbthciport.c or mpnetworkport.c). One example is already done in this PR for stm32.

  • OpenAMP's RPMsg component and the rest of the logic is implemented in extmod/modopenamp.c. This module provides anendpoint type (a logical connection on top of RPMsg channel) that can be used to communicate with the remote core.

Example: The following script loads a firmware image that implements a virtual uart over RPMsg channel, built for STM32H7's M4 core, starts it, and communicates with the M4 once the core is ready to communicate. The remote core becomes ready to communicate after the master/host core initializes a shared memory area, and it announces its readiness by creating a new RPMsg channel. At this point, the ns_callback is called, and the host processor creates an endpoint to communicate over that RPMsg channel. Note the firmware is parsed and loaded from an elf file stored on the filesystem, I can share the source somewhere later as an example or for testing.

import openamp
import time

ept = None


def ept_recv_callback(src_addr, data):
    print(f'Received message on endpoint "{data}"')


def ns_bind_callback(src_addr, name):
    global ept
    print(f'New service announcement src address: {src_addr} name: "{name}"')
    # Create a new RPMsg endpoint to communicate with the M4.
    ept = openamp.RPMsg(
        name, src_addr=openamp.RPMSG_ADDR_ANY, dst_addr=src_addr, callback=ept_recv_callback
    )


# Initialize OpenAMP. Name service callback is called when the remote
# processor creates an RPMsg channel, and is ready to communicate.
openamp.init(ns_callback=ns_bind_callback)

# Create a remoteproc object, load its firmware and start it.
# Note you can also start from an entry point (ex 0x081E0000)
#rproc = openamp.RProc(0x081E0000)
rproc = openamp.RProc("vuart.elf")
rproc.start()

while True:
    if ept is not None:
        ept.send("Hello World!", timeout=1000)
    time.sleep_ms(1000)

Output:

registered generic bus
remoteproc_load: check remoteproc status
remoteproc_load: open executable image
remoteproc_load: check loader
remoteproc_load: loading headers
Loading ELF headering
Loading ELF program header.
Loading ELF section header.
remoteproc_load, load header 0x0, 0x1000, next 0x18098, 0x258
Loading ELF section header.
Loading ELF section header complete.
Loading ELF shstrtab.
remoteproc_load, load header 0x18098, 0x258, next 0x1800d, 0x8a
Loading ELF shstrtab.
remoteproc_load, load header 0x1800d, 0x8a, next 0x1800d, 0x0
remoteproc_load: load executable data
segment: 1, total segs 1
load data: da 0x38000000, offset 0x10000, len = 0x7f90, memsize = 0xc138, state 0x20801
load data: da 0xffffffff, offset 0x0, len = 0x0, memsize = 0x0, state 0x40801
remoteproc_load: successfully load firmware
New service announcement src address: 1024 name: "m4-vuart-channel"
Received message on endpoint "Hello from M4!"

The firmware running on the M4 can be found here: https://github.com/iabdalkader/openamp_vuart

Todo:

  • Handle file system access in a generic way using mp_vfs
  • Support endpoint send/send non-blocking and off-channel.
  • Add optional trace buffer resource.
  • Support loading/starting firmware from Flash address.
  • Support loading/starting firmware from SD-RAM on H7.
  • Provide an example for the H7 M4 side (optional).
  • Note about libmetal it's basically impossible to add its upstream as a submodule, since it only supports cmake, and it hard-codes configure_file variables into headers, and it's basically expected to be built into a static library and installed somewhere. So for now I've used my own fork, with minor changes to make it more "MicroPython-friendly". This library hardly changes, I think it would make sense to maintain our own fork, I can transfer ownership of the libmetal repo to MicroPython later if you want, I have no need to maintain it.

@iabdalkader iabdalkader marked this pull request as draft November 13, 2023 16:28
Copy link

github-actions bot commented Nov 13, 2023

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:   +32 +0.004% standard
      stm32:   +24 +0.006% PYBV10
     mimxrt:   +24 +0.007% TEENSY40
        rp2:   +16 +0.005% RPI_PICO
       samd:   +24 +0.009% ADAFRUIT_ITSYBITSY_M4_EXPRESS

Copy link

codecov bot commented Nov 13, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.39%. Comparing base (7f5d8c4) to head (df2ff0c).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #12961   +/-   ##
=======================================
  Coverage   98.39%   98.39%           
=======================================
  Files         161      161           
  Lines       21078    21079    +1     
=======================================
+ Hits        20739    20740    +1     
  Misses        339      339           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@iabdalkader iabdalkader force-pushed the openamp_support branch 3 times, most recently from 445328b to a9d3ea6 Compare November 20, 2023 09:38
@iabdalkader iabdalkader marked this pull request as ready for review November 20, 2023 09:51
@iabdalkader iabdalkader force-pushed the openamp_support branch 17 times, most recently from a043cd3 to 5bb1b02 Compare November 23, 2023 13:18
@iabdalkader iabdalkader force-pushed the openamp_support branch 3 times, most recently from 1375bd0 to 1952b72 Compare November 24, 2023 16:27
@iabdalkader
Copy link
Contributor Author

@dpgeorge

It would be really nice if we can update the CMSIS headers to support zero and copy tables, this way I can remove the function that initializes the shared resource table (openamp_rsc_table_init) .

https://github.com/ARM-software/CMSIS_5/blob/a75f01746df18bb5b929dfb8dc6c9407fac3a0f3/CMSIS/Core/Include/cmsis_gcc.h#L137

@iabdalkader iabdalkader force-pushed the openamp_support branch 2 times, most recently from 6f142f0 to 1eeb92e Compare March 14, 2024 08:30
@dpgeorge
Copy link
Member

Note: I'm working on this PR and will merge it shortly.

OpenAMP framework provides a standard inter processor communications
infrastructure for RTOS and bare metal environments. There are 3 major
components in OpenAMP: libmetal, remoteproc and RPMsg. libmetal provides
abstraction of the low-level underlying hardware, remoteproc is used for
processor Life Cycle Management (LCM) like loading firmware, starting,
stopping a core etc., and RPMsg is a bus infrastructure that enables Inter
Processor Communications (IPC) between different cores.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
libmetal provides an abstraction of the underlying hardware, to support
other OpenAMP components.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
@iabdalkader
Copy link
Contributor Author

I reviewed the commits again, everything seems to be in order.

iabdalkader and others added 14 commits March 15, 2024 18:11
Add a MicroPython platform for libmetal, based on the generic platform.
The MicroPython platform uses common mp_hal_xxx functions and allows ports
to customize default configurations for libmetal.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
So there's only one location that does the ioctl(MP_STREAM_SEEK) call.

Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This module implements OpenAMP's basic initialization and shared resources
support, and provides support for OpenAMP's RPMsg component, by providing
an `endpoint` type (a logical connection on top of RPMsg channel) which can
be used to communicate with the remote core.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
RemoteProc provides an API to load firmware and control remote processors.

Note: port-specific operations must be implemented to support this class.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge dpgeorge merged commit df2ff0c into micropython:master Mar 15, 2024
@dpgeorge
Copy link
Member

Merged!!

Thanks @iabdalkader for implementing this, I think it will be a great feature for multicore SoCs, of which there are more and more these days.

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

Successfully merging this pull request may close these issues.

4 participants