Просмотр исходного кода

RPMsg-Lite update 05/2022

- Adjust rpmsg_lite_is_link_up() to return RL_TRUE/RL_FALSE
- Add support for custom shared memory arrangement per the RPMsg_Lite instance
- Updated version to 4.0.0
Michal Princ (nxa17570) 3 лет назад
Родитель
Сommit
9775c19b96

+ 1 - 0
README.md

@@ -97,6 +97,7 @@ The RPMsg-Lite can be configured at the compile time. The default configuration
 |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_ALLOW_CUSTOM_SHMEM_CONFIG  | (0)           | It allows to define custom shared memory configuration and replacing the shared memory related global settings from rpmsg_config.h This is useful when multiple instances are running in parallel but different shared memory arrangement (vring size & alignment, buffers size & count) is required. The default value is 0 (all RPMsg_Lite instances use the same shared memory arrangement as defined by common config macros). |
 |RL_ASSERT                     | see rpmsg_default_config.h | Assert implementation.    |
 
 # Contributing to the rpmsg-lite project

+ 1 - 1
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.2.0"
+PROJECT_NUMBER         = "Rev. 4.0.0"
 
 # 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

+ 3 - 0
doxygen/mainpage_rpmsg_lite.md

@@ -90,6 +90,7 @@ The RPMsg-Lite can be configured at the compile time. The default configuration
 |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_ALLOW_CUSTOM_SHMEM_CONFIG  | (0)           | It allows to define custom shared memory configuration and replacing the shared memory related global settings from rpmsg_config.h This is useful when multiple instances are running in parallel but different shared memory arrangement (vring size & alignment, buffers size & count) is required. The default value is 0 (all RPMsg_Lite instances use the same shared memory arrangement as defined by common config macros). |
 |RL_ASSERT                     | see rpmsg_default_config.h | Assert implementation.    |
 
 
@@ -113,4 +114,6 @@ This table summarizes revisions of this document.
 |9.0            | 12/2020 | Several MISRA C-2012 violations addressed <p> 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 <p> Added environment layers for Threadx <p> Added support for i.MX8QM multicore platform  |
 |10.0           | 06/2021 | Fixed incorrect description of the rpmsg_lite_get_endpoint_from_addr function <p> Updated RL_BUFFER_COUNT documentation <p> env_print macro adjusted to address MISRA 21.6 rule in MCUXpressoSDK projects  |
 |11.0           | 12/2021 | Improve static allocations - allow OS-specific objects being allocated statically, GitHub PR #14 <p> RPMsg-Lite: Minor Misra and typo corrections, GitHub PR #19, #20.  |
+|12.0           | 01/2022 | Introduce RL_ALLOW_CUSTOM_SHMEM_CONFIG configuration option to support custom shared memory arangement per the RPMsg_Lite instance.  |
+|13.0           | 04/2022 | Introduced new rpmsg_lite_wait_for_link_up() API function - this allows to avoid using busy loops in rtos environments, GitHub PR #21. <p> Adjust rpmsg_lite_is_link_up() to return RL_TRUE/RL_FALSE.  |
 

+ 3 - 1
lib/include/environment/freertos/rpmsg_env_specific.h

@@ -38,7 +38,9 @@ typedef struct
 typedef StaticSemaphore_t LOCK_STATIC_CONTEXT;
 typedef StaticQueue_t rpmsg_static_queue_ctxt;
 
-/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t)) */
+/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t))
+   This macro helps the application to statically allocate the queue object static storage memory. Note, the
+   RL_BUFFER_COUNT is not applied for all instances when RL_ALLOW_CUSTOM_SHMEM_CONFIG is set to 1 ! */
 #define RL_ENV_QUEUE_STATIC_STORAGE_SIZE (RL_BUFFER_COUNT * sizeof(rpmsg_queue_rx_cb_data_t))
 #endif
 

+ 3 - 1
lib/include/environment/qnx/rpmsg_env_specific.h

@@ -35,7 +35,9 @@ typedef struct
 
 typedef pthread_mutex_t LOCK_STATIC_CONTEXT;
 typedef env_queue_t rpmsg_static_queue_ctxt;
-/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t)) */
+/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t))
+   This macro helps the application to statically allocate the queue object static storage memory. Note, the
+   RL_BUFFER_COUNT is not applied for all instances when RL_ALLOW_CUSTOM_SHMEM_CONFIG is set to 1 ! */
 #define RL_ENV_QUEUE_STATIC_STORAGE_SIZE (RL_BUFFER_COUNT * sizeof(rpmsg_queue_rx_cb_data_t))
 #endif
 

+ 3 - 1
lib/include/environment/threadx/rpmsg_env_specific.h

@@ -35,7 +35,9 @@ typedef struct
 
 typedef TX_SEMAPHORE LOCK_STATIC_CONTEXT;
 typedef TX_QUEUE rpmsg_static_queue_ctxt;
-/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t)) */
+/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t))
+   This macro helps the application to statically allocate the queue object static storage memory. Note, the
+   RL_BUFFER_COUNT is not applied for all instances when RL_ALLOW_CUSTOM_SHMEM_CONFIG is set to 1 ! */
 #define RL_ENV_QUEUE_STATIC_STORAGE_SIZE (RL_BUFFER_COUNT * sizeof(rpmsg_queue_rx_cb_data_t))
 #endif
 

