From f12ffe998a9b52f0327e109b5b3005a2ef787770 Mon Sep 17 00:00:00 2001 From: "Michal Princ (nxa17570)" Date: Tue, 5 Jan 2021 15:08:37 +0100 Subject: [PATCH] RPMsg-Lite update 01/2021 - Several MISRA C-2012 violations addressed - Introduced RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION config option to allow opposite side notification sending each time received buffers are consumed and put into the queue of available buffers - Added environment layers for Threadx - Added support for i.MX8QM multicore platform - Updated version to 3.1.1 --- README.md | 1 + doxygen/Doxyfile.rpmsglite | 2 +- .../platform/imx8qm_m4/rpmsg_platform.h | 94 +++ .../platform/imxrt600_hifi4/rpmsg_platform.h | 13 +- .../platform/imxrt600_m33/rpmsg_platform.h | 11 +- lib/include/rpmsg_default_config.h | 13 +- lib/include/rpmsg_lite.h | 2 +- .../porting/environment/rpmsg_env_bm.c | 2 +- .../porting/environment/rpmsg_env_freertos.c | 2 +- .../porting/environment/rpmsg_env_threadx.c | 637 ++++++++++++++++++ .../porting/environment/rpmsg_env_zephyr.c | 2 +- .../platform/imx6sx_m4/rpmsg_platform.c | 9 +- .../platform/imx7d_m4/rpmsg_platform.c | 9 +- .../platform/imx7ulp_m4/rpmsg_platform.c | 13 +- .../platform/imx8mm_m4/rpmsg_platform.c | 13 +- .../platform/imx8mn_m7/rpmsg_platform.c | 13 +- .../platform/imx8mq_m4/rpmsg_platform.c | 4 +- .../platform/imx8qm_m4/rpmsg_platform.c | 485 +++++++++++++ .../platform/imxrt600_hifi4/rpmsg_platform.c | 217 ++---- .../platform/imxrt600_m33/rpmsg_platform.c | 50 +- .../porting/platform/k32l3a6/rpmsg_platform.c | 53 +- .../platform/lpc5410x/rpmsg_platform.c | 13 +- .../platform/lpc5411x/rpmsg_platform.c | 13 +- .../platform/lpc55s69/rpmsg_platform.c | 4 +- lib/rpmsg_lite/rpmsg_lite.c | 18 + 25 files changed, 1419 insertions(+), 274 deletions(-) create mode 100644 lib/include/platform/imx8qm_m4/rpmsg_platform.h create mode 100644 lib/rpmsg_lite/porting/environment/rpmsg_env_threadx.c create mode 100644 lib/rpmsg_lite/porting/platform/imx8qm_m4/rpmsg_platform.c diff --git a/README.md b/README.md index 3accdfb..6758e62 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ The RPMsg-Lite can be configured at the compile time. The default configuration |RL_USE_MCMGR_IPC_ISR_HANDLER | (0) | When enabled IPC interrupts are managed by the Multicore Manager (IPC interrupts router), when disabled RPMsg-Lite manages IPC interrupts by itself. | |RL_USE_ENVIRONMENT_CONTEXT | (0) | When enabled the environment layer uses its own context. Required for some environments (QNX). The default value is 0 (no context, saves some RAM). | |RL_DEBUG_CHECK_BUFFERS | (0) | When enabled buffer debug checks in rpmsg_lite_send_nocopy() and rpmsg_lite_release_rx_buffer() functions are disabled. Do not use in RPMsg-Lite to Linux configuration. | +|RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION | (0) | When enabled the opposite side is notified each time received buffers are consumed and put into the queue of available buffers. Enable this option in RPMsg-Lite to Linux configuration to allow unblocking of the Linux blocking send. The default value is 0 (RPMsg-Lite to RPMsg-Lite communication). | |RL_ASSERT | see rpmsg_default_config.h | Assert implementation. | # Contributing to the rpmsg-lite project diff --git a/doxygen/Doxyfile.rpmsglite b/doxygen/Doxyfile.rpmsglite index c629455..b0c8cba 100644 --- a/doxygen/Doxyfile.rpmsglite +++ b/doxygen/Doxyfile.rpmsglite @@ -38,7 +38,7 @@ PROJECT_NAME = "RPMsg-Lite User's Guide" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "Rev. 3.1.0" +PROJECT_NUMBER = "Rev. 3.1.1" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/lib/include/platform/imx8qm_m4/rpmsg_platform.h b/lib/include/platform/imx8qm_m4/rpmsg_platform.h new file mode 100644 index 0000000..b633cdc --- /dev/null +++ b/lib/include/platform/imx8qm_m4/rpmsg_platform.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef RPMSG_PLATFORM_H_ +#define RPMSG_PLATFORM_H_ + +#include + +/* RPMSG MU channel index */ +#define RPMSG_MU_CHANNEL (1) + +/* + * Linux requires the ALIGN to 0x1000(4KB) instead of 0x80 + */ +#ifndef VRING_ALIGN +#define VRING_ALIGN (0x1000U) +#endif + +/* contains pool of descriptors and two circular buffers */ +#ifndef VRING_SIZE +#define VRING_SIZE (0x8000UL) +#endif + +/* size of shared memory + 2*VRING size */ +#define RL_VRING_OVERHEAD (2UL * VRING_SIZE) + +/* VQ_ID in 8QM is defined as follows: + * com_id: [3:3] communication ID, used to identify the MU instance. + * vring_id: [2:1] vring ID, used to identify the vring. + * q_id: [0:0] queue ID, used to identify the tvq or rvq. + * com_id + vring_id = link_id + */ + +#define RL_GET_VQ_ID(link_id, queue_id) (((queue_id)&0x1U) | (((link_id) << 1U) & 0xFFFFFFFEU)) +#define RL_GET_LINK_ID(vq_id) ((vq_id) >> 1U) +#define RL_GET_COM_ID(vq_id) ((vq_id) >> 3U) +#define RL_GET_Q_ID(vq_id) ((vq_id)&0x1U) + +#define RL_GEN_LINK_ID(com_id, vring_id) (((com_id) << 2U) | (vring_id)) +#define RL_GEN_MU_MSG(vq_id) (uint32_t)(((vq_id)&0x7U) << 16U) /* com_id is discarded in msg */ + +#define RL_PLATFORM_IMX8QM_M4_A_COM_ID (0U) +#define RL_PLATFORM_IMX8QM_M4_M4_COM_ID (1U) + +#define RL_PLATFORM_IMX8QM_M4_SRTM_VRING_ID (0U) +#define RL_PLATFORM_IMX8QM_M4_USER_VRING_ID (1U) + +#define RL_PLATFORM_HIGHEST_LINK_ID RL_GEN_LINK_ID(RL_PLATFORM_IMX8QM_M4_M4_COM_ID, RL_PLATFORM_IMX8QM_M4_USER_VRING_ID) + +#define RL_PLATFORM_IMX8QM_M4_A_SRTM_LINK_ID \ + RL_GEN_LINK_ID(RL_PLATFORM_IMX8QM_M4_A_COM_ID, RL_PLATFORM_IMX8QM_M4_SRTM_VRING_ID) +#define RL_PLATFORM_IMX8QM_M4_A_USER_LINK_ID \ + RL_GEN_LINK_ID(RL_PLATFORM_IMX8QM_M4_A_COM_ID, RL_PLATFORM_IMX8QM_M4_USER_VRING_ID) +#define RL_PLATFORM_IMX8QM_M4_M4_SRTM_LINK_ID \ + RL_GEN_LINK_ID(RL_PLATFORM_IMX8QM_M4_M4_COM_ID, RL_PLATFORM_IMX8QM_M4_SRTM_VRING_ID) +#define RL_PLATFORM_IMX8QM_M4_M4_USER_LINK_ID \ + RL_GEN_LINK_ID(RL_PLATFORM_IMX8QM_M4_M4_COM_ID, RL_PLATFORM_IMX8QM_M4_USER_VRING_ID) + +/* platform interrupt related functions */ +int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data); +int32_t platform_deinit_interrupt(uint32_t vector_id); +int32_t platform_interrupt_enable(uint32_t vector_id); +int32_t platform_interrupt_disable(uint32_t vector_id); +int32_t platform_in_isr(void); +void platform_notify(uint32_t vector_id); + +/* platform low-level time-delay (busy loop) */ +void platform_time_delay(uint32_t num_msec); + +/* platform memory functions */ +void platform_map_mem_region(uint32_t vrt_addr, uint32_t phy_addr, uint32_t size, uint32_t flags); +void platform_cache_all_flush_invalidate(void); +void platform_cache_disable(void); +uint32_t platform_vatopa(void *addr); +void *platform_patova(uint32_t addr); + +/* platform init/deinit */ +int32_t platform_init(void); +int32_t platform_deinit(void); + +#if defined(MIMX8QM_CM4_CORE0) +int32_t LSIO_MU5_INT_B_IRQHandler(void); +int32_t LSIO_MU7_INT_A_IRQHandler(void); +#elif defined(MIMX8QM_CM4_CORE1) +int32_t LSIO_MU6_INT_B_IRQHandler(void); +int32_t LSIO_MU7_INT_B_IRQHandler(void); +#endif + +#endif /* RPMSG_PLATFORM_H_ */ diff --git a/lib/include/platform/imxrt600_hifi4/rpmsg_platform.h b/lib/include/platform/imxrt600_hifi4/rpmsg_platform.h index ebb859e..fbe471e 100644 --- a/lib/include/platform/imxrt600_hifi4/rpmsg_platform.h +++ b/lib/include/platform/imxrt600_hifi4/rpmsg_platform.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * All rights reserved. * * @@ -11,13 +11,8 @@ #include -/* RPMSG MU channel index */ -#define RPMSG_MU_CHANNEL (1) - -#define RPMSG_LITE_LINK_ID 0x1 - /* - * No need to align the VRING as defined in Linux because LPCNEXT0 is not intended + * No need to align the VRING as defined in Linux because RT600 is not intended * to run the Linux */ #ifndef VRING_ALIGN @@ -36,8 +31,8 @@ #define RL_GET_LINK_ID(id) (((id)&0xFFFFFFFEU) >> 1U) #define RL_GET_Q_ID(id) ((id)&0x1U) -#define RL_PLATFORM_LPCNEXT0_LINK_ID (0U) -#define RL_PLATFORM_HIGHEST_LINK_ID (1U) +#define RL_PLATFORM_IMXRT600_LINK_ID (0U) +#define RL_PLATFORM_HIGHEST_LINK_ID (0U) /* platform interrupt related functions */ int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data); diff --git a/lib/include/platform/imxrt600_m33/rpmsg_platform.h b/lib/include/platform/imxrt600_m33/rpmsg_platform.h index 840b229..d10a548 100644 --- a/lib/include/platform/imxrt600_m33/rpmsg_platform.h +++ b/lib/include/platform/imxrt600_m33/rpmsg_platform.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * All rights reserved. * * @@ -10,11 +10,8 @@ #include -/* RPMSG MU channel index */ -#define RPMSG_MU_CHANNEL (1) - /* - * No need to align the VRING as defined in Linux because LPC6324 is not intended + * No need to align the VRING as defined in Linux because RT600 is not intended * to run the Linux */ #ifndef VRING_ALIGN @@ -33,8 +30,8 @@ #define RL_GET_LINK_ID(id) (((id)&0xFFFFFFFEU) >> 1U) #define RL_GET_Q_ID(id) ((id)&0x1U) -#define RL_PLATFORM_LPC6324_M33_DSP_LINK_ID (0U) -#define RL_PLATFORM_HIGHEST_LINK_ID (0U) +#define RL_PLATFORM_IMXRT600_LINK_ID (0U) +#define RL_PLATFORM_HIGHEST_LINK_ID (0U) /* platform interrupt related functions */ int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data); diff --git a/lib/include/rpmsg_default_config.h b/lib/include/rpmsg_default_config.h index da95570..503542f 100644 --- a/lib/include/rpmsg_default_config.h +++ b/lib/include/rpmsg_default_config.h @@ -2,7 +2,7 @@ * Copyright (c) 2014, Mentor Graphics Corporation * Copyright (c) 2015 Xilinx, Inc. * Copyright (c) 2016 Freescale Semiconductor, Inc. - * Copyright 2016-2019 NXP + * Copyright 2016-2020 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -124,6 +124,17 @@ #define RL_DEBUG_CHECK_BUFFERS (0) #endif +//! @def RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION +//! +//! When enabled the opposite side is notified each time received buffers +//! are consumed and put into the queue of available buffers. +//! Enable this option in RPMsg-Lite to Linux configuration to allow unblocking +//! of the Linux blocking send. +//! The default value is 0 (RPMsg-Lite to RPMsg-Lite communication). +#ifndef RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION +#define RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION (0) +#endif + //! @def RL_HANG //! //! Default implementation of hang assert function diff --git a/lib/include/rpmsg_lite.h b/lib/include/rpmsg_lite.h index 77871ab..3880913 100644 --- a/lib/include/rpmsg_lite.h +++ b/lib/include/rpmsg_lite.h @@ -51,7 +51,7 @@ extern "C" { * Definitions ******************************************************************************/ -#define RL_VERSION "3.1.0" /*!< Current RPMsg Lite version */ +#define RL_VERSION "3.1.1" /*!< Current RPMsg Lite version */ /* Shared memory "allocator" parameters */ #define RL_WORD_SIZE (sizeof(uint32_t)) diff --git a/lib/rpmsg_lite/porting/environment/rpmsg_env_bm.c b/lib/rpmsg_lite/porting/environment/rpmsg_env_bm.c index 05ebb04..93ba58d 100644 --- a/lib/rpmsg_lite/porting/environment/rpmsg_env_bm.c +++ b/lib/rpmsg_lite/porting/environment/rpmsg_env_bm.c @@ -33,7 +33,7 @@ /************************************************************************** * FILE NAME * - * bm_env.c + * rpmsg_env_bm.c * * * DESCRIPTION diff --git a/lib/rpmsg_lite/porting/environment/rpmsg_env_freertos.c b/lib/rpmsg_lite/porting/environment/rpmsg_env_freertos.c index f8f0abb..947a905 100644 --- a/lib/rpmsg_lite/porting/environment/rpmsg_env_freertos.c +++ b/lib/rpmsg_lite/porting/environment/rpmsg_env_freertos.c @@ -33,7 +33,7 @@ /************************************************************************** * FILE NAME * - * freertos_env.c + * rpmsg_env_freertos.c * * * DESCRIPTION diff --git a/lib/rpmsg_lite/porting/environment/rpmsg_env_threadx.c b/lib/rpmsg_lite/porting/environment/rpmsg_env_threadx.c new file mode 100644 index 0000000..46d311c --- /dev/null +++ b/lib/rpmsg_lite/porting/environment/rpmsg_env_threadx.c @@ -0,0 +1,637 @@ +/* + * Copyright 2020 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * rpmsg_env_threadx.c + * + * + * DESCRIPTION + * + * This file is ThreadX Implementation of env layer for OpenAMP. + * + * + **************************************************************************/ +#include "rpmsg_env.h" +#include "tx_api.h" +#include "tx_event_flags.h" +#include "rpmsg_platform.h" +#include "fsl_common.h" +#include "rpmsg_compiler.h" +#include "fsl_component_mem_manager.h" +#include +#include +#include "virtqueue.h" + +static int32_t env_init_counter = 0; +static TX_SEMAPHORE env_sema; + +/* RL_ENV_MAX_MUTEX_COUNT is an arbitrary count greater than 'count' + if the inital count is 1, this function behaves as a mutex + if it is greater than 1, it acts as a "resource allocator" with + the maximum of 'count' resources available. + Currently, only the first use-case is applicable/applied in RPMsg-Lite. + */ +#define RL_ENV_MAX_MUTEX_COUNT (10) + +/* Max supported ISR counts */ +#define ISR_COUNT (32U) +/*! + * Structure to keep track of registered ISR's. + */ +struct isr_info +{ + void *data; +}; +static struct isr_info isr_table[ISR_COUNT]; + +#if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) +#error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 0" +#endif + +/*! + * env_in_isr + * + * @returns - true, if currently in ISR + * + */ +static int32_t env_in_isr(void) +{ + return platform_in_isr(); +} + +/*! + * env_init + * + * Initializes OS/ThreadX environment. + * + */ +int32_t env_init(void) +{ + int32_t retval; + uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */ + + // verify 'env_init_counter' + RL_ASSERT(env_init_counter >= 0); + if (env_init_counter < 0) + { + EnableGlobalIRQ(regPrimask); /* re-enable scheduler */ + return -1; + } + env_init_counter++; + // multiple call of 'env_init' - return ok + if (env_init_counter == 1) + { + // first call + if (TX_SUCCESS != _tx_semaphore_create((TX_SEMAPHORE *)&env_sema, NULL, 0)) + { + EnableGlobalIRQ(regPrimask); + return -1; + } + (void)memset(isr_table, 0, sizeof(isr_table)); + EnableGlobalIRQ(regPrimask); + retval = platform_init(); + tx_semaphore_put((TX_SEMAPHORE *)&env_sema); + + return retval; + } + else + { + EnableGlobalIRQ(regPrimask); + /* Get the semaphore and then return it, + * this allows for platform_init() to block + * if needed and other tasks to wait for the + * blocking to be done. + * This is in ENV layer as this is ENV specific.*/ + if (TX_SUCCESS == tx_semaphore_get((TX_SEMAPHORE *)&env_sema, TX_WAIT_FOREVER)) + { + tx_semaphore_put((TX_SEMAPHORE *)&env_sema); + } + return 0; + } +} + +/*! + * env_deinit + * + * Uninitializes OS/BM environment. + * + * @returns - execution status + */ +int32_t env_deinit(void) +{ + int32_t retval; + + uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */ + // verify 'env_init_counter' + RL_ASSERT(env_init_counter > 0); + if (env_init_counter <= 0) + { + EnableGlobalIRQ(regPrimask); + return -1; + } + + // counter on zero - call platform deinit + env_init_counter--; + // multiple call of 'env_deinit' - return ok + if (env_init_counter <= 0) + { + // last call + (void)memset(isr_table, 0, sizeof(isr_table)); + retval = platform_deinit(); + (void)_tx_semaphore_delete((TX_SEMAPHORE *)&env_sema); + (void)memset(&env_sema, 0, sizeof(env_sema)); + EnableGlobalIRQ(regPrimask); + return retval; + } + else + { + EnableGlobalIRQ(regPrimask); + return 0; + } +} + +/*! + * env_allocate_memory - implementation + * + * @param size + */ +void *env_allocate_memory(uint32_t size) +{ + return (MEM_BufferAlloc(size)); +} + +/*! + * env_free_memory - implementation + * + * @param ptr + */ +void env_free_memory(void *ptr) +{ + if (ptr != ((void *)0)) + { + MEM_BufferFree(ptr); + } +} + +/*! + * + * env_memset - implementation + * + * @param ptr + * @param value + * @param size + */ +void env_memset(void *ptr, int32_t value, uint32_t size) +{ + (void)memset(ptr, value, size); +} + +/*! + * + * env_memcpy - implementation + * + * @param dst + * @param src + * @param len + */ +void env_memcpy(void *dst, void const *src, uint32_t len) +{ + (void)memcpy(dst, src, len); +} + +/*! + * + * env_strcmp - implementation + * + * @param dst + * @param src + */ + +int32_t env_strcmp(const char *dst, const char *src) +{ + return (strcmp(dst, src)); +} + +/*! + * + * env_strncpy - implementation + * + * @param dest + * @param src + * @param len + */ +void env_strncpy(char *dest, const char *src, uint32_t len) +{ + (void)strncpy(dest, src, len); +} + +/*! + * + * env_strncmp - implementation + * + * @param dest + * @param src + * @param len + */ +int32_t env_strncmp(char *dest, const char *src, uint32_t len) +{ + return (strncmp(dest, src, len)); +} + +/*! + * + * env_mb - implementation + * + */ +void env_mb(void) +{ + MEM_BARRIER(); +} + +/*! + * env_rmb - implementation + */ +void env_rmb(void) +{ + MEM_BARRIER(); +} + +/*! + * env_wmb - implementation + */ +void env_wmb(void) +{ + MEM_BARRIER(); +} + +/*! + * env_map_vatopa - implementation + * + * @param address + */ +uint32_t env_map_vatopa(void *address) +{ + return platform_vatopa(address); +} + +/*! + * env_map_patova - implementation + * + * @param address + */ +void *env_map_patova(uint32_t address) +{ + return platform_patova(address); +} + +/*! + * env_create_mutex + * + * Creates a mutex with the given initial count. + * + */ +int32_t env_create_mutex(void **lock, int32_t count) +{ + TX_SEMAPHORE *semaphore_ptr; + + semaphore_ptr = (TX_SEMAPHORE *)env_allocate_memory(sizeof(TX_SEMAPHORE)); + if (semaphore_ptr == ((void *)0)) + { + return -1; + } + + if (count > RL_ENV_MAX_MUTEX_COUNT) + { + return -1; + } + + if (TX_SUCCESS != _tx_semaphore_create((TX_SEMAPHORE *)semaphore_ptr, NULL, count)) + { + return -1; + } + *lock = (void *)semaphore_ptr; + return 0; +} + +/*! + * env_delete_mutex + * + * Deletes the given lock + * + */ +void env_delete_mutex(void *lock) +{ + (void)_tx_semaphore_delete((TX_SEMAPHORE *)lock); + env_free_memory(lock); +} + +/*! + * env_lock_mutex + * + * Tries to acquire the lock, if lock is not available then call to + * this function will suspend. + */ +void env_lock_mutex(void *lock) +{ + if (env_in_isr() == 0) + { + (void)tx_semaphore_get((TX_SEMAPHORE *)lock, TX_WAIT_FOREVER); + } +} + +/*! + * env_unlock_mutex + * + * Releases the given lock. + */ +void env_unlock_mutex(void *lock) +{ + if (env_in_isr() == 0) + { + tx_semaphore_put((TX_SEMAPHORE *)lock); + } +} + +/*! + * env_create_sync_lock + * + * Creates a synchronization lock primitive. It is used + * when signal has to be sent from the interrupt context to main + * thread context. + */ +int32_t env_create_sync_lock(void **lock, int32_t state) +{ + return env_create_mutex(lock, state); /* state=1 .. initially free */ +} + +/*! + * env_delete_sync_lock + * + * Deletes the given lock + * + */ +void env_delete_sync_lock(void *lock) +{ + if (lock != ((void *)0)) + { + env_delete_mutex(lock); + } +} + +/*! + * env_acquire_sync_lock + * + * Tries to acquire the lock, if lock is not available then call to + * this function waits for lock to become available. + */ +void env_acquire_sync_lock(void *lock) +{ + if (lock != ((void *)0)) + { + env_lock_mutex(lock); + } +} + +/*! + * env_release_sync_lock + * + * Releases the given lock. + */ +void env_release_sync_lock(void *lock) +{ + if (lock != ((void *)0)) + { + env_unlock_mutex(lock); + } +} + +/*! + * env_sleep_msec + * + * Suspends the calling thread for given time , in msecs. + */ +void env_sleep_msec(uint32_t num_msec) +{ + tx_thread_sleep(num_msec); +} + +/*! + * env_register_isr + * + * Registers interrupt handler data for the given interrupt vector. + * + * @param vector_id - virtual interrupt vector number + * @param data - interrupt handler data (virtqueue) + */ +void env_register_isr(uint32_t vector_id, void *data) +{ + RL_ASSERT(vector_id < ISR_COUNT); + if (vector_id < ISR_COUNT) + { + isr_table[vector_id].data = data; + } +} + +/*! + * env_unregister_isr + * + * Unregisters interrupt handler data for the given interrupt vector. + * + * @param vector_id - virtual interrupt vector number + */ +void env_unregister_isr(uint32_t vector_id) +{ + RL_ASSERT(vector_id < ISR_COUNT); + if (vector_id < ISR_COUNT) + { + isr_table[vector_id].data = ((void *)0); + } +} + +/*! + * env_enable_interrupt + * + * Enables the given interrupt + * + * @param vector_id - virtual interrupt vector number + */ + +void env_enable_interrupt(uint32_t vector_id) +{ + (void)platform_interrupt_enable(vector_id); +} + +/*! + * env_disable_interrupt + * + * Disables the given interrupt + * + * @param vector_id - virtual interrupt vector number + */ + +void env_disable_interrupt(uint32_t vector_id) +{ + (void)platform_interrupt_disable(vector_id); +} + +/*! + * env_map_memory + * + * Enables memory mapping for given memory region. + * + * @param pa - physical address of memory + * @param va - logical address of memory + * @param size - memory size + * param flags - flags for cache/uncached and access type + */ + +void env_map_memory(uint32_t pa, uint32_t va, uint32_t size, uint32_t flags) +{ + platform_map_mem_region(va, pa, size, flags); +} + +/*! + * env_disable_cache + * + * Disables system caches. + * + */ + +void env_disable_cache(void) +{ + platform_cache_all_flush_invalidate(); + platform_cache_disable(); +} + +/*========================================================= */ +/* Util data / functions */ + +void env_isr(uint32_t vector) +{ + struct isr_info *info; + RL_ASSERT(vector < ISR_COUNT); + if (vector < ISR_COUNT) + { + info = &isr_table[vector]; + virtqueue_notification((struct virtqueue *)info->data); + } +} + +/* + * env_create_queue + * + * Creates a message queue. + * + * @param queue - pointer to created queue + * @param length - maximum number of elements in the queue + * @param element_size - queue element size in bytes + * + * @return - status of function execution + */ +int32_t env_create_queue(void **queue, int32_t length, int32_t element_size) +{ + if (TX_SUCCESS == _tx_queue_create((TX_QUEUE *)*queue, NULL, element_size, NULL, length)) + { + return 0; + } + else + { + return -1; + } +} + +/*! + * env_delete_queue + * + * Deletes the message queue. + * + * @param queue - queue to delete + */ + +void env_delete_queue(void *queue) +{ + tx_queue_delete(queue); +} + +/*! + * env_put_queue + * + * Put an element in a queue. + * + * @param queue - queue to put element in + * @param msg - pointer to the message to be put into the queue + * @param timeout_ms - timeout in ms + * + * @return - status of function execution + */ + +int32_t env_put_queue(void *queue, void *msg, uint32_t timeout_ms) +{ + if (TX_SUCCESS == tx_queue_send((TX_QUEUE *)queue, msg, timeout_ms)) + { + return 0; + } + else + { + return -1; + } +} + +/*! + * env_get_queue + * + * Get an element out of a queue. + * + * @param queue - queue to get element from + * @param msg - pointer to a memory to save the message + * @param timeout_ms - timeout in ms + * + * @return - status of function execution + */ + +int32_t env_get_queue(void *queue, void *msg, uint32_t timeout_ms) +{ + if (TX_SUCCESS == tx_queue_receive((TX_QUEUE *)queue, msg, timeout_ms)) + { + return 0; + } + else + { + return -1; + } +} + +/*! + * env_get_current_queue_size + * + * Get current queue size. + * + * @param queue - queue pointer + * + * @return - Number of queued items in the queue + */ + +int32_t env_get_current_queue_size(void *queue) +{ + int32_t enqueued; + ULONG available_storage; + TX_THREAD *first_suspended; + ULONG suspended_count; + TX_QUEUE *next_queue; + if (TX_SUCCESS == tx_queue_info_get((TX_QUEUE *)queue, NULL, (ULONG *)&enqueued, &available_storage, + &first_suspended, &suspended_count, &next_queue)) + { + return 0; + } + else + { + return -1; + } +} diff --git a/lib/rpmsg_lite/porting/environment/rpmsg_env_zephyr.c b/lib/rpmsg_lite/porting/environment/rpmsg_env_zephyr.c index 8eb21eb..cf07c73 100644 --- a/lib/rpmsg_lite/porting/environment/rpmsg_env_zephyr.c +++ b/lib/rpmsg_lite/porting/environment/rpmsg_env_zephyr.c @@ -33,7 +33,7 @@ /************************************************************************** * FILE NAME * - * rpmsg_zephyr_env.c + * rpmsg_env_zephyr.c * * * DESCRIPTION diff --git a/lib/rpmsg_lite/porting/platform/imx6sx_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx6sx_m4/rpmsg_platform.c index c862c00..6963640 100644 --- a/lib/rpmsg_lite/porting/platform/imx6sx_m4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx6sx_m4/rpmsg_platform.c @@ -96,9 +96,12 @@ void rpmsg_handler(void) channel = msg >> 16; env_isr(channel); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif diff --git a/lib/rpmsg_lite/porting/platform/imx7d_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx7d_m4/rpmsg_platform.c index c862c00..6963640 100644 --- a/lib/rpmsg_lite/porting/platform/imx7d_m4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx7d_m4/rpmsg_platform.c @@ -96,9 +96,12 @@ void rpmsg_handler(void) channel = msg >> 16; env_isr(channel); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif diff --git a/lib/rpmsg_lite/porting/platform/imx7ulp_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx7ulp_m4/rpmsg_platform.c index 657bdfb..fde4128 100644 --- a/lib/rpmsg_lite/porting/platform/imx7ulp_m4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx7ulp_m4/rpmsg_platform.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016 Freescale Semiconductor, Inc. - * Copyright 2016-2019 NXP + * Copyright 2016-2020 NXP * All rights reserved. * * @@ -89,7 +89,7 @@ void platform_notify(uint32_t vector_id) /* * MU Interrrupt RPMsg handler */ -int32_t MU_A_IRQHandler() +int32_t MU_A_IRQHandler(void) { uint32_t channel; @@ -98,9 +98,12 @@ int32_t MU_A_IRQHandler() channel = MU_ReceiveMsgNonBlocking(MUA, RPMSG_MU_CHANNEL); // Read message from RX register. env_isr(channel >> 16); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif diff --git a/lib/rpmsg_lite/porting/platform/imx8mm_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx8mm_m4/rpmsg_platform.c index 0d4fae1..f4319d2 100644 --- a/lib/rpmsg_lite/porting/platform/imx8mm_m4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx8mm_m4/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 NXP + * Copyright 2017-2020 NXP * All rights reserved. * * @@ -86,7 +86,7 @@ void platform_notify(uint32_t vector_id) /* * MU Interrrupt RPMsg handler */ -int32_t MU_M4_IRQHandler() +int32_t MU_M4_IRQHandler(void) { uint32_t channel; @@ -95,9 +95,12 @@ int32_t MU_M4_IRQHandler() channel = MU_ReceiveMsgNonBlocking(MUB, RPMSG_MU_CHANNEL); // Read message from RX register. env_isr(channel >> 16); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif diff --git a/lib/rpmsg_lite/porting/platform/imx8mn_m7/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx8mn_m7/rpmsg_platform.c index e3c2a9e..6ac6eb6 100644 --- a/lib/rpmsg_lite/porting/platform/imx8mn_m7/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx8mn_m7/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 NXP + * Copyright 2017-2020 NXP * All rights reserved. * * @@ -86,7 +86,7 @@ void platform_notify(uint32_t vector_id) /* * MU Interrrupt RPMsg handler */ -int32_t MU_M7_IRQHandler() +int32_t MU_M7_IRQHandler(void) { uint32_t channel; @@ -95,9 +95,12 @@ int32_t MU_M7_IRQHandler() channel = MU_ReceiveMsgNonBlocking(MUB, RPMSG_MU_CHANNEL); // Read message from RX register. env_isr(channel >> 16); } - /* Add for ARM errata 838869, affects Cortex-M7, Cortex-M7F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif diff --git a/lib/rpmsg_lite/porting/platform/imx8mq_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx8mq_m4/rpmsg_platform.c index f70e08e..131d488 100644 --- a/lib/rpmsg_lite/porting/platform/imx8mq_m4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imx8mq_m4/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 NXP + * Copyright 2017-2020 NXP * All rights reserved. * * @@ -86,7 +86,7 @@ void platform_notify(uint32_t vector_id) /* * MU Interrrupt RPMsg handler */ -int32_t MU_M4_IRQHandler() +int32_t MU_M4_IRQHandler(void) { uint32_t channel; diff --git a/lib/rpmsg_lite/porting/platform/imx8qm_m4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imx8qm_m4/rpmsg_platform.c new file mode 100644 index 0000000..2855356 --- /dev/null +++ b/lib/rpmsg_lite/porting/platform/imx8qm_m4/rpmsg_platform.c @@ -0,0 +1,485 @@ +/* + * Copyright 2017-2019 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include "rpmsg_platform.h" +#include "rpmsg_env.h" + +#include "fsl_device_registers.h" +#include "fsl_mu.h" +#include "fsl_irqsteer.h" + +#if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) +#error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 0" +#endif + +#define APP_MU_IRQ_PRIORITY (3U) + +/* The MU instance used for CM4 and A core communication */ +#if defined(MIMX8QM_CM4_CORE0) +#define APP_M4_A_MU LSIO__MU5_B +#define APP_M4_A_MU_IRQn LSIO_MU5_INT_B_IRQn +#elif defined(MIMX8QM_CM4_CORE1) +#define APP_M4_A_MU LSIO__MU6_B +#define APP_M4_A_MU_IRQn LSIO_MU6_INT_B_IRQn +#else +#error "Unsupported CPU core!" +#endif + +/* The MU instance used for the communication between two CM4 cores */ +/* + ------------------------------------------------------- + Platform | M4_0 PT | M4_1 PT | A core PT + i.MX8QM/QX | LSIO MU5_B | - | LSIO MU5_A + i.MX8QM | - | LSIO MU6_B | LSIO MU6_A + i.MX8QM | LSIO MU7_A | LSIO MU7_B | - + ------------------------------------------------------- +*/ +#if defined(MIMX8QM_CM4_CORE0) +#define APP_M4_M4_MU LSIO__MU7_A +#define APP_M4_M4_MU_IRQn LSIO_MU7_INT_A_IRQn +#elif defined(MIMX8QM_CM4_CORE1) +#define APP_M4_M4_MU LSIO__MU7_B +#define APP_M4_M4_MU_IRQn LSIO_MU7_INT_B_IRQn +#endif + +#define APP_M4_MU_NVIC_IRQn IRQSTEER_3_IRQn + +/* NVIC IRQn that correspond to the LSIO MU IRQn is obtained with the following + * calculation: + * + * NVIC_IRQn = IRQSTEER_0_IRQn + (LSIO_MU_IRQn - FSL_FEATURE_IRQSTEER_IRQ_START_INDEX) / 64 + * + * LSIO_MU_IRQn min = LSIO_MU0_INT_IRQn = 259 + * LSIO_MU_IRQn max = LSIO_MU13_INT_B_IRQn = 291 + * + * With all the LSIO MUs, the NVIC_IRQn = 35, that corresponds to IRQSTEER_3_IRQn + */ + +static int32_t isr_counter0 = 0; /* RL_PLATFORM_IMX8QM_M4_A_USER_LINK_ID isr counter */ +static int32_t isr_counter1 = 0; /* RL_PLATFORM_IMX8QM_M4_M4_USER_LINK_ID isr counter */ +static int32_t disable_counter0 = 0; +static int32_t disable_counter1 = 0; +static void *platform_lock; + +static void platform_global_isr_disable(void) +{ + __asm volatile("cpsid i"); +} + +static void platform_global_isr_enable(void) +{ + __asm volatile("cpsie i"); +} + +int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data) +{ + /* Register ISR to environment layer */ + env_register_isr(vector_id, isr_data); + + /* Prepare the MU Hardware, enable channel 1 interrupt */ + env_lock_mutex(platform_lock); + + switch (RL_GET_COM_ID(vector_id)) + { + case RL_PLATFORM_IMX8QM_M4_A_COM_ID: + RL_ASSERT(0 <= isr_counter0); + if (isr_counter0 == 0) + { + MU_EnableInterrupts(APP_M4_A_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + } + isr_counter0++; + break; + case RL_PLATFORM_IMX8QM_M4_M4_COM_ID: + RL_ASSERT(0 <= isr_counter1); + if (isr_counter1 == 0) + { + MU_EnableInterrupts(APP_M4_M4_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + } + isr_counter1++; + break; + default: + /* All the cases have been listed above, the default clause should not be reached. */ + break; + } + + env_unlock_mutex(platform_lock); + + return 0; +} + +int32_t platform_deinit_interrupt(uint32_t vector_id) +{ + /* Prepare the MU Hardware */ + env_lock_mutex(platform_lock); + + switch (RL_GET_COM_ID(vector_id)) + { + case RL_PLATFORM_IMX8QM_M4_A_COM_ID: + RL_ASSERT(0 < isr_counter0); + isr_counter0--; + if (isr_counter0 == 0) + { + MU_DisableInterrupts(APP_M4_A_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + } + break; + case RL_PLATFORM_IMX8QM_M4_M4_COM_ID: + RL_ASSERT(0 < isr_counter1); + isr_counter1--; + if (isr_counter1 == 0) + { + MU_DisableInterrupts(APP_M4_M4_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + } + break; + default: + /* All the cases have been listed above, the default clause should not be reached. */ + break; + } + + /* Unregister ISR from environment layer */ + env_unregister_isr(vector_id); + + env_unlock_mutex(platform_lock); + + return 0; +} + +void platform_notify(uint32_t vector_id) +{ + /* Only vring id and queue id is needed in msg */ + uint32_t msg = RL_GEN_MU_MSG(vector_id); + + env_lock_mutex(platform_lock); + /* As Linux suggests, use MU->Data Channel 1 as communication channel */ + switch (RL_GET_COM_ID(vector_id)) + { + case RL_PLATFORM_IMX8QM_M4_A_COM_ID: + MU_SendMsg(APP_M4_A_MU, RPMSG_MU_CHANNEL, msg); + break; + case RL_PLATFORM_IMX8QM_M4_M4_COM_ID: + MU_SendMsg(APP_M4_M4_MU, RPMSG_MU_CHANNEL, msg); + break; + default: + /* All the cases have been listed above, the default clause should not be reached. */ + break; + } + env_unlock_mutex(platform_lock); +} + +/* + * MU Interrrupt RPMsg handler + */ +#if defined(MIMX8QM_CM4_CORE0) +int32_t LSIO_MU5_INT_B_IRQHandler(void) +{ + uint32_t channel; + + if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MU_GetStatusFlags(APP_M4_A_MU)) != 0UL) + { + channel = MU_ReceiveMsgNonBlocking(APP_M4_A_MU, RPMSG_MU_CHANNEL); /* Read message from RX register. */ + env_isr((uint32_t)((channel >> 16) | (RL_PLATFORM_IMX8QM_M4_A_COM_ID << 3))); + } + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) + __DSB(); +#endif + + return 0; +} + +#elif defined(MIMX8QM_CM4_CORE1) +int32_t LSIO_MU6_INT_B_IRQHandler(void) +{ + uint32_t channel; + + if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MU_GetStatusFlags(APP_M4_A_MU)) != 0UL) + { + channel = MU_ReceiveMsgNonBlocking(APP_M4_A_MU, RPMSG_MU_CHANNEL); /* Read message from RX register. */ + env_isr((uint32_t)((channel >> 16) | (RL_PLATFORM_IMX8QM_M4_A_COM_ID << 3))); + } + + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) + __DSB(); +#endif + return 0; +} +#endif + +#if defined(MIMX8QM_CM4_CORE0) +int32_t LSIO_MU7_INT_A_IRQHandler(void) +{ + uint32_t channel; + + if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MU_GetStatusFlags(APP_M4_M4_MU)) != 0UL) + { + channel = MU_ReceiveMsgNonBlocking(APP_M4_M4_MU, RPMSG_MU_CHANNEL); /* Read message from RX register. */ + env_isr((uint32_t)((channel >> 16) | (RL_PLATFORM_IMX8QM_M4_M4_COM_ID << 3))); + } + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) + __DSB(); +#endif + + return 0; +} +#elif defined(MIMX8QM_CM4_CORE1) +int32_t LSIO_MU7_INT_B_IRQHandler(void) +{ + uint32_t channel; + + if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MU_GetStatusFlags(APP_M4_M4_MU)) != 0UL) + { + channel = MU_ReceiveMsgNonBlocking(APP_M4_M4_MU, RPMSG_MU_CHANNEL); /* Read message from RX register. */ + env_isr((uint32_t)((channel >> 16) | (RL_PLATFORM_IMX8QM_M4_M4_COM_ID << 3))); + } + + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) + __DSB(); +#endif + + return 0; +} +#endif +/** + * platform_time_delay + * + * @param num_msec Delay time in ms. + * + * This is not an accurate delay, it ensures at least num_msec passed when return. + */ +void platform_time_delay(uint32_t num_msec) +{ + uint32_t loop; + + /* Recalculate the CPU frequency */ + SystemCoreClockUpdate(); + + /* Calculate the CPU loops to delay, each loop has 3 cycles */ + loop = SystemCoreClock / 3U / 1000U * num_msec; + + /* There's some difference among toolchains, 3 or 4 cycles each loop */ + while (loop > 0U) + { + __NOP(); + loop--; + } +} + +/** + * platform_in_isr + * + * Return whether CPU is processing IRQ + * + * @return True for IRQ, false otherwise. + * + */ +int32_t platform_in_isr(void) +{ + return (((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0UL) ? 1 : 0); +} + +/** + * platform_interrupt_enable + * + * Enable peripheral-related interrupt + * + * @param vector_id Virtual vector ID that needs to be converted to IRQ number + * + * @return vector_id Return value is never checked. + * + */ +int32_t platform_interrupt_enable(uint32_t vector_id) +{ + platform_global_isr_disable(); + + switch (RL_GET_COM_ID(vector_id)) + { + case RL_PLATFORM_IMX8QM_M4_A_COM_ID: + RL_ASSERT(0 < disable_counter0); + disable_counter0--; + if (disable_counter0 == 0) + { + NVIC_EnableIRQ(APP_M4_MU_NVIC_IRQn); + } + break; + case RL_PLATFORM_IMX8QM_M4_M4_COM_ID: + RL_ASSERT(0 < disable_counter1); + disable_counter1--; + if (disable_counter1 == 0) + { + NVIC_EnableIRQ(APP_M4_MU_NVIC_IRQn); + } + break; + default: + /* All the cases have been listed above, the default clause should not be reached. */ + break; + } + platform_global_isr_enable(); + return ((int32_t)vector_id); +} + +/** + * platform_interrupt_disable + * + * Disable peripheral-related interrupt. + * + * @param vector_id Virtual vector ID that needs to be converted to IRQ number + * + * @return vector_id Return value is never checked. + * + */ +int32_t platform_interrupt_disable(uint32_t vector_id) +{ + platform_global_isr_disable(); + /* virtqueues use the same NVIC vector + if counter is set - the interrupts are disabled */ + switch (RL_GET_COM_ID(vector_id)) + { + case RL_PLATFORM_IMX8QM_M4_A_COM_ID: + RL_ASSERT(0 <= disable_counter0); + if (disable_counter0 == 0) + { + NVIC_DisableIRQ(APP_M4_MU_NVIC_IRQn); + } + disable_counter0++; + break; + case RL_PLATFORM_IMX8QM_M4_M4_COM_ID: + RL_ASSERT(0 <= disable_counter1); + if (disable_counter1 == 0) + { + NVIC_DisableIRQ(APP_M4_MU_NVIC_IRQn); + } + disable_counter1++; + break; + default: + /* All the cases have been listed above, the default clause should not be reached. */ + break; + } + + platform_global_isr_enable(); + return ((int32_t)vector_id); +} + +/** + * platform_map_mem_region + * + * Dummy implementation + * + */ +void platform_map_mem_region(uint32_t vrt_addr, uint32_t phy_addr, uint32_t size, uint32_t flags) +{ +} + +/** + * platform_cache_all_flush_invalidate + * + * Dummy implementation + * + */ +void platform_cache_all_flush_invalidate(void) +{ +} + +/** + * platform_cache_disable + * + * Dummy implementation + * + */ +void platform_cache_disable(void) +{ +} + +/** + * platform_vatopa + * + * Dummy implementation + * + */ +uint32_t platform_vatopa(void *addr) +{ + return ((uint32_t)(char *)addr); +} + +/** + * platform_patova + * + * Dummy implementation + * + */ +void *platform_patova(uint32_t addr) +{ + return ((void *)(char *)addr); +} + +/** + * platform_init + * + * platform/environment init + */ +int32_t platform_init(void) +{ + /* + * Prepare for the MU Interrupt + * MU must be initialized before rpmsg init is called + */ + MU_Init(APP_M4_A_MU); + NVIC_SetPriority(APP_M4_MU_NVIC_IRQn, APP_MU_IRQ_PRIORITY); + NVIC_EnableIRQ(APP_M4_MU_NVIC_IRQn); + IRQSTEER_EnableInterrupt(IRQSTEER, APP_M4_A_MU_IRQn); + + /* Prepare for the MU Interrupt for the MU used between two M4s*/ + MU_Init(APP_M4_M4_MU); + NVIC_SetPriority(APP_M4_MU_NVIC_IRQn, APP_MU_IRQ_PRIORITY); + NVIC_EnableIRQ(APP_M4_MU_NVIC_IRQn); + IRQSTEER_EnableInterrupt(IRQSTEER, APP_M4_M4_MU_IRQn); + + /* Create lock used in multi-instanced RPMsg */ + if (0 != env_create_mutex(&platform_lock, 1)) + { + return -1; + } + + return 0; +} + +/** + * platform_deinit + * + * platform/environment deinit process + */ +int32_t platform_deinit(void) +{ + MU_Deinit(APP_M4_A_MU); + IRQSTEER_DisableInterrupt(IRQSTEER, APP_M4_A_MU_IRQn); + MU_Deinit(APP_M4_M4_MU); + IRQSTEER_DisableInterrupt(IRQSTEER, APP_M4_M4_MU_IRQn); + + /* Delete lock used in multi-instanced RPMsg */ + env_delete_mutex(platform_lock); + platform_lock = ((void *)0); + return 0; +} diff --git a/lib/rpmsg_lite/porting/platform/imxrt600_hifi4/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imxrt600_hifi4/rpmsg_platform.c index 7db196e..a847a74 100644 --- a/lib/rpmsg_lite/porting/platform/imxrt600_hifi4/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imxrt600_hifi4/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * All rights reserved. * * @@ -12,42 +12,37 @@ #include "rpmsg_platform.h" #include "rpmsg_env.h" #include + +#ifndef FSL_RTOS_FREE_RTOS #include +#endif + #include "fsl_device_registers.h" #include "fsl_mu.h" -#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) -//@Lei -//#include "mcmgr.h" +#if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) +#error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 0" #endif static int32_t isr_counter = 0; static int32_t disable_counter = 0; static void *platform_lock; -#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) -static void mcmgr_event_handler(uint16_t vring_idx, void *context) -{ - env_isr((uint32_t)vring_idx); -} -#else void MU_B_IRQHandler(void *arg) { - uint32_t channel; - - if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MUB->SR) != 0UL) + uint32_t flags; + flags = MU_GetStatusFlags(MUB); + if (((uint32_t)kMU_GenInt0Flag & flags) != 0UL) { - channel = MUB->RR[RPMSG_MU_CHANNEL]; /* Read message from RX register. */ - env_isr(RL_GET_VQ_ID(RPMSG_LITE_LINK_ID, RL_GET_Q_ID(channel >> 16))); + MU_ClearStatusFlags(MUB, (uint32_t)kMU_GenInt0Flag); + env_isr(0); + } + if (((uint32_t)kMU_GenInt1Flag & flags) != 0UL) + { + MU_ClearStatusFlags(MUB, (uint32_t)kMU_GenInt1Flag); + env_isr(1); } - -/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) - __DSB(); -#endif } -#endif int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data) { @@ -58,34 +53,11 @@ int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data) RL_ASSERT(0 <= isr_counter); - if (isr_counter == 0) + if (isr_counter < 2) { - /* @Yuan Enable MUB receive interrupt. */ - uint32_t reg = MUB->CR & ~(0xf0008); - MUB->CR = reg | ((1UL << 27U) >> RPMSG_MU_CHANNEL); - -#if defined(__CM4_CMSIS_VERSION) - NVIC_SetPriority(MAILBOX_IRQn, 5); -#elif defined(__XCC__) - - /* - * @Lei Register interrupt based on vq_id. It has to be hashed as - * 0 is NMI - * 1 is SW - * 2 & 3 is Timer, Timer.0 & Timer.1 - * 4 is profiling - * 5~15 level 1 interrupts - * 16~23 level 2 interrupts - * 24~31 level 3 interrupts - * Note that different priority interrupts are not nesting in one stack - */ - //_xtos_set_interrupt_handler(6, MU_B_IRQHandler); - xos_register_interrupt_handler(6, MU_B_IRQHandler, ((void *)0)); - -#else - NVIC_SetPriority(MAILBOX_IRQn, 2); -#endif + MU_EnableInterrupts(MUB, 1UL << (31UL - vector_id)); } + isr_counter++; env_unlock_mutex(platform_lock); @@ -100,20 +72,10 @@ int32_t platform_deinit_interrupt(uint32_t vector_id) RL_ASSERT(0 < isr_counter); isr_counter--; - if (isr_counter == 0) + + if (isr_counter < 2) { - /* @Yuan Disable MUB receive interrupt. */ - uint32_t reg = MUB->CR & ~(0xf0008 | ((1UL << 27U) >> RPMSG_MU_CHANNEL)); - MUB->CR = reg; -#if defined(__XCC__) - /* - * @Lei Set handler to 0 to cease the interrupt. - */ - // _xtos_set_interrupt_handler(6, ((void *)0)); - xos_register_interrupt_handler(6, ((void *)0), ((void *)0)); -#else - NVIC_DisableIRQ(MAILBOX_IRQn); -#endif + MU_DisableInterrupts(MUB, 1UL << (31UL - vector_id)); } /* Unregister ISR from environment layer */ @@ -126,31 +88,9 @@ int32_t platform_deinit_interrupt(uint32_t vector_id) void platform_notify(uint32_t vector_id) { - uint32_t msg = (uint32_t)(vector_id << 16); -//#if defined (__XCC__) -/* - * @Lei MCMGR not supported at this moment. - */ -#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) env_lock_mutex(platform_lock); - MCMGR_TriggerEvent(kMCMGR_RemoteRPMsgEvent, (uint16_t)RL_GET_Q_ID(vector_id)); + (void)MU_TriggerInterrupts(MUB, 1UL << (19UL - RL_GET_Q_ID(vector_id))); env_unlock_mutex(platform_lock); -#else - switch (RL_GET_LINK_ID(vector_id)) - { - case RPMSG_LITE_LINK_ID: - env_lock_mutex(platform_lock); - while (!(MUB->SR & ((1U << 23) >> RPMSG_MU_CHANNEL))) - { - } - - MUB->TR[RPMSG_MU_CHANNEL] = msg; - env_unlock_mutex(platform_lock); - return; - default: - return; - } -#endif } /** @@ -162,25 +102,19 @@ void platform_notify(uint32_t vector_id) */ void platform_time_delay(uint32_t num_msec) { -/* - * @Lei Cycle accurate time delay. - */ -#if defined(__XCC__) -// 8MHz main clock on FPGA -#define SystemCoreClock 8000000 + uint32_t loop; - uint32_t loop, ccount; + /* Recalculate the CPU frequency */ + SystemCoreClockUpdate(); - /* Get current cycle count */ - ccount = xthal_get_ccount(); - /* Calculate cycles to be delayed */ - loop = SystemCoreClock / 1000U * num_msec; + /* Calculate the CPU loops to delay, each loop has approx. 6 cycles */ + loop = SystemCoreClock / 6U / 1000U * num_msec; - do + while (loop > 0U) { - loop -= xthal_get_ccount() - ccount; - } while (loop > 0); -#endif + asm("nop"); + loop--; + } } /** @@ -193,15 +127,7 @@ void platform_time_delay(uint32_t num_msec) */ int32_t platform_in_isr(void) { -/* - * @Lei HIFI doesn't have direct API or a register file to indicate the core in IRQ. TBD. - * Always return false. - */ -#if defined(__XCC__) - return 0; -#elif - return (((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0UL) ? 1 : 0); -#endif + return (xthal_get_interrupt() & xthal_get_intenable()); } /** @@ -217,26 +143,14 @@ int32_t platform_in_isr(void) int32_t platform_interrupt_enable(uint32_t vector_id) { RL_ASSERT(0 < disable_counter); - /* - * @Lei Enable the interrupt. Don't forget to hash the ID. - * @Yuan Select MUB interrupt as DSP IRQ6 source. - * - */ - -#if defined(__XCC__) - // _xtos_ints_on(1<<(6)); + +#ifdef FSL_RTOS_FREE_RTOS + xt_interrupt_enable(6); +#else xos_interrupt_enable(6); +#endif disable_counter--; return ((int32_t)vector_id); -#elif - __asm volatile("cpsid i"); - disable_counter--; - - if (disable_counter == 0) - NVIC_EnableIRQ(MAILBOX_IRQn); - __asm volatile("cpsie i"); - return ((int32_t)vector_id); -#endif } /** @@ -253,25 +167,13 @@ int32_t platform_interrupt_disable(uint32_t vector_id) { RL_ASSERT(0 <= disable_counter); - /* - * @Lei Disable the interrupt. Don't forget to hash the ID. - */ -#if defined(__XCC__) - // _xtos_ints_off(1<<(6)); +#ifdef FSL_RTOS_FREE_RTOS + xt_interrupt_disable(6); +#else xos_interrupt_disable(6); +#endif disable_counter++; return ((int32_t)vector_id); -#elif - __asm volatile("cpsid i"); - // virtqueues use the same NVIC vector - // if counter is set - the interrupts are disabled - if (disable_counter == 0) - NVIC_DisableIRQ(MAILBOX_IRQn); - - disable_counter++; - __asm volatile("cpsie i"); - return ((int32_t)vector_id); -#endif } /** @@ -333,22 +235,19 @@ void *platform_patova(uint32_t addr) */ int32_t platform_init(void) { -#if defined(__XCC__) -/* - * @Lei MCMGR not supported at this moment. - */ -#elif defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) - MCMGR_RegisterEvent(kMCMGR_RemoteRPMsgEvent, mcmgr_event_handler, ((void *)0)); -#else - MAILBOX_Init(MAILBOX); -#endif - /* Create lock used in multi-instanced RPMsg */ if (0 != env_create_mutex(&platform_lock, 1)) { return -1; } + /* Register interrupt handler for MU_B on HiFi4 */ +#ifdef FSL_RTOS_FREE_RTOS + xt_set_interrupt_handler(6, MU_B_IRQHandler, ((void *)0)); +#else + xos_register_interrupt_handler(6, MU_B_IRQHandler, ((void *)0)); +#endif + return 0; } @@ -359,22 +258,12 @@ int32_t platform_init(void) */ int32_t platform_deinit(void) { -#if defined(__XCC__) -/* - * @Lei MCMGR not supported at this moment. - */ -/* Import from LPC5411x and keep it here - do not deinit mailbox, if there - is a pending ISR on the other core! */ -#elif defined(__CM4_CMSIS_VERSION) - while (0 != MAILBOX_GetValue(MAILBOX, kMAILBOX_CM0Plus)) - ; +#ifdef FSL_RTOS_FREE_RTOS + xt_set_interrupt_handler(6, ((void *)0), ((void *)0)); #else - while (0 != MAILBOX_GetValue(MAILBOX, kMAILBOX_CM4)) - ; + xos_register_interrupt_handler(6, ((void *)0), ((void *)0)); #endif - // MAILBOX_Deinit(MAILBOX); - /* Delete lock used in multi-instanced RPMsg */ env_delete_mutex(platform_lock); platform_lock = ((void *)0); diff --git a/lib/rpmsg_lite/porting/platform/imxrt600_m33/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/imxrt600_m33/rpmsg_platform.c index 3277d93..8bb62f4 100644 --- a/lib/rpmsg_lite/porting/platform/imxrt600_m33/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/imxrt600_m33/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * All rights reserved. * * @@ -37,22 +37,22 @@ static void mcmgr_event_handler(uint16_t vring_idx, void *context) { env_isr((uint32_t)vring_idx); } + #else void MU_A_IRQHandler(void) { - uint32_t channel; - - if ((((1UL << 27U) >> RPMSG_MU_CHANNEL) & MU_GetStatusFlags(APP_MU)) != 0UL) + uint32_t flags; + flags = MU_GetStatusFlags(APP_MU); + if (((uint32_t)kMU_GenInt0Flag & flags) != 0UL) { - channel = MU_ReceiveMsgNonBlocking(APP_MU, RPMSG_MU_CHANNEL); /* Read message from RX register. */ - env_isr(RL_GET_VQ_ID(RL_PLATFORM_LPC6324_M33_DSP_LINK_ID, RL_GET_Q_ID(channel >> 16))); + MU_ClearStatusFlags(APP_MU, (uint32_t)kMU_GenInt0Flag); + env_isr(0); + } + if (((uint32_t)kMU_GenInt1Flag & flags) != 0UL) + { + MU_ClearStatusFlags(APP_MU, (uint32_t)kMU_GenInt1Flag); + env_isr(1); } - -/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) - __DSB(); -#endif } #endif @@ -74,9 +74,9 @@ int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data) env_lock_mutex(platform_lock); RL_ASSERT(0 <= isr_counter); - if (isr_counter == 0) + if (isr_counter < 2) { - MU_EnableInterrupts(APP_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + MU_EnableInterrupts(APP_MU, 1UL << (31UL - vector_id)); } isr_counter++; @@ -92,9 +92,9 @@ int32_t platform_deinit_interrupt(uint32_t vector_id) RL_ASSERT(0 < isr_counter); isr_counter--; - if (isr_counter == 0) + if (isr_counter < 2) { - MU_DisableInterrupts(APP_MU, (1UL << 27U) >> RPMSG_MU_CHANNEL); + MU_DisableInterrupts(APP_MU, 1UL << (31UL - vector_id)); } /* Unregister ISR from environment layer */ @@ -107,24 +107,14 @@ int32_t platform_deinit_interrupt(uint32_t vector_id) void platform_notify(uint32_t vector_id) { - uint32_t msg = (uint32_t)(vector_id << 16); - -#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) env_lock_mutex(platform_lock); - MCMGR_TriggerEvent(kMCMGR_RemoteRPMsgEvent, RL_GET_Q_ID(vector_id)); +#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) + (void)MCMGR_TriggerEvent(kMCMGR_RemoteRPMsgEvent, RL_GET_Q_ID(vector_id)); env_unlock_mutex(platform_lock); #else - switch (RL_GET_LINK_ID(vector_id)) - { - case 0: - env_lock_mutex(platform_lock); - MU_SendMsg(APP_MU, RPMSG_MU_CHANNEL, msg); - env_unlock_mutex(platform_lock); - return; - default: - return; - } + (void)MU_TriggerInterrupts(APP_MU, 1UL << (19UL - RL_GET_Q_ID(vector_id))); #endif + env_unlock_mutex(platform_lock); } /** diff --git a/lib/rpmsg_lite/porting/platform/k32l3a6/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/k32l3a6/rpmsg_platform.c index 7d9e933..d602b62 100644 --- a/lib/rpmsg_lite/porting/platform/k32l3a6/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/k32l3a6/rpmsg_platform.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * All rights reserved. * * @@ -36,36 +36,42 @@ static void mu_isr(MU_Type *base) { uint32_t flags; flags = MU_GetStatusFlags(base); - if ((kMU_GenInt0Flag & flags) != 0UL) + if (((uint32_t)kMU_GenInt0Flag & flags) != 0UL) { - MU_ClearStatusFlags(base, kMU_GenInt0Flag); + MU_ClearStatusFlags(base, (uint32_t)kMU_GenInt0Flag); env_isr(0); } - if ((kMU_GenInt1Flag & flags) != 0UL) + if (((uint32_t)kMU_GenInt1Flag & flags) != 0UL) { - MU_ClearStatusFlags(base, kMU_GenInt1Flag); + MU_ClearStatusFlags(base, (uint32_t)kMU_GenInt1Flag); env_isr(1); } } #if defined(FSL_FEATURE_MU_SIDE_A) -int32_t MUA_IRQHandler() +int32_t MUA_IRQHandler(void) { mu_isr(MUA); - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif return 0; } #elif defined(FSL_FEATURE_MU_SIDE_B) -int32_t MUB_IRQHandler() +int32_t MUB_IRQHandler(void) { mu_isr(MUB); - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif return 0; @@ -94,9 +100,9 @@ int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data) if (isr_counter < 2) { #if defined(FSL_FEATURE_MU_SIDE_A) - MU_EnableInterrupts(MUA, 1 << (31 - vector_id)); + MU_EnableInterrupts(MUA, 1UL << (31UL - vector_id)); #elif defined(FSL_FEATURE_MU_SIDE_B) - MU_EnableInterrupts(MUB, 1 << (31 - vector_id)); + MU_EnableInterrupts(MUB, 1UL << (31UL - vector_id)); #endif } isr_counter++; @@ -116,9 +122,9 @@ int32_t platform_deinit_interrupt(uint32_t vector_id) if (isr_counter < 2) { #if defined(FSL_FEATURE_MU_SIDE_A) - MU_DisableInterrupts(MUA, 1 << (31 - vector_id)); + MU_DisableInterrupts(MUA, 1UL << (31UL - vector_id)); #elif defined(FSL_FEATURE_MU_SIDE_B) - MU_DisableInterrupts(MUB, 1 << (31 - vector_id)); + MU_DisableInterrupts(MUB, 1UL << (31UL - vector_id)); #endif } @@ -136,14 +142,15 @@ void platform_notify(uint32_t vector_id) #if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1) (void)MCMGR_TriggerEventForce(kMCMGR_RemoteRPMsgEvent, (uint16_t)RL_GET_Q_ID(vector_id)); #else -/* Write directly into the MU TX register, no need to wait until the content is cleared - (consumed by the receiver side) because the same walue of the virtqueu ID is written - into this register when trigerring the ISR for the receiver side. The whole queue of - received buffers for associated virtqueue is handled in the ISR then. */ +/* Write directly into the MU Control Register to trigger General Purpose Interrupt Request (GIR). + No need to wait until the previous interrupt is processed because the same value + of the virtqueue ID is used for GIR mask when triggering the ISR for the receiver side. + The whole queue of received buffers for associated virtqueue is then handled in the ISR + on the receiver side. */ #if defined(FSL_FEATURE_MU_SIDE_A) - MU_TriggerInterrupts(MUA, 1 << (19 - RL_GET_Q_ID(vector_id))); + (void)MU_TriggerInterrupts(MUA, 1UL << (19UL - RL_GET_Q_ID(vector_id))); #elif defined(FSL_FEATURE_MU_SIDE_B) - MU_TriggerInterrupts(MUB, 1 << (19 - RL_GET_Q_ID(vector_id))); + (void)MU_TriggerInterrupts(MUB, 1UL << (19UL - RL_GET_Q_ID(vector_id))); #endif #endif env_unlock_mutex(platform_lock); diff --git a/lib/rpmsg_lite/porting/platform/lpc5410x/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/lpc5410x/rpmsg_platform.c index 4aebb4b..1ebd4ff 100644 --- a/lib/rpmsg_lite/porting/platform/lpc5410x/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/lpc5410x/rpmsg_platform.c @@ -55,9 +55,12 @@ void MAILBOX_IRQHandler(void) env_isr(1); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif } @@ -130,8 +133,8 @@ void platform_notify(uint32_t vector_id) case RL_PLATFORM_LPC5410x_M4_M0_LINK_ID: env_lock_mutex(platform_lock); /* Write directly into the Mailbox register, no need to wait until the content is cleared - (consumed by the receiver side) because the same walue of the virtqueu ID is written - into this register when trigerring the ISR for the receiver side. The whole queue of + (consumed by the receiver side) because the same value of the virtqueue ID is written + into this register when triggering the ISR for the receiver side. The whole queue of received buffers for associated virtqueue is handled in the ISR then. */ #if defined(FSL_FEATURE_MAILBOX_SIDE_A) MAILBOX_SetValueBits(MAILBOX, kMAILBOX_CM0Plus, (1 << RL_GET_Q_ID(vector_id))); diff --git a/lib/rpmsg_lite/porting/platform/lpc5411x/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/lpc5411x/rpmsg_platform.c index ba6dcf9..65be127 100644 --- a/lib/rpmsg_lite/porting/platform/lpc5411x/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/lpc5411x/rpmsg_platform.c @@ -55,9 +55,12 @@ void MAILBOX_IRQHandler(void) env_isr(1); } - /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping - exception return operation might vector to incorrect interrupt */ -#if defined __CORTEX_M && (__CORTEX_M == 4U) + /* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping + * exception return operation might vector to incorrect interrupt. + * For Cortex-M7, if core speed much faster than peripheral register write speed, + * the peripheral interrupt flags may be still set after exiting ISR, this results to + * the same error similar with errata 83869 */ +#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U)) __DSB(); #endif } @@ -130,8 +133,8 @@ void platform_notify(uint32_t vector_id) case RL_PLATFORM_LPC5411x_M4_M0_LINK_ID: env_lock_mutex(platform_lock); /* Write directly into the Mailbox register, no need to wait until the content is cleared - (consumed by the receiver side) because the same walue of the virtqueu ID is written - into this register when trigerring the ISR for the receiver side. The whole queue of + (consumed by the receiver side) because the same value of the virtqueue ID is written + into this register when triggering the ISR for the receiver side. The whole queue of received buffers for associated virtqueue is handled in the ISR then. */ #if defined(FSL_FEATURE_MAILBOX_SIDE_A) MAILBOX_SetValueBits(MAILBOX, kMAILBOX_CM0Plus, (1 << RL_GET_Q_ID(vector_id))); diff --git a/lib/rpmsg_lite/porting/platform/lpc55s69/rpmsg_platform.c b/lib/rpmsg_lite/porting/platform/lpc55s69/rpmsg_platform.c index ae090e4..38dd038 100644 --- a/lib/rpmsg_lite/porting/platform/lpc55s69/rpmsg_platform.c +++ b/lib/rpmsg_lite/porting/platform/lpc55s69/rpmsg_platform.c @@ -119,8 +119,8 @@ void platform_notify(uint32_t vector_id) case RL_PLATFORM_LPC55S69_M33_M33_LINK_ID: env_lock_mutex(platform_lock); /* Write directly into the Mailbox register, no need to wait until the content is cleared - (consumed by the receiver side) because the same walue of the virtqueu ID is written - into this register when trigerring the ISR for the receiver side. The whole queue of + (consumed by the receiver side) because the same value of the virtqueue ID is written + into this register when triggering the ISR for the receiver side. The whole queue of received buffers for associated virtqueue is handled in the ISR then. */ #if defined(FSL_FEATURE_MAILBOX_SIDE_A) MAILBOX_SetValueBits(MAILBOX, kMAILBOX_CM33_Core1, (1 << RL_GET_Q_ID(vector_id))); diff --git a/lib/rpmsg_lite/rpmsg_lite.c b/lib/rpmsg_lite/rpmsg_lite.c index afe2af0..7c69379 100644 --- a/lib/rpmsg_lite/rpmsg_lite.c +++ b/lib/rpmsg_lite/rpmsg_lite.c @@ -154,6 +154,9 @@ static void rpmsg_lite_rx_callback(struct virtqueue *vq) int32_t cb_ret; struct llist *node; struct rpmsg_lite_instance *rpmsg_lite_dev = (struct rpmsg_lite_instance *)vq->priv; +#if defined(RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION) && (RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION == 1) + uint32_t rx_freed = RL_FALSE; +#endif RL_ASSERT(rpmsg_lite_dev != RL_NULL); @@ -182,8 +185,18 @@ static void rpmsg_lite_rx_callback(struct virtqueue *vq) else { rpmsg_lite_dev->vq_ops->vq_rx_free(rpmsg_lite_dev->rvq, rpmsg_msg, len, idx); +#if defined(RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION) && (RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION == 1) + rx_freed = RL_TRUE; +#endif } rpmsg_msg = (struct rpmsg_std_msg *)rpmsg_lite_dev->vq_ops->vq_rx(rpmsg_lite_dev->rvq, &len, &idx); +#if defined(RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION) && (RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION == 1) + if ((rpmsg_msg == RL_NULL) && (rx_freed == RL_TRUE)) + { + /* Let the remote device know that some buffers have been freed */ + virtqueue_kick(rpmsg_lite_dev->rvq); + } +#endif } #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) @@ -843,6 +856,11 @@ int32_t rpmsg_lite_release_rx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev, (uint32_t)virtqueue_get_buffer_length(rpmsg_lite_dev->rvq, rpmsg_msg->hdr.reserved.idx), rpmsg_msg->hdr.reserved.idx); +#if defined(RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION) && (RL_ALLOW_CONSUMED_BUFFERS_NOTIFICATION == 1) + /* Let the remote device know that a buffer has been freed */ + virtqueue_kick(rpmsg_lite_dev->rvq); +#endif + env_unlock_mutex(rpmsg_lite_dev->lock); return RL_SUCCESS;