diff --git a/erpc_c/port/erpc_setup_extensions_freertos.cpp b/erpc_c/port/erpc_setup_extensions_freertos.cpp index 9d45126bf..2135b4020 100644 --- a/erpc_c/port/erpc_setup_extensions_freertos.cpp +++ b/erpc_c/port/erpc_setup_extensions_freertos.cpp @@ -16,6 +16,9 @@ using namespace erpc; static Semaphore *s_erpc_call_in_progress = NULL; static TimerHandle_t s_erpc_call_timer_cb = NULL; +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC +static StaticTimer_t s_static_erpc_call_timer_cb; +#endif void erpc::erpc_pre_cb_default(void) { @@ -46,8 +49,13 @@ void erpc_init_call_progress_detection_default( s_erpc_call_in_progress = new Semaphore(1); assert(s_erpc_call_in_progress && "Creating eRPC semaphore failed."); +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + s_erpc_call_timer_cb = xTimerCreateStatic("Erpc client call timer", waitTimeMs / portTICK_PERIOD_MS, pdFALSE, NULL, + erpc_call_timer_cb, &s_static_erpc_call_timer_cb); +#else s_erpc_call_timer_cb = xTimerCreate("Erpc client call timer", waitTimeMs / portTICK_PERIOD_MS, pdFALSE, NULL, erpc_call_timer_cb); +#endif assert(s_erpc_call_timer_cb && "Creating eRPC timer failed."); } @@ -55,7 +63,9 @@ void erpc_deinit_call_progress_detection_default(void) { if (s_erpc_call_in_progress != NULL) { +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_DYNAMIC delete s_erpc_call_in_progress; +#endif s_erpc_call_in_progress = NULL; } diff --git a/erpc_c/port/erpc_threading.h b/erpc_c/port/erpc_threading.h index 5fb62cc02..5e033b1bc 100644 --- a/erpc_c/port/erpc_threading.h +++ b/erpc_c/port/erpc_threading.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. * Copyright 2016-2020 NXP + * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * * @@ -70,6 +71,11 @@ class Thread public: //! @brief Unique identifier for a thread. typedef void *thread_id_t; +#if ERPC_THREADS_IS(FREERTOS) + typedef StackType_t *thread_stack_pointer; +#else + typedef void *thread_stack_pointer; +#endif /*! * @brief Default constructor for use with the init() method. @@ -77,7 +83,7 @@ class Thread * If this constructor is used, the init() method must be called before the thread can be * started. * - * @param name Optional name for the thread. + * @param[in] name Optional name for the thread. */ Thread(const char *name = 0); @@ -86,12 +92,14 @@ class Thread * * This constructor fully initializes the thread object. * - * @param entry - * @param priority - * @param stackSize - * @param name Optional name for the thread. + * @param[in] entry + * @param[in] priority + * @param[in] stackSize + * @param[in] name Optional name for the thread. + * @param[in] stackPtr Mandatory task stack pointer for static api usage. */ - Thread(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, const char *name = 0); + Thread(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, const char *name = 0, + thread_stack_pointer stackPtr = 0); /*! * @brief Destructor. @@ -118,8 +126,9 @@ class Thread * @param[in] entry Entry function. * @param[in] priority Task priority. * @param[in] stackSize Stack size. + * @param[in] stackPtr Mandatory task stack pointer for static api usage. */ - void init(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0); + void init(thread_entry_t entry, uint32_t priority = 0, uint32_t stackSize = 0, thread_stack_pointer stackPtr = 0); /*! * @brief This function starts thread execution. @@ -152,7 +161,7 @@ class Thread return reinterpret_cast(m_thread->get_id()); #elif ERPC_THREADS_IS(WIN32) return reinterpret_cast(m_thread); -#elif ERPC_THREADS_IS(THREADX) +#elif ERPC_THREADS_IS(THREADX) return reinterpret_cast(m_thread.tx_thread_id); #endif } @@ -212,18 +221,22 @@ class Thread virtual void threadEntryPoint(void); private: - const char *m_name; /*!< Thread name. */ - thread_entry_t m_entry; /*!< Thread entry function. */ - void *m_arg; /*!< Entry parameter. */ - uint32_t m_stackSize; /*!< Stack size. */ - uint32_t m_priority; /*!< Task priority. */ + const char *m_name; /*!< Thread name. */ + thread_entry_t m_entry; /*!< Thread entry function. */ + void *m_arg; /*!< Entry parameter. */ + uint32_t m_stackSize; /*!< Stack size. */ + uint32_t m_priority; /*!< Task priority. */ + thread_stack_pointer m_stackPtr; /*!< Task pointer. */ #if ERPC_THREADS_IS(PTHREADS) static pthread_key_t s_threadObjectKey; /*!< Thread key. */ pthread_t m_thread; /*!< Current thread. */ #elif ERPC_THREADS_IS(FREERTOS) - TaskHandle_t m_task; /*!< Current task. */ - Thread *m_next; /*!< Pointer to next Thread. */ - static Thread *s_first; /*!< Pointer to first Thread. */ + TaskHandle_t m_task; /*!< Current task. */ + Thread *m_next; /*!< Pointer to next Thread. */ + static Thread *s_first; /*!< Pointer to first Thread. */ +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + StaticTask_t m_staticTask; /*!< Hold static task data. */ +#endif #elif ERPC_THREADS_IS(ZEPHYR) struct k_thread m_thread; /*!< Current thread. */ k_thread_stack_t *m_stack; /*!< Pointer to stack. */ @@ -238,7 +251,7 @@ class Thread static Thread *s_first; /*!< Pointer to first Thread. */ static CRITICAL_SECTION m_critical_section; static BOOL m_critical_section_inited; -#elif ERPC_THREADS_IS(THREADX) +#elif ERPC_THREADS_IS(THREADX) TX_THREAD m_thread; /*!< Underlying Thread instance */ Thread *m_next; /*!< Pointer to next Thread. */ static Thread *s_first; /*!< Pointer to first Thread. */ @@ -397,7 +410,8 @@ class Mutex #if ERPC_THREADS_IS(PTHREADS) pthread_mutex_t m_mutex; /*!< Mutex.*/ #elif ERPC_THREADS_IS(FREERTOS) - SemaphoreHandle_t m_mutex; /*!< Mutex.*/ + SemaphoreHandle_t m_mutex; /*!< Mutex.*/ + StaticSemaphore_t m_staticQueue; /*!< Static queue. */ #elif ERPC_THREADS_IS(ZEPHYR) struct k_mutex m_mutex; /*!< Mutex.*/ #elif ERPC_THREADS_IS(MBED) @@ -484,7 +498,8 @@ class Semaphore until some predicate on shared data is satisfied. */ Mutex m_mutex; /*!< Mutext. */ #elif ERPC_THREADS_IS(FREERTOS) - SemaphoreHandle_t m_sem; /*!< Semaphore. */ + SemaphoreHandle_t m_sem; /*!< Semaphore. */ + StaticSemaphore_t m_staticQueue; /*!< Static queue. */ #elif ERPC_THREADS_IS(ZEPHYR) struct k_sem m_sem; /*!< Semaphore. */ #elif ERPC_THREADS_IS(MBED) diff --git a/erpc_c/port/erpc_threading_freertos.cpp b/erpc_c/port/erpc_threading_freertos.cpp index 2e7dc4166..cf91b2dff 100644 --- a/erpc_c/port/erpc_threading_freertos.cpp +++ b/erpc_c/port/erpc_threading_freertos.cpp @@ -38,7 +38,8 @@ Thread::Thread(const char *name) { } -Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name) +Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, const char *name, + thread_stack_pointer stackPtr) : m_name(name) , m_entry(entry) , m_arg(0) @@ -51,16 +52,18 @@ Thread::Thread(thread_entry_t entry, uint32_t priority, uint32_t stackSize, cons Thread::~Thread(void) {} -void Thread::init(thread_entry_t entry, uint32_t priority, uint32_t stackSize) +void Thread::init(thread_entry_t entry, uint32_t priority, uint32_t stackSize, thread_stack_pointer stackPtr) { m_entry = entry; m_stackSize = stackSize; m_priority = priority; + m_stackPtr = stackPtr; } void Thread::start(void *arg) { m_arg = arg; + bool taskCreated = false; // Enter a critical section to disable preemptive scheduling until we add the newly // created thread to the linked list. This prevents a race condition if the new thread is @@ -68,9 +71,31 @@ void Thread::start(void *arg) // which will scan the linked list. taskENTER_CRITICAL(); - if (pdPASS == xTaskCreate(threadEntryPointStub, (m_name ? m_name : "task"), +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + if (m_stackPtr != NULL) + { + m_task = + xTaskCreateStatic(threadEntryPointStub, (m_name ? m_name : "task"), ((m_stackSize + sizeof(uint32_t) - 1) / sizeof(uint32_t)), // Round up number of words. - this, m_priority, &m_task)) + this, m_priority, m_stackPtr, &m_staticTask); + taskCreated = true; + } +#endif + +#if configSUPPORT_DYNAMIC_ALLOCATION + if (m_stackPtr == NULL) + { + if (pdPASS == + xTaskCreate(threadEntryPointStub, (m_name ? m_name : "task"), + ((m_stackSize + sizeof(uint32_t) - 1) / sizeof(uint32_t)), // Round up number of words. + this, m_priority, &m_task)) + { + taskCreated = true; + } + } +#endif + + if (taskCreated) { // Link in this thread to the list. if (NULL != s_first) @@ -180,7 +205,13 @@ void Thread::threadEntryPointStub(void *arg) Mutex::Mutex(void) : m_mutex(0) { +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + m_mutex = xSemaphoreCreateRecursiveMutexStatic(&m_staticQueue); +#elif configSUPPORT_DYNAMIC_ALLOCATION m_mutex = xSemaphoreCreateRecursiveMutex(); +#else +#error "Allocation method didn't match" +#endif } Mutex::~Mutex(void) @@ -208,7 +239,13 @@ Semaphore::Semaphore(int count) : m_sem(0) { // Set max count to highest signed int. +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC + m_sem = xSemaphoreCreateCountingStatic(0x7fffffff, count, &m_staticQueue); +#elif configSUPPORT_DYNAMIC_ALLOCATION m_sem = xSemaphoreCreateCounting(0x7fffffff, count); +#else +#error "Allocation method didn't match" +#endif } Semaphore::~Semaphore(void) diff --git a/erpc_c/transports/erpc_rpmsg_lite_base_transport.h b/erpc_c/transports/erpc_rpmsg_lite_base_transport.h old mode 100644 new mode 100755 index b0dc9ccb7..58ce16bf9 --- a/erpc_c/transports/erpc_rpmsg_lite_base_transport.h +++ b/erpc_c/transports/erpc_rpmsg_lite_base_transport.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. * Copyright 2016 NXP + * Copyright 2021 ACRIOS Systems s.r.o. * All rights reserved. * * @@ -11,8 +12,17 @@ #define _EMBEDDED_RPC__RPMSG_LITE_BASE_TRANSPORT_H_ #include "erpc_transport.h" +#include "erpc_config_internal.h" #include "rpmsg_lite.h" +#include "rpmsg_env_specific.h" + +#if ERPC_ALLOCATION_POLICY == ERPC_ALLOCATION_POLICY_STATIC +#ifndef RL_USE_STATIC_API +#warning "RPMSG is not set to use static allocation" +#endif +#endif + /*! * @addtogroup rpmsg_lite_transport @@ -54,6 +64,12 @@ class RPMsgBaseTransport : public Transport protected: static struct rpmsg_lite_instance *s_rpmsg; /*!< Pointer to instance of RPMSG lite. */ static uint8_t s_initialized; /*!< Represent information if the rpmsg-lite was initialized. */ +#if RL_USE_STATIC_API + struct rpmsg_lite_instance m_static_context; + struct rpmsg_lite_ept_static_context m_ept_context; + rpmsg_static_queue_ctxt m_queue_context; + uint8_t m_queue_stack[RL_ENV_QUEUE_STATIC_STORAGE_SIZE]; +#endif }; } // namespace erpc diff --git a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp old mode 100644 new mode 100755 index a9bfb9dfc..c4fda31f2 --- a/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_lite_rtos_transport.cpp @@ -78,7 +78,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi if (0U == s_initialized) { +#if RL_USE_STATIC_API + s_rpmsg = rpmsg_lite_master_init(base_address, length, rpmsg_link_id, RL_NO_FLAGS, &m_static_context); +#else s_rpmsg = rpmsg_lite_master_init(base_address, length, rpmsg_link_id, RL_NO_FLAGS); +#endif if (s_rpmsg == RL_NULL) { status = kErpcStatus_InitFailed; @@ -86,7 +90,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg, m_queue_stack, &m_queue_context); +#else m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); +#endif if (m_rpmsg_queue == RL_NULL) { status = kErpcStatus_InitFailed; @@ -95,7 +103,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue, &m_ept_context); +#else m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); +#endif if (m_rpmsg_ept == RL_NULL) { status = kErpcStatus_InitFailed; @@ -137,7 +149,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi if (0U == s_initialized) { +#if RL_USE_STATIC_API + s_rpmsg = rpmsg_lite_remote_init(base_address, rpmsg_link_id, RL_NO_FLAGS, &m_static_context); +#else s_rpmsg = rpmsg_lite_remote_init(base_address, rpmsg_link_id, RL_NO_FLAGS); +#endif if (s_rpmsg == RL_NULL) { status = kErpcStatus_InitFailed; @@ -155,7 +171,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi { } +#if RL_USE_STATIC_API + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg, m_queue_stack, &m_queue_context); +#else m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); +#endif if (m_rpmsg_queue == RL_NULL) { status = kErpcStatus_InitFailed; @@ -164,7 +184,11 @@ erpc_status_t RPMsgRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, voi if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue, &m_ept_context); +#else m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); +#endif if (m_rpmsg_ept == RL_NULL) { status = kErpcStatus_InitFailed; diff --git a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp old mode 100644 new mode 100755 index d572f3881..09fa19c48 --- a/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp +++ b/erpc_c/transports/erpc_rpmsg_tty_rtos_transport.cpp @@ -85,7 +85,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, if (0U == s_initialized) { +#if RL_USE_STATIC_API + s_rpmsg = rpmsg_lite_master_init(base_address, length, rpmsg_link_id, RL_NO_FLAGS, &m_static_context); +#else s_rpmsg = rpmsg_lite_master_init(base_address, length, rpmsg_link_id, RL_NO_FLAGS); +#endif if (s_rpmsg == RL_NULL) { status = kErpcStatus_InitFailed; @@ -93,7 +97,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg, m_queue_stack, &m_queue_context); +#else m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); +#endif if (m_rpmsg_queue == RL_NULL) { status = kErpcStatus_InitFailed; @@ -102,7 +110,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue, &m_ept_context); +#else m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); +#endif if (m_rpmsg_ept == RL_NULL) { status = kErpcStatus_InitFailed; @@ -144,7 +156,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, if (0U == s_initialized) { +#if RL_USE_STATIC_API + s_rpmsg = rpmsg_lite_remote_init(base_address, rpmsg_link_id, RL_NO_FLAGS, &m_static_context); +#else s_rpmsg = rpmsg_lite_remote_init(base_address, rpmsg_link_id, RL_NO_FLAGS); +#endif if (s_rpmsg == RL_NULL) { status = kErpcStatus_InitFailed; @@ -162,7 +178,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, { } +#if RL_USE_STATIC_API + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg, m_queue_stack, &m_queue_context); +#else m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); +#endif if (m_rpmsg_queue == RL_NULL) { status = kErpcStatus_InitFailed; @@ -171,7 +191,11 @@ erpc_status_t RPMsgTTYRTOSTransport::init(uint32_t src_addr, uint32_t dst_addr, if (status == kErpcStatus_Success) { +#if RL_USE_STATIC_API + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue, &m_ept_context); +#else m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); +#endif if (m_rpmsg_ept == RL_NULL) { status = kErpcStatus_InitFailed;