+ 3 - 1
lib/include/environment/xos/rpmsg_env_specific.h

@@ -34,7 +34,9 @@ typedef struct
 
 typedef XosSem LOCK_STATIC_CONTEXT;
 typedef void rpmsg_static_queue_ctxt;
-/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t)) */
+/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t))
+   This macro helps the application to statically allocate the queue object static storage memory. Note, the
+   RL_BUFFER_COUNT is not applied for all instances when RL_ALLOW_CUSTOM_SHMEM_CONFIG is set to 1 ! */
 #define RL_ENV_QUEUE_STATIC_STORAGE_SIZE (XOS_MSGQ_SIZE(RL_BUFFER_COUNT, sizeof(rpmsg_queue_rx_cb_data_t)))
 #endif
 

+ 3 - 1
lib/include/environment/zephyr/rpmsg_env_specific.h

@@ -26,7 +26,9 @@
 
 typedef k_sem LOCK_STATIC_CONTEXT;
 typedef k_msgq rpmsg_static_queue_ctxt;
-/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t)) */
+/* Queue object static storage size in bytes, should be defined as (RL_BUFFER_COUNT*sizeof(rpmsg_queue_rx_cb_data_t))
+   This macro helps the application to statically allocate the queue object static storage memory. Note, the
+   RL_BUFFER_COUNT is not applied for all instances when RL_ALLOW_CUSTOM_SHMEM_CONFIG is set to 1 ! */
 #define RL_ENV_QUEUE_STATIC_STORAGE_SIZE (RL_BUFFER_COUNT * sizeof(rpmsg_queue_rx_cb_data_t))
 #endif
 

+ 27 - 0
lib/include/rpmsg_default_config.h

@@ -56,6 +56,20 @@
 #define RL_MS_PER_INTERVAL (1)
 #endif
 
+//! @def RL_ALLOW_CUSTOM_SHMEM_CONFIG
+//!
+//! This option allows to define custom shared memory configuration and replacing
+//! the shared memory related global settings from rpmsg_config.h This is useful
+//! when multiple instances are running in parallel but different shared memory
+//! arrangement (vring size & alignment, buffers size & count) is required. Note,
+//! that once enabled the platform_get_custom_shmem_config() function needs
+//! to be implemented in platform layer. The default value is 0 (all RPMsg_Lite
+//! instances use the same shared memory arrangement as defined by common config macros).
+#ifndef RL_ALLOW_CUSTOM_SHMEM_CONFIG
+#define RL_ALLOW_CUSTOM_SHMEM_CONFIG (0)
+#endif
+
+#if !(defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1))
 //! @def RL_BUFFER_PAYLOAD_SIZE
 //!
 //! Size of the buffer payload, it must be equal to (240, 496, 1008, ...)
@@ -77,6 +91,19 @@
 #define RL_BUFFER_COUNT (2U)
 #endif
 
+#else
+//! Define the buffer payload and count per different link IDs (rpmsg_lite instance) when RL_ALLOW_CUSTOM_SHMEM_CONFIG
+//! is set.
+//! Refer to the rpmsg_plaform.h for the used link IDs.
+#ifndef RL_BUFFER_PAYLOAD_SIZE
+#define RL_BUFFER_PAYLOAD_SIZE(link_id) (496U)
+#endif
+
+#ifndef RL_BUFFER_COUNT
+#define RL_BUFFER_COUNT(link_id) (((link_id) == 0U) ? 256U : 2U)
+#endif
+#endif /* !(defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1))*/
+
 //! @def RL_API_HAS_ZEROCOPY
 //!
 //! Zero-copy API functions enabled/disabled.

+ 1 - 1
lib/include/rpmsg_env.h

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * Copyright 2021 ACRIOS Systems s.r.o.
  * All rights reserved.
  *

+ 8 - 8
lib/include/rpmsg_lite.h

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * Copyright 2021 ACRIOS Systems s.r.o.
  * All rights reserved.
  *
