/* * Copyright (c) 2014, Mentor Graphics Corporation * Copyright (c) 2015 Xilinx, Inc. * Copyright (c) 2016 Freescale Semiconductor, Inc. * Copyright 2016-2020 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef RPMSG_LITE_H_ #define RPMSG_LITE_H_ #if defined(__cplusplus) extern "C" { #endif #include #include "virtqueue.h" #include "rpmsg_env.h" #include "llist.h" #include "rpmsg_compiler.h" #include "rpmsg_default_config.h" //! @addtogroup rpmsg_lite //! @{ /******************************************************************************* * Definitions ******************************************************************************/ #define RL_VERSION "3.1.2" /*!< Current RPMsg Lite version */ /* Shared memory "allocator" parameters */ #define RL_WORD_SIZE (sizeof(uint32_t)) #define RL_WORD_ALIGN_UP(a) \ (((((uint32_t)a) & (RL_WORD_SIZE - 1U)) != 0U) ? ((((uint32_t)a) & (~(RL_WORD_SIZE - 1U))) + 4U) : ((uint32_t)a)) #define RL_WORD_ALIGN_DOWN(a) \ (((((uint32_t)a) & (RL_WORD_SIZE - 1U)) != 0U) ? (((uint32_t)a) & (~(RL_WORD_SIZE - 1U))) : ((uint32_t)a)) /* Definitions for device types , null pointer, etc.*/ #define RL_SUCCESS (0) #define RL_NULL ((void *)0) #define RL_REMOTE (0) #define RL_MASTER (1) #define RL_TRUE (1U) #define RL_FALSE (0U) #define RL_ADDR_ANY (0xFFFFFFFFU) #define RL_RELEASE (0) #define RL_HOLD (1) #define RL_DONT_BLOCK (0) #define RL_BLOCK (0xFFFFFFFFU) /* Error macros. */ #define RL_ERRORS_BASE (-5000) #define RL_ERR_NO_MEM (RL_ERRORS_BASE - 1) #define RL_ERR_BUFF_SIZE (RL_ERRORS_BASE - 2) #define RL_ERR_PARAM (RL_ERRORS_BASE - 3) #define RL_ERR_DEV_ID (RL_ERRORS_BASE - 4) #define RL_ERR_MAX_VQ (RL_ERRORS_BASE - 5) #define RL_ERR_NO_BUFF (RL_ERRORS_BASE - 6) #define RL_NOT_READY (RL_ERRORS_BASE - 7) #define RL_ALREADY_DONE (RL_ERRORS_BASE - 8) /* Init flags */ #define RL_NO_FLAGS (0) /*! \typedef rl_ept_rx_cb_t \brief Receive callback function type. */ typedef int32_t (*rl_ept_rx_cb_t)(void *payload, uint32_t payload_len, uint32_t src, void *priv); /*! * RPMsg Lite Endpoint structure */ struct rpmsg_lite_endpoint { uint32_t addr; /*!< endpoint address */ rl_ept_rx_cb_t rx_cb; /*!< ISR callback function */ void *rx_cb_data; /*!< ISR callback data */ void *rfu; /*!< reserved for future usage */ /* 16 bytes aligned on 32bit architecture */ }; /*! * RPMsg Lite Endpoint static context */ struct rpmsg_lite_ept_static_context { struct rpmsg_lite_endpoint ept; /*!< memory for endpoint structure */ struct llist node; /*!< memory for linked list node structure */ }; /*! * Structure describing the local instance * of RPMSG lite communication stack and * holds all runtime variables needed internally * by the stack. */ struct rpmsg_lite_instance { struct virtqueue *rvq; /*!< receive virtqueue */ struct virtqueue *tvq; /*!< transmit virtqueue */ struct llist *rl_endpoints; /*!< linked list of endpoints */ LOCK *lock; /*!< local RPMsg Lite mutex lock */ uint32_t link_state; /*!< state of the link, up/down*/ char *sh_mem_base; /*!< base address of the shared memory */ uint32_t sh_mem_remaining; /*!< amount of remaining unused buffers in shared memory */ uint32_t sh_mem_total; /*!< total amount of buffers in shared memory */ struct virtqueue_ops const *vq_ops; /*!< ops functions table pointer */ #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) void *env; /*!< pointer to the environment layer context */ #endif #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) struct vq_static_context vq_ctxt[2]; #endif }; /******************************************************************************* * API ******************************************************************************/ /* Exported API functions */ /*! * @brief Initializes the RPMsg-Lite communication stack. * Must be called prior to any other RPMSG lite API. * To be called by the master side. * * @param shmem_addr Shared memory base used for this instance of RPMsg-Lite * @param shmem_length Length of memory area given by previous parameter * @param link_id Link ID used to define the rpmsg-lite instance, see rpmsg_platform.h * @param init_flags Initialization flags * @param env_cfg Initialization data for the environement RPMsg-Lite layer, used when * the environment layer uses its own context (RL_USE_ENVIRONMENT_CONTEXT) * @param static_context RPMsg-Lite preallocated context pointer, used in case of static api (RL_USE_STATIC_API) * * @return New RPMsg-Lite instance pointer or RL_NULL. * */ #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr, size_t shmem_length, uint32_t link_id, uint32_t init_flags, struct rpmsg_lite_instance *static_context); #elif defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) struct rpmsg_lite_instance *rpmsg_lite_master_init( void *shmem_addr, size_t shmem_length, uint32_t link_id, uint32_t init_flags, void *env_cfg); #else struct rpmsg_lite_instance *rpmsg_lite_master_init(void *shmem_addr, size_t shmem_length, uint32_t link_id, uint32_t init_flags); #endif /** * @brief Initializes the RPMsg-Lite communication stack. * Must be called prior to any other RPMsg-Lite API. * To be called by the remote side. * * @param shmem_addr Shared memory base used for this instance of RPMsg-Lite * @param link_id Link ID used to define the rpmsg-lite instance, see rpmsg_platform.h * @param init_flags Initialization flags * @param env_cfg Initialization data for the environement RPMsg-Lite layer, used when * the environment layer uses its own context (RL_USE_ENVIRONMENT_CONTEXT) * @param static_context RPMsg-Lite preallocated context pointer, used in case of static api (RL_USE_STATIC_API) * * @return New RPMsg-Lite instance pointer or RL_NULL. * */ #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t link_id, uint32_t init_flags, struct rpmsg_lite_instance *static_context); #elif defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1) struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t link_id, uint32_t init_flags, void *env_cfg); #else struct rpmsg_lite_instance *rpmsg_lite_remote_init(void *shmem_addr, uint32_t link_id, uint32_t init_flags); #endif /*! * * @brief Reset RPMsg-Lite communication stack. To be called by the remote side. * When system wake up from sleep state, master side(DSP) will be reinitialized. Remote side * should call this function to recover enviroment to reset state. * * @param rpmsg_lite_dev RPMsg-Lite instance */ void rpmsg_lite_remote_env_reset(struct rpmsg_lite_instance *rpmsg_lite_dev); /*! * * @brief Deinitialized the RPMsg-Lite communication stack * This function always succeeds. * rpmsg_lite_init() can be called again after this * function has been called. * * @param rpmsg_lite_dev RPMsg-Lite instance * * @return Status of function execution, RL_SUCCESS on success. */ int32_t rpmsg_lite_deinit(struct rpmsg_lite_instance *rpmsg_lite_dev); /*! * @brief Create a new rpmsg endpoint, which can be used * for communication. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param addr Desired address, RL_ADDR_ANY for automatic selection * @param rx_cb Callback function called on receive * @param rx_cb_data Callback data pointer, passed to rx_cb * @param ept_context Endpoint preallocated context pointer, used in case of static api (RL_USE_STATIC_API) * * @return RL_NULL on error, new endpoint pointer on success. * */ #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1) struct rpmsg_lite_endpoint *rpmsg_lite_create_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, uint32_t addr, rl_ept_rx_cb_t rx_cb, void *rx_cb_data, struct rpmsg_lite_ept_static_context *ept_context); #else struct rpmsg_lite_endpoint *rpmsg_lite_create_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, uint32_t addr, rl_ept_rx_cb_t rx_cb, void *rx_cb_data); #endif /*! * @brief This function deletes rpmsg endpoint and performs cleanup. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param rl_ept Pointer to endpoint to destroy * */ int32_t rpmsg_lite_destroy_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *rl_ept); /*! * * @brief Sends a message contained in data field of length size * to the remote endpoint with address dst. * ept->addr is used as source address in the rpmsg header * of the message being sent. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param ept Sender endpoint * @param dst Remote endpoint address * @param data Payload buffer * @param size Size of payload, in bytes * @param timeout Timeout in ms, 0 if nonblocking * * @return Status of function execution, RL_SUCCESS on success. * */ int32_t rpmsg_lite_send(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *ept, uint32_t dst, char *data, uint32_t size, uint32_t timeout); /*! * @brief Function to get the link state * * @param rpmsg_lite_dev RPMsg-Lite instance * * @return True when link up, false when down. * */ int32_t rpmsg_lite_is_link_up(struct rpmsg_lite_instance *rpmsg_lite_dev); #if defined(RL_API_HAS_ZEROCOPY) && (RL_API_HAS_ZEROCOPY == 1) /*! * @brief Releases the rx buffer for future reuse in vring. * This API can be called at process context when the * message in rx buffer is processed. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param rxbuf Rx buffer with message payload * * @return Status of function execution, RL_SUCCESS on success. */ int32_t rpmsg_lite_release_rx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev, void *rxbuf); int32_t rpmsg_lite_release_rx_buffer_dur_recover(struct rpmsg_lite_instance *rpmsg_lite_dev, void *rxbuf); /*! * @brief Allocates the tx buffer for message payload. * * This API can only be called at process context to get the tx buffer in vring. By this way, the * application can directly put its message into the vring tx buffer without copy from an application buffer. * It is the application responsibility to correctly fill the allocated tx buffer by data and passing correct * parameters to the rpmsg_lite_send_nocopy() function to perform data no-copy-send mechanism. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param[in] size Pointer to store maximum payload size available * @param[in] timeout Integer, wait upto timeout ms or not for buffer to become available * * @return The tx buffer address on success and RL_NULL on failure. * * @see rpmsg_lite_send_nocopy */ void *rpmsg_lite_alloc_tx_buffer(struct rpmsg_lite_instance *rpmsg_lite_dev, uint32_t *size, uint32_t timeout); /*! * @brief Sends a message in tx buffer allocated by rpmsg_lite_alloc_tx_buffer() * * This function sends txbuf of length len to the remote dst address, * and uses ept->addr as the source address. * The application has to take the responsibility for: * 1. tx buffer allocation (rpmsg_lite_alloc_tx_buffer()) * 2. filling the data to be sent into the pre-allocated tx buffer * 3. not exceeding the buffer size when filling the data * 4. data cache coherency * * After the rpmsg_lite_send_nocopy() function is issued the tx buffer is no more owned * by the sending task and must not be touched anymore unless the rpmsg_lite_send_nocopy() * function fails and returns an error. * * @param rpmsg_lite_dev RPMsg-Lite instance * @param[in] ept Sender endpoint pointer * @param[in] dst Destination address * @param[in] data TX buffer with message filled * @param[in] size Length of payload * * @return 0 on success and an appropriate error value on failure. * * @see rpmsg_lite_alloc_tx_buffer */ int32_t rpmsg_lite_send_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *ept, uint32_t dst, void *data, uint32_t size); #endif /* RL_API_HAS_ZEROCOPY */ //! @} #if defined(__cplusplus) } #endif #endif /* RPMSG_LITE_H_ */