mimxrt: Add support for OpenAMP.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
pull/14120/head
iabdalkader 2024-03-23 16:11:15 +01:00 zatwierdzone przez Damien George
rodzic 23d7a915c1
commit 87d821ab49
6 zmienionych plików z 364 dodań i 1 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}