@@ -39,10 +39,10 @@ extern "C" {
 #endif
 
 #include <stddef.h>
+#include "rpmsg_compiler.h"
 #include "virtqueue.h"
 #include "rpmsg_env.h"
 #include "llist.h"
-#include "rpmsg_compiler.h"
 #include "rpmsg_default_config.h"
 
 //! @addtogroup rpmsg_lite
@@ -52,7 +52,7 @@ extern "C" {
  * Definitions
  ******************************************************************************/
 
-#define RL_VERSION "3.2.0" /*!< Current RPMsg Lite version */
+#define RL_VERSION "4.0.0" /*!< Current RPMsg Lite version */
 
 /* Shared memory "allocator" parameters */
 #define RL_WORD_SIZE (sizeof(uint32_t))
@@ -67,8 +67,8 @@ extern "C" {
 #define RL_NULL       ((void *)0)
 #define RL_REMOTE     (0)
 #define RL_MASTER     (1)
-#define RL_TRUE       (1U)
-#define RL_FALSE      (0U)
+#define RL_TRUE       (1UL)
+#define RL_FALSE      (0UL)
 #define RL_ADDR_ANY   (0xFFFFFFFFU)
 #define RL_RELEASE    (0)
 #define RL_HOLD       (1)
@@ -287,12 +287,12 @@ int32_t rpmsg_lite_send(struct rpmsg_lite_instance *rpmsg_lite_dev,
 /*!
  * @brief Function to get the link state
  *
- * @param rpmsg_lite_dev    RPMsg-Lite instance
+ * @param rpmsg_lite_dev    RPMsg-Lite instance pointer
  *
- * @return True when link up, false when down.
+ * @return RL_TRUE when link up, RL_FALSE when down.
  *
  */
-int32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev);
+uint32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev);
 
 /*!
  * @brief Function to wait until the link is up. Returns

+ 6 - 6
lib/rpmsg_lite/porting/environment/rpmsg_env_bm.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,10 +43,10 @@
  *
  **************************************************************************/
 
+#include "rpmsg_compiler.h"
 #include "rpmsg_env.h"
 #include "rpmsg_platform.h"
 #include "virtqueue.h"
-#include "rpmsg_compiler.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -54,10 +54,10 @@
 static int32_t env_init_counter = 0;
 
 /* Max supported ISR counts */
-#define ISR_COUNT (12U) /* Change for multiple remote cores */
-                        /*!
-                         * Structure to keep track of registered ISR's.
-                         */
+#define ISR_COUNT (12U)
+/*!
+ * Structure to keep track of registered ISR's.
+ */
 struct isr_info
 {
     void *data;

+ 19 - 18
lib/rpmsg_lite/porting/environment/rpmsg_env_freertos.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * Copyright 2021 ACRIOS Systems s.r.o.
  * All rights reserved.
  *
@@ -44,20 +44,21 @@
  *
  **************************************************************************/
 
+#include "rpmsg_compiler.h"
 #include "rpmsg_env.h"
 #include "FreeRTOS.h"
 #include "task.h"
 #include "semphr.h"
 #include "rpmsg_platform.h"
 #include "virtqueue.h"
-#include "rpmsg_compiler.h"
 #include "event_groups.h"
+#include "rpmsg_lite.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-static int32_t env_init_counter   = 0;
-static SemaphoreHandle_t env_sema = ((void *)0);
+static int32_t env_init_counter       = 0;
+static SemaphoreHandle_t env_sema     = ((void *)0);
 static EventGroupHandle_t event_group = ((void *)0);
 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
 LOCK_STATIC_CONTEXT env_sem_static_context;
@@ -107,10 +108,10 @@ static int32_t env_in_isr(void)
  */
 void env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id)
 {
-    (void)xEventGroupClearBits(event_group, (1 << link_id));
+    (void)xEventGroupClearBits(event_group, (EventBits_t)(1UL << link_id));
     if (*link_state != 1U)
     {
-        xEventGroupWaitBits(event_group, (1 << link_id), pdFALSE, pdTRUE, portMAX_DELAY);
+        (void)xEventGroupWaitBits(event_group, (EventBits_t)(1UL << link_id), pdFALSE, pdTRUE, portMAX_DELAY);
     }
 }
 
@@ -125,12 +126,12 @@ void env_tx_callback(uint32_t link_id)
     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
     if (env_in_isr() != 0)
     {
-        (void)xEventGroupSetBitsFromISR(event_group, (1 << link_id), &xHigherPriorityTaskWoken);
-        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+        (void)xEventGroupSetBitsFromISR(event_group, (EventBits_t)(1UL << link_id), &xHigherPriorityTaskWoken);
+        portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
     }
     else
     {
-        (void)xEventGroupSetBits(event_group, (1 << link_id));
+        (void)xEventGroupSetBits(event_group, (EventBits_t)(1UL << link_id));
     }
 }
 
@@ -144,7 +145,7 @@ int32_t env_init(void)
 {
     int32_t retval;
     vTaskSuspendAll(); /* stop scheduler */
-    // verify 'env_init_counter'
+    /* verify 'env_init_counter' */
     RL_ASSERT(env_init_counter >= 0);
     if (env_init_counter < 0)
     {
@@ -152,15 +153,15 @@ int32_t env_init(void)
         return -1;
     }
     env_init_counter++;
-    // multiple call of 'env_init' - return ok
+    /* multiple call of 'env_init' - return ok */
     if (env_init_counter == 1)
     {
-        // first call
+        /* first call */
 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
-        env_sema = xSemaphoreCreateBinaryStatic(&env_sem_static_context);
+        env_sema    = xSemaphoreCreateBinaryStatic(&env_sem_static_context);
         event_group = xEventGroupCreateStatic(&event_group_static_context);
 #else
-        env_sema = xSemaphoreCreateBinary();
+        env_sema    = xSemaphoreCreateBinary();
         event_group = xEventGroupCreate();
 #endif
 #if (configUSE_16_BIT_TICKS == 1)
@@ -203,7 +204,7 @@ int32_t env_deinit(void)
     int32_t retval;
 
     vTaskSuspendAll(); /* stop scheduler */
-    // verify 'env_init_counter'
+    /* verify 'env_init_counter' */
     RL_ASSERT(env_init_counter > 0);
     if (env_init_counter <= 0)
     {
@@ -211,12 +212,12 @@ int32_t env_deinit(void)
         return -1;
     }
 
-    // counter on zero - call platform deinit
+    /* counter on zero - call platform deinit */
     env_init_counter--;
-    // multiple call of 'env_deinit' - return ok
+    /* multiple call of 'env_deinit' - return ok */
     if (env_init_counter <= 0)
     {
-        // last call
+        /* last call */
         (void)memset(isr_table, 0, sizeof(isr_table));
         retval = platform_deinit();
         vEventGroupDelete(event_group);

+ 25 - 1
lib/rpmsg_lite/porting/environment/rpmsg_env_qnx.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -109,6 +109,30 @@ void *env_get_platform_context(void *env_context)
     return env->platform_context;
 }
 
+/*!
+ * env_wait_for_link_up
+ *
+ * Wait until the link_state parameter of the rpmsg_lite_instance is set.
+ * Busy loop implementation for now, to be replaced by events.
+ *
+ */
+void env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id)
+{
+    while (*link_state != 1U)
+    {
+    }
+}
+
+/*!
+ * env_tx_callback
+ *
+ * Set event to notify task waiting in env_wait_for_link_up().
+ *
+ */
+void env_tx_callback(uint32_t link_id)
+{
+}
+
 /*!
  * env_init
  *

+ 39 - 9
lib/rpmsg_lite/porting/environment/rpmsg_env_threadx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 NXP
+ * Copyright 2020-2022 NXP
  * All rights reserved.
  *
  *
@@ -18,12 +18,12 @@
  *
  *
  **************************************************************************/
+#include "rpmsg_compiler.h"
 #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 <stdlib.h>
 #include <string.h>
@@ -31,6 +31,7 @@
 
 static int32_t env_init_counter = 0;
 static TX_SEMAPHORE env_sema;
+static TX_EVENT_FLAGS_GROUP event_group;
 
 /* RL_ENV_MAX_MUTEX_COUNT is an arbitrary count greater than 'count'
    if the inital count is 1, this function behaves as a mutex
@@ -66,6 +67,32 @@ static int32_t env_in_isr(void)
     return platform_in_isr();
 }
 
+/*!
+ * env_wait_for_link_up
+ *
+ * Wait until the link_state parameter of the rpmsg_lite_instance is set.
+ * Utilize events to avoid busy loop implementation.
+ *
+ */
+void env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id)
+{
+    if (*link_state != 1U)
+    {
+        tx_event_flags_get(&event_group, (1UL << link_id), TX_AND, NULL, TX_WAIT_FOREVER);
+    }
+}
+
+/*!
+ * env_tx_callback
+ *
+ * Set event to notify task waiting in env_wait_for_link_up().
+ *
+ */
+void env_tx_callback(uint32_t link_id)
+{
+    tx_event_flags_set(&event_group, (1UL << link_id), TX_OR);
+}
+
 /*!
  * env_init
  *
@@ -77,7 +104,7 @@ int32_t env_init(void)
     int32_t retval;
     uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */
 
-    // verify 'env_init_counter'
+    /* verify 'env_init_counter' */
     RL_ASSERT(env_init_counter >= 0);
     if (env_init_counter < 0)
     {
@@ -85,15 +112,16 @@ int32_t env_init(void)
         return -1;
     }
     env_init_counter++;
-    // multiple call of 'env_init' - return ok
+    /* multiple call of 'env_init' - return ok */
     if (env_init_counter == 1)
     {
-        // first call
+        /* first call */
         if (TX_SUCCESS != _tx_semaphore_create((TX_SEMAPHORE *)&env_sema, NULL, 0))
         {
             EnableGlobalIRQ(regPrimask);
             return -1;
         }
+        (void)tx_event_flags_create(&event_group, NULL);
         (void)memset(isr_table, 0, sizeof(isr_table));
         EnableGlobalIRQ(regPrimask);
         retval = platform_init();
@@ -129,7 +157,7 @@ int32_t env_deinit(void)
     int32_t retval;
 
     uint32_t regPrimask = DisableGlobalIRQ(); /* stop scheduler */
-    // verify 'env_init_counter'
+    /* verify 'env_init_counter' */
     RL_ASSERT(env_init_counter > 0);
     if (env_init_counter <= 0)
     {
@@ -137,14 +165,16 @@ int32_t env_deinit(void)
         return -1;
     }
 
-    // counter on zero - call platform deinit
+    /* counter on zero - call platform deinit */
     env_init_counter--;
-    // multiple call of 'env_deinit' - return ok
+    /* multiple call of 'env_deinit' - return ok */
     if (env_init_counter <= 0)
     {
-        // last call
+        /* last call */
         (void)memset(isr_table, 0, sizeof(isr_table));
         retval = platform_deinit();
+        (void)tx_event_flags_delete(&event_group);
+        (void)memset(&event_group, 0, sizeof(event_group));
         (void)_tx_semaphore_delete((TX_SEMAPHORE *)&env_sema);
         (void)memset(&env_sema, 0, sizeof(env_sema));
         EnableGlobalIRQ(regPrimask);

+ 33 - 4
lib/rpmsg_lite/porting/environment/rpmsg_env_xos.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2021 NXP
+ * Copyright 2022 NXP
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,18 +43,19 @@
  *
  **************************************************************************/
 
+#include "rpmsg_compiler.h"
 #include "rpmsg_env.h"
 #include "rpmsg_lite.h"
 #include <xtensa/xos.h>
 #include "rpmsg_platform.h"
 #include "virtqueue.h"
-#include "rpmsg_compiler.h"
 
 #include <stdlib.h>
 #include <string.h>
 
-static int32_t env_init_counter = 0;
-static struct XosSem env_sema   = {0};
+static int32_t env_init_counter  = 0;
+static struct XosSem env_sema    = {0};
+static struct XosEvent env_event = {0};
 
 /* RL_ENV_MAX_MUTEX_COUNT is an arbitrary count greater than 'count'
    if the inital count is 1, this function behaves as a mutex
@@ -90,6 +91,32 @@ static int32_t env_in_isr(void)
     return platform_in_isr();
 }
 
+/*!
+ * env_wait_for_link_up
+ *
+ * Wait until the link_state parameter of the rpmsg_lite_instance is set.
+ * Utilize events to avoid busy loop implementation.
+ *
+ */
+void env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id)
+{
+    if (*link_state != 1U)
+    {
+        xos_event_wait_all(&env_event, (1UL << link_id));
+    }
+}
+
+/*!
+ * env_tx_callback
+ *
+ * Set event to notify task waiting in env_wait_for_link_up().
+ *
+ */
+void env_tx_callback(uint32_t link_id)
+{
+    xos_event_set(&env_event, (1UL << link_id));
+}
+
 /*!
  * env_init
  *
@@ -113,6 +140,7 @@ int32_t env_init(void)
     {
         /* first call */
         (void)xos_sem_create(&env_sema, XOS_SEM_WAIT_PRIORITY, 1);
+        (void)xos_event_create(&env_event, 0xFFFFFFFFu, XOS_EVENT_AUTO_CLEAR);
         (void)memset(isr_table, 0, sizeof(isr_table));
         xos_restore_interrupts(regPrimask);
         retval = platform_init();
@@ -164,6 +192,7 @@ int32_t env_deinit(void)
         /* last call */
         (void)memset(isr_table, 0, sizeof(isr_table));
         retval = platform_deinit();
+        (void)xos_event_delete(&env_event);
         (void)xos_sem_delete(&env_sema);
         xos_restore_interrupts(regPrimask);
 

+ 38 - 10
lib/rpmsg_lite/porting/environment/rpmsg_env_zephyr.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,11 +43,11 @@
  *
  **************************************************************************/
 
+#include "rpmsg_compiler.h"
 #include "rpmsg_env.h"
 #include <zephyr.h>
 #include "rpmsg_platform.h"
 #include "virtqueue.h"
-#include "rpmsg_compiler.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -66,6 +66,7 @@
 
 static int32_t env_init_counter = 0;
 static struct k_sem env_sema    = {0};
+static struct k_event env_event = {0};
 
 /* Max supported ISR counts */
 #define ISR_COUNT (32U)
@@ -89,6 +90,32 @@ static int32_t env_in_isr(void)
     return platform_in_isr();
 }
 
+/*!
+ * env_wait_for_link_up
+ *
+ * Wait until the link_state parameter of the rpmsg_lite_instance is set.
+ * Utilize events to avoid busy loop implementation.
+ *
+ */
+void env_wait_for_link_up(volatile uint32_t *link_state, uint32_t link_id)
+{
+    if (*link_state != 1U)
+    {
+        k_event_wait_all(&env_event, (1UL << link_id), false, K_FOREVER);
+    }
+}
+
+/*!
+ * env_tx_callback
+ *
+ * Set event to notify task waiting in env_wait_for_link_up().
+ *
+ */
+void env_tx_callback(uint32_t link_id)
+{
+    k_event_post(&env_event, (1UL << link_id));
+}
+
 /*!
  * env_init
  *
@@ -112,6 +139,7 @@ int32_t env_init(void)
     {
         /* first call */
         k_sem_init(&env_sema, 0, 1);
+        k_event_init(&env_event);
         (void)memset(isr_table, 0, sizeof(isr_table));
         k_sched_unlock();
         retval = platform_init();
@@ -239,26 +267,26 @@ int32_t env_strcmp(const char *dst, const char *src)
  *
  * env_strncpy - implementation
  *
- * @param dst
+ * @param dest
  * @param src
  * @param len
  */
-void env_strncpy(char *dst, const char *src, uint32_t len)
+void env_strncpy(char *dest, const char *src, uint32_t len)
 {
-    (void)strncpy(dst, src, len);
+    (void)strncpy(dest, src, len);
 }
 
 /*!
  *
  * env_strncmp - implementation
  *
- * @param dst
+ * @param dest
  * @param src
  * @param len
  */
-int32_t env_strncmp(char *dst, const char *src, uint32_t len)
+int32_t env_strncmp(char *dest, const char *src, uint32_t len)
 {
-    return (strncmp(dst, src, len));
+    return (strncmp(dest, src, len));
 }
 
 /*!
@@ -493,7 +521,7 @@ void env_unregister_isr(uint32_t vector_id)
  *
  * Enables the given interrupt
  *
- * @param vector_id   - interrupt vector number
+ * @param vector_id   - virtual interrupt vector number
  */
 
 void env_enable_interrupt(uint32_t vector_id)
@@ -506,7 +534,7 @@ void env_enable_interrupt(uint32_t vector_id)
  *
  * Disables the given interrupt
  *
- * @param vector_id   - interrupt vector number
+ * @param vector_id   - virtual interrupt vector number
  */
 
 void env_disable_interrupt(uint32_t vector_id)

+ 139 - 26
lib/rpmsg_lite/rpmsg_lite.c

@@ -2,7 +2,7 @@
  * Copyright (c) 2014, Mentor Graphics Corporation
  * Copyright (c) 2015 Xilinx, Inc.
  * Copyright (c) 2016 Freescale Semiconductor, Inc.
- * Copyright 2016-2021 NXP
+ * Copyright 2016-2022 NXP
  * Copyright 2021 ACRIOS Systems s.r.o.
  * All rights reserved.
  *
@@ -87,6 +87,8 @@ struct virtqueue_ops
 /* Zero-Copy extension macros */
 #define RPMSG_STD_MSG_FROM_BUF(buf) (struct rpmsg_std_msg *)(void *)((char *)(buf)-offsetof(struct rpmsg_std_msg, data))
 
+#if !(defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1))
+/* Check RL_BUFFER_COUNT and RL_BUFFER_SIZE only when RL_ALLOW_CUSTOM_SHMEM_CONFIG is not set to 1 */
 #if (!RL_BUFFER_COUNT) || (RL_BUFFER_COUNT & (RL_BUFFER_COUNT - 1))
 #error "RL_BUFFER_COUNT must be power of two (2, 4, ...)"
 #endif
@@ -99,6 +101,7 @@ struct virtqueue_ops
     "RL_BUFFER_SIZE must be power of two (256, 512, ...)"\
        "RL_BUFFER_PAYLOAD_SIZE must be equal to (240, 496, 1008, ...) [2^n - 16]."
 #endif
+#endif /* !(defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)) */
 
 /*!
  * @brief
@@ -575,14 +578,14 @@ mmmmmmm m    m          mm   mmmmm  mmmmm
 
 *******************************************/
 
-int32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev)
+uint32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev)
 {
     if (rpmsg_lite_dev == RL_NULL)
     {
-        return 0;
+        return 0U;
     }
 
-    return (int32_t)(rpmsg_lite_dev->link_state);
+    return (RL_TRUE == rpmsg_lite_dev->link_state ? RL_TRUE : RL_FALSE);
 }
 
 void rpmsg_lite_wait_for_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev)
