demo工程暂存 优化菜单界面UI和功能

This commit is contained in:
2024-04-29 16:32:24 +08:00
commit 330cd25cf1
3310 changed files with 2163318 additions and 0 deletions

View File

@ -0,0 +1,414 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_bm.c
*
*
* DESCRIPTION
*
* This file is Bare Metal Implementation of env layer for OpenAMP.
*
*
**************************************************************************/
#include "rpmsg_env.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;
/* Max supported ISR counts */
#define ISR_COUNT (12U) /* Change for multiple remote cores */
/*!
* 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_init
*
* Initializes OS/BM environment.
*
*/
int32_t env_init(void)
{
// verify 'env_init_counter'
RL_ASSERT(env_init_counter >= 0);
if (env_init_counter < 0)
{
return -1;
}
env_init_counter++;
// multiple call of 'env_init' - return ok
if (1 < env_init_counter)
{
return 0;
}
// first call
(void)memset(isr_table, 0, sizeof(isr_table));
return platform_init();
}
/*!
* env_deinit
*
* Uninitializes OS/BM environment.
*
* @returns Execution status
*/
int32_t env_deinit(void)
{
// verify 'env_init_counter'
RL_ASSERT(env_init_counter > 0);
if (env_init_counter <= 0)
{
return -1;
}
// counter on zero - call platform deinit
env_init_counter--;
// multiple call of 'env_deinit' - return ok
if (0 < env_init_counter)
{
return 0;
}
// last call
return platform_deinit();
}
/*!
* env_allocate_memory - implementation
*
* @param size
*/
void *env_allocate_memory(uint32_t size)
{
return (malloc(size));
}
/*!
* env_free_memory - implementation
*
* @param ptr
*/
void env_free_memory(void *ptr)
{
if (ptr != ((void *)0))
{
free(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)
{
/* make the mutex pointer point to itself
* this marks the mutex handle as initialized.
*/
*lock = lock;
return 0;
}
/*!
* env_delete_mutex
*
* Deletes the given lock
*
*/
void env_delete_mutex(void *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)
{
/* No mutex needed for RPMsg-Lite in BM environment,
* since the API is not shared with ISR context. */
}
/*!
* env_unlock_mutex
*
* Releases the given lock.
*/
void env_unlock_mutex(void *lock)
{
/* No mutex needed for RPMsg-Lite in BM environment,
* since the API is not shared with ISR context. */
}
/*!
* env_sleep_msec
*
* Suspends the calling thread for given time , in msecs.
*/
void env_sleep_msec(uint32_t num_msec)
{
platform_time_delay(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 for BM */
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);
}
}

View File

@ -0,0 +1,703 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_freertos.c
*
*
* DESCRIPTION
*
* This file is FreeRTOS Implementation of env layer for OpenAMP.
*
*
**************************************************************************/
#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 <stdlib.h>
#include <string.h>
static int32_t env_init_counter = 0;
static SemaphoreHandle_t env_sema = ((void *)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
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 xPortIsInsideInterrupt();
}
/*!
* env_init
*
* Initializes OS/BM environment.
*
*/
int32_t env_init(void)
{
int32_t retval;
vTaskSuspendAll(); /* stop scheduler */
// verify 'env_init_counter'
RL_ASSERT(env_init_counter >= 0);
if (env_init_counter < 0)
{
(void)xTaskResumeAll(); /* re-enable scheduler */
return -1;
}
env_init_counter++;
// multiple call of 'env_init' - return ok
if (env_init_counter == 1)
{
// first call
env_sema = xSemaphoreCreateBinary();
(void)memset(isr_table, 0, sizeof(isr_table));
(void)xTaskResumeAll();
retval = platform_init();
(void)xSemaphoreGive(env_sema);
return retval;
}
else
{
(void)xTaskResumeAll();
/* 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 (pdTRUE == xSemaphoreTake(env_sema, portMAX_DELAY))
{
(void)xSemaphoreGive(env_sema);
}
return 0;
}
}
/*!
* env_deinit
*
* Uninitializes OS/BM environment.
*
* @returns - execution status
*/
int32_t env_deinit(void)
{
int32_t retval;
vTaskSuspendAll(); /* stop scheduler */
// verify 'env_init_counter'
RL_ASSERT(env_init_counter > 0);
if (env_init_counter <= 0)
{
(void)xTaskResumeAll(); /* re-enable scheduler */
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();
vSemaphoreDelete(env_sema);
env_sema = ((void *)0);
(void)xTaskResumeAll();
return retval;
}
else
{
(void)xTaskResumeAll();
return 0;
}
}
/*!
* env_allocate_memory - implementation
*
* @param size
*/
void *env_allocate_memory(uint32_t size)
{
return (pvPortMalloc(size));
}
/*!
* env_free_memory - implementation
*
* @param ptr
*/
void env_free_memory(void *ptr)
{
if (ptr != ((void *)0))
{
vPortFree(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)
{
if (count > RL_ENV_MAX_MUTEX_COUNT)
{
return -1;
}
*lock = xSemaphoreCreateCounting((UBaseType_t)RL_ENV_MAX_MUTEX_COUNT, (UBaseType_t)count);
if (*lock != ((void *)0))
{
return 0;
}
else
{
return -1;
}
}
/*!
* env_delete_mutex
*
* Deletes the given lock
*
*/
void env_delete_mutex(void *lock)
{
vSemaphoreDelete(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)
{
SemaphoreHandle_t xSemaphore = (SemaphoreHandle_t)lock;
if (env_in_isr() == 0)
{
(void)xSemaphoreTake(xSemaphore, portMAX_DELAY);
}
}
/*!
* env_unlock_mutex
*
* Releases the given lock.
*/
void env_unlock_mutex(void *lock)
{
SemaphoreHandle_t xSemaphore = (SemaphoreHandle_t)lock;
if (env_in_isr() == 0)
{
(void)xSemaphoreGive(xSemaphore);
}
}
/*!
* 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)
{
BaseType_t xTaskWokenByReceive = pdFALSE;
SemaphoreHandle_t xSemaphore = (SemaphoreHandle_t)lock;
if (env_in_isr() != 0)
{
(void)xSemaphoreTakeFromISR(xSemaphore, &xTaskWokenByReceive);
portEND_SWITCHING_ISR(xTaskWokenByReceive);
}
else
{
(void)xSemaphoreTake(xSemaphore, portMAX_DELAY);
}
}
/*!
* env_release_sync_lock
*
* Releases the given lock.
*/
void env_release_sync_lock(void *lock)
{
BaseType_t xTaskWokenByReceive = pdFALSE;
SemaphoreHandle_t xSemaphore = (SemaphoreHandle_t)lock;
if (env_in_isr() != 0)
{
(void)xSemaphoreGiveFromISR(xSemaphore, &xTaskWokenByReceive);
portEND_SWITCHING_ISR(xTaskWokenByReceive);
}
else
{
(void)xSemaphoreGive(xSemaphore);
}
}
/*!
* env_sleep_msec
*
* Suspends the calling thread for given time , in msecs.
*/
void env_sleep_msec(uint32_t num_msec)
{
vTaskDelay(num_msec / portTICK_PERIOD_MS);
}
/*!
* 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();
}
/*!
*
* env_get_timestamp
*
* Returns a 64 bit time stamp.
*
*
*/
uint64_t env_get_timestamp(void)
{
if (env_in_isr() != 0)
{
return (uint64_t)xTaskGetTickCountFromISR();
}
else
{
return (uint64_t)xTaskGetTickCount();
}
}
/*========================================================= */
/* 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)
{
*queue = xQueueCreate((UBaseType_t)length, (UBaseType_t)element_size);
if (*queue != ((void *)0))
{
return 0;
}
else
{
return -1;
}
}
/*!
* env_delete_queue
*
* Deletes the message queue.
*
* @param queue - queue to delete
*/
void env_delete_queue(void *queue)
{
vQueueDelete(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)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (env_in_isr() != 0)
{
if (xQueueSendFromISR(queue, msg, &xHigherPriorityTaskWoken) == pdPASS)
{
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
return 1;
}
}
else
{
if (xQueueSend(queue, msg, ((portMAX_DELAY == timeout_ms) ? portMAX_DELAY : timeout_ms / portTICK_PERIOD_MS)) ==
pdPASS)
{
return 1;
}
}
return 0;
}
/*!
* 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)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (env_in_isr() != 0)
{
if (xQueueReceiveFromISR(queue, msg, &xHigherPriorityTaskWoken) == pdPASS)
{
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
return 1;
}
}
else
{
if (xQueueReceive(queue, msg,
((portMAX_DELAY == timeout_ms) ? portMAX_DELAY : timeout_ms / portTICK_PERIOD_MS)) == pdPASS)
{
return 1;
}
}
return 0;
}
/*!
* 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)
{
if (env_in_isr() != 0)
{
return ((int32_t)uxQueueMessagesWaitingFromISR(queue));
}
else
{
return ((int32_t)uxQueueMessagesWaiting(queue));
}
}

View File

@ -0,0 +1,708 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_qnx.c
*
*
* DESCRIPTION
*
* This file is QNX Implementation of env layer.
*
*
**************************************************************************/
#include "rpmsg_env.h"
#include "rpmsg_platform.h"
#include "virtqueue.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <mqueue.h>
#include "rpmsg_env_qnx.h"
#if __PTR_BITS__ > 32
#include <fcntl.h>
#include <aarch64/inline.h>
#else
#include <arm/inline.h>
#endif
/* Max supported ISR counts */
#define ISR_COUNT (32U)
#if (!defined(RL_USE_ENVIRONMENT_CONTEXT)) || (RL_USE_ENVIRONMENT_CONTEXT != 1)
#error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 1"
#endif
/**
* Structure to keep track of registered ISR's.
*/
struct isr_info
{
void *data;
volatile uint32_t enabled;
};
/**
* Structure to hold queue information
*/
typedef struct env_queue
{
mqd_t mqd;
size_t msg_len;
} env_queue_t;
/**
* Env. context structure
*/
typedef struct env_context
{
void *platform_context; /* Pointer to platform context */
uint32_t pa; /* Physical address of memory pool reserved for rpmsg */
void *va; /* Virtual address of the memory pool */
struct isr_info isr_table[ISR_COUNT]; /* Table with registered Virt. queue data */
} env_context_t;
/**
* Returns pointer to platform context.
*
* @param env_context Pointer to env. context
*
* @return Pointer to platform context
*/
void *env_get_platform_context(void *env_context)
{
env_context_t *env = env_context;
return env->platform_context;
}
/*!
* env_init
*
* Initializes OS/BM environment.
*
*/
int32_t env_init(void **env_context, void *env_init_data)
{
rpmsg_env_init_t *init = env_init_data;
imx_rpmsg_env_cfg_t *user_cfg;
if (init != ((void *)0))
{
user_cfg = init->user_input;
env_context_t *ctx = env_allocate_memory(sizeof(env_context_t));
if (ctx == ((void *)0))
{
return -1;
}
/* Save virtual and phy address of mmaped memory region */
ctx->pa = init->pa;
ctx->va = init->va;
/* Initialize platform, dereference user_input to get platform cfg address */
if (platform_init(&ctx->platform_context, ctx, user_cfg ? user_cfg->platform_cfg : ((void *)0)) != 0)
{
env_free_memory(ctx);
return -1;
}
*env_context = ctx;
return 0;
}
return -1;
}
/*!
* env_deinit
*
* Uninitializes OS/BM environment.
*
* @returns - execution status
*/
int32_t env_deinit(void *env_context)
{
env_context_t *ctx = env_context;
platform_deinit(ctx->platform_context);
env_free_memory(ctx);
return 0;
}
/*!
* env_allocate_memory - implementation
*
* @param size
*/
void *env_allocate_memory(uint32_t size)
{
return malloc(size);
}
/*!
* env_free_memory - implementation
*
* @param ptr
*/
void env_free_memory(void *ptr)
{
free(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)
{
dsb();
}
/*!
* env_rmb - implementation
*/
void env_rmb(void)
{
dsb();
}
/*!
* env_wmb - implementation
*/
void env_wmb(void)
{
dsb();
}
/*!
* env_map_vatopa - implementation
*
* @param address
*/
uint32_t env_map_vatopa(void *env, void *address)
{
#if IMX_MMAP_VA_ON_PA
return ((uint32_t)address);
#else
/* This is faster then mem_offset64() */
env_context_t *ctx = env;
uint64_t va = (uint64_t)address;
uint64_t va_start = (uint64_t)ctx->va;
uint64_t pa = ctx->pa + (va - va_start);
return pa;
#endif
}
/*!
* env_map_patova - implementation
*
* @param address
*/
void *env_map_patova(void *env, uint32_t address)
{
#if IMX_MMAP_VA_ON_PA
return ((void *)address);
#else
env_context_t *ctx = env;
uint64_t va_start = (uint64_t)ctx->va;
uint64_t va = (va_start + (address - ctx->pa));
return (void *)va;
#endif
}
/*!
* env_create_mutex
*
* Creates a mutex with the given initial count.
*
*/
int32_t env_create_mutex(void **lock, int32_t count)
{
*lock = env_allocate_memory(sizeof(pthread_mutex_t));
if (*lock == ((void *)0))
{
return -1;
}
if (pthread_mutex_init((pthread_mutex_t *)*lock, ((void *)0)) != EOK)
{
env_free_memory(*lock);
*lock = ((void *)0);
return -1;
}
return 0;
}
/*!
* env_delete_mutex
*
* Deletes the given lock
*
*/
void env_delete_mutex(void *lock)
{
pthread_mutex_destroy(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)
{
pthread_mutex_lock(lock);
}
/*!
* env_unlock_mutex
*
* Releases the given lock.
*/
void env_unlock_mutex(void *lock)
{
pthread_mutex_unlock(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)
{
env_lock_mutex(lock);
}
/*!
* env_release_sync_lock
*
* Releases the given lock.
*/
void env_release_sync_lock(void *lock)
{
env_unlock_mutex(lock);
}
/*!
* env_sleep_msec
*
* Suspends the calling thread for given time , in msecs.
*/
void env_sleep_msec(uint32_t num_msec)
{
delay(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(void *env, uint32_t vector_id, void *data)
{
env_context_t *ctx = env;
RL_ASSERT(vector_id < ISR_COUNT);
if (vector_id < ISR_COUNT)
{
ctx->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(void *env, uint32_t vector_id)
{
env_context_t *ctx = env;
RL_ASSERT(vector_id < ISR_COUNT);
if (vector_id < ISR_COUNT)
{
ctx->isr_table[vector_id].data = ((void *)0);
ctx->isr_table[vector_id].enabled = 0;
}
}
/*!
* env_enable_interrupt
*
* Enables the given interrupt
*
* @param vector_id - virtual interrupt vector number
*/
void env_enable_interrupt(void *env, uint32_t vector_id)
{
env_context_t *ctx = env;
RL_ASSERT(vector_id < ISR_COUNT);
if (vector_id < ISR_COUNT)
{
ctx->isr_table[vector_id].enabled = 1;
}
}
/*!
* env_disable_interrupt
*
* Disables the given interrupt
*
* @param vector_id - virtual interrupt vector number
*/
void env_disable_interrupt(void *env, uint32_t vector_id)
{
env_context_t *ctx = env;
RL_ASSERT(vector_id < ISR_COUNT);
if (vector_id < ISR_COUNT)
{
ctx->isr_table[vector_id].enabled = 0;
}
}
/*!
* 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();
}
/*!
*
* env_get_timestamp
*
* Returns a 64 bit time stamp.
*
*
*/
uint32_t long env_get_timestamp(void)
{
fprintf(stderr, "%s unsupported\n", __FUNCTION__);
return 0;
}
/*========================================================= */
/* Util data / functions */
/**
* Called from receive thread
*
* @param env Pointer to env context
* @param vector Vector ID.
*/
void env_isr(void *env, uint32_t vector)
{
struct isr_info *info;
env_context_t *ctx = env;
RL_ASSERT(vector < ISR_COUNT);
if (vector < ISR_COUNT)
{
info = &ctx->isr_table[vector];
if (info->enabled)
{
virtqueue_notification((struct virtqueue *)info->data);
}
}
}
/**
* Called by rpmsg to init an interrupt
*
* @param env Pointer to env context.
* @param vq_id Virt. queue ID.
* @param isr_data Pointer to interrupt data.
*
* @return Execution status.
*/
int32_t env_init_interrupt(void *env, int32_t vq_id, void *isr_data)
{
env_register_isr(env, vq_id, isr_data);
return 0;
}
/**
* Called by rpmsg to deinit an interrupt.
*
* @param env Pointer to env context.
* @param vq_id Virt. queue ID.
*
* @return Execution status.
*/
int32_t env_deinit_interrupt(void *env, int32_t vq_id)
{
env_unregister_isr(env, vq_id);
return 0;
}
/**
* 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)
{
char name[100];
struct mq_attr mqstat;
env_queue_t *q = env_allocate_memory(sizeof(env_queue_t));
if (q == ((void *)0))
{
return -1;
}
/* Creates a unique queue in /dev/mq/PID_virtaddr_length */
sprintf(name, "/%u_0x%lx_%u", getpid(), (uint64_t)q, length);
mqstat.mq_maxmsg = length;
mqstat.mq_msgsize = element_size;
mqstat.mq_flags = 0;
mqstat.mq_curmsgs = 0;
mqstat.mq_recvwait = 0;
mqstat.mq_sendwait = 0;
q->msg_len = element_size;
q->mqd = mq_open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, &mqstat);
if (q->mqd == -1)
{
env_free_memory(q);
fprintf(stderr, "mq_open failed: %s\n", strerror(errno));
return -1;
}
/* Return queue */
*queue = q;
return 0;
}
/*!
* env_delete_queue
*
* Deletes the message queue.
*
* @param queue - queue to delete
*/
void env_delete_queue(void *queue)
{
env_queue_t *q = queue;
mq_close(q->mqd);
env_free_memory(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)
{
env_queue_t *q = queue;
if (mq_send(q->mqd, (const char *)msg, q->msg_len, 0))
{
fprintf(stderr, "mq_send failed: %s\n", strerror(errno));
return 0;
}
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)
{
env_queue_t *q = queue;
if (mq_receive(q->mqd, msg, q->msg_len, ((void *)0)) == -1)
{
fprintf(stderr, "mq_receive failed: %s\n", strerror(errno));
return 0;
}
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)
{
struct mq_attr mqstat;
env_queue_t *q = queue;
if (mq_getattr(q->mqd, &mqstat) != -1)
{
return mqstat.mq_curmsgs;
}
return 0;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2016-2019 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:
*
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* * 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.
*
* * 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.
*
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_qnx.h
*
*
* DESCRIPTION
*
* This file is QNX header file of env layer.
*
*
**************************************************************************/
#ifndef RPMSG_ENV_QNX_H_
#define RPMSG_ENV_QNX_H_
#include <sys/imx_rpmsg_lite.h>
typedef struct rpmsg_env_init
{
void *user_input; /* Pointer to user init cfg */
uint32_t pa; /* Physical address of memory pool reserved for rpmsg */
void *va; /* Virtual address of the memory pool */
} rpmsg_env_init_t;
#endif /* RPMSG_ENV_QNX_H_ */

View File

@ -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 <stdlib.h>
#include <string.h>
#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;
}
}

View File

@ -0,0 +1,681 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2021 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.
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_xos.c
*
*
* DESCRIPTION
*
* This file is XOS Implementation of env layer for RPMsg_Lite.
*
*
**************************************************************************/
#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};
/* 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 XOS environment.
*
*/
int32_t env_init(void)
{
int32_t retval;
uint32_t regPrimask = xos_disable_interrupts(); /* stop scheduler */
/* verify 'env_init_counter' */
RL_ASSERT(env_init_counter >= 0);
if (env_init_counter < 0)
{
xos_restore_interrupts(regPrimask); /* re-enable scheduler */
return -1;
}
env_init_counter++;
/* multiple call of 'env_init' - return ok */
if (env_init_counter == 1)
{
/* first call */
(void)xos_sem_create(&env_sema, XOS_SEM_WAIT_PRIORITY, 1);
(void)memset(isr_table, 0, sizeof(isr_table));
xos_restore_interrupts(regPrimask);
retval = platform_init();
(void)xos_sem_put(&env_sema);
return retval;
}
else
{
xos_restore_interrupts(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 (XOS_OK == xos_sem_get(&env_sema))
{
(void)xos_sem_put(&env_sema);
}
return 0;
}
}
/*!
* env_deinit
*
* Uninitializes XOS environment.
*
* @returns - execution status
*/
int32_t env_deinit(void)
{
int32_t retval;
uint32_t regPrimask = xos_disable_interrupts(); /* stop scheduler */
/* verify 'env_init_counter' */
RL_ASSERT(env_init_counter > 0);
if (env_init_counter <= 0)
{
xos_restore_interrupts(regPrimask); /* re-enable scheduler */
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)xos_sem_delete(&env_sema);
xos_restore_interrupts(regPrimask);
return retval;
}
else
{
xos_restore_interrupts(regPrimask);
return 0;
}
}
/*!
* env_allocate_memory - implementation
*
* @param size
*/
void *env_allocate_memory(uint32_t size)
{
return (malloc(size));
}
/*!
* env_free_memory - implementation
*
* @param ptr
*/
void env_free_memory(void *ptr)
{
if (ptr != ((void *)0))
{
free(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)
{
struct XosSem *semaphore_ptr;
if (count > RL_ENV_MAX_MUTEX_COUNT)
{
return -1;
}
semaphore_ptr = (struct XosSem *)env_allocate_memory(sizeof(struct XosSem));
if (semaphore_ptr == ((void *)0))
{
return -1;
}
if (XOS_OK == xos_sem_create(semaphore_ptr, XOS_SEM_WAIT_PRIORITY, count))
{
*lock = (void *)semaphore_ptr;
return 0;
}
else
{
env_free_memory(semaphore_ptr);
return -1;
}
}
/*!
* env_delete_mutex
*
* Deletes the given lock
*
*/
void env_delete_mutex(void *lock)
{
xos_sem_delete(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)xos_sem_get((struct XosSem *)lock);
}
}
/*!
* env_unlock_mutex
*
* Releases the given lock.
*/
void env_unlock_mutex(void *lock)
{
if (env_in_isr() == 0)
{
(void)xos_sem_put((struct XosSem *)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)
{
(void)xos_thread_sleep_msec(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)
{
char *queue_ptr = ((void *)0);
queue_ptr = (char *)env_allocate_memory(XOS_MSGQ_SIZE(length, element_size));
if (queue_ptr != ((void *)0))
{
if (XOS_OK ==
xos_msgq_create((XosMsgQueue *)queue_ptr, (uint16_t)length, (uint32_t)element_size, XOS_MSGQ_WAIT_PRIORITY))
{
*queue = (void *)queue_ptr;
return 0;
}
else
{
env_free_memory(queue_ptr);
return -1;
}
}
return -1;
}
/*!
* env_delete_queue
*
* Deletes the message queue.
*
* @param queue - queue to delete
*/
void env_delete_queue(void *queue)
{
xos_msgq_delete(queue);
env_free_memory(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 (RL_BLOCK == timeout_ms)
{
/* If no space is available, this function will block if called from a thread, but will
return immediately if called from an interrupt handler. */
if (XOS_OK == xos_msgq_put(queue, msg))
{
return 1;
}
}
else
{
/* If no space is available, this function will block if called from a thread, but will
return immediately if called from an interrupt handler. */
if (XOS_OK == xos_msgq_put_timeout(queue, msg, xos_msecs_to_cycles(timeout_ms)))
{
return 1;
}
}
return 0;
}
/*!
* 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 (RL_BLOCK == timeout_ms)
{
/* If no message is available, this function will block if called from a thread, but will return
immediately if called from an interrupt handler. */
if (XOS_OK == xos_msgq_get(queue, msg))
{
return 1;
}
}
else
{
/* If no message is available, this function will block if called from a thread, but will return
immediately if called from an interrupt handler. The thread will be unblocked when a message
arrives in the queue or the timeout expires. */
if (XOS_OK == xos_msgq_get_timeout(queue, msg, xos_msecs_to_cycles(timeout_ms)))
{
return 1;
}
}
return 0;
}
/*!
* 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)
{
return ((int32_t)xos_msgq_empty(queue));
}

View File

@ -0,0 +1,648 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
/**************************************************************************
* FILE NAME
*
* rpmsg_env_zephyr.c
*
*
* DESCRIPTION
*
* This file is Zephyr RTOS Implementation of env layer for OpenAMP.
*
*
**************************************************************************/
#include "rpmsg_env.h"
#include <zephyr.h>
#include "rpmsg_platform.h"
#include "virtqueue.h"
#include "rpmsg_compiler.h"
#include <stdlib.h>
#include <string.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
/* 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)
static int32_t env_init_counter = 0;
static struct k_sem env_sema = {0};
/* 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];
/*!
* env_in_isr
*
* @returns - true, if currently in ISR
*
*/
static int32_t env_in_isr(void)
{
return platform_in_isr();
}
/*!
* env_init
*
* Initializes OS/BM environment.
*
*/
int32_t env_init(void)
{
int32_t retval;
k_sched_lock(); /* stop scheduler */
/* verify 'env_init_counter' */
RL_ASSERT(env_init_counter >= 0);
if (env_init_counter < 0)
{
k_sched_unlock(); /* re-enable scheduler */
return -1;
}
env_init_counter++;
/* multiple call of 'env_init' - return ok */
if (env_init_counter == 1)
{
/* first call */
k_sem_init(&env_sema, 0, 1);
(void)memset(isr_table, 0, sizeof(isr_table));
k_sched_unlock();
retval = platform_init();
k_sem_give(&env_sema);
return retval;
}
else
{
k_sched_unlock();
/* 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.*/
k_sem_take(&env_sema, K_FOREVER);
k_sem_give(&env_sema);
return 0;
}
}
/*!
* env_deinit
*
* Uninitializes OS/BM environment.
*
* @returns - execution status
*/
int32_t env_deinit(void)
{
int32_t retval;
k_sched_lock(); /* stop scheduler */
/* verify 'env_init_counter' */
RL_ASSERT(env_init_counter > 0);
if (env_init_counter <= 0)
{
k_sched_unlock(); /* re-enable scheduler */
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();
k_sem_reset(&env_sema);
k_sched_unlock();
return retval;
}
else
{
k_sched_unlock();
return 0;
}
}
/*!
* env_allocate_memory - implementation
*
* @param size
*/
void *env_allocate_memory(uint32_t size)
{
return (k_malloc(size));
}
/*!
* env_free_memory - implementation
*
* @param ptr
*/
void env_free_memory(void *ptr)
{
if (ptr != ((void *)0))
{
k_free(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 dst
* @param src
* @param len
*/
void env_strncpy(char *dst, const char *src, uint32_t len)
{
(void)strncpy(dst, src, len);
}
/*!
*
* env_strncmp - implementation
*
* @param dst
* @param src
* @param len
*/
int32_t env_strncmp(char *dst, const char *src, uint32_t len)
{
return (strncmp(dst, 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)
{
struct k_sem *semaphore_ptr;
semaphore_ptr = (struct k_sem *)env_allocate_memory(sizeof(struct k_sem));
if (semaphore_ptr == ((void *)0))
{
return -1;
}
if (count > RL_ENV_MAX_MUTEX_COUNT)
{
return -1;
}
k_sem_init(semaphore_ptr, count, RL_ENV_MAX_MUTEX_COUNT);
*lock = (void *)semaphore_ptr;
return 0;
}
/*!
* env_delete_mutex
*
* Deletes the given lock
*
*/
void env_delete_mutex(void *lock)
{
k_sem_reset(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)
{
k_sem_take((struct k_sem *)lock, K_FOREVER);
}
}
/*!
* env_unlock_mutex
*
* Releases the given lock.
*/
void env_unlock_mutex(void *lock)
{
if (env_in_isr() == 0)
{
k_sem_give((struct k_sem *)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)
{
k_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 - 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 - 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)
{
struct k_msgq *queue_ptr = ((void *)0);
char *msgq_buffer_ptr = ((void *)0);
queue_ptr = (struct k_msgq *)env_allocate_memory(sizeof(struct k_msgq));
msgq_buffer_ptr = (char *)env_allocate_memory(length * element_size);
if ((queue_ptr == ((void *)0)) || (msgq_buffer_ptr == ((void *)0)))
{
return -1;
}
k_msgq_init(queue_ptr, msgq_buffer_ptr, element_size, length);
*queue = (void *)queue_ptr;
return 0;
}
/*!
* env_delete_queue
*
* Deletes the message queue.
*
* @param queue - queue to delete
*/
void env_delete_queue(void *queue)
{
k_msgq_purge((struct k_msgq *)queue);
env_free_memory(((struct k_msgq *)queue)->buffer_start);
env_free_memory(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 (env_in_isr() != 0)
{
timeout_ms = 0; /* force timeout == 0 when in ISR */
}
if (0 == k_msgq_put((struct k_msgq *)queue, msg, timeout_ms))
{
return 1;
}
return 0;
}
/*!
* 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 (env_in_isr() != 0)
{
timeout_ms = 0; /* force timeout == 0 when in ISR */
}
if (0 == k_msgq_get((struct k_msgq *)queue, msg, timeout_ms))
{
return 1;
}
return 0;
}
/*!
* 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)
{
return k_msgq_num_used_get((struct k_msgq *)queue);
}

View File

@ -0,0 +1,292 @@
/*
* Copyright 2019-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "rpmsg_platform.h"
#include "rpmsg_env.h"
#include "co_util.h"
#include "fr30xx.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
/* The IPC instance used for CM33 and DSP core communication */
static IPC_HandleTypeDef ipc_mcu;
static int32_t isr_counter = 0;
static int32_t disable_counter = 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);
env_lock_mutex(platform_lock);
RL_ASSERT(0 <= isr_counter);
// if (isr_counter < 2)
// {
// printf("MU_EnableInterrupts(APP_MU, 1UL << (31UL - vector_id));");
// }
isr_counter++;
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);
RL_ASSERT(0 < isr_counter);
isr_counter--;
// if (isr_counter < 2)
// {
// printf("MU_DisableInterrupts(APP_MU, 1UL << (31UL - vector_id));");
// }
/* Unregister ISR from environment layer */
env_unregister_isr(vector_id);
env_unlock_mutex(platform_lock);
return 0;
}
void platform_notify(uint32_t vector_id)
{
env_lock_mutex(platform_lock);
if (vector_id == 0) {
ipc_msg_send(&ipc_mcu, IPC_CH_0, 0);
}
else if (vector_id == 1) {
ipc_msg_send(&ipc_mcu, IPC_CH_1, 0);
}
else {
while(1);
}
env_unlock_mutex(platform_lock);
}
/**
* 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)
{
system_delay_us(1000 * num_msec);
}
/**
* 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)
{
RL_ASSERT(0 < disable_counter);
platform_global_isr_disable();
disable_counter--;
if (disable_counter == 0)
{
NVIC_EnableIRQ(IPC_MCU_IRQn);
}
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)
{
RL_ASSERT(0 <= disable_counter);
platform_global_isr_disable();
/* virtqueues use the same NVIC vector
if counter is set - the interrupts are disabled */
if (disable_counter == 0)
{
NVIC_DisableIRQ(IPC_MCU_IRQn);
}
disable_counter++;
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
*
* Translate CM33 addresses to DSP addresses
*
*/
uint32_t platform_vatopa(void *addr)
{
return (uint32_t)addr;
}
/**
* platform_patova
*
* Translate DSP addresses to CM33 addresses
*
*/
void *platform_patova(uint32_t addr)
{
return (void *)addr;
}
static void ipc_mcu_rx(struct __IPC_HandleTypeDef *hipc, enum_IPC_Chl_Sel_t ch, uint32_t msg)
{
// printf("ipc_mcu_rx: %d, 0x%08x\r\n", ch, msg);
if (ch == IPC_CH_0) {
env_isr(0);
}
else if (ch == IPC_CH_1) {
env_isr(1);
}
}
static void ipc_mcu_tx(struct __IPC_HandleTypeDef *hipc, enum_IPC_Chl_Sel_t ch)
{
// printf("ipc_mcu_tx: %d\r\n", ch);
}
void ipc_mcu_irq(void)
{
ipc_IRQHandler(&ipc_mcu);
}
/**
* platform_init
*
* platform/environment init
*/
int32_t platform_init(void)
{
__SYSTEM_APP_IPC_CLK_ENABLE();
ipc_mcu.IPCx = IPC_MCU;
ipc_mcu.RxEnableChannels = IPC_CH_0 | IPC_CH_1;
ipc_mcu.TxEnableChannels = IPC_CH_0 | IPC_CH_1;
ipc_mcu.RxCallback = ipc_mcu_rx;
ipc_mcu.TxCallback = ipc_mcu_tx;
ipc_init(&ipc_mcu);
/* 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)
{
/* Delete lock used in multi-instanced RPMsg */
env_delete_mutex(platform_lock);
platform_lock = ((void *)0);
return 0;
}
/**
* platform_reinit
*
* platform/environment reinit
*/
int32_t platform_reinit(void)
{
__SYSTEM_APP_IPC_CLK_ENABLE();
ipc_init(&ipc_mcu);
NVIC_EnableIRQ(IPC_MCU_IRQn);
return 0;
}

View File

@ -0,0 +1,303 @@
/*
* Copyright 2019-2021 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "rpmsg_platform.h"
#include "rpmsg_env.h"
#include "fsl_device_registers.h"
#include "fsl_mu.h"
#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
#include "mcmgr.h"
#endif
#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 CM33 and DSP core communication */
#define APP_MU MUA
#define APP_MU_IRQn MU_A_IRQn
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_A_IRQHandler(void)
{
uint32_t flags;
flags = MU_GetStatusFlags(APP_MU);
if (((uint32_t)kMU_GenInt0Flag & flags) != 0UL)
{
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);
}
}
#endif
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);
env_lock_mutex(platform_lock);
RL_ASSERT(0 <= isr_counter);
if (isr_counter < 2)
{
MU_EnableInterrupts(APP_MU, 1UL << (31UL - vector_id));
}
isr_counter++;
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);
RL_ASSERT(0 < isr_counter);
isr_counter--;
if (isr_counter < 2)
{
MU_DisableInterrupts(APP_MU, 1UL << (31UL - vector_id));
}
/* Unregister ISR from environment layer */
env_unregister_isr(vector_id);
env_unlock_mutex(platform_lock);
return 0;
}
void platform_notify(uint32_t vector_id)
{
env_lock_mutex(platform_lock);
#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
(void)MU_TriggerInterrupts(APP_MU, 1UL << (19UL - RL_GET_Q_ID(vector_id)));
#endif
env_unlock_mutex(platform_lock);
}
/**
* 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)
{
RL_ASSERT(0 < disable_counter);
platform_global_isr_disable();
disable_counter--;
if (disable_counter == 0)
{
NVIC_EnableIRQ(APP_MU_IRQn);
}
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)
{
RL_ASSERT(0 <= disable_counter);
platform_global_isr_disable();
/* virtqueues use the same NVIC vector
if counter is set - the interrupts are disabled */
if (disable_counter == 0)
{
NVIC_DisableIRQ(APP_MU_IRQn);
}
disable_counter++;
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
*
* Translate CM33 addresses to DSP addresses
*
*/
uint32_t platform_vatopa(void *addr)
{
return (((uint32_t)(char *)addr & 0x0FFFFFFFu) + 0x800000u);
}
/**
* platform_patova
*
* Translate DSP addresses to CM33 addresses
*
*/
void *platform_patova(uint32_t addr)
{
return (void *)(char *)((addr - 0x00800000u) | 0x20000000u);
}
/**
* platform_init
*
* platform/environment init
*/
int32_t platform_init(void)
{
#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
mcmgr_status_t retval = kStatus_MCMGR_Error;
retval = MCMGR_RegisterEvent(kMCMGR_RemoteRPMsgEvent, mcmgr_event_handler, ((void *)0));
if (kStatus_MCMGR_Success != retval)
{
return -1;
}
#else
MU_Init(APP_MU);
NVIC_SetPriority(APP_MU_IRQn, APP_MU_IRQ_PRIORITY);
NVIC_EnableIRQ(APP_MU_IRQn);
#endif
/* 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_MU);
/* Delete lock used in multi-instanced RPMsg */
env_delete_mutex(platform_lock);
platform_lock = ((void *)0);
return 0;
}

View File

@ -0,0 +1,303 @@
/*
* Copyright 2019-2020 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "rpmsg_platform.h"
#include "rpmsg_env.h"
#include "fsl_device_registers.h"
#include "fsl_mu.h"
#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
#include "mcmgr.h"
#endif
#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 CM33 and DSP core communication */
#define APP_MU MUA
#define APP_MU_IRQn MU_A_IRQn
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_A_IRQHandler(void)
{
uint32_t flags;
flags = MU_GetStatusFlags(APP_MU);
if (((uint32_t)kMU_GenInt0Flag & flags) != 0UL)
{
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);
}
}
#endif
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);
env_lock_mutex(platform_lock);
RL_ASSERT(0 <= isr_counter);
if (isr_counter < 2)
{
MU_EnableInterrupts(APP_MU, 1UL << (31UL - vector_id));
}
isr_counter++;
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);
RL_ASSERT(0 < isr_counter);
isr_counter--;
if (isr_counter < 2)
{
MU_DisableInterrupts(APP_MU, 1UL << (31UL - vector_id));
}
/* Unregister ISR from environment layer */
env_unregister_isr(vector_id);
env_unlock_mutex(platform_lock);
return 0;
}
void platform_notify(uint32_t vector_id)
{
env_lock_mutex(platform_lock);
#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
(void)MU_TriggerInterrupts(APP_MU, 1UL << (19UL - RL_GET_Q_ID(vector_id)));
#endif
env_unlock_mutex(platform_lock);
}
/**
* 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)
{
RL_ASSERT(0 < disable_counter);
platform_global_isr_disable();
disable_counter--;
if (disable_counter == 0)
{
NVIC_EnableIRQ(APP_MU_IRQn);
}
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)
{
RL_ASSERT(0 <= disable_counter);
platform_global_isr_disable();
/* virtqueues use the same NVIC vector
if counter is set - the interrupts are disabled */
if (disable_counter == 0)
{
NVIC_DisableIRQ(APP_MU_IRQn);
}
disable_counter++;
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)
{
#if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
mcmgr_status_t retval = kStatus_MCMGR_Error;
retval = MCMGR_RegisterEvent(kMCMGR_RemoteRPMsgEvent, mcmgr_event_handler, ((void *)0));
if (kStatus_MCMGR_Success != retval)
{
return -1;
}
#else
MU_Init(APP_MU);
NVIC_SetPriority(APP_MU_IRQn, APP_MU_IRQ_PRIORITY);
NVIC_EnableIRQ(APP_MU_IRQn);
#endif
/* 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_MU);
/* Delete lock used in multi-instanced RPMsg */
env_delete_mutex(platform_lock);
platform_lock = ((void *)0);
return 0;
}

View File

@ -0,0 +1,350 @@
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "dsp.h"
#include "rpmsg.h"
#include "rpmsg_lite.h"
#include "rpmsg_queue.h"
#include "rpmsg_ns.h"
#define RPMSG_LITE_LINK_ID 0
#define SH_MEM_TOTAL_SIZE (1536U)
#define EPT_ADDR_SYNC 1
#define EPT_ADDR_ASYNC 2
#ifndef RAM_PROJECT
static __attribute__((section(".ARM.__at_0x20000000"))) uint8_t rpmsg_share_mem[SH_MEM_TOTAL_SIZE];
#else
static uint8_t *rpmsg_share_mem = (void *)0x20000000;
#endif
static rpmsg_queue_handle queue_sync = NULL;
static rpmsg_queue_handle queue_async = NULL;
static struct rpmsg_lite_endpoint *ept_sync = NULL;
static struct rpmsg_lite_endpoint *ept_async = NULL;
static struct rpmsg_lite_instance *remote_rpmsg = NULL;
static struct rpmsg_lite_instance *master_rpmsg = NULL;
static LOCK *ept_sync_lock;
static void (*msg_callback)(struct rpmsg_lite_instance *rpmsg, struct rpmsg_msg_t *msg) = NULL;
/************************************************************************************
* @fn rpmsg_sync_invoke
*
* @brief Start synchronous invocation to the other side.
*
* @param rpmsg: rpmsg instance.
* @param func_id: request function ID.
* @param param: all parameters.
* @param ret: return value.
*
* @return the function is handled by the other side normally or note
*/
uint32_t rpmsg_sync_invoke(struct rpmsg_lite_instance *rpmsg, uint32_t func_id, void *param, uint32_t *ret)
{
struct rpmsg_msg_t *msg;
uint32_t msg_len;
uint32_t src_addr;
uint32_t status;
int32_t remote_call_ret;
if (rpmsg == NULL) {
return -1;
}
env_lock_mutex(ept_sync_lock);
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_DSP);
msg = rpmsg_lite_alloc_tx_buffer(rpmsg, &msg_len, RL_BLOCK);
msg->msg_type = RPMSG_MSG_TYPE_SYNC_INVOKE;
msg->p.sync_func.func_id = func_id;
msg->p.sync_func.param = param;
// fputc('S', NULL);
rpmsg_lite_send_nocopy(rpmsg, ept_async, EPT_ADDR_ASYNC, msg, msg_len);
remote_call_ret = rpmsg_queue_recv_nocopy(rpmsg, queue_sync, (uint32_t *)&src_addr, (char **)&msg, &msg_len, 1000);
assert(RL_SUCCESS == remote_call_ret);
// fputc('s', NULL);
if (ret) {
*ret = msg->p.sync_ret.result;
}
status = msg->p.sync_ret.status;
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_DSP);
env_unlock_mutex(ept_sync_lock);
rpmsg_lite_release_rx_buffer(rpmsg, msg);
return status;
}
/************************************************************************************
* @fn rpmsg_send_async
*
* @brief Send message or command to the other side.
*
* @param rpmsg: rpmsg instance.
* @param async_msg: asynchronous message, this struct will be copied into share memory.
*
* @return The message is sent to the other side successfully or not
*/
uint32_t rpmsg_send_async(struct rpmsg_lite_instance *rpmsg, struct rpmsg_async_msg_t *async_msg)
{
struct rpmsg_msg_t *msg;
uint32_t msg_len;
uint32_t src_addr;
msg = rpmsg_lite_alloc_tx_buffer(rpmsg, &msg_len, RL_BLOCK);
msg->msg_type = RPMSG_MSG_TYPE_ASYNC_MSG;
memcpy((void *)&msg->p.async_msg, (void *)async_msg, sizeof(struct rpmsg_async_msg_t));
rpmsg_lite_send_nocopy(rpmsg, ept_async, EPT_ADDR_ASYNC, msg, msg_len);
return 0;
}
/************************************************************************************
* @fn rpmsg_send_sync_ret
*
* @brief Send response to the other side after execute synchronous invocation.
*
* @param rpmsg: rpmsg instance.
* @param status: handle the invocation normally or not.
* @param ret: return value of request function.
*
* @return The message is sent to the other side successfully or not
*/
uint32_t rpmsg_send_sync_ret(struct rpmsg_lite_instance *rpmsg, uint32_t status, uint32_t ret)
{
struct rpmsg_msg_t *msg;
uint32_t msg_len;
uint32_t src_addr;
msg = rpmsg_lite_alloc_tx_buffer(rpmsg, &msg_len, RL_BLOCK);
msg->msg_type = RPMSG_MSG_TYPE_SYNC_RETURN;
msg->p.sync_ret.status = status;
msg->p.sync_ret.result = ret;
rpmsg_lite_send_nocopy(rpmsg, ept_sync, EPT_ADDR_SYNC, msg, msg_len);
return 0;
}
/************************************************************************************
* @fn rpmsg_master_init
*
* @brief Initialize rpmsg-lite master side, this function is used in DSP side in general usage.
*
* @param callback: callback function to receive message from the other side.
*
* @return initialized rpmsg-lite master instance
*/
struct rpmsg_lite_instance *rpmsg_master_init(void (*recv)(struct rpmsg_lite_instance *rpmsg, struct rpmsg_msg_t *msg))
{
struct rpmsg_lite_instance *my_rpmsg;
struct rpmsg_msg_t *msg;
uint32_t src_addr;
uint32_t msg_len;
my_rpmsg = rpmsg_lite_master_init((void *)0x20000000, SH_MEM_TOTAL_SIZE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS);
queue_sync = rpmsg_queue_create(my_rpmsg);
queue_async = rpmsg_queue_create(my_rpmsg);
ept_sync = rpmsg_lite_create_ept(my_rpmsg, EPT_ADDR_SYNC, rpmsg_queue_rx_cb, queue_sync);
ept_async = rpmsg_lite_create_ept(my_rpmsg, EPT_ADDR_ASYNC, rpmsg_queue_rx_cb, queue_async);
env_create_mutex((void **)&ept_sync_lock, 1);
msg_callback = recv;
master_rpmsg = my_rpmsg;
/* notice remote side "I'm ready." */
msg = rpmsg_lite_alloc_tx_buffer(my_rpmsg, &msg_len, RL_BLOCK);
msg->msg_type = RPMSG_MSG_TYPE_MASTER_READY;
rpmsg_lite_send_nocopy(my_rpmsg, ept_sync, EPT_ADDR_SYNC, msg, msg_len);
return my_rpmsg;
}
/************************************************************************************
* @fn rpmsg_remote_init
*
* @brief Initialize rpmsg-lite remote side, this function is used in CM33 side in general usage.
*
* @param callback: callback function to receive message from the other side.
*
* @return initialized rpmsg-lite remote instance
*/
struct rpmsg_lite_instance *rpmsg_remote_init(void (*recv)(struct rpmsg_lite_instance *rpmsg, struct rpmsg_msg_t *msg))
{
struct rpmsg_lite_instance *my_rpmsg;
struct rpmsg_msg_t *msg;
uint32_t src_addr;
uint32_t msg_len;
my_rpmsg = rpmsg_lite_remote_init((void *)&rpmsg_share_mem[0], RPMSG_LITE_LINK_ID, RL_NO_FLAGS);
// while (0 == rpmsg_lite_is_link_up(my_rpmsg));
queue_sync = rpmsg_queue_create(my_rpmsg);
queue_async = rpmsg_queue_create(my_rpmsg);
ept_sync = rpmsg_lite_create_ept(my_rpmsg, EPT_ADDR_SYNC, rpmsg_queue_rx_cb, queue_sync);
ept_async = rpmsg_lite_create_ept(my_rpmsg, EPT_ADDR_ASYNC, rpmsg_queue_rx_cb, queue_async);
env_create_mutex((void **)&ept_sync_lock, 1);
msg_callback = recv;
remote_rpmsg = my_rpmsg;
return my_rpmsg;
}
/************************************************************************************
* @fn rpmsg_wait_master_ready
*
* @brief used by remote side to wait for master become ready after calling rpmsg_remote_init and
* boot up DSP (master side).
*
* @param rpmsg: rpmsg instance of remote side.
*/
void rpmsg_wait_master_ready(struct rpmsg_lite_instance *rpmsg)
{
struct rpmsg_msg_t *msg;
uint32_t src_addr;
uint32_t msg_len;
/* wait for "I'm ready." from master side */
rpmsg_queue_recv_nocopy(rpmsg, queue_sync, (uint32_t *)&src_addr, (char **)&msg, &msg_len, RL_BLOCK);
while ((src_addr != EPT_ADDR_SYNC) || (msg->msg_type != RPMSG_MSG_TYPE_MASTER_READY));
rpmsg_lite_release_rx_buffer(rpmsg, msg);
}
/************************************************************************************
* @fn rpmsg_destroy
*
* @brief destroy an initialized rpmsg-lite instance.
*
* @param rpmsg: rpmsg-lite instance.
*/
void rpmsg_destroy(struct rpmsg_lite_instance *rpmsg)
{
env_lock_mutex(ept_sync_lock);
(void)rpmsg_lite_destroy_ept(rpmsg, ept_sync);
ept_sync = ((void *)0);
(void)rpmsg_lite_destroy_ept(rpmsg, ept_async);
ept_async = ((void *)0);
(void)rpmsg_queue_destroy(rpmsg, queue_sync);
queue_sync = ((void *)0);
(void)rpmsg_queue_destroy(rpmsg, queue_async);
queue_async = ((void *)0);
(void)rpmsg_lite_deinit(rpmsg);
if (rpmsg == remote_rpmsg) {
remote_rpmsg = NULL;
}
if (rpmsg == master_rpmsg) {
master_rpmsg = NULL;
}
env_unlock_mutex(ept_sync_lock);
env_delete_mutex(ept_sync_lock);
ept_sync_lock = ((void *)0);
}
/************************************************************************************
* @fn rpmsg_recv_msg
*
* @brief Called by app layer to receive message from the other side in blocking mode.
*
* @param rpmsg: rpmsg-lite instance.
* @param msg: data storage address
* @param msg_len: message length
*
* @return the endpoint address used by the other side to send this message
*/
uint32_t rpmsg_recv_msg(struct rpmsg_lite_instance *rpmsg, struct rpmsg_msg_t **msg, uint32_t *msg_len)
{
uint32_t src_addr;
rpmsg_queue_recv_nocopy(rpmsg, queue_async, (uint32_t *)&src_addr, (char **)msg, msg_len, RL_BLOCK);
return src_addr;
}
/************************************************************************************
* @fn rpmsg_get_remote_instance
*
* @brief Called by other module to get created remote_rpmsg instance.
*
* @return remote rpmsg instance
*/
struct rpmsg_lite_instance *rpmsg_get_remote_instance(void)
{
return remote_rpmsg;
}
/************************************************************************************
* @fn rpmsg_get_master_instance
*
* @brief Called by other module to get created master_rpmsg instance.
*
* @return master rpmsg instance
*/
struct rpmsg_lite_instance *rpmsg_get_master_instance(void)
{
return master_rpmsg;
}
static int32_t rpmsg_queue_rx_tmp(void *payload, uint32_t payload_len, uint32_t src, void *priv)
{
struct rpmsg_msg_t *msg = payload;
if ((src == EPT_ADDR_SYNC) && (msg->msg_type == RPMSG_MSG_TYPE_MASTER_READY)) {
ept_sync->rx_cb = rpmsg_queue_rx_cb;
rpmsg_lite_release_rx_buffer_dur_recover(rpmsg_get_remote_instance(), msg);
}
return 0;
}
/************************************************************************************
* @fn rpmsg_remote_recover
*
* @brief In wake up procedure, this function is used to recover rpmsg. This function
* should be called before interrupt is enabled.
*/
void rpmsg_remote_recover(void)
{
GLOBAL_INT_DISABLE();
rpmsg_lite_remote_env_reset(rpmsg_get_remote_instance());
ept_sync->rx_cb = rpmsg_queue_rx_tmp;
while (ept_sync->rx_cb == rpmsg_queue_rx_tmp) {
void ipc_mcu_irq(void);
ipc_mcu_irq();
}
GLOBAL_INT_RESTORE();
}
//void rpmsg_task(void *arg)
//{
// struct rpmsg_msg_t *msg;
// uint32_t msg_len;
// uint32_t src_addr;
// while (1) {
// rpmsg_queue_recv_nocopy(arg, queue_async, (uint32_t *)&src_addr, (char **)&msg, &msg_len, RL_BLOCK);
//
// if (msg_callback) {
// msg_callback(arg, msg);
// }
// }
//}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
#include "rpmsg_lite.h"
#include "rpmsg_ns.h"
#include <stdint.h>
#define RL_NS_NAME_SIZE (32)
/*!
* struct rpmsg_ns_msg - dynamic name service announcement message
* @name: name of remote service that is published
* @addr: address of remote service that is published
* @flags: indicates whether service is created or destroyed
*
* This message is sent across to publish a new service, or announce
* about its removal. When we receive these messages, an appropriate
* rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
* or ->remove() handler of the appropriate rpmsg driver will be invoked
* (if/as-soon-as one is registered).
*/
RL_PACKED_BEGIN
struct rpmsg_ns_msg
{
char name[RL_NS_NAME_SIZE];
uint32_t addr;
uint32_t flags;
} RL_PACKED_END;
/*!
* @brief
* Nameservice callback, called in interrupt context
*
* @param payload Pointer to the buffer containing received data
* @param payload_len Size of data received, in bytes
* @param src Pointer to address of the endpoint from which data is received
* @param priv Private data provided during endpoint creation
*
* @return RL_RELEASE, message is always freed
*
*/
static int32_t rpmsg_ns_rx_cb(void *payload, uint32_t payload_len, uint32_t src, void *priv)
{
struct rpmsg_ns_msg *ns_msg_ptr = payload;
struct rpmsg_ns_callback_data *cb_ctxt = priv;
RL_ASSERT(priv != RL_NULL);
RL_ASSERT(cb_ctxt->cb != RL_NULL);
/* Drop likely bad messages received at nameservice address */
if (payload_len == sizeof(struct rpmsg_ns_msg))
{
cb_ctxt->cb(ns_msg_ptr->addr, ns_msg_ptr->name, ns_msg_ptr->flags, cb_ctxt->user_data);
}
return RL_RELEASE;
}
#if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
rpmsg_ns_handle rpmsg_ns_bind(struct rpmsg_lite_instance *rpmsg_lite_dev,
rpmsg_ns_new_ept_cb app_cb,
void *user_data,
rpmsg_ns_static_context *ns_ept_ctxt)
#else
rpmsg_ns_handle rpmsg_ns_bind(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_ns_new_ept_cb app_cb, void *user_data)
#endif /* RL_USE_STATIC_API */
{
struct rpmsg_ns_context *ns_ctxt;
if (app_cb == RL_NULL)
{
return RL_NULL;
}
#if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
if (ns_ept_ctxt == RL_NULL)
{
return RL_NULL;
}
ns_ctxt = &ns_ept_ctxt->ns_ctxt;
/* Set-up the nameservice callback context */
ns_ept_ctxt->cb_ctxt.user_data = user_data;
ns_ept_ctxt->cb_ctxt.cb = app_cb;
ns_ctxt->cb_ctxt = &ns_ept_ctxt->cb_ctxt;
ns_ctxt->ept = rpmsg_lite_create_ept(rpmsg_lite_dev, RL_NS_EPT_ADDR, rpmsg_ns_rx_cb, (void *)ns_ctxt->cb_ctxt,
&ns_ept_ctxt->ept_ctxt);
#else
{
struct rpmsg_ns_callback_data *cb_ctxt;
cb_ctxt = env_allocate_memory(sizeof(struct rpmsg_ns_callback_data));
if (cb_ctxt == RL_NULL)
{
return RL_NULL;
}
ns_ctxt = env_allocate_memory(sizeof(struct rpmsg_ns_context));
if (ns_ctxt == RL_NULL)
{
env_free_memory(cb_ctxt);
return RL_NULL;
}
/* Set-up the nameservice callback context */
cb_ctxt->user_data = user_data;
cb_ctxt->cb = app_cb;
ns_ctxt->cb_ctxt = cb_ctxt;
ns_ctxt->ept = rpmsg_lite_create_ept(rpmsg_lite_dev, RL_NS_EPT_ADDR, rpmsg_ns_rx_cb, (void *)ns_ctxt->cb_ctxt);
}
#endif /* RL_USE_STATIC_API */
return (rpmsg_ns_handle)ns_ctxt;
}
int32_t rpmsg_ns_unbind(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_ns_handle handle)
{
struct rpmsg_ns_context *ns_ctxt = (struct rpmsg_ns_context *)handle;
#if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
return rpmsg_lite_destroy_ept(rpmsg_lite_dev, ns_ctxt->ept);
#else
{
int32_t retval;
retval = rpmsg_lite_destroy_ept(rpmsg_lite_dev, ns_ctxt->ept);
env_free_memory(ns_ctxt->cb_ctxt);
env_free_memory(ns_ctxt);
return retval;
}
#endif
}
int32_t rpmsg_ns_announce(struct rpmsg_lite_instance *rpmsg_lite_dev,
struct rpmsg_lite_endpoint *new_ept,
const char *ept_name,
uint32_t flags)
{
struct rpmsg_ns_msg ns_msg;
if (ept_name == RL_NULL)
{
return RL_ERR_PARAM;
}
if (new_ept == RL_NULL)
{
return RL_ERR_PARAM;
}
env_strncpy(ns_msg.name, ept_name, RL_NS_NAME_SIZE);
ns_msg.flags = flags;
ns_msg.addr = new_ept->addr;
return rpmsg_lite_send(rpmsg_lite_dev, new_ept, RL_NS_EPT_ADDR, (char *)&ns_msg, sizeof(struct rpmsg_ns_msg),
RL_BLOCK);
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* Copyright (c) 2015 Xilinx, Inc.
* Copyright (c) 2016 Freescale Semiconductor, Inc.
* Copyright 2016-2019 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.
*/
#include "rpmsg_lite.h"
#include "rpmsg_queue.h"
typedef struct
{
uint32_t src;
void *data;
uint32_t len;
} rpmsg_queue_rx_cb_data_t;
int32_t rpmsg_queue_rx_cb(void *payload, uint32_t payload_len, uint32_t src, void *priv)
{
rpmsg_queue_rx_cb_data_t msg;
RL_ASSERT(priv != RL_NULL);
msg.data = payload;
msg.len = payload_len;
msg.src = src;
/* if message is successfully added into queue then hold rpmsg buffer */
if (0 != env_put_queue(priv, &msg, 0))
{
/* hold the rx buffer */
return RL_HOLD;
}
return RL_RELEASE;
}
rpmsg_queue_handle rpmsg_queue_create(struct rpmsg_lite_instance *rpmsg_lite_dev)
{
int32_t status;
void *q = RL_NULL;
if (rpmsg_lite_dev == RL_NULL)
{
return RL_NULL;
}
/* create message queue for channel default endpoint */
status = env_create_queue(&q, (int32_t)rpmsg_lite_dev->rvq->vq_nentries, (int32_t)sizeof(rpmsg_queue_rx_cb_data_t));
if ((status != 0) || (q == RL_NULL))
{
return RL_NULL;
}
return ((rpmsg_queue_handle)q);
}
int32_t rpmsg_queue_destroy(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_queue_handle q)
{
if (rpmsg_lite_dev == RL_NULL)
{
return RL_ERR_PARAM;
}
if (q == RL_NULL)
{
return RL_ERR_PARAM;
}
env_delete_queue((void *)q);
return RL_SUCCESS;
}
int32_t rpmsg_queue_recv(struct rpmsg_lite_instance *rpmsg_lite_dev,
rpmsg_queue_handle q,
uint32_t *src,
char *data,
uint32_t maxlen,
uint32_t *len,
uint32_t timeout)
{
rpmsg_queue_rx_cb_data_t msg = {0};
int32_t retval = RL_SUCCESS;
if (rpmsg_lite_dev == RL_NULL)
{
return RL_ERR_PARAM;
}
if (q == RL_NULL)
{
return RL_ERR_PARAM;
}
if (data == RL_NULL)
{
return RL_ERR_PARAM;
}
/* Get an element out of the message queue for the selected endpoint */
if (0 != env_get_queue((void *)q, &msg, timeout))
{
if (src != RL_NULL)
{
*src = msg.src;
}
if (len != RL_NULL)
{
*len = msg.len;
}
if (maxlen >= msg.len)
{
env_memcpy(data, msg.data, msg.len);
}
else
{
retval = RL_ERR_BUFF_SIZE;
}
/* Release used buffer. */
return ((RL_SUCCESS == rpmsg_lite_release_rx_buffer(rpmsg_lite_dev, msg.data)) ? retval : RL_ERR_PARAM);
}
else
{
return RL_ERR_NO_BUFF; /* failed */
}
}
int32_t rpmsg_queue_recv_nocopy(struct rpmsg_lite_instance *rpmsg_lite_dev,
rpmsg_queue_handle q,
uint32_t *src,
char **data,
uint32_t *len,
uint32_t timeout)
{
rpmsg_queue_rx_cb_data_t msg = {0};
if (rpmsg_lite_dev == RL_NULL)
{
return RL_ERR_PARAM;
}
if (data == RL_NULL)
{
return RL_ERR_PARAM;
}
if (q == RL_NULL)
{
return RL_ERR_PARAM;
}
/* Get an element out of the message queue for the selected endpoint */
if (0 != env_get_queue((void *)q, &msg, timeout))
{
if (src != RL_NULL)
{
*src = msg.src;
}
if (len != RL_NULL)
{
*len = msg.len;
}
*data = msg.data;
return RL_SUCCESS; /* success */
}
return RL_ERR_NO_BUFF; /* failed */
}
int32_t rpmsg_queue_nocopy_free(struct rpmsg_lite_instance *rpmsg_lite_dev, void *data)
{
if (rpmsg_lite_dev == RL_NULL)
{
return RL_ERR_PARAM;
}
if (data == RL_NULL)
{
return RL_ERR_PARAM;
}
/* Release used buffer. */
return ((RL_SUCCESS == rpmsg_lite_release_rx_buffer(rpmsg_lite_dev, data)) ? RL_SUCCESS : RL_ERR_PARAM);
}
int32_t rpmsg_queue_get_current_size(rpmsg_queue_handle q)
{
if (q == RL_NULL)
{
return RL_ERR_PARAM;
}
/* Return actual queue size. */
return env_get_current_queue_size((void *)q);
}