summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/mimxrt/Makefile14
-rw-r--r--ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk2
-rw-r--r--ports/mimxrt/boards/MIMXRT1176.ld4
-rw-r--r--ports/mimxrt/mpmetalport.c111
-rw-r--r--ports/mimxrt/mpmetalport.h73
-rw-r--r--ports/mimxrt/mpremoteprocport.c161
6 files changed, 364 insertions, 1 deletions
diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile
index dd1f5aa7c..96abb11bf 100644
--- a/ports/mimxrt/Makefile
+++ b/ports/mimxrt/Makefile
@@ -172,7 +172,8 @@ SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_common_arm.c \
$(MCU_DIR)/drivers/fsl_anatop_ai.c \
$(MCU_DIR)/drivers/fsl_caam.c \
- $(MCU_DIR)/drivers/fsl_lpadc.c
+ $(MCU_DIR)/drivers/fsl_lpadc.c \
+ $(MCU_DIR)/drivers/fsl_mu.c
else
SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_adc.c \
@@ -267,6 +268,17 @@ ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
SRC_C += mpnimbleport.c
endif
+# Add mimxrt-specific implementation of libmetal (and optionally OpenAMP's rproc).
+# Note: libmetal code is generated via a pre-processor so ensure that runs first.
+ifeq ($(MICROPY_PY_OPENAMP),1)
+SRC_C += mpmetalport.c
+$(BUILD)/mpmetalport.o: $(BUILD)/openamp/metal/config.h
+ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1)
+SRC_C += mpremoteprocport.c
+$(BUILD)/mpremoteprocport.o: $(BUILD)/openamp/metal/config.h
+endif
+endif
+
# Math library source files
ifeq ($(MICROPY_FLOAT_IMPL),double)
LIBM_SRC_C += $(SRC_LIB_LIBM_DBL_C)
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
index 1488730f7..6e5ee56aa 100644
--- a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
@@ -13,6 +13,8 @@ MICROPY_HW_SDRAM_SIZE = 0x4000000 # 64MB
MICROPY_PY_LWIP = 1
MICROPY_PY_SSL = 1
MICROPY_SSL_MBEDTLS = 1
+MICROPY_PY_OPENAMP = 1
+MICROPY_PY_OPENAMP_REMOTEPROC = 1
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/mimxrt/boards/MIMXRT1176.ld b/ports/mimxrt/boards/MIMXRT1176.ld
index d66c86a04..4d114ef96 100644
--- a/ports/mimxrt/boards/MIMXRT1176.ld
+++ b/ports/mimxrt/boards/MIMXRT1176.ld
@@ -57,3 +57,7 @@ _gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
_gc_heap_start = ORIGIN(m_ocrm);
_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm);
#endif
+
+/* CM4 DTCM */
+_openamp_shm_region_start = 0x20220000;
+_openamp_shm_region_end = 0x20230000;
diff --git a/ports/mimxrt/mpmetalport.c b/ports/mimxrt/mpmetalport.c
new file mode 100644
index 000000000..ca0c30fb2
--- /dev/null
+++ b/ports/mimxrt/mpmetalport.c
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Arduino SA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * libmetal mimxrt port.
+ */
+
+#include "py/mperrno.h"
+#include "py/mphal.h"
+
+#include "fsl_common.h"
+#include "fsl_mu.h"
+#include CPU_HEADER_H
+
+#include "metal/sys.h"
+#include "metal/utilities.h"
+#include "metal/device.h"
+
+struct metal_state _metal;
+static mp_sched_node_t rproc_notify_node;
+
+#define IRQ_PRI_MU NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 10, 0)
+
+int metal_sys_init(const struct metal_init_params *params) {
+ metal_unused(params);
+
+ // Init MU.
+ MU_Init(MUA);
+
+ // Configure and enable MU IRQs.
+ MU_ClearStatusFlags(MUA, kMU_GenInt0Flag);
+ NVIC_SetPriority(MUA_IRQn, IRQ_PRI_MU);
+ NVIC_EnableIRQ(MUA_IRQn);
+ MU_EnableInterrupts(MUA, kMU_GenInt0InterruptEnable);
+
+ #ifndef VIRTIO_USE_DCACHE
+ // If cache management is not enabled, configure the MPU to disable caching
+ // for the entire shared memory region.
+ ARM_MPU_Disable();
+ MPU->RBAR = ARM_MPU_RBAR(10, METAL_MPU_REGION_BASE);
+ // Normal type, not shareable, non-cacheable
+ MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, METAL_MPU_REGION_SIZE);
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
+ #endif
+
+ metal_bus_register(&metal_generic_bus);
+ return 0;
+}
+
+void metal_sys_finish(void) {
+ NVIC_DisableIRQ(MUA_IRQn);
+ metal_bus_unregister(&metal_generic_bus);
+}
+
+unsigned int sys_irq_save_disable(void) {
+ return disable_irq();
+}
+
+void sys_irq_restore_enable(unsigned int state) {
+ enable_irq(state);
+}
+
+void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
+ size_t size, unsigned int flags) {
+ metal_unused(pa);
+ metal_unused(size);
+ metal_unused(flags);
+ return va;
+}
+
+void metal_machine_cache_flush(void *addr, unsigned int len) {
+ SCB_CleanDCache_by_Addr(addr, len);
+}
+
+void metal_machine_cache_invalidate(void *addr, unsigned int len) {
+ SCB_InvalidateDCache_by_Addr(addr, len);
+}
+
+int metal_rproc_notify(void *priv, uint32_t id) {
+ MU_TriggerInterrupts(MUA, kMU_GenInt0InterruptTrigger);
+ return 0;
+}
+
+void MUA_IRQHandler(void) {
+ if (MU_GetStatusFlags(MUA) & kMU_GenInt0Flag) {
+ MU_ClearStatusFlags(MUA, kMU_GenInt0Flag);
+ mp_sched_schedule_node(&rproc_notify_node, openamp_remoteproc_notified);
+ }
+ __DSB();
+}
diff --git a/ports/mimxrt/mpmetalport.h b/ports/mimxrt/mpmetalport.h
new file mode 100644
index 000000000..994d57cc3
--- /dev/null
+++ b/ports/mimxrt/mpmetalport.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Arduino SA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * libmetal mimxrt port.
+ */
+#ifndef MICROPY_INCLUDED_MIMXRT_MPMETALPORT_H
+#define MICROPY_INCLUDED_MIMXRT_MPMETALPORT_H
+
+#include <stdlib.h>
+#include "py/mphal.h"
+#include "py/runtime.h"
+
+#define METAL_HAVE_STDATOMIC_H 0
+#define METAL_HAVE_FUTEX_H 0
+
+#define METAL_MAX_DEVICE_REGIONS 2
+
+// Set to 1 to enable the default log handler.
+#define METAL_LOG_HANDLER_ENABLE 0
+
+#define metal_cpu_yield()
+
+// Shared memory config
+#define METAL_SHM_NAME "OPENAMP_SHM"
+// Note 1K must be reserved at the start of the openamp
+// shared memory region, for the shared resource table.
+#define METAL_RSC_ADDR ((void *)_openamp_shm_region_start)
+#define METAL_RSC_SIZE (1024)
+
+#define METAL_SHM_ADDR ((metal_phys_addr_t)(_openamp_shm_region_start + METAL_RSC_SIZE))
+#define METAL_SHM_SIZE ((size_t)(_openamp_shm_region_end - _openamp_shm_region_start - METAL_RSC_SIZE))
+
+#define METAL_MPU_REGION_BASE ((uint32_t)_openamp_shm_region_start)
+#define METAL_MPU_REGION_SIZE (ARM_MPU_REGION_SIZE_64KB)
+
+extern const char _openamp_shm_region_start[];
+extern const char _openamp_shm_region_end[];
+
+int metal_rproc_notify(void *priv, uint32_t id);
+extern void openamp_remoteproc_notified(mp_sched_node_t *node);
+
+static inline int __metal_sleep_usec(unsigned int usec) {
+ mp_hal_delay_us(usec);
+ return 0;
+}
+
+static inline void metal_generic_default_poll(void) {
+ MICROPY_EVENT_POLL_HOOK
+}
+
+#endif // MICROPY_INCLUDED_MIMXRT_METAL_PORT_H
diff --git a/ports/mimxrt/mpremoteprocport.c b/ports/mimxrt/mpremoteprocport.c
new file mode 100644
index 000000000..1e2cefc7e
--- /dev/null
+++ b/ports/mimxrt/mpremoteprocport.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Arduino SA
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * modremoteproc mimxrt port.
+ */
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "fsl_common.h"
+#include "fsl_mu.h"
+
+#include "metal/alloc.h"
+#include "metal/errno.h"
+#include "metal/io.h"
+#include "metal/sys.h"
+#include "metal/device.h"
+#include "metal/utilities.h"
+#include "extmod/modopenamp_remoteproc.h"
+
+struct remoteproc *mp_openamp_remoteproc_init(struct remoteproc *rproc,
+ const struct remoteproc_ops *ops, void *arg) {
+ metal_log(METAL_LOG_DEBUG, "rproc_init()\n");
+
+ rproc->ops = ops;
+ rproc->state = RPROC_OFFLINE;
+ // Allocate the image store and save it in private data.
+ rproc->priv = mp_openamp_remoteproc_store_alloc();
+ return rproc;
+}
+
+void *mp_openamp_remoteproc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
+ metal_phys_addr_t *da, size_t size, unsigned int attribute,
+ struct metal_io_region **io) {
+ metal_log(METAL_LOG_DEBUG, "rproc_mmap(): pa 0x%p da 0x%p io 0x%p size %u\n", *pa, *da, *io, size);
+
+ struct remoteproc_mem *mem;
+ metal_phys_addr_t lpa = *pa;
+ metal_phys_addr_t lda = *da;
+
+ if (lda == METAL_BAD_PHYS) {
+ return NULL;
+ }
+
+ if (lpa == METAL_BAD_PHYS) {
+ lpa = lda;
+ }
+
+ if (lpa >= 0x1FFE0000 && lpa < 0x1FFFFFFF) {
+ // Map CM4 ITCM to CM7 address space.
+ lpa = 0x20200000 | (((uint32_t)lpa) & 0x1FFFF);
+ metal_log(METAL_LOG_DEBUG, "rproc_mmap(): remap 0x%p -> 0x%p\n", lda, lpa);
+ } else if (lpa >= 0x20000000 && lpa < 0x20020000) {
+ // Map CM4 DTCM to CM7 address space.
+ lpa = 0x20220000 | (((uint32_t)lpa) & 0x1FFFF);
+ metal_log(METAL_LOG_DEBUG, "rproc_mmap(): remap 0x%p -> 0x%p\n", lda, lpa);
+ }
+
+ mem = metal_allocate_memory(sizeof(*mem));
+ if (!mem) {
+ return NULL;
+ }
+
+ *io = metal_allocate_memory(sizeof(struct metal_io_region));
+ if (!*io) {
+ metal_free_memory(mem);
+ return NULL;
+ }
+
+ remoteproc_init_mem(mem, NULL, lpa, lda, size, *io);
+
+ metal_io_init(*io, (void *)lpa, &mem->pa, size,
+ sizeof(metal_phys_addr_t) << 3, attribute, NULL);
+
+ remoteproc_add_mem(rproc, mem);
+ *pa = lpa;
+ *da = lda;
+ return metal_io_phys_to_virt(*io, mem->pa);
+}
+
+int mp_openamp_remoteproc_start(struct remoteproc *rproc) {
+ metal_log(METAL_LOG_DEBUG, "rproc_start()\n");
+ if (SRC->SCR & SRC_SCR_BT_RELEASE_M4_MASK) {
+ // The CM4 core is already running.
+ metal_log(METAL_LOG_DEBUG, "rproc_start(): CM4 core is already booted.\n");
+ return -1;
+ }
+
+ // Flush M7 cache.
+ struct metal_list *node;
+ metal_list_for_each(&rproc->mems, node) {
+ struct remoteproc_mem *mem;
+ mem = metal_container_of(node, struct remoteproc_mem, node);
+ metal_log(METAL_LOG_DEBUG, "rproc_start() clean: pa 0x%p size %u\n", (uint32_t *)mem->pa, mem->size);
+ SCB_CleanDCache_by_Addr((uint32_t *)mem->pa, mem->size);
+ }
+
+ unsigned long offset = 0;
+ struct metal_io_region *io = remoteproc_get_io_with_da(rproc, rproc->bootaddr, &offset);
+ if (!io) {
+ return -1;
+ }
+
+ IOMUXC_LPSR_GPR->GPR0 = IOMUXC_LPSR_GPR_GPR0_CM4_INIT_VTOR_LOW(((uint32_t)io->virt) >> 3);
+ (void)IOMUXC_LPSR_GPR->GPR0;
+ IOMUXC_LPSR_GPR->GPR1 = IOMUXC_LPSR_GPR_GPR1_CM4_INIT_VTOR_HIGH(((uint32_t)io->virt) >> 16);
+ (void)IOMUXC_LPSR_GPR->GPR1;
+
+ SRC->CTRL_M4CORE = SRC_CTRL_M4CORE_SW_RESET_MASK;
+ SRC->SCR |= SRC_SCR_BT_RELEASE_M4_MASK;
+ return 0;
+}
+
+int mp_openamp_remoteproc_stop(struct remoteproc *rproc) {
+ metal_log(METAL_LOG_DEBUG, "rproc_stop()\n");
+ if (rproc->state == RPROC_RUNNING) {
+ NVIC_SystemReset();
+ }
+ return 0;
+}
+
+int mp_openamp_remoteproc_config(struct remoteproc *rproc, void *data) {
+ metal_log(METAL_LOG_DEBUG, "rproc_config()\n");
+ (void)rproc;
+ return 0;
+}
+
+void mp_openamp_remoteproc_remove(struct remoteproc *rproc) {
+ metal_log(METAL_LOG_DEBUG, "rproc_remove()\n");
+ (void)rproc;
+}
+
+int mp_openamp_remoteproc_shutdown(struct remoteproc *rproc) {
+ metal_log(METAL_LOG_DEBUG, "rproc_shutdown()\n");
+ if (rproc->state == RPROC_RUNNING) {
+ NVIC_SystemReset();
+ }
+ return 0;
+}