@@ -698,7 +701,11 @@ int32_t rpmsg_lite_send(struct rpmsg_lite_instance *rpmsg_lite_dev,
     }
 
     // FIXME : may be just copy the data size equal to buffer length and Tx it.
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    if (size > (uint32_t)RL_BUFFER_PAYLOAD_SIZE(rpmsg_lite_dev->link_id))
+#else
     if (size > (uint32_t)RL_BUFFER_PAYLOAD_SIZE)
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
     {
         return RL_ERR_BUFF_SIZE;
     }
@@ -777,7 +784,11 @@ int32_t rpmsg_lite_send_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev,
         return RL_ERR_PARAM;
     }
 
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    if (size > (uint32_t)RL_BUFFER_PAYLOAD_SIZE(rpmsg_lite_dev->link_id))
+#else
     if (size > (uint32_t)RL_BUFFER_PAYLOAD_SIZE)
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
     {
         return RL_ERR_BUFF_SIZE;
     }
@@ -793,12 +804,15 @@ int32_t rpmsg_lite_send_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev,
     RL_ASSERT(
         /* master check */
         ((rpmsg_lite_dev->vq_ops == &master_vq_ops) &&
-         (data >= (void *)(rpmsg_lite_dev->sh_mem_base + (RL_BUFFER_COUNT * RL_BUFFER_SIZE))) &&
-         (data <= (void *)(rpmsg_lite_dev->sh_mem_base + (2 * RL_BUFFER_COUNT * RL_BUFFER_SIZE)))) ||
+         (data >= (void *)(rpmsg_lite_dev->sh_mem_base +
+                           (rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len))) &&
+         (data <= (void *)(rpmsg_lite_dev->sh_mem_base +
+                           (2 * rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len)))) ||
 
         /* remote check */
         ((rpmsg_lite_dev->vq_ops == &remote_vq_ops) && (data >= (void *)rpmsg_lite_dev->sh_mem_base) &&
-         (data <= (void *)(rpmsg_lite_dev->sh_mem_base + (RL_BUFFER_COUNT * RL_BUFFER_SIZE)))))
+         (data <= (void *)(rpmsg_lite_dev->sh_mem_base +
+                           (rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len)))))
 #endif
 
     rpmsg_msg = RPMSG_STD_MSG_FROM_BUF(data);
@@ -849,12 +863,15 @@ int32_t rpmsg_lite_release_rx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev,
     RL_ASSERT(
         /* master check */
         ((rpmsg_lite_dev->vq_ops == &master_vq_ops) && (rxbuf >= (void *)rpmsg_lite_dev->sh_mem_base) &&
-         (rxbuf <= (void *)(rpmsg_lite_dev->sh_mem_base + (RL_BUFFER_COUNT * RL_BUFFER_SIZE)))) ||
+         (rxbuf <= (void *)(rpmsg_lite_dev->sh_mem_base +
+                            (rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len)))) ||
 
         /* remote check */
         ((rpmsg_lite_dev->vq_ops == &remote_vq_ops) &&
-         (rxbuf >= (void *)(rpmsg_lite_dev->sh_mem_base + (RL_BUFFER_COUNT * RL_BUFFER_SIZE))) &&
-         (rxbuf <= (void *)(rpmsg_lite_dev->sh_mem_base + (2 * RL_BUFFER_COUNT * RL_BUFFER_SIZE)))))
+         (rxbuf >= (void *)(rpmsg_lite_dev->sh_mem_base +
+                            (rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len))) &&
+         (rxbuf <= (void *)(rpmsg_lite_dev->sh_mem_base +
+                            (2 * rpmsg_lite_dev->rvq->vq_nentries * rpmsg_lite_dev->rvq->vq_ring.desc->len)))))
 #endif
 
     rpmsg_msg = RPMSG_STD_MSG_FROM_BUF(rxbuf);
@@ -913,22 +930,52 @@ struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr,
     uint32_t idx, j;
     struct rpmsg_lite_instance *rpmsg_lite_dev = RL_NULL;
 
-    if ((2U * (uint32_t)RL_BUFFER_COUNT) >
-        ((RL_WORD_ALIGN_DOWN(shmem_length - (uint32_t)RL_VRING_OVERHEAD)) / (uint32_t)RL_BUFFER_SIZE))
+    if (link_id > RL_PLATFORM_HIGHEST_LINK_ID)
     {
         return RL_NULL;
     }
 
-    if (link_id > RL_PLATFORM_HIGHEST_LINK_ID)
+    if (shmem_addr == RL_NULL)
     {
         return RL_NULL;
     }
 
-    if (shmem_addr == RL_NULL)
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    /* Get the custom shmem configuration defined per each rpmsg_lite instance
+       (i.e. per each link id) from the platform layer */
+    rpmsg_platform_shmem_config_t shmem_config = {0};
+    if (RL_SUCCESS != platform_get_custom_shmem_config(link_id, &shmem_config))
+    {
+        return RL_NULL;
+    }
+
+    /* shmem_config.buffer_count must be power of two (2, 4, ...) */
+    if (0U != (shmem_config.buffer_count & (shmem_config.buffer_count - 1U)))
+    {
+        return RL_NULL;
+    }
+
+    /* buffer size must be power of two (256, 512, ...) */
+    if (0U != ((shmem_config.buffer_payload_size + 16UL) & ((shmem_config.buffer_payload_size + 16UL) - 1U)))
+    {
+        return RL_NULL;
+    }
+
+    if ((2U * (uint32_t)shmem_config.buffer_count) >
+        ((RL_WORD_ALIGN_DOWN(shmem_length - 2U * shmem_config.vring_size)) /
+         (uint32_t)(shmem_config.buffer_payload_size + 16UL)))
+    {
+        return RL_NULL;
+    }
+#else
+    if ((2U * (uint32_t)RL_BUFFER_COUNT) >
+        ((RL_WORD_ALIGN_DOWN(shmem_length - (uint32_t)RL_VRING_OVERHEAD)) / (uint32_t)RL_BUFFER_SIZE))
     {
         return RL_NULL;
     }
 
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
+
 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
     if (static_context == RL_NULL)
     {
@@ -963,9 +1010,15 @@ struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr,
      * Since device is RPMSG Remote so we need to manage the
      * shared buffers. Create shared memory pool to handle buffers.
      */
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    rpmsg_lite_dev->sh_mem_base = (char *)RL_WORD_ALIGN_UP((uint32_t)(char *)shmem_addr + 2U * shmem_config.vring_size);
+    rpmsg_lite_dev->sh_mem_remaining = (RL_WORD_ALIGN_DOWN(shmem_length - 2U * shmem_config.vring_size)) /
+                                       (uint32_t)(shmem_config.buffer_payload_size + 16UL);
+#else
     rpmsg_lite_dev->sh_mem_base = (char *)RL_WORD_ALIGN_UP((uint32_t)(char *)shmem_addr + (uint32_t)RL_VRING_OVERHEAD);
     rpmsg_lite_dev->sh_mem_remaining =
         (RL_WORD_ALIGN_DOWN(shmem_length - (uint32_t)RL_VRING_OVERHEAD)) / (uint32_t)RL_BUFFER_SIZE;
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
     rpmsg_lite_dev->sh_mem_total = rpmsg_lite_dev->sh_mem_remaining;
 
     /* Initialize names and callbacks*/
@@ -978,10 +1031,17 @@ struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr,
     /* Create virtqueue for each vring. */
     for (idx = 0U; idx < 2U; idx++)
     {
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+        ring_info.phy_addr =
+            (void *)(char *)((uint32_t)(char *)shmem_addr + (uint32_t)((idx == 0U) ? (0U) : (shmem_config.vring_size)));
+        ring_info.align     = shmem_config.vring_align;
+        ring_info.num_descs = shmem_config.buffer_count;
+#else
         ring_info.phy_addr =
             (void *)(char *)((uint32_t)(char *)shmem_addr + (uint32_t)((idx == 0U) ? (0U) : (VRING_SIZE)));
-        ring_info.align     = VRING_ALIGN;
+        ring_info.align = VRING_ALIGN;
         ring_info.num_descs = RL_BUFFER_COUNT;
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
 
         env_memset((void *)ring_info.phy_addr, 0x00, (uint32_t)vring_size(ring_info.num_descs, ring_info.align));
 
@@ -1041,22 +1101,41 @@ struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr,
         for (idx = 0U; ((idx < vqs[j]->vq_nentries) && (idx < rpmsg_lite_dev->sh_mem_total)); idx++)
         {
             /* Initialize TX virtqueue buffers for remote device */
-            buffer =
-                (rpmsg_lite_dev->sh_mem_remaining > 0U) ?
-                    (rpmsg_lite_dev->sh_mem_base +
-                     (uint32_t)RL_BUFFER_SIZE * (rpmsg_lite_dev->sh_mem_total - rpmsg_lite_dev->sh_mem_remaining--)) :
-                    (RL_NULL);
+            buffer = (rpmsg_lite_dev->sh_mem_remaining > 0U) ?
+                         (rpmsg_lite_dev->sh_mem_base +
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+                          (uint32_t)(shmem_config.buffer_payload_size + 16UL) *
+                              (rpmsg_lite_dev->sh_mem_total - rpmsg_lite_dev->sh_mem_remaining--)) :
+#else
+                          (uint32_t)RL_BUFFER_SIZE *
+                              (rpmsg_lite_dev->sh_mem_total - rpmsg_lite_dev->sh_mem_remaining--)) :
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
+                         (RL_NULL);
 
             RL_ASSERT(buffer != RL_NULL);
 
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+            env_memset(buffer, 0x00, (uint32_t)(shmem_config.buffer_payload_size + 16UL));
+#else
             env_memset(buffer, 0x00, (uint32_t)RL_BUFFER_SIZE);
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
             if (vqs[j] == rpmsg_lite_dev->rvq)
             {
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+                status =
+                    virtqueue_fill_avail_buffers(vqs[j], buffer, (uint32_t)(shmem_config.buffer_payload_size + 16UL));
+#else
                 status = virtqueue_fill_avail_buffers(vqs[j], buffer, (uint32_t)RL_BUFFER_SIZE);
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
             }
             else if (vqs[j] == rpmsg_lite_dev->tvq)
             {
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+                status =
+                    virtqueue_fill_used_buffers(vqs[j], buffer, (uint32_t)(shmem_config.buffer_payload_size + 16UL));
+#else
                 status = virtqueue_fill_used_buffers(vqs[j], buffer, (uint32_t)RL_BUFFER_SIZE);
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
             }
             else
             {
@@ -1135,6 +1214,28 @@ struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t li
         return RL_NULL;
     }
 
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    /* Get the custom shmem configuration defined per each rpmsg_lite instance
+       (i.e. per each link id) from the platform layer */
+    rpmsg_platform_shmem_config_t shmem_config = {0};
+    if (RL_SUCCESS != platform_get_custom_shmem_config(link_id, &shmem_config))
+    {
+        return RL_NULL;
+    }
+
+    /* shmem_config.buffer_count must be power of two (2, 4, ...) */
+    if (0U != (shmem_config.buffer_count & (shmem_config.buffer_count - 1U)))
+    {
+        return RL_NULL;
+    }
+
+    /* buffer size must be power of two (256, 512, ...) */
+    if (0U != ((shmem_config.buffer_payload_size + 16UL) & ((shmem_config.buffer_payload_size + 16UL) - 1U)))
+    {
+        return RL_NULL;
+    }
+#endif /* defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1) */
+
 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
     if (static_context == RL_NULL)
     {
@@ -1165,20 +1266,32 @@ struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t li
     }
 
     rpmsg_lite_dev->link_id = link_id;
-    vq_names[0]                 = "tx_vq"; /* swapped in case of remote */
-    vq_names[1]                 = "rx_vq";
-    callback[0]                 = rpmsg_lite_tx_callback;
-    callback[1]                 = rpmsg_lite_rx_callback;
-    rpmsg_lite_dev->vq_ops      = &remote_vq_ops;
+
+    vq_names[0]            = "tx_vq"; /* swapped in case of remote */
+    vq_names[1]            = "rx_vq";
+    callback[0]            = rpmsg_lite_tx_callback;
+    callback[1]            = rpmsg_lite_rx_callback;
+    rpmsg_lite_dev->vq_ops = &remote_vq_ops;
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+    rpmsg_lite_dev->sh_mem_base = (char *)RL_WORD_ALIGN_UP((uint32_t)(char *)shmem_addr + 2U * shmem_config.vring_size);
+#else
     rpmsg_lite_dev->sh_mem_base = (char *)RL_WORD_ALIGN_UP((uint32_t)(char *)shmem_addr + (uint32_t)RL_VRING_OVERHEAD);
+#endif /* defined(RL_ALLOW_CUSTOM_VRING_CONFIG) && (RL_ALLOW_CUSTOM_VRING_CONFIG == 1) */
 
     /* Create virtqueue for each vring. */
     for (idx = 0U; idx < 2U; idx++)
     {
+#if defined(RL_ALLOW_CUSTOM_SHMEM_CONFIG) && (RL_ALLOW_CUSTOM_SHMEM_CONFIG == 1)
+        ring_info.phy_addr =
+            (void *)(char *)((uint32_t)(char *)shmem_addr + (uint32_t)((idx == 0U) ? (0U) : (shmem_config.vring_size)));
+        ring_info.align     = shmem_config.vring_align;
+        ring_info.num_descs = shmem_config.buffer_count;
+#else
         ring_info.phy_addr =
             (void *)(char *)((uint32_t)(char *)shmem_addr + (uint32_t)((idx == 0U) ? (0U) : (VRING_SIZE)));
-        ring_info.align     = VRING_ALIGN;
+        ring_info.align = VRING_ALIGN;
         ring_info.num_descs = RL_BUFFER_COUNT;
+#endif /* defined(RL_ALLOW_CUSTOM_VRING_CONFIG) && (RL_ALLOW_CUSTOM_VRING_CONFIG == 1) */
 
 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
         status = virtqueue_create_static((uint16_t)(RL_GET_VQ_ID(link_id, idx)), vq_names[idx], &ring_info,