diff --git a/src/platform/cc13xx_26xx/icall_FreeRTOS.c b/src/platform/cc13xx_26xx/icall_FreeRTOS.c
deleted file mode 100644
index 1711f2882986ce..00000000000000
--- a/src/platform/cc13xx_26xx/icall_FreeRTOS.c
+++ /dev/null
@@ -1,4124 +0,0 @@
-/******************************************************************************
- @file icall_FreeRTOS.c
-
- @brief Indirect function Call dispatcher implementation on top of OS.
-
- This implementation uses heapmgr.h to implement a simple heap with low
- memory overhead but large processing overhead.
- The size of the heap is determined with HEAPMGR_SIZE macro, which can
- be overridden with a compile option.
- Note: The ICall layer (e.g. this file) is using TI internal implementation of POSIX.
- For now, the ICall layer is not supports using outer POSIX on the application layer.
-
- Group: WCS, LPC, BTS
- Target Device: cc13xx_cc26xx
-
- ******************************************************************************
-
- Copyright (c) 2013-2024, Texas Instruments Incorporated
- 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 Texas Instruments Incorporated 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 OWNER 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.
-
- ******************************************************************************
-
-
- *****************************************************************************/
-
-#ifdef FREERTOS
-#include
-#include
-#include "bget.h"
-#endif
-
-
-#ifdef FREERTOS
-#include
-#include
-#include
-#endif
-
-
-#include
-#include
-#define Hwi_disable HwiP_disable
-#define Hwi_restore HwiP_restore
-#define Hwi_disableinterrupt HwiP_disableInterrupt
-#define Hwi_enableinterrupt HwiP_enableInterrupt
-#define Swi_restore SwiP_restore
-#define Swi_disable SwiP_disable
-#define BIOS_WAIT_FOREVER (~(0U))
-#define BIOS_NO_WAIT (0U)
-
-#include "osal.h"
-#include "icall.h"
-#include "icall_platform.h"
-#include
-#include
-
-
-
-#ifndef ICALL_FEATURE_SEPARATE_IMGINFO
-#include
-#endif /* ICALL_FEATURE_SEPARATE_IMGINFO */
-
-
-//typedef uint32_t * Task_Handle;
-
-
-#ifndef Task_self
-#define Task_self ICall_taskSelf
-#endif
-
-
-#ifndef ICALL_MAX_NUM_ENTITIES
-/**
- * Maximum number of entities that use ICall, including service entities
- * and application entities.
- * The value may be overridden by a compile option.
- * Note that there are at least,
- * Primitive service, Stack services along with potentially generic
- * framework service for the stack thread.
- */
-#define ICALL_MAX_NUM_ENTITIES 6
-#endif
-
-#ifndef ICALL_MAX_NUM_TASKS
-/**
- * Maximum number of threads which include entities.
- * The value may be overridden by a compile option.
- */
-#define ICALL_MAX_NUM_TASKS 2
-#endif
-
-/**
- * @internal
- * Service class value used to indicate an invalid (unused) entry
- */
-#define ICALL_SERVICE_CLASS_INVALID_ENTRY 0x0000
-
-/**
- * @internal
- * Service class value used to indicate an entry for an application entity
- */
-#define ICALL_SERVICE_CLASS_APPLICATION ICALL_SERVICE_CLASS_MASK
-
-/**
- * @internal
- * Primitive service entity ID
- */
-#define ICALL_PRIMITIVE_ENTITY_ID 0
-
-/**
- * @internal
- * Accessor macro to get a header field (next) from a message pointer
- */
-#define ICALL_MSG_NEXT(_p) (((ICall_MsgHdr *)(_p) - 1)->next)
-
-/**
- * @internal
- * Accessor macro to get a header field (dest_id) from a message pointer
- */
-#define ICALL_MSG_DEST_ID(_p) (((ICall_MsgHdr *)(_p) - 1)->dest_id)
-
-
-#ifndef ICALL_TIMER_TASK_STACK_SIZE
-/**
- * @internal
- * Timer thread stack size
- */
-#define ICALL_TIMER_TASK_STACK_SIZE (512)
-#endif //ICALL_TIMER_TASK_STACK_SIZE
-
-/**
- * @internal
- * Creation of the synchronous object between application and service
- */
-
-#ifdef ICALL_EVENTS
-#define ICALL_SYNC_HANDLE_CREATE() (Event_create(NULL, NULL))
-#else /* ICALL_EVENTS */
-#define ICALL_SYNC_HANDLE_CREATE() (Semaphore_create(0, NULL, NULL))
-#endif /* ICALL_EVENTS */
-
-
-/**
- * @internal
- * post the synchronous object between application and service
- */
-#ifdef ICALL_EVENTS
-#define ICALL_SYNC_HANDLE_POST(x) (Event_post(x, ICALL_MSG_EVENT_ID))
-#define ICALL_SYNC_HANDLE_POST_WM(x) (Event_post(x, ICALL_WAITMATCH_EVENT_ID))
-#else /* ICALL_EVENTS */
-#define ICALL_SYNC_HANDLE_POST(x) (Semaphore_post(x))
-#define ICALL_SYNC_HANDLE_POST_WM(x) (Semaphore_post(x)) /* Semaphore does not have event ID */
-#endif /* ICALL_EVENTS */
-
-
-/**
- * @internal
- * pend for the synchronous object between application and service
- */
-#ifdef ICALL_EVENTS
-#define ICALL_SYNC_HANDLE_PEND(x, t) (Event_pend(x, 0, ICALL_MSG_EVENT_ID ,t))
-#define ICALL_SYNC_HANDLE_PEND_WM(x, t) (Event_pend(x, 0, ICALL_WAITMATCH_EVENT_ID, t))
-#else /* ICALL_EVENTS */
-#define ICALL_SYNC_HANDLE_PEND(x, t) (Semaphore_pend(x, t))
-#define ICALL_SYNC_HANDLE_PEND_WM(x, t) (Semaphore_pend(x, t)) /* Semaphore does not have event ID */
-#endif /* ICALL_EVENTS */
-
-/**
- * @internal
- * ticks
- */
-#define CLOCK_TICKS_PERIOD (10)
-
-
-/**
- * @internal
- * Data structure used to access critical section
- * state variable.
- * Without this data structure, C code will violate
- * C89 or C99 strict aliasing rule.
- */
-typedef union _icall_cs_state_union_t
-{
- /** critical section variable as declared in the interface */
- ICall_CSState state;
- /** @internal field used to access internal data */
- struct _icall_cs_state_aggr_t
- {
- /** field to store Swi_disable() return value */
- uint_least16_t swikey;
- /** field to store Hwi_disable() return value */
- uint_least16_t hwikey;
- } each;
-} ICall_CSStateUnion;
-
-/**
- * @internal Primitive service handler function type
- */
-typedef ICall_Errno (*ICall_PrimSvcFunc)(ICall_FuncArgsHdr *);
-
-#ifdef ICALL_FEATURE_SEPARATE_IMGINFO
-/* Image information shall be in separate module */
-
-/**
- * Array of entry function addresses of external images.
- *
- * Note that function address must be odd number for Thumb mode functions.
- */
-extern const ICall_RemoteTaskEntry ICall_imgEntries[];
-/**
- * Array of task priorities of external images.
- * One task is created per image to start off the image entry function.
- * Each element of this array correspond to the task priority of
- * each entry function defined in @ref ICall_imgEntries.
- */
-extern const int ICall_imgTaskPriorities[];
-
-/**
- * Array of task stack sizes of external images.
- * One task is created per image to start off the image entry function.
- * Each element of this array correspond to the task stack size of
- * each entry function defined in @ref ICall_imgEntries.
- */
-extern const size_t ICall_imgTaskStackSizes[];
-
-/**
- * Array of custom initialization parameters (pointers).
- * Each initialization parameter (pointer) is passed to each corresponding
- * image entry function defined in @ref ICall_imgEntries;
- */
-extern const void *ICall_imgInitParams[];
-
-/**
- * Number of external images.
- */
-extern const uint_least8_t ICall_numImages;
-
-#define icall_threadEntries ICall_imgEntries
-#define ICall_threadPriorities ICall_imgTaskPriorities
-#define ICall_threadStackSizes ICall_imgTaskStackSizes
-#define ICall_getInitParams(_i) (ICall_imgInitParams[i])
-#define ICALL_REMOTE_THREAD_COUNT ICall_numImages
-#else /* ICALL_FEATURE_SEPARATE_IMGINFO */
-/**
- * @internal
- * Array of entry function of external images.
- */
-static const ICall_RemoteTaskEntry icall_threadEntries[] = ICALL_ADDR_MAPS;
-
-/** @internal external image count */
-#define ICALL_REMOTE_THREAD_COUNT \
- (sizeof(icall_threadEntries)/sizeof(icall_threadEntries[0]))
-
-/** @internal thread priorities to be assigned to each remote thread */
-#ifndef BLE_STACK_TASK_PRIORITY
-static const int ICall_threadPriorities[] = {ICALL_TASK_PRIORITIES};
-#else
-static const int ICall_threadPriorities[] = {BLE_STACK_TASK_PRIORITY};
-#endif
-
-/** @internal thread stack max depth for each remote thread */
-static const size_t ICall_threadStackSizes[] = ICALL_TASK_STACK_SIZES;
-
-/** @internal initialization parameter (pointer) for each remote thread */
-#ifdef ICALL_CUSTOM_INIT_PARAMS
-static const void *ICall_initParams[] = ICALL_CUSTOM_INIT_PARAMS;
-#define ICall_getInitParams(_i) (ICall_initParams[i])
-#else /* ICALL_CUSTOM_INIT_PARAMS */
-#define ICall_getInitParams(_i) NULL
-#endif /* ICALL_CUSTOM_INIT_PARAMS */
-
-#endif /* ICALL_FEATURE_SEPARATE_IMGINFO */
-
-/** @internal message queue */
-typedef void *ICall_MsgQueue;
-
-/** @internal data structure about a task using ICall module */
-typedef struct _icall_task_entry_t
-{
- TaskHandle_t task;
- ICall_SyncHandle syncHandle;
- ICall_MsgQueue queue;
-} ICall_TaskEntry;
-
-/** @internal data structure about an entity using ICall module */
-typedef struct _icall_entity_entry_t
-{
- ICall_ServiceEnum service;
- ICall_TaskEntry *task;
- ICall_ServiceFunc fn;
-} ICall_entityEntry;
-
-/** @internal storage to track all tasks using ICall module */
-static ICall_TaskEntry ICall_tasks[ICALL_MAX_NUM_TASKS];
-
-/** @internal storage to track all entities using ICall module */
-static ICall_entityEntry ICall_entities[ICALL_MAX_NUM_ENTITIES];
-
-#ifndef FREERTOS
-extern mqd_t g_EventsQueueID;
-#endif
-/**
- * @internal
- * Wakeup schedule data structure definition
- */
-
-#ifdef FREERTOS
-void ICALL_Task_restore(UBaseType_t *OriginalParam);
-void ICALL_Task_disable(UBaseType_t *OriginalParam);
-#else
-
-void ICALL_Task_restore(struct sched_param *OriginalParam);
-void ICALL_Task_disable(struct sched_param *OriginalParam);
-#endif
-typedef struct _icall_schedule_t
-{
- ClockP_Handle clockP;
- ICall_TimerCback cback;
- void *arg;
-} ICall_ScheduleEntry;
-
-
-/* For now critical sections completely disable hardware interrupts
- * because they are used from ISRs in MAC layer implementation.
- * If MAC layer implementation changes, critical section
- * implementation may change to reduce overall interrupt latency.
- */
-/* Enter critical section implementation. See header file for comment. */
-ICall_CSState ICall_enterCSImpl(void)
-{
-
- ICall_CSStateUnion cu;
- cu.each.swikey = (uint_least16_t) Swi_disable();
- cu.each.hwikey = (uint_least16_t) Hwi_disable();
- return cu.state;
-}
-#ifdef FREERTOS
-TaskHandle_t ICall_taskSelf(void)
-#else
-Task_Handle ICall_taskSelf(void)
-#endif
-{
-
- TaskHandle_t task = NULL;
-#ifdef FREERTOS
- task = (TaskHandle_t) xTaskGetCurrentTaskHandle();
-#else
- task = ;
-#endif // FREERTOS
- return (task);
-}
-
-/* See header file for comment */
-ICall_EnterCS ICall_enterCriticalSection = ICall_enterCSImpl;
-
-/* leave critical section implementation. See header file for comment */
-void ICall_leaveCSImpl(ICall_CSState key)
-{
- ICall_CSStateUnion *cu = (ICall_CSStateUnion *) &key;
- Hwi_restore((uint32_t) cu->each.hwikey);
- Swi_restore((uint32_t) cu->each.swikey);
-}
-
-/* See header file for comment */
-ICall_LeaveCS ICall_leaveCriticalSection = ICall_leaveCSImpl;
-
-/* Implementing a simple heap using heapmgr.h template.
- * This simple heap depends on critical section implementation
- * and hence the template is used after critical section definition. */
-void *ICall_heapMalloc(uint32_t size);
-void *ICall_heapRealloc(void *blk, uint32_t size);
-void ICall_heapFree(void *blk);
-
-#define HEAPMGR_INIT ICall_heapInit
-#define HEAPMGR_MALLOC ICall_heapMalloc
-#define HEAPMGR_FREE ICall_heapFree
-#define HEAPMGR_REALLOC ICall_heapRealloc
-#define HEAPMGR_GETSTATS ICall_heapGetStats
-#define HEAPMGR_MALLOC_LIMITED ICall_heapMallocLimited
-
-void ICall_heapMgrGetMetrics(uint32_t *pBlkMax,
- uint32_t *pBlkCnt,
- uint32_t *pBlkFree,
- uint32_t *pMemAlo,
- uint32_t *pMemMax,
- uint32_t *pMemUB);
-#ifdef HEAPMGR_METRICS
-#define HEAPMGR_GETMETRICS ICall_heapMgrGetMetrics
-#endif
-
-#define HEAPMGR_LOCK() \
- do { ICall_heapCSState = ICall_enterCSImpl(); } while (0)
-#define HEAPMGR_UNLOCK() \
- do { ICall_leaveCSImpl(ICall_heapCSState); } while (0)
-#define HEAPMGR_IMPL_INIT()
-/* Note that a static variable can be used to contain critical section
- * state since heapmgr.h template ensures that there is no nested
- * lock call. */
-
-#if defined(HEAPMGR_CONFIG) && ((HEAPMGR_CONFIG == 0) || (HEAPMGR_CONFIG == 0x80))
-#include
-#elif defined(HEAPMGR_CONFIG) && ( (HEAPMGR_CONFIG == 1) || (HEAPMGR_CONFIG == 0x81))
-#include
-#elif defined(HEAPMGR_CONFIG) && ( (HEAPMGR_CONFIG == 2) || (HEAPMGR_CONFIG == 0x82))
-#include
-#elif defined(FREERTOS)
-#include "TI_heap_wrapper.h"
-#else
-static ICall_CSState ICall_heapCSState;
-#include
-#endif
-
-/**
- * @internal Searches for a task entry within @ref ICall_tasks.
- * @param taskhandle OS task handle
- * @return Pointer to task entry when found, or NULL.
- */
-static ICall_TaskEntry *ICall_searchTask(TaskHandle_t taskhandle)
-{
- size_t i;
- ICall_CSState key;
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
- {
- if (!ICall_tasks[i].task)
- {
- /* Empty slot */
- break;
- }
- if ((TaskHandle_t)taskhandle == (TaskHandle_t)ICall_tasks[i].task)
- {
- ICall_leaveCSImpl(key);
- return &ICall_tasks[i];
- }
- }
- ICall_leaveCSImpl(key);
- return NULL;
-}
-
-/**
- * @internal Searches for a task entry within @ref ICall_tasks or
- * build an entry if the entry table is empty.
- * @param taskhandle OS task handle
- * @return Pointer to task entry when found, or NULL.
- */
-
-static ICall_TaskEntry *ICall_newTask(TaskHandle_t taskhandle)
-{
- size_t i;
- ICall_CSState key;
-
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
- {
- if (!ICall_tasks[i].task)
- {
- /* Empty slot */
- ICall_TaskEntry *taskentry = &ICall_tasks[i];
- taskentry->task = taskhandle;
- taskentry->queue = NULL;
-
-#ifdef FREERTOS
- taskentry->syncHandle = xQueueCreate(20, sizeof(uint32_t));
-#endif
-
- if (taskentry->syncHandle == 0)
- {
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- }
-
- ICall_leaveCSImpl(key);
- return taskentry;
- }
- if (taskhandle == (TaskHandle_t)ICall_tasks[i].task)
- {
- ICall_leaveCSImpl(key);
- return &ICall_tasks[i];
- }
- }
- ICall_leaveCSImpl(key);
- return NULL;
-}
-
-/* See header file for comments. */
-ICall_EntityID ICall_searchServiceEntity(ICall_ServiceEnum service)
-{
- size_t i;
- ICall_CSState key;
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Empty slot */
- break;
- }
- if (service == ICall_entities[i].service)
- {
- ICall_leaveCSImpl(key);
- return (ICall_EntityID) i;
- }
- }
- ICall_leaveCSImpl(key);
- return ICALL_INVALID_ENTITY_ID;
-}
-
-/**
- * @internal Searches for a service entity entry.
- * @param service service id
- * @return Pointer to entity entry of the service or
- * NULL when none found.
- */
-static ICall_entityEntry *
-ICall_searchService(ICall_ServiceEnum service)
-{
- ICall_EntityID entity = ICall_searchServiceEntity(service);
- if (entity == ICALL_INVALID_ENTITY_ID)
- {
- return NULL;
- }
- return &ICall_entities[entity];
-}
-
-/* Dispatcher implementation. See ICall_dispatcher declaration
- * for comment. */
-static ICall_Errno ICall_dispatch(ICall_FuncArgsHdr *args)
-{
- ICall_entityEntry *entity;
-
- entity = ICall_searchService(args->service);
- if (!entity)
- {
- return ICALL_ERRNO_INVALID_SERVICE;
- }
- if (!entity->fn)
- {
- return ICALL_ERRNO_INVALID_FUNCTION;
- }
-
- return entity->fn(args);
-}
-
-/* See header file for comments */
-ICall_Dispatcher ICall_dispatcher = ICall_dispatch;
-
-/* Static instance of ICall_RemoteTaskArg to pass to
- * remote task entry function.
- * See header file for comments */
-static const ICall_RemoteTaskArg ICall_taskEntryFuncs =
-{
- ICall_dispatch,
- ICall_enterCSImpl,
- ICall_leaveCSImpl
-};
-
-/**
- * @internal Thread entry function wrapper that complies with
- * OS.
- * @param arg0 actual entry function
- * @param arg1 ignored
- */
-TaskHandle_t RemoteTask = NULL;
-
-//pthread_t RemoteTask;
-
-struct argsForPosixTaskStart
-{
- void *arg0;
- void *arg1;
-};
-struct argsForPosixTaskStart POSIX_args;
-
-typedef void (*TaskFunction_t)( void * );
-
-static void ICall_taskEntry(void *arg)
-
-{
- void * arg0 = ((struct argsForPosixTaskStart *)(arg))->arg0;
- void * arg1 = ((struct argsForPosixTaskStart *)(arg))->arg1;
-
- ICall_CSState key;
- key = ICall_enterCSImpl();
- if (ICall_newTask(ICall_taskSelf()) == NULL)
- {
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- }
- ICall_leaveCSImpl(key);
-
- /* Attempt to yield prior to running task */
- taskYIELD();
-
- ICall_RemoteTaskEntry entryfn = (ICall_RemoteTaskEntry) arg0;
-
- entryfn(&ICall_taskEntryFuncs, (void *) arg1);
-
- //return NULL;
-}
-
-#ifndef ICALL_JT
-/* forward reference */
-static void ICall_initPrim(void);
-#endif /* ICALL_JT */
-
-/* See header file for comments. */
-void ICall_init(void)
-{
- size_t i;
-
- for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
- {
- ICall_tasks[i].task = NULL;
- ICall_tasks[i].queue = NULL;
- }
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- ICall_entities[i].service = ICALL_SERVICE_CLASS_INVALID_ENTRY;
- }
-
-#ifndef ICALL_JT
- /* Initialize primitive service */
- ICall_initPrim();
-#else
- /* Initialize heap */
-#ifndef FREERTOS
- ICall_heapInit();
-#endif //FREERTOS
-#endif
-}
-
-
-/* See header file for comments */
-void ICall_createRemoteTasksAtRuntime(ICall_RemoteTask_t *remoteTaskTable, uint8_t nbElems)
-{
- size_t i;
- /* ICALL_Task_disable is a cheap locking mechanism to lock tasks
- * which may attempt to access the service call dispatcher
- * till all services are registered.
- */
- UBaseType_t OriginalParam;
- ICALL_Task_disable(&OriginalParam);
- for (i = 0; i < nbElems; i++)
- {
-#ifdef FREERTOS
- BaseType_t xReturned;
-
- /* Pass the args via external sturct (POSIX use only single arg) */
- POSIX_args.arg0 = (void*)remoteTaskTable[i].startupEntry;
- POSIX_args.arg1 = (void*)remoteTaskTable[i].ICall_imgInitParam;
-
- xReturned = xTaskCreate(
- ICall_taskEntry, /* Function that implements the task. */
- "x", /* Text name for the task. */
- remoteTaskTable[i].imgTaskStackSize / sizeof(uint32_t), /* Stack size in words, not bytes. */
- ( void * ) &POSIX_args, /* Parameter passed into the task. */
- remoteTaskTable[i].imgTaskPriority, /* Priority at which the task is created. */
- &RemoteTask ); /* Used to pass out the created task's handle. */
-
- if(xReturned == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
- {
- /* Creation of FreeRTOS task failed */
- while(1);
- }
- }
- ICALL_Task_restore(&OriginalParam);
-#endif
-}
-
-/* See header file for comments */
-void ICall_createRemoteTasks(void)
-{
- size_t i;
- ICall_RemoteTask_t remoteTaskTable[ICALL_REMOTE_THREAD_COUNT];
-
- for (i = 0; i < ICALL_REMOTE_THREAD_COUNT; i++)
- {
- remoteTaskTable[i].imgTaskPriority = ICall_threadPriorities[i];
- remoteTaskTable[i].imgTaskStackSize = ICall_threadStackSizes[i];
- remoteTaskTable[i].startupEntry = icall_threadEntries[i];
- remoteTaskTable[i].ICall_imgInitParam = (void *) ICall_getInitParams(i);
- }
- ICall_createRemoteTasksAtRuntime(remoteTaskTable, ICALL_REMOTE_THREAD_COUNT);
-}
-
-
-
-#ifdef FREERTOS
-void ICALL_Task_disable(UBaseType_t *OriginalParam)
-
-#else
-void ICALL_Task_disable(struct sched_param *OriginalParam)
-#endif
-{
-
-#ifdef FREERTOS
- TaskStatus_t pxTaskStatus;
- vTaskGetInfo(ICall_taskSelf(), &pxTaskStatus, pdFALSE, eInvalid);
- *OriginalParam = pxTaskStatus.uxCurrentPriority;
-
- vTaskPrioritySet(ICall_taskSelf(), configMAX_PRIORITIES - 1);
-#endif
-
-
-}
-#ifdef FREERTOS
-void ICALL_Task_restore(UBaseType_t *OriginalParam)
-#else
-void ICALL_Task_restore(struct sched_param *OriginalParam)
-#endif
-{
-
-#ifdef FREERTOS
- vTaskPrioritySet(ICall_taskSelf(), *OriginalParam);
-
-#else
- pthread_t pthreadID = pthread_self();
- pthread_setschedparam(pthreadID, 0, OriginalParam);
-#endif
-}
-
-
-/* See header file for comments */
-ICall_TaskHandle ICall_getRemoteTaskHandle(uint8 index)
-{
- TaskHandle_t *task = NULL;
-
-
- UBaseType_t OriginalParam;
- ICALL_Task_disable(&OriginalParam);
-
- if (index < ICALL_MAX_NUM_TASKS)
- {
- task = &ICall_tasks[index].task;
- }
-
- ICALL_Task_restore(&OriginalParam);
-
- return((ICall_TaskHandle)task);
-}
-
-/* Primitive service implementation follows */
-
-#ifndef ICALL_JT
-/**
- * @internal Enrolls a service
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when service id is already
- * registered by another entity.
- * @ref ICALL_ERRNO_NO_RESOURCE when maximum number of services
- * are already registered.
- */
-static ICall_Errno ICall_primEnroll(ICall_EnrollServiceArgs *args)
-{
- size_t i;
- ICall_TaskEntry *taskentry = ICall_newTask(Task_self());
- ICall_CSState key;
-
- /* Note that certain service does not handle a message
- * and hence, taskentry might be NULL.
- */
- if (taskentry == NULL)
- {
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Use this entry */
- ICall_entities[i].service = args->service;
- ICall_entities[i].task = taskentry;
- ICall_entities[i].fn = args->fn;
- args->entity = (ICall_EntityID) i;
- args->msgSyncHdl = taskentry->syncHandle;
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_SUCCESS;
- }
- else if (args->service == ICall_entities[i].service)
- {
- /* Duplicate service enrollment */
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
- }
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_NO_RESOURCE;
-
-}
-
-/**
- * @internal Registers an application
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- */
-static ICall_Errno ICall_primRegisterApp(ICall_RegisterAppArgs *args)
-{
- size_t i;
- ICall_TaskEntry *taskentry = ICall_newTask(Task_self());
- ICall_CSState key;
-
- if (!taskentry)
- {
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- return ICALL_ERRNO_NO_RESOURCE;
- }
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Use this entry */
- ICall_entities[i].service = ICALL_SERVICE_CLASS_APPLICATION;
- ICall_entities[i].task = taskentry;
- ICall_entities[i].fn = NULL;
- args->entity = (ICall_EntityID) i;
- args->msgSyncHdl = taskentry->syncHandle;
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_SUCCESS;
- }
- }
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_NO_RESOURCE;
-}
-
-/**
- * @internal Allocates memory block for a message.
- * @param args arguments
- */
-static ICall_Errno ICall_primAllocMsg(ICall_AllocArgs *args)
-{
- ICall_MsgHdr *hdr =
- (ICall_MsgHdr *) ICall_heapMalloc(sizeof(ICall_MsgHdr) + args->size);
-
- if (!hdr)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
- hdr->len = args->size;
- hdr->next = NULL;
- hdr->dest_id = ICALL_UNDEF_DEST_ID;
- args->ptr = (void *) (hdr + 1);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Frees the memory block allocated for a message.
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS
- */
-static ICall_Errno ICall_primFreeMsg(ICall_FreeArgs *args)
-{
- ICall_MsgHdr *hdr = (ICall_MsgHdr *) args->ptr - 1;
- ICall_heapFree(hdr);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * Allocates a memory block.
- * Note that this function is for use by ICall implementation.
- *
- * @param size size in bytes
- * @return pointer to the allocated memory block or NULL
- */
-void *ICall_mallocImpl(uint_fast16_t size)
-{
- return ICall_heapMalloc(size);
-}
-
-/**
- * Frees a memory block.
- * Note that this function is for use by ICall implementation.
- *
- * @param ptr pointer to the memory block
- */
-void ICall_freeImpl(void *ptr)
-{
- ICall_heapFree(ptr);
-}
-
-/**
- * @internal Allocates a memory block
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when memory block cannot
- * be allocated.
- */
-static ICall_Errno ICall_primMalloc(ICall_AllocArgs *args)
-{
- args->ptr = ICall_heapMalloc(args->size);
- if (args->ptr == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Frees a memory block
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS
- */
-static ICall_Errno ICall_primFree(ICall_FreeArgs *args)
-{
- ICall_heapFree(args->ptr);
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_JT */
-
-/**
- * @internal Queues a message to a message queue.
- * @param q_ptr message queue
- * @param msg_ptr message pointer
- */
-static void ICall_msgEnqueue( ICall_MsgQueue *q_ptr, void *msg_ptr )
-{
- void *list;
- ICall_CSState key;
-
- // Hold off interrupts
- key = ICall_enterCSImpl();
-
- ICALL_MSG_NEXT( msg_ptr ) = NULL;
- // If first message in queue
- if ( *q_ptr == NULL )
- {
- *q_ptr = msg_ptr;
- }
- else
- {
- // Find end of queue
- for ( list = *q_ptr; ICALL_MSG_NEXT( list ) != NULL;
- list = ICALL_MSG_NEXT( list ) );
-
- // Add message to end of queue
- ICALL_MSG_NEXT( list ) = msg_ptr;
- }
-
- // Re-enable interrupts
- ICall_leaveCSImpl(key);
-}
-
-/**
- * @internal Dequeues a message from a message queue
- * @param q_ptr message queue pointer
- * @return Dequeued message pointer or NULL if none.
- */
-static void *ICall_msgDequeue( ICall_MsgQueue *q_ptr )
-{
- void *msg_ptr = NULL;
- ICall_CSState key;
-
- // Hold off interrupts
- key = ICall_enterCSImpl();
-
- if ( *q_ptr != NULL )
- {
- // Dequeue message
- msg_ptr = *q_ptr;
- *q_ptr = ICALL_MSG_NEXT( msg_ptr );
- ICALL_MSG_NEXT( msg_ptr ) = NULL;
- ICALL_MSG_DEST_ID( msg_ptr ) = ICALL_UNDEF_DEST_ID;
- }
-
- // Re-enable interrupts
- ICall_leaveCSImpl(key);
-
- return msg_ptr;
-}
-
-/**
- * @internal Prepends a list of messages to a message queue
- * @param q_ptr message queue pointer
- * @param head message list to prepend
- */
-static void ICall_msgPrepend( ICall_MsgQueue *q_ptr, ICall_MsgQueue head )
-{
- void *msg_ptr = NULL;
- ICall_CSState key;
-
- // Hold off interrupts
- key = ICall_enterCSImpl();
-
- if ( head != NULL )
- {
- /* Find the end of the queue */
- msg_ptr = head;
- while (ICALL_MSG_NEXT( msg_ptr ) != NULL)
- {
- msg_ptr = ICALL_MSG_NEXT( msg_ptr );
- }
- ICALL_MSG_NEXT(msg_ptr) = *q_ptr;
- *q_ptr = head;
- }
-
- // Re-enable interrupts
- ICall_leaveCSImpl(key);
-}
-
-#ifndef ICALL_JT
-/**
- * @internal Sends a message to an entity.
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when either src
- * or dest is not a valid entity id or when
- * dest is an entity id of an entity that does
- * not receive a message
- * (e.g., ICall primitive service entity).
- */
-static ICall_Errno ICall_primSend(ICall_SendArgs *args)
-{
- ICall_CSState key;
- ICall_MsgHdr *hdr = (ICall_MsgHdr *) args->msg - 1;
-
- if (args->dest.entityId >= ICALL_MAX_NUM_ENTITIES ||
- args->src >= ICALL_MAX_NUM_ENTITIES)
- {
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
- key = ICall_enterCSImpl();
- if (!ICall_entities[args->dest.entityId].task)
- {
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
-
- ICall_leaveCSImpl(key);
- /* Note that once the entry is valid,
- * the value does not change and hence it is OK
- * to leave the critical section.
- */
-
- hdr->srcentity = args->src;
- hdr->dstentity = args->dest.entityId;
- hdr->format = args->format;
- ICall_msgEnqueue(&ICall_entities[args->dest.entityId].task->queue, args->msg);
- ICALL_SYNC_HANDLE_POST(ICall_entities[args->dest.entityId].task->syncHandle);
-
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Retrieves a message, queued to receive queue of the calling thread.
- *
- * @param args arguments
- * @return @ref ICALL_ERRNO_SUCCESS when a message was successfully
- * retrieved.
- * @ref ICALL_ERRNO_NOMSG when no message was queued to
- * the receive queue at the moment.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread
- * does not have a received queue associated with it.
- * This happens when neither ICall_enrollService() nor
- * ICall_registerApp() was ever called from the calling
- * thread.
- */
-static ICall_Errno ICall_primFetchMsg(ICall_FetchMsgArgs *args)
-{
- Task_Handle taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- ICall_MsgHdr *hdr;
-
- if (!taskentry)
- {
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- /* Successful */
- args->msg = ICall_msgDequeue(&taskentry->queue);
-
- if (args->msg == NULL)
- {
- return ICALL_ERRNO_NOMSG;
- }
- hdr = (ICall_MsgHdr *) args->msg - 1;
- args->src.entityId = hdr->srcentity;
- args->dest = hdr->dstentity;
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_JT */
-
-
-/**
- * @internal
- * Transforms and entityId into a serviceId.
- * @param entityId entity id
- * @param servId pointer to a variable to store
- * the resultant service id
- * @return @ICALL_ERRNO_SUCCESS if the transformation was successful.
- * @ICALL_ERRNO_INVALID_SERVICE if no matching service
- * is found for the entity id.
- */
-static ICall_Errno ICall_primEntityId2ServiceId(ICall_EntityID entityId,
- ICall_ServiceEnum *servId)
-{
- if (entityId >= ICALL_MAX_NUM_ENTITIES ||
- ICall_entities[entityId].service ==
- ICALL_SERVICE_CLASS_INVALID_ENTRY ||
- ICall_entities[entityId].service ==
- ICALL_SERVICE_CLASS_APPLICATION)
- {
- return ICALL_ERRNO_INVALID_SERVICE;
- }
- *servId = ICall_entities[entityId].service;
- return ICALL_ERRNO_SUCCESS;
-}
-
-#ifndef ICALL_JT
-/**
- * @internal Transforms and entityId into a serviceId.
- * @param args arguments
- * @return return values corresponding to those of ICall_entityId2ServiceId()
- */
-static ICall_Errno ICall_primE2S(ICall_EntityId2ServiceIdArgs *args)
-{
- return ICall_primEntityId2ServiceId(args->entityId, &args->servId);
-}
-
-/**
- * @internal Sends a message to a registered server.
- * @param args arguments corresponding to those of ICall_sendServiceMsg().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_SERVICE when the 'dest'
- * is unregistered service.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when the 'src'
- * is not a valid entity id or when 'dest' is
- * is a service that does not receive a message
- * (such as ICall primitive service).
- */
-static ICall_Errno ICall_primSendServiceMsg(ICall_SendArgs *args)
-{
- ICall_EntityID dstentity = ICall_searchServiceEntity(args->dest.servId);
-
- if (dstentity == ICALL_INVALID_ENTITY_ID)
- {
- return ICALL_ERRNO_INVALID_SERVICE;
- }
- args->dest.entityId = dstentity;
- return ICall_primSend(args);
-}
-
-/**
- * @internal Retrieves a message received at the message queue
- * associated with the calling thread.
- *
- * Note that this function should be used by an application
- * which does not expect any message from non-server entity.
- *
- * @param args arguments corresponding to those of ICall_fetchServiceMsg()
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- * and a message was retrieved.
- * @ref ICALL_ERRNO_NOMSG when there is no queued message
- * at the moment.
- * @ref ICALL_ERRNO_CORRUPT_MSG when a message queued in
- * front of the thread's receive queue was not sent by
- * a server. Note that in this case, the message is
- * not retrieved but thrown away.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
- * called from a thread which has not registered
- * an entity, either through ICall_enrollService()
- * or through ICall_registerApp().
- */
-static ICall_Errno ICall_primFetchServiceMsg(ICall_FetchMsgArgs *args)
-{
- ICall_ServiceEnum servId;
- ICall_Errno errno = ICall_primFetchMsg(args);
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- if (ICall_primEntityId2ServiceId(args->src.entityId, &servId) !=
- ICALL_ERRNO_SUCCESS)
- {
- /* Source entity ID cannot be translated to service id */
- ICall_freeMsg(args->msg);
- return ICALL_ERRNO_CORRUPT_MSG;
- }
- args->src.servId = servId;
-
-#ifdef ICALL_EVENTS
- /*
- * Because Events are binary flags, the task's queue must be checked for
- * any remaining messages. If there are the ICall event flag must be
- * re-posted due to it being cleared on the last pend.
- */
- ICall_primRepostSync();
-#endif //ICALL_EVENTS
- }
- return errno;
-}
-#endif /* ICALL_JT */
-/**
- * @internal
- * Converts milliseconds to number of ticks.
- * @param msecs milliseconds
- * @param ticks pointer to a variable to store the resultant number of ticks
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_INVALID_PARAMETER when conversion failed
- * as the input goes out of range for the output data type.
- */
-static ICall_Errno ICall_msecs2Ticks(uint_fast32_t msecs, uint32_t *ticks)
-{
- uint_fast64_t intermediate = msecs;
-
- /*convert to microSec*/
- intermediate *= 1000;
- /*divide with the ticks perios*/
- intermediate /= ICall_getTickPeriod();
- if (intermediate >= ((uint_fast64_t) 1 << (sizeof(uint32_t)*8 - 1)))
- {
- /* Out of range.
- * Note that we use only half of the range so that client can
- * determine whether the time has passed or time has yet to come.
- */
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
- *ticks = (uint32_t) intermediate;
- return ICALL_ERRNO_SUCCESS;
-}
-
-#ifndef ICALL_JT
-/**
- * @internal
- * Waits for a signal to the synchronization object associated with the calling
- * thread.
- *
- * Note that the synchronization object associated with a thread is signaled
- * when a message is queued to the message receive queue of the thread
- * or when ICall_signal() function is called onto the synchronization object.
- *
- * @param args arguments corresponding to those of ICall_wait().
- * @return @ref ICALL_ERRNO_SUCCESS when the synchronization object is
- * signaled.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the synchronization object being signaled.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when the milliseconds
- * is greater than the value of ICall_getMaxMSecs().
- */
-static ICall_Errno ICall_primWait(ICall_WaitArgs *args)
-{
- Task_Handle taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- uint32_t timeout;
-
- {
- BIOS_ThreadType threadtype = BIOS_getThreadType();
-
- if (threadtype == BIOS_ThreadType_Hwi ||
- threadtype == BIOS_ThreadType_Swi)
- {
- /* Blocking call is not allowed from Hwi or Swi.
- * Note that though theoretically, Swi or lower priority Hwi may block
- * on an event to be generated by a higher priority Hwi, it is not a
- * safe practice and hence it is disabled.
- */
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- }
-
- if (!taskentry)
- {
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- /* Successful */
- if (args->milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- /* Convert milliseconds to number of ticks */
- ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return errno;
- }
- }
-
- if (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
- {
- return ICALL_ERRNO_SUCCESS;
- }
-
- return ICALL_ERRNO_TIMEOUT;
-}
-
-/**
- * @internal signals a synchronziation object.
- * @param args arguments corresponding to those of ICall_signal()
- * @return return value corresponding to those of ICall_signal()
- */
-static ICall_Errno ICall_primSignal(ICall_SignalArgs *args)
-{
- ICALL_SYNC_HANDLE_POST(args->syncHandle);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal aborts program
- * @param args arguments corresponding to those of ICall_abort()
- * @return return value corresponding to those of ICall_abort()
- */
-static ICall_Errno ICall_primAbort(ICall_FuncArgsHdr *args)
-{
- ICALL_HOOK_ABORT_FUNC();
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Enables an interrupt.
- * @param args arguments corresponding to those of ICall_enableint()
- * @return return values corresponding to those of ICall_enableint()
- */
-static ICall_Errno ICall_primEnableint(ICall_intNumArgs *args)
-{
- Hwi_enableinterrupt(args->intnum);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Disables an interrupt.
- * @param args arguments corresponding to those of ICall_disableint()
- * @return return values corresponding to those of ICall_disableint()
- */
-static ICall_Errno ICall_primDisableint(ICall_intNumArgs *args)
-{
- Hwi_disableinterrupt(args->intnum);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Enables master interrupt and context switching.
- * @param args arguments corresponding to those of ICall_enableMint()
- * @return return values corresponding to those of ICall_enableMint()
- */
-static ICall_Errno ICall_primEnableMint(ICall_FuncArgsHdr *args)
-{
- Hwi_enable();
- Swi_enable();
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Disables master interrupt and context switching.
- * @param args arguments corresponding to those of ICall_disableMint()
- * @return return values corresponding to those of ICall_disableMint()
- */
-static ICall_Errno ICall_primDisableMint(ICall_FuncArgsHdr *args)
-{
- Swi_disable();
- Hwi_disable();
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal registers an interrupt service routine
- * @param args arguments corresponding to those of ICall_registerISR()
- * @return return values corresponding to those of ICall_registerISR()
- */
-static ICall_Errno ICall_primRegisterISR(ICall_RegisterISRArgs *args)
-{
- Hwi_Params hwiParams;
-
- Hwi_Params_init(&hwiParams);
- hwiParams.priority = 0xE0; // default all registered ints to lowest priority
-
- if (Hwi_create( args->intnum,
- (void (*)((void *)))args->isrfunc,
- &hwiParams,
- NULL) == NULL)
- {
- ICALL_HOOK_ABORT_FUNC();
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal registers an interrupt service routine
- * @param args arguments corresponding to those of ICall_registerISR_Ext()
- * @return return values corresponding to those of ICall_registerISR_ext()
- */
-static ICall_Errno ICall_primRegisterISR_Ext(ICall_RegisterISRArgs_Ext *args)
-{
- Hwi_Params hwiParams;
-
- Hwi_Params_init(&hwiParams);
- hwiParams.priority = args->intPriority;
-
- if (Hwi_create( args->intnum,
- (void (*)((void *)))args->isrfunc,
- &hwiParams,
- NULL) == NULL)
- {
- ICALL_HOOK_ABORT_FUNC();
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Gets tick counter value
- * @param args arguments corresponding to those of ICall_getTicks()
- * @return return values corresponding to those of ICall_getTicks()
- */
-static ICall_Errno ICall_primGetTicks(ICall_Getuint32_tArgs *args)
-{
- args->value = Clock_getTicks();
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_JT */
-
-/**
- * @internal
- * Clock event handler function.
- * This function is used to implement the wakeup scheduler.
- *
- * @param arg an @ref ICall_ScheduleEntry
- */
-
-static void ICall_clockFunc(uintptr_t arg)
-{
- ICall_ScheduleEntry *entry = (ICall_ScheduleEntry *) arg;
-
- entry->cback(entry->arg);
-}
-
-#ifndef ICALL_JT
-/**
- * @internal
- * Set up or restart a timer.
- *
- * @param args arguments corresponding to those of ICall_setTimer()
- * @return @ref ICALL_ERRNO_SUCCESS when successful;
- * @ref ICALL_ERRNO_INVALID_PARAMETER if timer designated by the
- * timer ID value was not set up before.
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- * Check ICall heap size and OS heap size if this happens.
- */
-static ICall_Errno ICall_primSetTimer(ICall_SetTimerArgs *args)
-{
- ICall_ScheduleEntry *entry;
-
- if (args->timerid == ICALL_INVALID_TIMER_ID)
- {
- Clock_Params params;
-
- /* Create a new timer */
- entry = ICall_heapMalloc(sizeof(ICall_ScheduleEntry));
- if (entry == NULL)
- {
- /* allocation failed */
- return ICALL_ERRNO_NO_RESOURCE;
- }
- Clock_Params_init(¶ms);
- params.startFlag = FALSE;
- params.period = 0;
- params.arg = ((void *)) entry;
- entry->clock = Clock_create(ICall_clockFunc,
- args->timeout,
- ¶ms, NULL);
- if (!entry->clock)
- {
- /* abort */
- ICall_abort();
- ICall_heapFree(entry);
- return ICALL_ERRNO_NO_RESOURCE;
- }
- entry->cback = args->cback;
- entry->arg = args->arg;
- args->timerid = (ICall_TimerID) entry;
- }
- else
- {
- ICall_CSState key;
-
- entry = (ICall_ScheduleEntry *) args->timerid;
-
- /* Critical section is entered to disable interrupts that might cause call
- * to callback due to race condition */
- key = ICall_enterCriticalSection();
- Clock_stop(entry->clock);
- entry->arg = args->arg;
- ICall_leaveCriticalSection(key);
- }
-
- Clock_setTimeout(entry->clock, args->timeout);
- Clock_start(entry->clock);
-
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal
- * Set up or restart a timer.
- *
- * @param args arguments corresponding to those of ICall_setTimerMSecs()
- * @return @ref ICALL_ERRNO_SUCCESS when successful;
- * @ref ICALL_ERRNO_INVALID_PARAMETER when msecs is greater than
- * maximum value supported.
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- * Check ICall heap size and OS heap size if this happens.
- */
-static ICall_Errno ICall_primSetTimerMSecs(ICall_SetTimerArgs *args)
-{
- uint32_t ticks;
- /* Convert to tick time */
- ICall_Errno errno = ICall_msecs2Ticks(args->timeout, &ticks);
-
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return errno;
- }
- args->timeout = ticks;
- return ICall_primSetTimer(args);
-}
-
-/**
- * @internal
- * Stops a timer.
- *
- * @param args arguments corresponding to those of ICall_stopTimer()
- *
- * @return @ref ICALL_ERRNO_SUCCESS when successful;
- * @ref ICALL_ERRNO_INVALID_PARAMETER
- * if id is @ref ICALL_INVALID_TIMER_ID.
- */
-static ICall_Errno ICall_primStopTimer(ICall_StopTimerArgs *args)
-{
- ICall_ScheduleEntry *entry = (ICall_ScheduleEntry *) args->timerid;
-
- if (args->timerid == ICALL_INVALID_TIMER_ID)
- {
- return ICALL_ERRNO_INVALID_PARAMETER;
- }
-
- Clock_stop(entry->clock);
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Gets tick period
- * @param args arguments corresponding to those of ICall_getTickPeriod()
- * @return return values corresponding to those of ICall_getTickPeriod()
- */
-static ICall_Errno ICall_primGetTickPeriod(ICall_Getuint32_tArgs *args)
-{
- args->value = Clock_tickPeriod;
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal Gets maximum period supported
- * @param args arguments corresponding to those of ICall_getMaxMSecs()
- * @return return values corresponding to those of ICall_getMaxMSecs()
- */
-static ICall_Errno ICall_primGetMaxMSecs(ICall_Getuint32_tArgs *args)
-{
- uint_fast64_t tmp = ((uint_fast64_t) 0x7ffffffful) * Clock_tickPeriod;
- tmp /= 1000;
- if (tmp >= 0x80000000ul)
- {
- tmp = 0x7ffffffful;
- }
- args->value = (uint_least32_t) tmp;
- return ICALL_ERRNO_SUCCESS;
-}
-
-/**
- * @internal
- * Waits for a message that matches comparison
- *
- * @param args arguments corresponding to those of ICall_waitMatch().
- * @return @ref ICALL_ERRNO_SUCCESS when the synchronization object is
- * signaled.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the semaphore being signaled.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when the milliseconds
- * is greater than the value of ICall_getMaxMSecs().
- */
-static ICall_Errno ICall_primWaitMatch(ICall_WaitMatchArgs *args)
-{
- Task_Handle taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- ICall_MsgQueue prependQueue = NULL;
-#ifndef ICALL_EVENTS
- uint_fast16_t consumedCount = 0;
-#endif
- uint32_t timeout;
- uint_fast32_t timeoutStamp;
- ICall_Errno errno;
-
- {
- BIOS_ThreadType threadtype = BIOS_getThreadType();
-
- if (threadtype == BIOS_ThreadType_Hwi ||
- threadtype == BIOS_ThreadType_Swi)
- {
- /* Blocking call is not allowed from Hwi or Swi.
- * Note that though theoretically, Swi or lower priority Hwi may block
- * on an event to be generated by a higher priority Hwi, it is not a
- * safe practice and hence it is disabled.
- */
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- }
-
- if (!taskentry)
- {
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- /* Successful */
- if (args->milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- /* Convert milliseconds to number of ticks */
- errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return errno;
- }
- }
-
- errno = ICALL_ERRNO_TIMEOUT;
- timeoutStamp = Clock_getTicks() + timeout;
- while (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
- {
- ICall_FetchMsgArgs fetchArgs;
- ICall_ServiceEnum servId;
- errno = ICall_primFetchMsg(&fetchArgs);
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- if (ICall_primEntityId2ServiceId(fetchArgs.src.entityId, &servId) ==
- ICALL_ERRNO_SUCCESS)
- {
- if (args->matchFn(servId, fetchArgs.dest, fetchArgs.msg))
- {
- /* Matching message found*/
- args->servId = servId;
- args->dest = fetchArgs.dest;
- args->msg = fetchArgs.msg;
- errno = ICALL_ERRNO_SUCCESS;
- break;
- }
- }
- /* Message was received but it wasn't expected one.
- * Add to the prepend queue */
- ICall_msgEnqueue(&prependQueue, fetchArgs.msg);
-#ifdef ICALL_EVENTS
- /* Event are binary semaphore, so if several messsages are posted while
- * we are processing one, it's possible that some of them are 'missed' and
- * not processed. Sending a event to ourself force this loop to run until
- * all the messages in the queue are processed.
- */
- ICALL_SYNC_HANDLE_POST(taskentry->syncHandle);
-#endif
- }
-
- /* Prepare for timeout exit */
- errno = ICALL_ERRNO_TIMEOUT;
-
-#ifndef ICALL_EVENTS
- /* Keep the decremented semaphore count */
- consumedCount++;
-#endif /* ICALL_EVENTS */
- if (timeout != BIOS_WAIT_FOREVER &&
- timeout != BIOS_NO_WAIT)
- {
- /* Readjust timeout */
- uint32_t newTimeout = timeoutStamp - Clock_getTicks();
- if (newTimeout == 0 || newTimeout > timeout)
- {
- break;
- }
- timeout = newTimeout;
- }
- }
-
-#ifdef ICALL_EVENTS
- /*
- * Because Events are binary semaphores, the task's queue must be checked for
- * any remaining messages. If there are, the ICall event flag must be
- * re-posted due to it being cleared on the last pend.
- */
- ICall_primRepostSync();
-#endif //ICALL_EVENTS
-
- /* Prepend retrieved irrelevant messages */
- ICall_msgPrepend(&taskentry->queue, prependQueue);
-#ifndef ICALL_EVENTS
- /* Re-increment the consumed semaphores */
- for (; consumedCount > 0; consumedCount--)
- {
- Semaphore_post(taskentry->syncHandle);
- }
-#endif /* ICALL_EVENTS */
- return errno;
-}
-
-/**
- * @internal
- * Retrieves an entity ID of an entity associated with the calling thread.
- *
- * @param args arguments corresponding to those of ICall_getEntityId().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when no entity was associated
- * with the calling thread.
- */
-static ICall_Errno ICall_primGetEntityId(ICall_GetEntityIdArgs *args)
-{
- Task_Handle taskhandle = Task_self();
- ICall_CSState key;
- size_t i;
-
- {
- BIOS_ThreadType threadtype = BIOS_getThreadType();
-
- if (threadtype == BIOS_ThreadType_Hwi ||
- threadtype == BIOS_ThreadType_Swi)
- {
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- }
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Not found */
- break;
- }
- if (ICall_entities[i].task->task == taskhandle)
- {
- /* Found */
- args->entity = i;
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_SUCCESS;
- }
- }
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_UNKNOWN_THREAD;
-}
-
-/**
- * @internal
- * Checks whether the calling thread provides the designated service.
- *
- * @param args arguments corresponding to those of ICall_threadServes().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread is
- * unrecognized.
- * @ref ICALL_ERRNO_INVALID_SERVICE if the service id is not enrolled
- * by any thread.
- */
-static ICall_Errno ICall_primThreadServes(ICall_ThreadServesArgs *args)
-{
- Task_Handle taskhandle;
- ICall_CSState key;
- size_t i;
-
- {
- BIOS_ThreadType threadtype = BIOS_getThreadType();
-
- if (threadtype == BIOS_ThreadType_Hwi ||
- threadtype == BIOS_ThreadType_Swi)
- {
- return ICALL_ERRNO_UNKNOWN_THREAD;
- }
- }
-
- taskhandle = Task_self();
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Not found */
- break;
- }
- else if (ICall_entities[i].service == args->servId)
- {
- args->result = (uint_fast8_t)
- (ICall_entities[i].task->task == taskhandle);
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_SUCCESS;
- }
- }
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_INVALID_SERVICE;
-}
-
-/**
- * @internal
- * Creates an RTOS task.
- *
- * @param args arguments corresponding to those of ICall_createTask().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
- */
-static ICall_Errno ICall_primCreateTask(ICall_CreateTaskArgs *args)
-{
- /* Task_Params is a huge structure.
- * To reduce stack usage, heap is used instead.
- * This implies that ICall_createTask() must be called before heap
- * space may be exhausted.
- */
- Task_Params *params = (Task_Params *) ICall_heapMalloc(sizeof(Task_Params));
- Task_Handle task;
-
- if (params == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
-
- Task_Params_init(params);
- params->priority = args->priority;
- params->stackSize = args->stacksize;
- params->arg0 = args->arg;
-
- task = Task_create((Task_FuncPtr) args->entryfn, params, NULL);
- ICall_heapFree(params);
-
- if (task == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_JT */
-
-#ifdef ICALL_RTOS_EVENT_API
-/**
- * @internal
- * Creates an event.
- *
- * @param args arguments corresponding to those of ICall_createEvent().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
- */
-static ICall_Errno ICall_primCreateEvent(ICall_CreateEventArgs *args)
-{
- args->event = Event_create(NULL, NULL);
-
- if (args->event == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_RTOS_EVENT_API */
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * @internal
- * Creates a semaphore.
- *
- * @param args arguments corresponding to those of ICall_createSemaphore().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
- */
-static ICall_Errno ICall_primCreateSemaphore(ICall_CreateSemaphoreArgs *args)
-{
- /* Semaphore_Params is a huge structure.
- * To reduce stack usage, heap is used instead.
- * This implies that ICall_createSemaphore() must be called before heap
- * space may be exhausted.
- */
- Semaphore_Params *semParams =
- (Semaphore_Params *) ICall_heapMalloc(sizeof(Semaphore_Params));
-
- if (semParams == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
-
- Semaphore_Params_init(semParams);
- if (args->mode == ICALL_SEMAPHORE_MODE_BINARY)
- {
- semParams->mode = Semaphore_Mode_BINARY;
- }
-
- args->sem = Semaphore_create(args->initcount, semParams, NULL);
- ICall_heapFree(semParams);
-
- if (args->sem == NULL)
- {
- return ICALL_ERRNO_NO_RESOURCE;
- }
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_RTOS_SEMAPHORE_API */
-#ifdef ICALL_RTOS_EVENT_API
-/**
- * @internal
- * Waits on a ICALL_MSG_EVENT_ID.
- *
- * @param args arguments corresponding to those of ICall_waitEvent().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_TIMEOUT when timeout occurred.
- */
-static ICall_Errno ICall_primWaitEvent(ICall_WaitEventArgs *args)
-{
- uint32_t timeout;
-
- if (args->milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return errno;
- }
- }
-
- if (Event_pend(args->event, 0, ICALL_MSG_EVENT_ID, timeout))
- {
- return ICALL_ERRNO_SUCCESS;
- }
- return ICALL_ERRNO_TIMEOUT;
-}
-#endif /* ICALL_RTOS_EVENT_API */
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * @internal
- * Waits on a semaphore.
- *
- * @param args arguments corresponding to those of ICall_waitSemaphore().
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_TIMEOUT when timeout occurred.
- */
-static ICall_Errno ICall_primWaitSemaphore(ICall_WaitSemaphoreArgs *args)
-{
- uint32_t timeout;
-
- if (args->milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return errno;
- }
- }
- if (Semaphore_pend(args->sem, timeout))
- {
- return ICALL_ERRNO_SUCCESS;
- }
- return ICALL_ERRNO_TIMEOUT;
-}
-#endif /* ICALL_RTOS_SEMAPHORE_API */
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * @internal signals a semaphore
- * @param args arguments corresponding to those of ICall_signal()
- * @return return value corresponding to those of ICall_signal()
- */
-static ICall_Errno ICall_primPostSemaphore(ICall_SignalArgs *args)
-{
- Semaphore_post(args->syncHandle);
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_RTOS_EVENT_API */
-#ifdef ICALL_RTOS_EVENT_API
-/**
- * @internal signals an event
- * @param args arguments corresponding to those of ICall_signal()
- * @return return value corresponding to those of ICall_signal()
- */
-static ICall_Errno ICall_primPostEvent(ICall_SignalEventsArgs *args)
-{
- Event_post(args->syncHandle, args->events);
- return ICALL_ERRNO_SUCCESS;
-}
-#endif /* ICALL_RTOS_EVENT_API */
-/**
- * @internal Primitive service function ID to handler function map
- */
-#ifndef ICALL_JT
-static const struct _icall_primsvcfunc_map_entry_t
-{
-#ifdef COVERAGE_TEST
- size_t id;
-#endif /* COVERAGE_TEST */
- ICall_PrimSvcFunc func;
-} ICall_primSvcFuncs[] =
-{
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_ENROLL,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primEnroll
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_REGISTER_APP,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primRegisterApp
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_MSG_ALLOC,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primAllocMsg
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_MSG_FREE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primFreeMsg
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_MALLOC,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primMalloc
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_FREE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primFree
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SEND_MSG,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primSend
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_FETCH_MSG,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primFetchMsg
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SEND_SERV_MSG,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primSendServiceMsg
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_FETCH_SERV_MSG,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primFetchServiceMsg
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primWait
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SIGNAL,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primSignal
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_ABORT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primAbort
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_ENABLE_int,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primEnableint
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_DISABLE_int,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primDisableint
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_ENABLE_Mint,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primEnableMint
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_DISABLE_Mint,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primDisableMint
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_REGISTER_ISR,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primRegisterISR
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_GET_TICKS,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primGetTicks
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SET_TIMER_MSECS,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primSetTimerMSecs
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_GET_TICK_PERIOD,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primGetTickPeriod
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_GET_MAX_MILLISECONDS,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primGetMaxMSecs
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_ENTITY2SERVICE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primE2S
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_UPD_ACTIVITY_COUNTER,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrUpdActivityCounter
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_REGISTER_NOTIFY,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrRegisterNotify
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_MATCH,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primWaitMatch
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_GET_ENTITY_ID,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primGetEntityId
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SET_TIMER,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primSetTimer
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_STOP_TIMER,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primStopTimer
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_CONFIG_AC_ACTION,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrConfigACAction
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_REQUIRE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrRequire
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_DISPENSE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrDispense
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_THREAD_SERVES,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primThreadServes
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_IS_STABLE_XOSC_HF,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrIsStableXOSCHF
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_GET_TRANSITION_STATE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrGetTransitionState
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_CREATE_TASK,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primCreateTask
- },
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_CREATE_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primCreateSemaphore
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primWaitSemaphore
- },
-
-#else /* ICALL_RTOS_SEMAPHORE_API */
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- NULL
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- NULL
- },
-#endif /* ICALL_RTOS_SEMAPHORE_API */
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_SWITCH_XOSC_HF,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrSwitchXOSCHF
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_PWR_GET_XOSC_STARTUP_TIME,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICallPlatform_pwrGetXOSCStartupTime
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_REGISTER_ISR_EXT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primRegisterISR_Ext
- },
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_POST_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primPostSemaphore
- },
-#else /*ICALL_RTOS_SEMAPHORE_API */
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_POST_SEMAPHORE,
-#endif /* COVERAGE_TEST */
- NULL
- }, /* ICALL_RTOS_SEMAPHORE_API */
-#endif
-
-#ifdef ICALL_RTOS_EVENT_API
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_CREATE_EVENT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primCreateEvent
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_EVENT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primWaitEvent
- },
-
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_POST_EVENT,
-#endif /* COVERAGE_TEST */
- (ICall_PrimSvcFunc) ICall_primPostEvent
- },
-#else /*ICALL_RTOS_EVENT_API */
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_CREATE_EVENT,
-#endif /* COVERAGE_TEST */
- NULL
- },
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_WAIT_EVENT,
-#endif /* COVERAGE_TEST */
- NULL
- }, /* ICALL_RTOS_EVENT_API */
- {
-#ifdef COVERAGE_TEST
- ICALL_PRIMITIVE_FUNC_POST_EVENT,
-#endif /* COVERAGE_TEST */
- NULL
- }, /* ICALL_RTOS_EVENT_API */
-#endif /* ICALL_RTOS_EVENT_API */
-};
-/**
- * @internal
- * Primitive service registered handler function
- * @param args arguments
- * @return error code
- */
-static ICall_Errno ICall_primService(ICall_FuncArgsHdr *args)
-{
- if (args->func >= sizeof(ICall_primSvcFuncs)/sizeof(ICall_primSvcFuncs[0]))
- {
- return ICALL_ERRNO_INVALID_FUNCTION;
- }
- return ICall_primSvcFuncs[args->func].func(args);
-}
-
-/**
- * @internal Enrolls primitive service
- */
-static void ICall_initPrim(void)
-{
- ICall_entities[0].service = ICALL_SERVICE_CLASS_PRIMITIVE;
- ICall_entities[0].fn = ICall_primService;
-
- /* Initialize heap */
- ICall_heapInit();
-
- /* TODO: Think about freezing permanently allocated memory blocks
- * for optimization.
- * Now that multiple stack images may share the same heap.
- * kick cannot be triggered by a single stack image.
- * Hence, maybe there should be an alternative API to
- * permanently allocate memory blocks, such as
- * by allocating the blocks at the end of the heap space. */
-}
-#endif /* ICALL_JT */
-
-#ifdef COVERAGE_TEST
-/**
- * @internal
- * Verification function for ICall implementation
- */
-void ICall_verify(void)
-{
- size_t i;
- for (i = 0; i < sizeof(ICall_primSvcFuncs)/sizeof(ICall_primSvcFuncs[0]); i++)
- {
- if (i != ICall_primSvcFuncs[i].id)
- {
- ICall_abort();
- }
- }
-}
-#endif /* COVERAGE_TEST */
-
-
-#ifdef ICALL_JT
-/**
- * Registers an application.
- * Note that this function must be called from the thread
- * from which ICall_wait() function will be called.
- *
- * @param entity pointer to a variable to store entity id assigned
- * to the application.
- * @param msgsem pointer to a variable to store the synchronous object handle
- * associated with the calling thread.
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- */
-ICall_Errno ICall_registerApp(ICall_EntityID *entity,
- ICall_SyncHandle *msgSyncHdl)
-{
-
- size_t i;
- ICall_TaskEntry *taskentry = ICall_newTask(Task_self());
- ICall_CSState key;
-
- if (!taskentry)
- {
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- return ICALL_ERRNO_NO_RESOURCE;
- }
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Use this entry */
- ICall_entities[i].service = ICALL_SERVICE_CLASS_APPLICATION;
- ICall_entities[i].task = taskentry;
- ICall_entities[i].fn = NULL;
- *entity = (ICall_EntityID) i;
- *msgSyncHdl = taskentry->syncHandle;
- ICall_leaveCSImpl(key);
- return ICALL_ERRNO_SUCCESS;
- }
- }
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_NO_RESOURCE);
-}
-
-/**
- * Allocates memory block for a message.
- * @param size size of the message body in bytes.
- * @return pointer to the start of the message body of the newly
- * allocated memory block, or NULL if the allocation
- * failed.
- */
-void *ICall_allocMsg(size_t size)
-{
- ICall_MsgHdr *hdr =
- (ICall_MsgHdr *) ICall_heapMalloc(sizeof(ICall_MsgHdr) + size);
-
- if (!hdr)
- {
- return NULL;
- }
- hdr->len = size;
- hdr->next = NULL;
- hdr->dest_id = ICALL_UNDEF_DEST_ID;
- return ((void *) (hdr + 1));
-
-}
-
-/**
- * Frees the memory block allocated for a message.
- * @param msg pointer to the start of the message body
- * which was returned from ICall_allocMsg().
- */
-void ICall_freeMsg(void *msg)
-{
- ICall_MsgHdr *hdr = (ICall_MsgHdr *) msg - 1;
- ICall_heapFree(hdr);
-}
-
-/**
- * Sends a message to a registered server.
- * @param src Entity id of the sender of the message
- * @param dest Service id
- * @param format Message format:
- * @ref ICALL_MSG_FORMAT_KEEP,
- * @ref ICALL_MSG_FORMAT_1ST_CHAR_TASK_ID or
- * @ref ICALL_MSG_FORMAT_3RD_CHAR_TASK_ID.
- * Message format indicates whether and which
- * field of the message must be transformed
- * into a implementation specific sender
- * identity for an external image.
- * When a service message interface is defined,
- * it may contain a field that is not understood
- * by the client but only understood by
- * the system on the server's side.
- * The format provides an information to the
- * messaging system on such a server
- * so that it can generically tag necessary
- * information to the message.
- * @param msg pointer to the message body to send.
- * Note that if message is successfully sent,
- * the caller should not reference the message any
- * longer.
- * However, if the function fails, the caller
- * still owns the reference to the message.
- * That is, caller may attempt another send,
- * or may free the memory block, etc.
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_SERVICE when the 'dest'
- * is unregistered service.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when the 'src'
- * is an out of range entity id or when 'dest' is
- * is a service that does not receive a message
- * (such as ICall primitive service).
- * Note that as far as 'src' is within the range,
- * this function won't notice the 'src' entity id
- * as invalid.
- */
-
-
-ICall_Errno
-ICall_sendServiceMsg(ICall_EntityID src,
- ICall_ServiceEnum dest,
- ICall_MSGFormat format, void *msg)
-{
- ICall_EntityID dstentity = ICall_searchServiceEntity(dest);
-
- if (dstentity == ICALL_INVALID_ENTITY_ID)
- {
- return ICALL_ERRNO_INVALID_SERVICE;
- }
- return (ICall_send(src, dstentity, format, msg));
-}
-
-/**
- * Retrieves a message received at the message queue
- * associated with the calling thread.
- *
- * Note that this function should be used by an application
- * which does not expect any message from non-server entity.
- *
- * @param src pointer to a variable to store the service id
- * of the registered server which sent the retrieved
- * message
- * @param dest pointer to a variable to store the entity id
- * of the destination of the message.
- * @param msg pointer to a pointer variable to store the
- * starting address of the message body being
- * retrieved.
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- * and a message was retrieved.
- * @ref ICALL_ERRNO_NOMSG when there is no queued message
- * at the moment.
- * @ref ICALL_ERRNO_CORRUPT_MSG when a message queued in
- * front of the thread's receive queue was not sent by
- * a server. Note that in this case, the message is
- * not retrieved but thrown away.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
- * called from a thread which has not registered
- * an entity, either through ICall_enrollService()
- * or through ICall_registerApp().
- */
-ICall_Errno
-ICall_fetchServiceMsg(ICall_ServiceEnum *src,
- ICall_EntityID *dest,
- void **msg)
-{
- ICall_ServiceEnum servId;
- ICall_Errno errno = ICall_fetchMsg((ICall_EntityID*)src, dest, msg);
-
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- if (ICall_primEntityId2ServiceId(*src, &servId) !=
- ICALL_ERRNO_SUCCESS)
- {
- /* Source entity ID cannot be translated to service id */
- ICall_freeMsg(*msg);
- return ICALL_ERRNO_CORRUPT_MSG;
- }
- *src = servId;
- }
- return (errno);
-
-}
-#if 0
-void convertMilliToTimepec(struct timespec *timeoutPosix,uint32_t timeout)
-{
- timeoutPosix->tv_sec = (timeout / 1000);
- timeout = timeout % 1000;
-
- /* 1 millisecond = 1 000 000 nanoseconds */
- timeoutPosix->tv_nsec = timeout * 1000000;
-}
-#endif
-
-
-/**
- * Waits for a signal to the semaphore associated with the calling thread.
- *
- * Note that the semaphore associated with a thread is signaled
- * when a message is queued to the message receive queue of the thread
- * or when ICall_signal() function is called onto the semaphore.
- *
- * @param milliseconds timeout period in milliseconds.
- * @return @ref ICALL_ERRNO_SUCCESS when the semaphore is signaled.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the semaphore being signaled.
- */
-ICall_Errno ICall_wait(uint_fast32_t milliseconds)
-{
- TaskHandle_t taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- uint32_t timeout;
- uint32_t event;
-
- int16_t retVal = 0;
-
- if (!taskentry)
- {
- return (ICALL_ERRNO_UNKNOWN_THREAD);
- }
- /* Successful */
- if (milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- /* Convert milliseconds to number of ticks */
- ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return (errno);
- }
- }
-
-#ifdef FREERTOS
- if (HwiP_inISR()) {
- xQueueReceiveFromISR(taskentry->syncHandle, (char*)&event, NULL);
- }
- else {
- xQueueReceive(taskentry->syncHandle, (char*)&event, milliseconds*100);
- }
-#endif
- if(retVal != (-1))
- {
- return (ICALL_ERRNO_SUCCESS);
- }
-
- return (ICALL_ERRNO_TIMEOUT);
-}
-
-/**
- * Signals a semaphore.
- * @param msgsem handle of a synchronous object to signal
- * @return @ref ICALL_ERRNO_SUCCESS
- */
-ICall_Errno ICall_signal(ICall_SyncHandle msgSyncHdl)
-{
- /* 0x80000000 is an internal Event_ID */
- uint32_t msg_ptr = 0x80000000;
- ICall_Errno status = ICALL_ERRNO_NO_RESOURCE;
-
-#ifdef FREERTOS
- uint8_t statusQ;
- if (HwiP_inISR()) {
- statusQ = xQueueSendFromISR(msgSyncHdl, (char*)&msg_ptr, NULL);
- }
- else {
- statusQ = xQueueSend(msgSyncHdl, (char*)&msg_ptr, 0);
- }
-
- if (statusQ == pdTRUE) {
- status = ICALL_ERRNO_SUCCESS;
- }
-#endif
- return (status);
-}
-
-/**
- * Registers a service entity
- * @param service service id of the enrolling service
- * @param fn handler function which handles function
- * calls to the service.
- * @param entity pointer to a variable to store the assigned entity id
- * @param msgsem pointer to a variable to store the synchronous object handle
- * associated with the calling thread.
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when service id is already
- * registered by another entity.
- * @ref ICALL_ERRNO_NO_RESOURCE when maximum number of services
- * are already registered.
- */
-ICall_Errno
-ICall_enrollService(ICall_ServiceEnum service,
- ICall_ServiceFunc fn,
- ICall_EntityID *entity,
- ICall_SyncHandle *msgSyncHdl)
-{
- size_t i;
- ICall_TaskEntry *taskentry = ICall_newTask(Task_self());
- ICall_CSState key;
-
- /* Note that certain service does not handle a message
- * and hence, taskentry might be NULL.
- */
- if (taskentry == NULL)
- {
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Use this entry */
- ICall_entities[i].service = service;
- ICall_entities[i].task = taskentry;
- ICall_entities[i].fn = fn;
- *entity = (ICall_EntityID) i;
- *msgSyncHdl = taskentry->syncHandle;
-
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_SUCCESS);
- }
- else if (service == ICall_entities[i].service)
- {
- /* Duplicate service enrollment */
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
- }
- /* abort */
- ICALL_HOOK_ABORT_FUNC();
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_NO_RESOURCE);
-
-}
-#ifdef FREERTOS
-
-/**
- * Allocates a memory block.
- * @param size size of the block in bytes.
- * @return address of the allocated memory block or NULL
- * if allocation fails.
- */
-
-void *ICall_heapMalloc(uint32_t size)
-{
- void* ret = NULL;
- ret = malloc(size);
- return ret;
-}
-
-/**
- * Frees an allocated memory block.
- * @param msg pointer to a memory block to free.
- */
-void ICall_heapFree(void *msg)
-{
- free(msg);
-}
-
-
-/**
- * Allocates a memory block, but check if enough memory will be left after the allocation.
- * @param size size of the block in bytes.
- * @return address of the allocated memory block or NULL
- * if allocation fails.
- */
-
-void *ICall_heapMallocLimited(uint_least16_t size)
-{
- return malloc(size);
-}
-
-/**
- * Get Statistic on Heap.
- * @param stats pointer to a heapStats_t structure.
- */
-
-/* Statistics currently are not supported via ICall apis.
- * Please consider to use bget statistics (or any of your internal heap statistics) */
-void ICall_heapGetStats(ICall_heapStats_t *pStats)
-{
-}
-
-#endif // FREERTOS
-/**
- * Allocates a memory block.
- * @param size size of the block in bytes.
- * @return address of the allocated memory block or NULL
- * if allocation fails.
- */
-void *ICall_malloc(uint_least16_t size)
-{
- return (ICall_heapMalloc(size));
-}
-
-/**
- * Frees an allocated memory block.
- * @param msg pointer to a memory block to free.
- */
-void ICall_free(void *msg)
-{
- ICall_heapFree(msg);
-}
-
-/**
- * Allocates a memory block, but check if enough memory will be left after the allocation.
- * @param size size of the block in bytes.
- * @return address of the allocated memory block or NULL
- * if allocation fails.
- */
-
-void *ICall_mallocLimited(uint_least16_t size)
-{
- return (ICall_heapMallocLimited(size));
-}
-
-/**
- * Get Statistic on Heap.
- * @param stats pointer to a heapStats_t structure.
- */
-void ICall_getHeapStats(ICall_heapStats_t *pStats)
-{
- ICall_heapGetStats(pStats);
-}
-
-
-#ifdef HEAPMGR_METRICS
-/**
- * @brief obtain heap usage metrics
- * @param pBlkMax pointer to a variable to store max cnt of all blocks ever seen at once
- * @param pBlkCnt pointer to a variable to store current cnt of all blocks
- * @param pBlkFree pointer to a variable to store current cnt of free blocks
- * @param pMemAlo pointer to a variable to store current total memory allocated
- * @param pMemMax pointer to a variable to store max total memory ever allocated at once
- * @param pMemUB pointer to a variable to store the upper bound of memory usage
- */
-void ICall_getHeapMgrGetMetrics(uint32_t *pBlkMax,
- uint32_t *pBlkCnt,
- uint32_t *pBlkFree,
- uint32_t *pMemAlo,
- uint32_t *pMemMax,
- uint32_t *pMemUB)
-{
- ICall_heapMgrGetMetrics( pBlkMax,
- pBlkCnt,
- pBlkFree,
- pMemAlo,
- pMemMax,
- pMemUB);
-}
-
-#endif
-/**
- * Sends a message to an entity.
- * @param src entity id of the sender
- * @param dest entity id of the destination of the message.
- * @param format message format. See ICall_sendServiceMsg().
- * @param msg pointer to the message body.
- * @return @ref ICALL_ERRNO_SUCCESS when successful.
- * @ref ICALL_ERRNO_INVALID_PARAMETER when either src
- * or dest is not a valid entity id or when
- * dest is an entity id of an entity that does
- * not receive a message
- * (e.g., ICall primitive service entity).
- */
-ICall_Errno ICall_send(ICall_EntityID src,
- ICall_EntityID dest,
- ICall_MSGFormat format,
- void *msg)
-{
- ICall_CSState key;
- ICall_MsgHdr *hdr = (ICall_MsgHdr *) msg - 1;
-
- if (dest >= ICALL_MAX_NUM_ENTITIES ||
- src >= ICALL_MAX_NUM_ENTITIES)
- {
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
- key = ICall_enterCSImpl();
- if (!ICall_entities[dest].task)
- {
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
-
- ICall_leaveCSImpl(key);
- /* Note that once the entry is valid,
- * the value does not change and hence it is OK
- * to leave the critical section.
- */
-
- hdr->srcentity = src;
- hdr->dstentity = dest;
- hdr->format = format;
-
- ICall_msgEnqueue(&ICall_entities[dest].task->queue, msg);
-/* 0x80000000 is an internal event number */
- uint32_t msg_ptr = 0x80000000;
-#ifdef FREERTOS
- uint8_t status;
-
- if (HwiP_inISR())
- {
- status = xQueueSendFromISR(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, NULL);
- }
- else
- {
- status = xQueueSend(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, 0);
- }
-
- if (status != pdPASS)
- {
- return status;
- }
-#endif
- return (ICALL_ERRNO_SUCCESS);
-}
-
-/**
- * Retrieves a message, queued to receive queue of the calling thread.
- *
- * @param src pointer to a variable to store the sender entity id
- * of the received message.
- * @param dest pointer to a variable to store the destination entity id
- * of the received message.
- * @param msg pointer to a pointer variable to store the starting
- * address of a received message body.
- * @return @ref ICALL_ERRNO_SUCCESS when a message was successfully
- * retrieved.
- * @ref ICALL_ERRNO_NOMSG when no message was queued to
- * the receive queue at the moment.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread
- * does not have a received queue associated with it.
- * This happens when neither ICall_enrollService() nor
- * ICall_registerApp() was ever called from the calling
- * thread.
- */
-ICall_Errno ICall_fetchMsg(ICall_EntityID *src,
- ICall_EntityID *dest,
- void **msg)
-{
- void *msgTemp;
- TaskHandle_t taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- ICall_MsgHdr *hdr;
-
- if (!taskentry)
- {
- return (ICALL_ERRNO_UNKNOWN_THREAD);
- }
- /* Successful */
- msgTemp = ICall_msgDequeue(&taskentry->queue);
-
- if (msgTemp == NULL)
- {
- return (ICALL_ERRNO_NOMSG);
- }
- hdr = (ICall_MsgHdr *) msgTemp - 1;
- *src = hdr->srcentity;
- *dest = hdr->dstentity;
- *msg = msgTemp;
- return (ICALL_ERRNO_SUCCESS);
-
-}
-
-/**
- * Transforms and entityId into a serviceId.
- * Note that this function is useful in case an application
- * waits for messages from both a server and another application,
- * in which case, the application can only use ICall_fetchMsg(),
- * not ICall_fetchServiceMsg() because the latter will return
- * @ref ICALL_ERRNO_CORRUPT_MSG when a message sent by the other
- * application is about to be fetched.
- * This function, then, is useful to retrieve service id
- * matching the source entity id in case the source entity
- * id is not that of the other application.
- *
- * @param entityId entity id
- * @param servId pointer to a variable to store
- * the resultant service id
- * @return @ref ICALL_ERRNO_SUCCESS if the transformation was successful.
- * @ref ICALL_ERRNO_INVALID_SERVICE if no matching service
- * is found for the entity id.
- */
-ICall_Errno ICall_entityId2ServiceId(ICall_EntityID entityId,
- ICall_ServiceEnum *servId)
-{
- return ICall_primEntityId2ServiceId(entityId, servId);
-}
-
-/**
- * Aborts.
- *
- * This is preferred over C runtime abort() function,
- * in an external image since the C runtime abort() is only
- * guaranteed in a root image which contains the C runtime
- * entry function that is executed upon startup.
- */
-ICall_Errno
-ICall_abort(void)
-{
-#ifdef HALNODEBUG
-#elif defined(EXT_HAL_ASSERT)
- HAL_ASSERT(HAL_ASSERT_CAUSE_ICALL_ABORT);
-#else
- {
- volatile uint8_t j=1;
- while(j);
- }
-#endif /* EXT_HAL_ASSERT */
- ICALL_HOOK_ABORT_FUNC();
- return(ICALL_ERRNO_SUCCESS);
-}
-
-/**
- * Enables interrupt.
- * @param intnum interrupt number
- * @return @ref ICALL_ERRNO_SUCCESS.
- */
-ICall_Errno
-ICall_enableint(int intnum)
-{
- Hwi_enableinterrupt(intnum);
- return (ICALL_ERRNO_SUCCESS);
-}
-
-/**
- * Disables interrupt
- * @param intnum interrupt number
- * @return @ref ICALL_ERRNO_SUCCESS
- */
-ICall_Errno
-ICall_disableint(int intnum)
-{
- Hwi_disableinterrupt(intnum);
- return (ICALL_ERRNO_SUCCESS);
-}
-
-
-
-/**
- * Gets the current tick counter value.
- * @return current tick counter value
- */
-uint_fast32_t
-ICall_getTicks(void)
-{
- return (ClockP_getSystemTicks());
-}
-
-/**
- * Gets the tick period.
- * @return tick period in microseconds.
- */
-uint_fast32_t
-ICall_getTickPeriod(void)
-{
- return CLOCK_TICKS_PERIOD;
-}
-
-/**
- * Gets the maximum timeout period supported by
- * ICall_setTimerMSecs() function.
- *
- * @return maximum timeout period in milliseconds
- */
-uint_fast32_t
-ICall_getMaxMSecs(void)
-{
-
- uint_fast64_t tmp = ((uint_fast64_t) 0x7ffffffful) * (ICall_getTickPeriod());
- tmp /= 1000;
- if (tmp >= 0x80000000ul)
- {
- tmp = 0x7ffffffful;
- }
- return ((uint_least32_t) tmp);
-}
-
-/**
- * Set up or restart a timer.
- * Note that the timer setup initially by this function may be restarted
- * using ICall_setTimer() function as well.
- *
- * @param msecs timeout period in milliseconds after which callback function
- * shall be called.
- * @param cback callback function pointer
- * @param arg argument to pass to the callback function
- * @param id pointer to the timer ID.
- * If a new timer must be set up, the value of the timer ID
- * must be set to @ref ICALL_INVALID_TIMER_ID when making this
- * call and when the function returns successfully, the variable
- * will be assigned a new timer ID value.
- * The value other than @ref ICALL_INVALID_TIMER_ID shall be
- * regarded as a request to restart the earlier set timer.
- * @return @ref ICALL_ERRNO_SUCCESS when successful;
- * @ref ICALL_ERRNO_INVALID_PARAMETER when msecs is greater than
- * maximum value supported;
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- * Check ICall heap size and OS heap size if this happens.
- *
- * @see ICall_getMaxMSecs()
- */
-ICall_Errno
-ICall_setTimerMSecs(uint_fast32_t msecs,
- ICall_TimerCback cback,
- void *arg,
- ICall_TimerID *id)
-{
- uint32_t ticks;
- uint32_t timeout;
- /* Convert to tick time */
- ICall_Errno errno = ICall_msecs2Ticks(msecs, &ticks);
-
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return (errno);
- }
- timeout = ticks;
- ICall_setTimer(timeout, cback, arg, id);
-
- return (errno);
-}
-
-/**
- * Set up or restart a timer.
- * Note that the timer setup initially by this function may be restarted
- * using ICall_setTimerMSecs() function as well.
- *
- * @param ticks timeout period in ticks after which the callback function
- * shall be called.
- * @param cback callback function pointer
- * @param arg argument to pass to the callback function
- * @param id pointer to the timer ID.
- * If a new timer must be set up, the value of the timer ID
- * must be set to @ref ICALL_INVALID_TIMER_ID when making this
- * call and when the function returns successfully, the variable
- * will be assigned a new timer ID value.
- * The value other than @ref ICALL_INVALID_TIMER_ID shall be
- * regarded as a request to restart the earlier set timer.
- * @return @ref ICALL_ERRNO_SUCCESS when successful;
- * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
- * Check ICall heap size and OS heap size if this happens.
- *
- * @see ICall_getTickPeriod()
- */
-
-
-ICall_Errno
-ICall_setTimer(uint32_t ticks,
- ICall_TimerCback cback,
- void *arg,
- ICall_TimerID *id)
-{
-
- ICall_ScheduleEntry *entry;
-
- if (*id == ICALL_INVALID_TIMER_ID)
- {
- ClockP_Params params;
-
- /* Create a new timer */
- entry = ICall_heapMalloc(sizeof(ICall_ScheduleEntry));
- if (entry == NULL)
- {
- /* allocation failed */
- return (ICALL_ERRNO_NO_RESOURCE);
- }
- ClockP_Params_init(¶ms);
- params.startFlag = FALSE;
- params.period = 0;
- params.arg = (uintptr_t) entry;
-
- entry->clockP = ClockP_create(ICall_clockFunc,
- ticks,
- ¶ms);
- if (!entry->clockP)
- {
- /* abort */
- ICall_abort();
- ICall_heapFree(entry);
- return (ICALL_ERRNO_NO_RESOURCE);
- }
- entry->cback = cback;
- entry->arg = arg;
- *id = (ICall_TimerID) entry;
- }
- else
- {
- ICall_CSState key;
-
- entry = (ICall_ScheduleEntry *) *id;
-
- /* Critical section is entered to disable interrupts that might cause call
- * to callback due to race condition */
- key = ICall_enterCriticalSection();
- ClockP_stop(entry->clockP);
- entry->arg = arg;
- ICall_leaveCriticalSection(key);
- }
- ClockP_setTimeout(entry->clockP, ticks);
-
- ClockP_start(entry->clockP);
-
- return (ICALL_ERRNO_SUCCESS);
-
-}
-
-/**
- * Stops a timer.
- *
- * @param id timer ID.
- */
-void
-ICall_stopTimer(ICall_TimerID id)
-{
- ICall_ScheduleEntry *entry = (ICall_ScheduleEntry *) id;
-
- if (id == ICALL_INVALID_TIMER_ID)
- {
- return;
- }
-
- ClockP_stop(entry->clockP);
-}
-
-/**
- * Increments or decrements power activity counter.
- *
- * When power activity counter is greater than zero,
- * the device shall stay in the active power state.
- * The caller has to make sure that it decrements the counter
- * as many times as it has incremented the counter
- * when there is no activity that requires the active power state.
- * It is recommended that each client increments the counter by just one,
- * but it is not mandated to be so.
- *
- * @param incFlag TRUE to indicate incrementing the counter.
- * FALSE to indicate decrementing the counter.
- * @return @ref TRUE if power is required.
- * @ref FALSE if power is not required.
- */
-bool
-ICall_pwrUpdActivityCounter(bool incFlag)
-{
- ICall_PwrUpdActivityCounterArgs args;
- args.incFlag = incFlag;
- ICallPlatform_pwrUpdActivityCounter(&args);
- return (args.pwrRequired);
-}
-
-/**
- * Configures power constraint/dependency set/release actions upon
- * activity counter change.
- *
- * When activity counter value drops to zero, all constraints and
- * dependencies configured by this function shall be released.
- * When activity counter value increments to one, all constraints
- * and dependencies configured by this function shall be set.
- *
- * @param bitmap a bitmap of constraint or dependency flags.
- * The flag definition is specific to each platform.
- * For instance, see ICallCC26xxDefs.h.
- *
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
- * flag in the bitmap is detected.
- */
-ICall_Errno
-ICall_pwrConfigACAction(ICall_PwrBitmap_t bitmap)
-{
- ICall_PwrBitmapArgs args;
- args.bitmap = bitmap;
- return (ICallPlatform_pwrConfigACAction(&args));
-}
-
-/**
- * Sets power constraints and dependencies.
- *
- * @param bitmap a bitmap of constraint or dependency flags.
- * The flag definition is specific to each platform.
- * For instance, see ICallCC26xxDefs.h.
- *
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
- * flag in the bitmap is detected.
- */
-ICall_Errno
-ICall_pwrRequire(ICall_PwrBitmap_t bitmap)
-{
- ICall_PwrBitmapArgs args;
- args.bitmap = bitmap;
- return (ICallPlatform_pwrRequire(&args));
-}
-
-/**
- * Releases power constraints and dependencies.
- *
- * @param bitmap a bitmap of constraint or dependency flags.
- * The flag definition is specific to each platform.
- * For instance, see ICallCC26xxDefs.h.
- *
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
- * flag in the bitmap is detected.
- */
-ICall_Errno
-ICall_pwrDispense(ICall_PwrBitmap_t bitmap)
-{
- ICall_PwrBitmapArgs args;
- args.bitmap = bitmap;
- return (ICallPlatform_pwrDispense(&args));
-}
-
-/**
- * Checks whether HF XOSC is stable.
- * This function must be called after HF XOSC is turned on
- * (through power dependency).
- *
- * @return TRUE when HF XOSC is stable.
- * FALSE when HF XOSC is not stable.
- */
-bool
-ICall_pwrIsStableXOSCHF(void)
-{
- ICall_GetBoolArgs args;
- (void) ICallPlatform_pwrIsStableXOSCHF(&args);
- return (args.value);
-}
-
-/**
- * Switch clock source to HF XOSC.
- * This function must be called after HF XOSC is stable.
- *
- * @return @ref ICALL_ERRNO_SUCCESS
- */
-ICall_Errno
-ICall_pwrSwitchXOSCHF(void)
-{
- ICall_FuncArgsHdr args;
- return (ICallPlatform_pwrSwitchXOSCHF(&args));
-}
-
-/**
- * Gets the estimated crystal oscillator startup time.
- *
- * @return estimated crystal oscillator startup time
- */
-uint32_t
-ICall_pwrGetXOSCStartupTime(uint_fast32_t timeUntilWakeupInMs)
-{
- ICall_PwrGetXOSCStartupTimeArgs args;
- args.timeUntilWakeupInMs = timeUntilWakeupInMs;
- (void) ICallPlatform_pwrGetXOSCStartupTime(&args);
- return (args.value);
-}
-
-/**
- * Registers a power state transition notify function.
- *
- * The registered notify function shall be called when the power state
- * changes.
- *
- * @param fn notify function pointer
- * @param obj pointer to data object to be passed to notify function.
- * This pointer must not be NULL and can point to an aggregate type
- * containing the @ref ICall_PwrNotifyData.
- * The object must not be released.
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_NO_RESOURCE when registration failed
- */
-ICall_Errno
-ICall_pwrRegisterNotify(ICall_PwrNotifyFn fn, ICall_PwrNotifyData *obj)
-{
- ICall_PwrRegisterNotifyArgs args;
- args.hdr.service = ICALL_SERVICE_CLASS_PRIMITIVE;
- args.hdr.func = ICALL_PRIMITIVE_FUNC_PWR_REGISTER_NOTIFY;
- args.fn = fn;
- args.obj = obj;
- return (ICallPlatform_pwrRegisterNotify(&args));
-}
-
-/**
- * Retrieves power transition state.
- *
- * @return Implementation specific transition state when successful
- * Zero when the function is not implemented.
- */
-uint_fast8_t
-ICall_pwrGetTransitionState(void)
-{
- ICall_PwrGetTransitionStateArgs args;
- ICall_Errno errno;
-
- errno = ICallPlatform_pwrGetTransitionState(&args);
-
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- return (args.state);
- }
- return (0);
-}
-
-/**
- * Creates a new RTOS task.
- *
- * @param entryfn task entry function.
- * @param priority task priority as understood by the underlying RTOS
- * @param stacksize stack size as understood by the underlying RTOS
- * @param arg argument to pass to the task entry function
- *
- * @return @ref ICALL_ERRNO_SUCCESS when successful
- * @ref ICALL_ERRNO_NO_RESOURCE when creation failed
- */
-
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * Creates a semaphore.
- *
- * @param mode Semaphore mode
- * @ref ICALL_SEMAPHORE_MODE_COUNTING, or
- * @ref ICALL_SEMAPHORE_MODE_BINARY
- * @param initcount initial count value
- * @return created semaphore when successful
- * NULL when creation failed
- */
-ICall_Semaphore
-ICall_createSemaphore(uint_fast8_t mode, int initcount)
-{
- /* Semaphore_Params is a huge structure.
- * To reduce stack usage, heap is used instead.
- * This implies that ICall_createSemaphore() must be called before heap
- * space may be exhausted.
- */
- ICall_Semaphore sem;
- Semaphore_Params *semParams =
- (Semaphore_Params *) ICall_heapMalloc(sizeof(Semaphore_Params));
-
- if (semParams == NULL)
- {
- return (NULL);
- }
-
- Semaphore_Params_init(semParams);
- if (mode == ICALL_SEMAPHORE_MODE_BINARY)
- {
- semParams->mode = Semaphore_Mode_BINARY;
- }
-
- sem = Semaphore_create(args->initcount, semParams, NULL);
- ICall_heapFree(semParams);
-
- return (sem);
-
-}
-#endif
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * Post on a semaphore
- *
- * @param sem semaphore.
- *
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- */
-ICall_Errno
-ICall_postSemaphore(ICall_Semaphore sem)
-{
- Semaphore_post(sem);
- return (ICALL_ERRNO_SUCCESS);
-}
-#endif /* ICALL_RTOS_SEMAPHORE_API */
-
-#ifdef ICALL_RTOS_EVENTS_API
-/**
- * Creates a event.
- *
- * @return created event when successful
- * NULL when creation failed
- */
-ICall_Event
-ICall_createEvent(void)
-{
- ICall_Event event = Event_create(NULL, NULL);
- return (event);
-
-
- ICall_CreateEventArgs args;
- ICall_Errno errno;
-
- args.hdr.service = ICALL_SERVICE_CLASS_PRIMITIVE;
- args.hdr.func = ICALL_PRIMITIVE_FUNC_CREATE_EVENT;
- errno = ICall_dispatcher(&args.hdr);
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- return (args.event);
- }
- return (NULL);
-}
-
-/**
- * Post on an event
- *
- * @param event event.
- *
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- */
-ICall_Errno
-ICall_postEvent(ICall_Event event, uint32_t events)
-{
- Event_post(event, events);
- return (ICALL_ERRNO_SUCCESS);
-}
-/**
- * Waits on a event for ICALL_MSG_EVENT_ID
- *
- * @param event event.
- * @param milliseconds timeout in milliseconds
- * or @ref ICALL_TIMEOUT_FOREVER to wait forever
- *
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- * and event was received.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the event being signaled.
- */
-ICall_Errno
-ICall_waitEvent(ICall_Event event, uint_fast32_t milliseconds)
-{
- uint32_t timeout;
-
- if (milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return (errno);
- }
- }
-
- if (Event_pend(event, 0, ICALL_MSG_EVENT_ID, timeout))
- {
- return (ICALL_ERRNO_SUCCESS);
- }
- return (ICALL_ERRNO_TIMEOUT);
-}
-#endif /* ICALL_RTOS_EVENTS_API */
-
-#ifdef ICALL_RTOS_SEMAPHORE_API
-/**
- * Waits on a semaphore
- *
- * @param sem semaphore.
- * @param milliseconds timeout in milliseconds
- * or @ref ICALL_TIMEOUT_FOREVER to wait forever
- *
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- * and semaphore was acquired.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the semaphore being signaled.
- */
-ICall_Errno
-ICall_waitSemaphore(ICall_Semaphore sem, uint_fast32_t milliseconds)
-{
- uint32_t timeout;
-
- if (milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return (errno);
- }
- }
- if (Semaphore_pend(sem, timeout))
- {
- return (ICALL_ERRNO_SUCCESS);
- }
- return (ICALL_ERRNO_TIMEOUT);
-}
-#endif /* ICALL_RTOS_SEMAPHORE_API */
-
-
-#if 0
-/* Util function that take time in ticks and convert it into ms - relate to system clock (returns system clock + converted ms) */
-static void AbsoluteTimeInMilliPlusTimer(uint_least32_t timeout,struct timespec *tsTimer)
-{
-
- clock_gettime(CLOCK_REALTIME, tsTimer);
-
- tsTimer->tv_sec += (timeout / 1000);
- tsTimer->tv_nsec += (timeout % 1000) * 1000000;
-}
-#endif
-
-/**
- * Waits for and retrieves a message received at the message queue
- * associated with the calling thread, which matches a certain condition.
- *
- * @param milliseconds timeout period in milliseconds.
- * @param matchFn pointer to a function that would return TRUE when
- * the message matches its condition.
- * @param src pointer to a variable to store the service id
- * of the registered server which sent the retrieved
- * message, or NULL if not interested in storing service id.
- * @param dest pointer to a variable to store the entity id
- * of the destination of the message,
- * of NULL if not interested in storing the destination entity id.
- * @param msg pointer to a pointer variable to store the
- * starting address of the message body being
- * retrieved. The pointer must not be NULL.
- * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
- * and a message was retrieved.
- * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
- * has passed since the call of the function without
- * the semaphore being signaled.
- * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
- * called from a thread which has not registered
- * an entity, either through ICall_enrollService()
- * or through ICall_registerApp().
- */
-ICall_Errno
-ICall_waitMatch(uint_least32_t milliseconds,
- ICall_MsgMatchFn matchFn,
- ICall_ServiceEnum *src,
- ICall_EntityID *dest,
- void **msg)
-{
- TaskHandle_t taskhandle = Task_self();
- ICall_TaskEntry *taskentry = ICall_searchTask(taskhandle);
- ICall_MsgQueue prependQueue = NULL;
-#ifndef ICALL_EVENTS
- uint_fast16_t consumedCount = 0;
-#endif
- uint32_t timeout;
- uint_fast32_t timeoutStamp;
- ICall_Errno errno;
-
- if (!taskentry)
- {
- return (ICALL_ERRNO_UNKNOWN_THREAD);
- }
- /* Successful */
- if (milliseconds == 0)
- {
- timeout = BIOS_NO_WAIT;
- }
- else if (milliseconds == ICALL_TIMEOUT_FOREVER)
- {
- timeout = BIOS_WAIT_FOREVER;
- }
- else
- {
- /* Convert milliseconds to number of ticks */
- errno = ICall_msecs2Ticks(milliseconds, &timeout);
- if (errno != ICALL_ERRNO_SUCCESS)
- {
- return (errno);
- }
- }
-
- errno = ICALL_ERRNO_TIMEOUT;
-
- timeoutStamp = ICall_getTicks() + timeout;
-
-#ifdef ICALL_LITE
-
- uint32_t events;
-
-#ifdef FREERTOS
- //TODO: Investigate ICALL Wait tick period (Last parameter)
- while( xQueueReceive(taskentry->syncHandle, (char*)&events, milliseconds*1000) == pdPASS )
-#endif
-#else /* !ICALL_LITE */
- while (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
-#endif /* ICALL_LITE */
- {
- ICall_EntityID fetchSrc;
- ICall_EntityID fetchDst;
- ICall_ServiceEnum servId;
- void *fetchMsg;
- errno = ICall_fetchMsg(&fetchSrc, &fetchDst, &fetchMsg);
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- if (ICall_primEntityId2ServiceId(fetchSrc, &servId) ==
- ICALL_ERRNO_SUCCESS)
- {
- if (matchFn(servId, fetchDst, fetchMsg))
- {
- /* Matching message found*/
- if (src != NULL)
- {
- *src = servId;
- }
- if (dest != NULL)
- {
- *dest = fetchDst;
- }
- *msg = fetchMsg;
- errno = ICALL_ERRNO_SUCCESS;
- break;
- }
- }
- /* Message was received but it wasn't expected one.
- * Add to the prepend queue */
- ICall_msgEnqueue(&prependQueue, fetchMsg);
-#ifdef ICALL_EVENTS
- /* Event are binary semaphore, so if several messsages are posted while
- * we are processing one, it's possible that some of them are 'missed' and
- * not processed. Sending a event to ourself force this loop to run until
- * all the messages in the queue are processed.
- */
-#ifdef ICALL_LITE
- /* 0x20000000 is an internal Event_ID */
- uint32_t msg_ptr = (0x20000000); //Event_Id_29;
-
-#ifdef FREERTOS
-
- uint8_t status;
- if (HwiP_inISR())
- {
- status = xQueueSendFromISR(taskentry->syncHandle, (char *) &msg_ptr, NULL);
- }
- else
- {
- status = xQueueSend(taskentry->syncHandle, (char *) &msg_ptr, 0);
- }
-
- if (status != pdTRUE)
- {
- return status;
- }
-#endif
-
-
-#else /* !ICALL_LITE */
- ICALL_SYNC_HANDLE_POST(taskentry->syncHandle);
-#endif /* ICALL_LITE*/
-#endif /* ICALL_EVENTS */
- }
-
- /* Prepare for timeout exit */
- errno = ICALL_ERRNO_TIMEOUT;
-
-#ifndef ICALL_EVENTS
- /* Keep the decremented semaphore count */
- consumedCount++;
-#endif /* ICALL_EVENTS */
- if (timeout != BIOS_WAIT_FOREVER &&
- timeout != BIOS_NO_WAIT)
- {
- /* Readjust timeout */
- uint32_t newTimeout = timeoutStamp - ICall_getTicks();
-
- if (newTimeout == 0 || newTimeout > timeout)
- {
- break;
- }
- timeout = newTimeout;
- }
- }
-
-
- /* Prepend retrieved irrelevant messages */
- ICall_msgPrepend(&taskentry->queue, prependQueue);
-#ifndef ICALL_EVENTS
- /* Re-increment the consumed semaphores */
- for (; consumedCount > 0; consumedCount--)
- {
- Semaphore_post(taskentry->syncHandle);
- }
-#endif /* ICALL_EVENTS */
- return (errno);
-}
-
-/**
- * Retrieves an entity ID of (arbitrary) one of the entities registered
- * from the calling thread.
- *
- * Note that, if multiple entities were registered from the same thread,
- * this function shall arbitrarily pick one of the entities.
- *
- * @return A valid entity ID or @ref ICALL_INVALID_ENTITY_ID
- * when no entity was registered from the calling thread.
- */
-ICall_EntityID
-ICall_getEntityId(void)
-{
- ICall_EntityID id;
- TaskHandle_t taskhandle = Task_self();
- ICall_CSState key;
- size_t i;
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Not found */
- break;
- }
- if (ICall_entities[i].task->task == (TaskHandle_t)taskhandle)
- {
- /* Found */
- id = i;
- ICall_leaveCSImpl(key);
- return (id);
- }
- }
- ICall_leaveCSImpl(key);
- return ICALL_INVALID_ENTITY_ID;
-
-}
-
-/**
- * Checks whether the calling thread provides the designated service.
- *
- * @param service Service enumeration value for the service.
- *
- * @return Non-zero if the current thread provides the designated service.
- * Zero, otherwise.
- */
-uint_fast8_t
-ICall_threadServes(ICall_ServiceEnum service)
-{
- uint_fast8_t res = 0;
- TaskHandle_t taskhandle;
- ICall_CSState key;
- size_t i;
- taskhandle = Task_self();
-
- key = ICall_enterCSImpl();
- for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
- {
- if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
- {
- /* Not found */
- break;
- }
- else if (ICall_entities[i].service == service)
- {
- res = (uint_fast8_t)
- (ICall_entities[i].task->task == taskhandle);
- }
- }
- ICall_leaveCSImpl(key);
- return (res);
-}
-
-/**
- * Retrieves an internal ID understood only by a service entity,
- * corresponding to an ICall entity ID.
- *
- * This function is used when a message body includes a field indicating a
- * software entity and the destination of the message has its own internal
- * message routing mechanism with its own entity enumeration system.
- *
- * @param service Service enumeration value for the service.
- * Currently @ref ICALL_SERVICE_CLASS_BLE_MSG is supported.
- * @param entity ICall entity ID.
- *
- * @return Stack specific 8 bit ID or 0xFF when failed.
- */
-uint_fast8_t
-ICall_getLocalMsgEntityId(ICall_ServiceEnum service, ICall_EntityID entity)
-{
- ICall_GetLocalMsgEntityIdArgs args;
- ICall_Errno errno;
- args.hdr.service = service;
- args.hdr.func = ICALL_MSG_FUNC_GET_LOCAL_MSG_ENTITY_ID;
- args.entity = entity;
- errno = ICall_dispatcher(&args.hdr);
- if (errno == ICALL_ERRNO_SUCCESS)
- {
- return (args.localId);
- }
- return (0xFF);
-}
-
-#endif /* ICALL_JT */
-
-#ifdef ICALL_LITE
- /*******************************************************************************
- * @fn matchLiteCS
- */
-static bool matchLiteCS(ICall_ServiceEnum src,
- ICall_EntityID dest, const void *msg)
-{
- (void) src;
- (void) dest;
- ICall_LiteCmdStatus *pMsg = (ICall_LiteCmdStatus *)msg;
- return (pMsg->cmdId == ICALL_LITE_DIRECT_API_DONE_CMD_ID);
-}
- /*******************************************************************************
- * @fn icall_directAPI
- * see headers for details.
- */
-uint32_t icall_directAPI( uint8_t service , icall_lite_id_t id, ... )
-{
- va_list argp;
- uint32_t res;
- icallLiteMsg_t liteMsg;
-
- // The following will push all parameter in the runtime stack.
- // This need to be call before any other local declaration of variable....
- va_start(argp, id);
-
- // Todo - add string for every icall API function, instead of printing function address
- BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : icall_directAPI to BLE func=0x%x, status=%d\n", id, 0);
- // Create the message that will be send to the requested service..
- liteMsg.hdr.len = sizeof(icallLiteMsg_t);
- liteMsg.hdr.next = NULL;
- liteMsg.hdr.dest_id = ICALL_UNDEF_DEST_ID;
- liteMsg.msg.directAPI = id;
- liteMsg.msg.pointerStack = (uint32_t*)(*((uint32_t*)(&argp)));
- ICall_sendServiceMsg(ICall_getEntityId(), service,
- ICALL_MSG_FORMAT_DIRECT_API_ID, &(liteMsg.msg));
-
- // Since stack needs to always have a higher priority than the thread calling
- // the API, when we reach this point the API has been executed by the stack.
- // This implies the following:
- // - API are not called in critical section or in section where task
- // switching is disabled
- // It is possible that the stack is blocking on this API, in this case a
- // sync object needs to be used in order for this call to resume only when
- // the API has been process in full.
- {
- ICall_Errno errno;
- void *pCmdStatus = NULL;
-
- errno = ICall_waitMatch(ICALL_TIMEOUT_PREDEFINE, matchLiteCS, NULL, NULL,
- (void **)&pCmdStatus);
- if (errno == ICALL_ERRNO_TIMEOUT)
- {
-#ifdef HALNODEBUG
-#elif defined(EXT_HAL_ASSERT)
- HAL_ASSERT(HAL_ASSERT_CAUSE_ICALL_TIMEOUT);
-#else /* !EXT_HAL_ASSERT */
- ICall_abort();
-#endif /* EXT_HAL_ASSERT */
- }
- else if (errno == ICALL_ERRNO_SUCCESS)
- {
- if (pCmdStatus)
- {
- ICall_freeMsg(pCmdStatus);
- }
- }
- else
- {
-#ifdef HALNODEBUG
-#else /* ! HALNODEBUG */
- ICall_abort();
-#endif /* HALNODEBUG */
- }
- }
-
- // The return parameter is set in the runtime stack, at the location of the
- // first parameter.
- res = liteMsg.msg.pointerStack[0];
-
- va_end(argp);
-
- return (res);
-}
-
- /*******************************************************************************
- * @fn ICall_sendServiceComplete
- * see headers for details.
- */
-ICall_Errno ICall_sendServiceComplete(ICall_EntityID src,
- ICall_EntityID dest,
- ICall_MSGFormat format,
- void *msg)
-{
- ICall_CSState key;
- ICall_MsgHdr *hdr = (ICall_MsgHdr *) msg - 1;
-
- if (dest >= ICALL_MAX_NUM_ENTITIES ||
- src >= ICALL_MAX_NUM_ENTITIES)
- {
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
- key = ICall_enterCSImpl();
- if (!ICall_entities[dest].task)
- {
- ICall_leaveCSImpl(key);
- return (ICALL_ERRNO_INVALID_PARAMETER);
- }
-
- ICall_leaveCSImpl(key);
- /* Note that once the entry is valid,
- * the value does not change and hence it is OK
- * to leave the critical section.
- */
-
- hdr->srcentity = src;
- hdr->dstentity = dest;
- hdr->format = format;
- ICall_msgEnqueue(&ICall_entities[dest].task->queue, msg);
-
- /* 0x20000000 is an internal Event_ID */
- uint32_t msg_ptr = (0x20000000); //Event_Id_29;
-#ifdef FREERTOS
- uint8_t status;
- if (HwiP_inISR())
- {
- status = xQueueSendFromISR(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, NULL);
- }
- else
- {
- status = xQueueSend(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, 0);
- }
-
- if (status != pdTRUE)
- {
- return status;
- }
-#endif
- return (ICALL_ERRNO_SUCCESS);
-}
-#endif /* ICALL_LITE*/
diff --git a/src/platform/cc13xx_26xx/icall_FreeRTOS.cpp b/src/platform/cc13xx_26xx/icall_FreeRTOS.cpp
new file mode 100644
index 00000000000000..469ef9b3e0074c
--- /dev/null
+++ b/src/platform/cc13xx_26xx/icall_FreeRTOS.cpp
@@ -0,0 +1,3926 @@
+/******************************************************************************
+ @file icall_FreeRTOS.c
+
+ @brief Indirect function Call dispatcher implementation on top of OS.
+
+ This implementation uses heapmgr.h to implement a simple heap with low
+ memory overhead but large processing overhead.
+ The size of the heap is determined with HEAPMGR_SIZE macro, which can
+ be overridden with a compile option.
+ Note: The ICall layer (e.g. this file) is using TI internal implementation of POSIX.
+ For now, the ICall layer is not supports using outer POSIX on the application layer.
+
+ Group: WCS, LPC, BTS
+ Target Device: cc13xx_cc26xx
+
+ ******************************************************************************
+
+ Copyright (c) 2013-2024, Texas Instruments Incorporated
+ 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 Texas Instruments Incorporated 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 OWNER 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.
+
+ ******************************************************************************
+
+
+ *****************************************************************************/
+
+#ifdef FREERTOS
+#include "bget.h"
+#include
+#include
+#endif
+
+#ifdef FREERTOS
+#include
+#include
+#include
+#endif
+
+#include
+#include
+#define Hwi_disable HwiP_disable
+#define Hwi_restore HwiP_restore
+#define Hwi_disableinterrupt HwiP_disableInterrupt
+#define Hwi_enableinterrupt HwiP_enableInterrupt
+#define Swi_restore SwiP_restore
+#define Swi_disable SwiP_disable
+#define BIOS_WAIT_FOREVER (~(0U))
+#define BIOS_NO_WAIT (0U)
+
+#include "icall.h"
+#include "icall_platform.h"
+#include "osal.h"
+#include
+#include
+
+#ifndef ICALL_FEATURE_SEPARATE_IMGINFO
+#include
+#endif /* ICALL_FEATURE_SEPARATE_IMGINFO */
+
+#ifndef Task_self
+#define Task_self ICall_taskSelf
+#endif
+
+#ifndef ICALL_MAX_NUM_ENTITIES
+/**
+ * Maximum number of entities that use ICall, including service entities
+ * and application entities.
+ * The value may be overridden by a compile option.
+ * Note that there are at least,
+ * Primitive service, Stack services along with potentially generic
+ * framework service for the stack thread.
+ */
+#define ICALL_MAX_NUM_ENTITIES 6
+#endif
+
+#ifndef ICALL_MAX_NUM_TASKS
+/**
+ * Maximum number of threads which include entities.
+ * The value may be overridden by a compile option.
+ */
+#define ICALL_MAX_NUM_TASKS 2
+#endif
+
+/**
+ * @internal
+ * Service class value used to indicate an invalid (unused) entry
+ */
+#define ICALL_SERVICE_CLASS_INVALID_ENTRY 0x0000
+
+/**
+ * @internal
+ * Service class value used to indicate an entry for an application entity
+ */
+#define ICALL_SERVICE_CLASS_APPLICATION ICALL_SERVICE_CLASS_MASK
+
+/**
+ * @internal
+ * Primitive service entity ID
+ */
+#define ICALL_PRIMITIVE_ENTITY_ID 0
+
+/**
+ * @internal
+ * Accessor macro to get a header field (next) from a message pointer
+ */
+#define ICALL_MSG_NEXT(_p) (((ICall_MsgHdr *) (_p) -1)->next)
+
+/**
+ * @internal
+ * Accessor macro to get a header field (dest_id) from a message pointer
+ */
+#define ICALL_MSG_DEST_ID(_p) (((ICall_MsgHdr *) (_p) -1)->dest_id)
+
+#ifndef ICALL_TIMER_TASK_STACK_SIZE
+/**
+ * @internal
+ * Timer thread stack size
+ */
+#define ICALL_TIMER_TASK_STACK_SIZE (512)
+#endif // ICALL_TIMER_TASK_STACK_SIZE
+
+/**
+ * @internal
+ * Creation of the synchronous object between application and service
+ */
+
+#ifdef ICALL_EVENTS
+#define ICALL_SYNC_HANDLE_CREATE() (Event_create(NULL, NULL))
+#else /* ICALL_EVENTS */
+#define ICALL_SYNC_HANDLE_CREATE() (Semaphore_create(0, NULL, NULL))
+#endif /* ICALL_EVENTS */
+
+/**
+ * @internal
+ * post the synchronous object between application and service
+ */
+#ifdef ICALL_EVENTS
+#define ICALL_SYNC_HANDLE_POST(x) (Event_post(x, ICALL_MSG_EVENT_ID))
+#define ICALL_SYNC_HANDLE_POST_WM(x) (Event_post(x, ICALL_WAITMATCH_EVENT_ID))
+#else /* ICALL_EVENTS */
+#define ICALL_SYNC_HANDLE_POST(x) (Semaphore_post(x))
+#define ICALL_SYNC_HANDLE_POST_WM(x) (Semaphore_post(x)) /* Semaphore does not have event ID */
+#endif /* ICALL_EVENTS */
+
+/**
+ * @internal
+ * pend for the synchronous object between application and service
+ */
+#ifdef ICALL_EVENTS
+#define ICALL_SYNC_HANDLE_PEND(x, t) (Event_pend(x, 0, ICALL_MSG_EVENT_ID, t))
+#define ICALL_SYNC_HANDLE_PEND_WM(x, t) (Event_pend(x, 0, ICALL_WAITMATCH_EVENT_ID, t))
+#else /* ICALL_EVENTS */
+#define ICALL_SYNC_HANDLE_PEND(x, t) (Semaphore_pend(x, t))
+#define ICALL_SYNC_HANDLE_PEND_WM(x, t) (Semaphore_pend(x, t)) /* Semaphore does not have event ID */
+#endif /* ICALL_EVENTS */
+
+/**
+ * @internal
+ * ticks
+ */
+#define CLOCK_TICKS_PERIOD (10)
+
+/**
+ * @internal
+ * Data structure used to access critical section
+ * state variable.
+ * Without this data structure, C code will violate
+ * C89 or C99 strict aliasing rule.
+ */
+typedef union _icall_cs_state_union_t
+{
+ /** critical section variable as declared in the interface */
+ ICall_CSState state;
+ /** @internal field used to access internal data */
+ struct _icall_cs_state_aggr_t
+ {
+ /** field to store Swi_disable() return value */
+ uint_least16_t swikey;
+ /** field to store Hwi_disable() return value */
+ uint_least16_t hwikey;
+ } each;
+} ICall_CSStateUnion;
+
+/**
+ * @internal Primitive service handler function type
+ */
+typedef ICall_Errno (*ICall_PrimSvcFunc)(ICall_FuncArgsHdr *);
+
+#ifdef ICALL_FEATURE_SEPARATE_IMGINFO
+/* Image information shall be in separate module */
+
+/**
+ * Array of entry function addresses of external images.
+ *
+ * Note that function address must be odd number for Thumb mode functions.
+ */
+extern const ICall_RemoteTaskEntry ICall_imgEntries[];
+/**
+ * Array of task priorities of external images.
+ * One task is created per image to start off the image entry function.
+ * Each element of this array correspond to the task priority of
+ * each entry function defined in @ref ICall_imgEntries.
+ */
+extern const int ICall_imgTaskPriorities[];
+
+/**
+ * Array of task stack sizes of external images.
+ * One task is created per image to start off the image entry function.
+ * Each element of this array correspond to the task stack size of
+ * each entry function defined in @ref ICall_imgEntries.
+ */
+extern const size_t ICall_imgTaskStackSizes[];
+
+/**
+ * Array of custom initialization parameters (pointers).
+ * Each initialization parameter (pointer) is passed to each corresponding
+ * image entry function defined in @ref ICall_imgEntries;
+ */
+extern const void * ICall_imgInitParams[];
+
+/**
+ * Number of external images.
+ */
+extern const uint_least8_t ICall_numImages;
+
+#define icall_threadEntries ICall_imgEntries
+#define ICall_threadPriorities ICall_imgTaskPriorities
+#define ICall_threadStackSizes ICall_imgTaskStackSizes
+#define ICall_getInitParams(_i) (ICall_imgInitParams[i])
+#define ICALL_REMOTE_THREAD_COUNT ICall_numImages
+#else /* ICALL_FEATURE_SEPARATE_IMGINFO */
+/**
+ * @internal
+ * Array of entry function of external images.
+ */
+static const ICall_RemoteTaskEntry icall_threadEntries[] = ICALL_ADDR_MAPS;
+
+/** @internal external image count */
+#define ICALL_REMOTE_THREAD_COUNT (sizeof(icall_threadEntries) / sizeof(icall_threadEntries[0]))
+
+/** @internal thread priorities to be assigned to each remote thread */
+#ifndef BLE_STACK_TASK_PRIORITY
+static const int ICall_threadPriorities[] = { ICALL_TASK_PRIORITIES };
+#else
+static const int ICall_threadPriorities[] = { BLE_STACK_TASK_PRIORITY };
+#endif
+
+/** @internal thread stack max depth for each remote thread */
+static const size_t ICall_threadStackSizes[] = ICALL_TASK_STACK_SIZES;
+
+/** @internal initialization parameter (pointer) for each remote thread */
+#ifdef ICALL_CUSTOM_INIT_PARAMS
+static const void * ICall_initParams[] = ICALL_CUSTOM_INIT_PARAMS;
+#define ICall_getInitParams(_i) (ICall_initParams[i])
+#else /* ICALL_CUSTOM_INIT_PARAMS */
+#define ICall_getInitParams(_i) NULL
+#endif /* ICALL_CUSTOM_INIT_PARAMS */
+
+#endif /* ICALL_FEATURE_SEPARATE_IMGINFO */
+
+/** @internal message queue */
+typedef void * ICall_MsgQueue;
+
+/** @internal data structure about a task using ICall module */
+typedef struct _icall_task_entry_t
+{
+ TaskHandle_t task;
+ ICall_SyncHandle syncHandle;
+ ICall_MsgQueue queue;
+} ICall_TaskEntry;
+
+/** @internal data structure about an entity using ICall module */
+typedef struct _icall_entity_entry_t
+{
+ ICall_ServiceEnum service;
+ ICall_TaskEntry * task;
+ ICall_ServiceFunc fn;
+} ICall_entityEntry;
+
+/** @internal storage to track all tasks using ICall module */
+static ICall_TaskEntry ICall_tasks[ICALL_MAX_NUM_TASKS];
+
+/** @internal storage to track all entities using ICall module */
+static ICall_entityEntry ICall_entities[ICALL_MAX_NUM_ENTITIES];
+
+#ifndef FREERTOS
+extern mqd_t g_EventsQueueID;
+#endif
+/**
+ * @internal
+ * Wakeup schedule data structure definition
+ */
+
+#ifdef FREERTOS
+void ICALL_Task_restore(UBaseType_t * OriginalParam);
+void ICALL_Task_disable(UBaseType_t * OriginalParam);
+#else
+
+void ICALL_Task_restore(struct sched_param * OriginalParam);
+void ICALL_Task_disable(struct sched_param * OriginalParam);
+#endif
+typedef struct _icall_schedule_t
+{
+ ClockP_Handle clockP;
+ ICall_TimerCback cback;
+ void * arg;
+} ICall_ScheduleEntry;
+
+/* For now critical sections completely disable hardware interrupts
+ * because they are used from ISRs in MAC layer implementation.
+ * If MAC layer implementation changes, critical section
+ * implementation may change to reduce overall interrupt latency.
+ */
+/* Enter critical section implementation. See header file for comment. */
+ICall_CSState ICall_enterCSImpl(void)
+{
+
+ ICall_CSStateUnion cu;
+ cu.each.swikey = (uint_least16_t) Swi_disable();
+ cu.each.hwikey = (uint_least16_t) Hwi_disable();
+ return cu.state;
+}
+#ifdef FREERTOS
+TaskHandle_t ICall_taskSelf(void)
+#else
+Task_Handle ICall_taskSelf(void)
+#endif
+{
+
+ TaskHandle_t task = NULL;
+#ifdef FREERTOS
+ task = (TaskHandle_t) xTaskGetCurrentTaskHandle();
+#else
+ task = ;
+#endif // FREERTOS
+ return (task);
+}
+
+/* See header file for comment */
+ICall_EnterCS ICall_enterCriticalSection = ICall_enterCSImpl;
+
+/* leave critical section implementation. See header file for comment */
+void ICall_leaveCSImpl(ICall_CSState key)
+{
+ ICall_CSStateUnion * cu = (ICall_CSStateUnion *) &key;
+ Hwi_restore((uint32_t) cu->each.hwikey);
+ Swi_restore((uint32_t) cu->each.swikey);
+}
+
+/* See header file for comment */
+ICall_LeaveCS ICall_leaveCriticalSection = ICall_leaveCSImpl;
+
+/* Implementing a simple heap using heapmgr.h template.
+ * This simple heap depends on critical section implementation
+ * and hence the template is used after critical section definition. */
+void * ICall_heapMalloc(uint32_t size);
+void * ICall_heapRealloc(void * blk, uint32_t size);
+void ICall_heapFree(void * blk);
+
+#define HEAPMGR_INIT ICall_heapInit
+#define HEAPMGR_MALLOC ICall_heapMalloc
+#define HEAPMGR_FREE ICall_heapFree
+#define HEAPMGR_REALLOC ICall_heapRealloc
+#define HEAPMGR_GETSTATS ICall_heapGetStats
+#define HEAPMGR_MALLOC_LIMITED ICall_heapMallocLimited
+
+void ICall_heapMgrGetMetrics(uint32_t * pBlkMax, uint32_t * pBlkCnt, uint32_t * pBlkFree, uint32_t * pMemAlo, uint32_t * pMemMax,
+ uint32_t * pMemUB);
+#ifdef HEAPMGR_METRICS
+#define HEAPMGR_GETMETRICS ICall_heapMgrGetMetrics
+#endif
+
+#define HEAPMGR_LOCK() \
+ do \
+ { \
+ ICall_heapCSState = ICall_enterCSImpl(); \
+ } while (0)
+#define HEAPMGR_UNLOCK() \
+ do \
+ { \
+ ICall_leaveCSImpl(ICall_heapCSState); \
+ } while (0)
+#define HEAPMGR_IMPL_INIT()
+/* Note that a static variable can be used to contain critical section
+ * state since heapmgr.h template ensures that there is no nested
+ * lock call. */
+
+#if defined(HEAPMGR_CONFIG) && ((HEAPMGR_CONFIG == 0) || (HEAPMGR_CONFIG == 0x80))
+#include
+#elif defined(HEAPMGR_CONFIG) && ((HEAPMGR_CONFIG == 1) || (HEAPMGR_CONFIG == 0x81))
+#include
+#elif defined(HEAPMGR_CONFIG) && ((HEAPMGR_CONFIG == 2) || (HEAPMGR_CONFIG == 0x82))
+#include
+#elif defined(FREERTOS)
+#include "TI_heap_wrapper.h"
+#else
+static ICall_CSState ICall_heapCSState;
+#include
+#endif
+
+/**
+ * @internal Searches for a task entry within @ref ICall_tasks.
+ * @param taskhandle OS task handle
+ * @return Pointer to task entry when found, or NULL.
+ */
+static ICall_TaskEntry * ICall_searchTask(TaskHandle_t taskhandle)
+{
+ size_t i;
+ ICall_CSState key;
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
+ {
+ if (!ICall_tasks[i].task)
+ {
+ /* Empty slot */
+ break;
+ }
+ if ((TaskHandle_t) taskhandle == (TaskHandle_t) ICall_tasks[i].task)
+ {
+ ICall_leaveCSImpl(key);
+ return &ICall_tasks[i];
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return NULL;
+}
+
+/**
+ * @internal Searches for a task entry within @ref ICall_tasks or
+ * build an entry if the entry table is empty.
+ * @param taskhandle OS task handle
+ * @return Pointer to task entry when found, or NULL.
+ */
+
+static ICall_TaskEntry * ICall_newTask(TaskHandle_t taskhandle)
+{
+ size_t i;
+ ICall_CSState key;
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
+ {
+ if (!ICall_tasks[i].task)
+ {
+ /* Empty slot */
+ ICall_TaskEntry * taskentry = &ICall_tasks[i];
+ taskentry->task = taskhandle;
+ taskentry->queue = NULL;
+
+#ifdef FREERTOS
+ taskentry->syncHandle = xQueueCreate(20, sizeof(uint32_t));
+#endif
+
+ if (taskentry->syncHandle == 0)
+ {
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ }
+
+ ICall_leaveCSImpl(key);
+ return taskentry;
+ }
+ if (taskhandle == (TaskHandle_t) ICall_tasks[i].task)
+ {
+ ICall_leaveCSImpl(key);
+ return &ICall_tasks[i];
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return NULL;
+}
+
+/* See header file for comments. */
+ICall_EntityID ICall_searchServiceEntity(ICall_ServiceEnum service)
+{
+ size_t i;
+ ICall_CSState key;
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Empty slot */
+ break;
+ }
+ if (service == ICall_entities[i].service)
+ {
+ ICall_leaveCSImpl(key);
+ return (ICall_EntityID) i;
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return ICALL_INVALID_ENTITY_ID;
+}
+
+/**
+ * @internal Searches for a service entity entry.
+ * @param service service id
+ * @return Pointer to entity entry of the service or
+ * NULL when none found.
+ */
+static ICall_entityEntry * ICall_searchService(ICall_ServiceEnum service)
+{
+ ICall_EntityID entity = ICall_searchServiceEntity(service);
+ if (entity == ICALL_INVALID_ENTITY_ID)
+ {
+ return NULL;
+ }
+ return &ICall_entities[entity];
+}
+
+/* Dispatcher implementation. See ICall_dispatcher declaration
+ * for comment. */
+static ICall_Errno ICall_dispatch(ICall_FuncArgsHdr * args)
+{
+ ICall_entityEntry * entity;
+
+ entity = ICall_searchService(args->service);
+ if (!entity)
+ {
+ return ICALL_ERRNO_INVALID_SERVICE;
+ }
+ if (!entity->fn)
+ {
+ return ICALL_ERRNO_INVALID_FUNCTION;
+ }
+
+ return entity->fn(args);
+}
+
+/* See header file for comments */
+ICall_Dispatcher ICall_dispatcher = ICall_dispatch;
+
+/* Static instance of ICall_RemoteTaskArg to pass to
+ * remote task entry function.
+ * See header file for comments */
+static const ICall_RemoteTaskArg ICall_taskEntryFuncs = { ICall_dispatch, ICall_enterCSImpl, ICall_leaveCSImpl };
+
+/**
+ * @internal Thread entry function wrapper that complies with
+ * OS.
+ * @param arg0 actual entry function
+ * @param arg1 ignored
+ */
+TaskHandle_t RemoteTask = NULL;
+
+// pthread_t RemoteTask;
+
+struct argsForPosixTaskStart
+{
+ void * arg0;
+ void * arg1;
+};
+struct argsForPosixTaskStart POSIX_args;
+
+typedef void (*TaskFunction_t)(void *);
+
+static void ICall_taskEntry(void * arg)
+
+{
+ void * arg0 = ((struct argsForPosixTaskStart *) (arg))->arg0;
+ void * arg1 = ((struct argsForPosixTaskStart *) (arg))->arg1;
+
+ ICall_CSState key;
+ key = ICall_enterCSImpl();
+ if (ICall_newTask(ICall_taskSelf()) == NULL)
+ {
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ }
+ ICall_leaveCSImpl(key);
+
+ /* Attempt to yield prior to running task */
+ taskYIELD();
+
+ ICall_RemoteTaskEntry entryfn = (ICall_RemoteTaskEntry) arg0;
+
+ entryfn(&ICall_taskEntryFuncs, (void *) arg1);
+
+ // return NULL;
+}
+
+#ifndef ICALL_JT
+/* forward reference */
+static void ICall_initPrim(void);
+#endif /* ICALL_JT */
+
+/* See header file for comments. */
+void ICall_init(void)
+{
+ size_t i;
+
+ for (i = 0; i < ICALL_MAX_NUM_TASKS; i++)
+ {
+ ICall_tasks[i].task = NULL;
+ ICall_tasks[i].queue = NULL;
+ }
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ ICall_entities[i].service = ICALL_SERVICE_CLASS_INVALID_ENTRY;
+ }
+
+#ifndef ICALL_JT
+ /* Initialize primitive service */
+ ICall_initPrim();
+#else
+ /* Initialize heap */
+#ifndef FREERTOS
+ ICall_heapInit();
+#endif // FREERTOS
+#endif
+}
+
+/* See header file for comments */
+void ICall_createRemoteTasksAtRuntime(ICall_RemoteTask_t * remoteTaskTable, uint8_t nbElems)
+{
+ size_t i;
+ /* ICALL_Task_disable is a cheap locking mechanism to lock tasks
+ * which may attempt to access the service call dispatcher
+ * till all services are registered.
+ */
+ UBaseType_t OriginalParam;
+ ICALL_Task_disable(&OriginalParam);
+ for (i = 0; i < nbElems; i++)
+ {
+#ifdef FREERTOS
+ BaseType_t xReturned;
+
+ /* Pass the args via external sturct (POSIX use only single arg) */
+ POSIX_args.arg0 = (void *) remoteTaskTable[i].startupEntry;
+ POSIX_args.arg1 = (void *) remoteTaskTable[i].ICall_imgInitParam;
+
+ xReturned = xTaskCreate(ICall_taskEntry, /* Function that implements the task. */
+ "x", /* Text name for the task. */
+ remoteTaskTable[i].imgTaskStackSize / sizeof(uint32_t), /* Stack size in words, not bytes. */
+ (void *) &POSIX_args, /* Parameter passed into the task. */
+ remoteTaskTable[i].imgTaskPriority, /* Priority at which the task is created. */
+ &RemoteTask); /* Used to pass out the created task's handle. */
+
+ if (xReturned == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
+ {
+ /* Creation of FreeRTOS task failed */
+ while (1)
+ ;
+ }
+ }
+ ICALL_Task_restore(&OriginalParam);
+#endif
+}
+
+/* See header file for comments */
+void ICall_createRemoteTasks(void)
+{
+ size_t i;
+ ICall_RemoteTask_t remoteTaskTable[ICALL_REMOTE_THREAD_COUNT];
+
+ for (i = 0; i < ICALL_REMOTE_THREAD_COUNT; i++)
+ {
+ remoteTaskTable[i].imgTaskPriority = ICall_threadPriorities[i];
+ remoteTaskTable[i].imgTaskStackSize = ICall_threadStackSizes[i];
+ remoteTaskTable[i].startupEntry = icall_threadEntries[i];
+ remoteTaskTable[i].ICall_imgInitParam = (void *) ICall_getInitParams(i);
+ }
+ ICall_createRemoteTasksAtRuntime(remoteTaskTable, ICALL_REMOTE_THREAD_COUNT);
+}
+
+#ifdef FREERTOS
+void ICALL_Task_disable(UBaseType_t * OriginalParam)
+
+#else
+ void ICALL_Task_disable(struct sched_param * OriginalParam)
+#endif
+{
+
+#ifdef FREERTOS
+ TaskStatus_t pxTaskStatus;
+ vTaskGetInfo(ICall_taskSelf(), &pxTaskStatus, pdFALSE, eInvalid);
+ *OriginalParam = pxTaskStatus.uxCurrentPriority;
+
+ vTaskPrioritySet(ICall_taskSelf(), configMAX_PRIORITIES - 1);
+#endif
+}
+#ifdef FREERTOS
+void ICALL_Task_restore(UBaseType_t * OriginalParam)
+#else
+ void ICALL_Task_restore(struct sched_param * OriginalParam)
+#endif
+{
+
+#ifdef FREERTOS
+ vTaskPrioritySet(ICall_taskSelf(), *OriginalParam);
+
+#else
+ pthread_t pthreadID = pthread_self();
+ pthread_setschedparam(pthreadID, 0, OriginalParam);
+#endif
+}
+
+/* See header file for comments */
+ICall_TaskHandle ICall_getRemoteTaskHandle(uint8 index)
+{
+ TaskHandle_t * task = NULL;
+
+ UBaseType_t OriginalParam;
+ ICALL_Task_disable(&OriginalParam);
+
+ if (index < ICALL_MAX_NUM_TASKS)
+ {
+ task = &ICall_tasks[index].task;
+ }
+
+ ICALL_Task_restore(&OriginalParam);
+
+ return ((ICall_TaskHandle) task);
+}
+
+/* Primitive service implementation follows */
+
+#ifndef ICALL_JT
+/**
+ * @internal Enrolls a service
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when service id is already
+ * registered by another entity.
+ * @ref ICALL_ERRNO_NO_RESOURCE when maximum number of services
+ * are already registered.
+ */
+static ICall_Errno ICall_primEnroll(ICall_EnrollServiceArgs * args)
+{
+ size_t i;
+ ICall_TaskEntry * taskentry = ICall_newTask(Task_self());
+ ICall_CSState key;
+
+ /* Note that certain service does not handle a message
+ * and hence, taskentry might be NULL.
+ */
+ if (taskentry == NULL)
+ {
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Use this entry */
+ ICall_entities[i].service = args->service;
+ ICall_entities[i].task = taskentry;
+ ICall_entities[i].fn = args->fn;
+ args->entity = (ICall_EntityID) i;
+ args->msgSyncHdl = taskentry->syncHandle;
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_SUCCESS;
+ }
+ else if (args->service == ICall_entities[i].service)
+ {
+ /* Duplicate service enrollment */
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+ }
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_NO_RESOURCE;
+}
+
+/**
+ * @internal Registers an application
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ */
+static ICall_Errno ICall_primRegisterApp(ICall_RegisterAppArgs * args)
+{
+ size_t i;
+ ICall_TaskEntry * taskentry = ICall_newTask(Task_self());
+ ICall_CSState key;
+
+ if (!taskentry)
+ {
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Use this entry */
+ ICall_entities[i].service = ICALL_SERVICE_CLASS_APPLICATION;
+ ICall_entities[i].task = taskentry;
+ ICall_entities[i].fn = NULL;
+ args->entity = (ICall_EntityID) i;
+ args->msgSyncHdl = taskentry->syncHandle;
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_SUCCESS;
+ }
+ }
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_NO_RESOURCE;
+}
+
+/**
+ * @internal Allocates memory block for a message.
+ * @param args arguments
+ */
+static ICall_Errno ICall_primAllocMsg(ICall_AllocArgs * args)
+{
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) ICall_heapMalloc(sizeof(ICall_MsgHdr) + args->size);
+
+ if (!hdr)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ hdr->len = args->size;
+ hdr->next = NULL;
+ hdr->dest_id = ICALL_UNDEF_DEST_ID;
+ args->ptr = (void *) (hdr + 1);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Frees the memory block allocated for a message.
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS
+ */
+static ICall_Errno ICall_primFreeMsg(ICall_FreeArgs * args)
+{
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) args->ptr - 1;
+ ICall_heapFree(hdr);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * Allocates a memory block.
+ * Note that this function is for use by ICall implementation.
+ *
+ * @param size size in bytes
+ * @return pointer to the allocated memory block or NULL
+ */
+void * ICall_mallocImpl(uint_fast16_t size)
+{
+ return ICall_heapMalloc(size);
+}
+
+/**
+ * Frees a memory block.
+ * Note that this function is for use by ICall implementation.
+ *
+ * @param ptr pointer to the memory block
+ */
+void ICall_freeImpl(void * ptr)
+{
+ ICall_heapFree(ptr);
+}
+
+/**
+ * @internal Allocates a memory block
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when memory block cannot
+ * be allocated.
+ */
+static ICall_Errno ICall_primMalloc(ICall_AllocArgs * args)
+{
+ args->ptr = ICall_heapMalloc(args->size);
+ if (args->ptr == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Frees a memory block
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS
+ */
+static ICall_Errno ICall_primFree(ICall_FreeArgs * args)
+{
+ ICall_heapFree(args->ptr);
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_JT */
+
+/**
+ * @internal Queues a message to a message queue.
+ * @param q_ptr message queue
+ * @param msg_ptr message pointer
+ */
+static void ICall_msgEnqueue(ICall_MsgQueue * q_ptr, void * msg_ptr)
+{
+ void * list;
+ ICall_CSState key;
+
+ // Hold off interrupts
+ key = ICall_enterCSImpl();
+
+ ICALL_MSG_NEXT(msg_ptr) = NULL;
+ // If first message in queue
+ if (*q_ptr == NULL)
+ {
+ *q_ptr = msg_ptr;
+ }
+ else
+ {
+ // Find end of queue
+ for (list = *q_ptr; ICALL_MSG_NEXT(list) != NULL; list = ICALL_MSG_NEXT(list))
+ ;
+
+ // Add message to end of queue
+ ICALL_MSG_NEXT(list) = msg_ptr;
+ }
+
+ // Re-enable interrupts
+ ICall_leaveCSImpl(key);
+}
+
+/**
+ * @internal Dequeues a message from a message queue
+ * @param q_ptr message queue pointer
+ * @return Dequeued message pointer or NULL if none.
+ */
+static void * ICall_msgDequeue(ICall_MsgQueue * q_ptr)
+{
+ void * msg_ptr = NULL;
+ ICall_CSState key;
+
+ // Hold off interrupts
+ key = ICall_enterCSImpl();
+
+ if (*q_ptr != NULL)
+ {
+ // Dequeue message
+ msg_ptr = *q_ptr;
+ *q_ptr = ICALL_MSG_NEXT(msg_ptr);
+ ICALL_MSG_NEXT(msg_ptr) = NULL;
+ ICALL_MSG_DEST_ID(msg_ptr) = ICALL_UNDEF_DEST_ID;
+ }
+
+ // Re-enable interrupts
+ ICall_leaveCSImpl(key);
+
+ return msg_ptr;
+}
+
+/**
+ * @internal Prepends a list of messages to a message queue
+ * @param q_ptr message queue pointer
+ * @param head message list to prepend
+ */
+static void ICall_msgPrepend(ICall_MsgQueue * q_ptr, ICall_MsgQueue head)
+{
+ void * msg_ptr = NULL;
+ ICall_CSState key;
+
+ // Hold off interrupts
+ key = ICall_enterCSImpl();
+
+ if (head != NULL)
+ {
+ /* Find the end of the queue */
+ msg_ptr = head;
+ while (ICALL_MSG_NEXT(msg_ptr) != NULL)
+ {
+ msg_ptr = ICALL_MSG_NEXT(msg_ptr);
+ }
+ ICALL_MSG_NEXT(msg_ptr) = *q_ptr;
+ *q_ptr = head;
+ }
+
+ // Re-enable interrupts
+ ICall_leaveCSImpl(key);
+}
+
+#ifndef ICALL_JT
+/**
+ * @internal Sends a message to an entity.
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when either src
+ * or dest is not a valid entity id or when
+ * dest is an entity id of an entity that does
+ * not receive a message
+ * (e.g., ICall primitive service entity).
+ */
+static ICall_Errno ICall_primSend(ICall_SendArgs * args)
+{
+ ICall_CSState key;
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) args->msg - 1;
+
+ if (args->dest.entityId >= ICALL_MAX_NUM_ENTITIES || args->src >= ICALL_MAX_NUM_ENTITIES)
+ {
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+ key = ICall_enterCSImpl();
+ if (!ICall_entities[args->dest.entityId].task)
+ {
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+
+ ICall_leaveCSImpl(key);
+ /* Note that once the entry is valid,
+ * the value does not change and hence it is OK
+ * to leave the critical section.
+ */
+
+ hdr->srcentity = args->src;
+ hdr->dstentity = args->dest.entityId;
+ hdr->format = args->format;
+ ICall_msgEnqueue(&ICall_entities[args->dest.entityId].task->queue, args->msg);
+ ICALL_SYNC_HANDLE_POST(ICall_entities[args->dest.entityId].task->syncHandle);
+
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Retrieves a message, queued to receive queue of the calling thread.
+ *
+ * @param args arguments
+ * @return @ref ICALL_ERRNO_SUCCESS when a message was successfully
+ * retrieved.
+ * @ref ICALL_ERRNO_NOMSG when no message was queued to
+ * the receive queue at the moment.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread
+ * does not have a received queue associated with it.
+ * This happens when neither ICall_enrollService() nor
+ * ICall_registerApp() was ever called from the calling
+ * thread.
+ */
+static ICall_Errno ICall_primFetchMsg(ICall_FetchMsgArgs * args)
+{
+ Task_Handle taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ ICall_MsgHdr * hdr;
+
+ if (!taskentry)
+ {
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ /* Successful */
+ args->msg = ICall_msgDequeue(&taskentry->queue);
+
+ if (args->msg == NULL)
+ {
+ return ICALL_ERRNO_NOMSG;
+ }
+ hdr = (ICall_MsgHdr *) args->msg - 1;
+ args->src.entityId = hdr->srcentity;
+ args->dest = hdr->dstentity;
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_JT */
+
+/**
+ * @internal
+ * Transforms and entityId into a serviceId.
+ * @param entityId entity id
+ * @param servId pointer to a variable to store
+ * the resultant service id
+ * @return @ICALL_ERRNO_SUCCESS if the transformation was successful.
+ * @ICALL_ERRNO_INVALID_SERVICE if no matching service
+ * is found for the entity id.
+ */
+static ICall_Errno ICall_primEntityId2ServiceId(ICall_EntityID entityId, ICall_ServiceEnum * servId)
+{
+ if (entityId >= ICALL_MAX_NUM_ENTITIES || ICall_entities[entityId].service == ICALL_SERVICE_CLASS_INVALID_ENTRY ||
+ ICall_entities[entityId].service == ICALL_SERVICE_CLASS_APPLICATION)
+ {
+ return ICALL_ERRNO_INVALID_SERVICE;
+ }
+ *servId = ICall_entities[entityId].service;
+ return ICALL_ERRNO_SUCCESS;
+}
+
+#ifndef ICALL_JT
+/**
+ * @internal Transforms and entityId into a serviceId.
+ * @param args arguments
+ * @return return values corresponding to those of ICall_entityId2ServiceId()
+ */
+static ICall_Errno ICall_primE2S(ICall_EntityId2ServiceIdArgs * args)
+{
+ return ICall_primEntityId2ServiceId(args->entityId, &args->servId);
+}
+
+/**
+ * @internal Sends a message to a registered server.
+ * @param args arguments corresponding to those of ICall_sendServiceMsg().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_SERVICE when the 'dest'
+ * is unregistered service.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when the 'src'
+ * is not a valid entity id or when 'dest' is
+ * is a service that does not receive a message
+ * (such as ICall primitive service).
+ */
+static ICall_Errno ICall_primSendServiceMsg(ICall_SendArgs * args)
+{
+ ICall_EntityID dstentity = ICall_searchServiceEntity(args->dest.servId);
+
+ if (dstentity == ICALL_INVALID_ENTITY_ID)
+ {
+ return ICALL_ERRNO_INVALID_SERVICE;
+ }
+ args->dest.entityId = dstentity;
+ return ICall_primSend(args);
+}
+
+/**
+ * @internal Retrieves a message received at the message queue
+ * associated with the calling thread.
+ *
+ * Note that this function should be used by an application
+ * which does not expect any message from non-server entity.
+ *
+ * @param args arguments corresponding to those of ICall_fetchServiceMsg()
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ * and a message was retrieved.
+ * @ref ICALL_ERRNO_NOMSG when there is no queued message
+ * at the moment.
+ * @ref ICALL_ERRNO_CORRUPT_MSG when a message queued in
+ * front of the thread's receive queue was not sent by
+ * a server. Note that in this case, the message is
+ * not retrieved but thrown away.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
+ * called from a thread which has not registered
+ * an entity, either through ICall_enrollService()
+ * or through ICall_registerApp().
+ */
+static ICall_Errno ICall_primFetchServiceMsg(ICall_FetchMsgArgs * args)
+{
+ ICall_ServiceEnum servId;
+ ICall_Errno errno = ICall_primFetchMsg(args);
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ if (ICall_primEntityId2ServiceId(args->src.entityId, &servId) != ICALL_ERRNO_SUCCESS)
+ {
+ /* Source entity ID cannot be translated to service id */
+ ICall_freeMsg(args->msg);
+ return ICALL_ERRNO_CORRUPT_MSG;
+ }
+ args->src.servId = servId;
+
+#ifdef ICALL_EVENTS
+ /*
+ * Because Events are binary flags, the task's queue must be checked for
+ * any remaining messages. If there are the ICall event flag must be
+ * re-posted due to it being cleared on the last pend.
+ */
+ ICall_primRepostSync();
+#endif // ICALL_EVENTS
+ }
+ return errno;
+}
+#endif /* ICALL_JT */
+/**
+ * @internal
+ * Converts milliseconds to number of ticks.
+ * @param msecs milliseconds
+ * @param ticks pointer to a variable to store the resultant number of ticks
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when conversion failed
+ * as the input goes out of range for the output data type.
+ */
+static ICall_Errno ICall_msecs2Ticks(uint_fast32_t msecs, uint32_t * ticks)
+{
+ uint_fast64_t intermediate = msecs;
+
+ /*convert to microSec*/
+ intermediate *= 1000;
+ /*divide with the ticks perios*/
+ intermediate /= ICall_getTickPeriod();
+ if (intermediate >= ((uint_fast64_t) 1 << (sizeof(uint32_t) * 8 - 1)))
+ {
+ /* Out of range.
+ * Note that we use only half of the range so that client can
+ * determine whether the time has passed or time has yet to come.
+ */
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+ *ticks = (uint32_t) intermediate;
+ return ICALL_ERRNO_SUCCESS;
+}
+
+#ifndef ICALL_JT
+/**
+ * @internal
+ * Waits for a signal to the synchronization object associated with the calling
+ * thread.
+ *
+ * Note that the synchronization object associated with a thread is signaled
+ * when a message is queued to the message receive queue of the thread
+ * or when ICall_signal() function is called onto the synchronization object.
+ *
+ * @param args arguments corresponding to those of ICall_wait().
+ * @return @ref ICALL_ERRNO_SUCCESS when the synchronization object is
+ * signaled.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the synchronization object being signaled.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when the milliseconds
+ * is greater than the value of ICall_getMaxMSecs().
+ */
+static ICall_Errno ICall_primWait(ICall_WaitArgs * args)
+{
+ Task_Handle taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ uint32_t timeout;
+
+ {
+ BIOS_ThreadType threadtype = BIOS_getThreadType();
+
+ if (threadtype == BIOS_ThreadType_Hwi || threadtype == BIOS_ThreadType_Swi)
+ {
+ /* Blocking call is not allowed from Hwi or Swi.
+ * Note that though theoretically, Swi or lower priority Hwi may block
+ * on an event to be generated by a higher priority Hwi, it is not a
+ * safe practice and hence it is disabled.
+ */
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ }
+
+ if (!taskentry)
+ {
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ /* Successful */
+ if (args->milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ /* Convert milliseconds to number of ticks */
+ ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return errno;
+ }
+ }
+
+ if (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
+ {
+ return ICALL_ERRNO_SUCCESS;
+ }
+
+ return ICALL_ERRNO_TIMEOUT;
+}
+
+/**
+ * @internal signals a synchronziation object.
+ * @param args arguments corresponding to those of ICall_signal()
+ * @return return value corresponding to those of ICall_signal()
+ */
+static ICall_Errno ICall_primSignal(ICall_SignalArgs * args)
+{
+ ICALL_SYNC_HANDLE_POST(args->syncHandle);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal aborts program
+ * @param args arguments corresponding to those of ICall_abort()
+ * @return return value corresponding to those of ICall_abort()
+ */
+static ICall_Errno ICall_primAbort(ICall_FuncArgsHdr * args)
+{
+ ICALL_HOOK_ABORT_FUNC();
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Enables an interrupt.
+ * @param args arguments corresponding to those of ICall_enableint()
+ * @return return values corresponding to those of ICall_enableint()
+ */
+static ICall_Errno ICall_primEnableint(ICall_intNumArgs * args)
+{
+ Hwi_enableinterrupt(args->intnum);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Disables an interrupt.
+ * @param args arguments corresponding to those of ICall_disableint()
+ * @return return values corresponding to those of ICall_disableint()
+ */
+static ICall_Errno ICall_primDisableint(ICall_intNumArgs * args)
+{
+ Hwi_disableinterrupt(args->intnum);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Enables master interrupt and context switching.
+ * @param args arguments corresponding to those of ICall_enableMint()
+ * @return return values corresponding to those of ICall_enableMint()
+ */
+static ICall_Errno ICall_primEnableMint(ICall_FuncArgsHdr * args)
+{
+ Hwi_enable();
+ Swi_enable();
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Disables master interrupt and context switching.
+ * @param args arguments corresponding to those of ICall_disableMint()
+ * @return return values corresponding to those of ICall_disableMint()
+ */
+static ICall_Errno ICall_primDisableMint(ICall_FuncArgsHdr * args)
+{
+ Swi_disable();
+ Hwi_disable();
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal registers an interrupt service routine
+ * @param args arguments corresponding to those of ICall_registerISR()
+ * @return return values corresponding to those of ICall_registerISR()
+ */
+static ICall_Errno ICall_primRegisterISR(ICall_RegisterISRArgs * args)
+{
+ Hwi_Params hwiParams;
+
+ Hwi_Params_init(&hwiParams);
+ hwiParams.priority = 0xE0; // default all registered ints to lowest priority
+
+ if (Hwi_create(args->intnum, (void (*)((void *) )) args->isrfunc, &hwiParams, NULL) == NULL)
+ {
+ ICALL_HOOK_ABORT_FUNC();
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal registers an interrupt service routine
+ * @param args arguments corresponding to those of ICall_registerISR_Ext()
+ * @return return values corresponding to those of ICall_registerISR_ext()
+ */
+static ICall_Errno ICall_primRegisterISR_Ext(ICall_RegisterISRArgs_Ext * args)
+{
+ Hwi_Params hwiParams;
+
+ Hwi_Params_init(&hwiParams);
+ hwiParams.priority = args->intPriority;
+
+ if (Hwi_create(args->intnum, (void (*)((void *) )) args->isrfunc, &hwiParams, NULL) == NULL)
+ {
+ ICALL_HOOK_ABORT_FUNC();
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Gets tick counter value
+ * @param args arguments corresponding to those of ICall_getTicks()
+ * @return return values corresponding to those of ICall_getTicks()
+ */
+static ICall_Errno ICall_primGetTicks(ICall_Getuint32_tArgs * args)
+{
+ args->value = Clock_getTicks();
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_JT */
+
+/**
+ * @internal
+ * Clock event handler function.
+ * This function is used to implement the wakeup scheduler.
+ *
+ * @param arg an @ref ICall_ScheduleEntry
+ */
+
+static void ICall_clockFunc(uintptr_t arg)
+{
+ ICall_ScheduleEntry * entry = (ICall_ScheduleEntry *) arg;
+
+ entry->cback(entry->arg);
+}
+
+#ifndef ICALL_JT
+/**
+ * @internal
+ * Set up or restart a timer.
+ *
+ * @param args arguments corresponding to those of ICall_setTimer()
+ * @return @ref ICALL_ERRNO_SUCCESS when successful;
+ * @ref ICALL_ERRNO_INVALID_PARAMETER if timer designated by the
+ * timer ID value was not set up before.
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ * Check ICall heap size and OS heap size if this happens.
+ */
+static ICall_Errno ICall_primSetTimer(ICall_SetTimerArgs * args)
+{
+ ICall_ScheduleEntry * entry;
+
+ if (args->timerid == ICALL_INVALID_TIMER_ID)
+ {
+ Clock_Params params;
+
+ /* Create a new timer */
+ entry = ICall_heapMalloc(sizeof(ICall_ScheduleEntry));
+ if (entry == NULL)
+ {
+ /* allocation failed */
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ Clock_Params_init(¶ms);
+ params.startFlag = FALSE;
+ params.period = 0;
+ params.arg = ((void *) ) entry;
+ entry->clock = Clock_create(ICall_clockFunc, args->timeout, ¶ms, NULL);
+ if (!entry->clock)
+ {
+ /* abort */
+ ICall_abort();
+ ICall_heapFree(entry);
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ entry->cback = args->cback;
+ entry->arg = args->arg;
+ args->timerid = (ICall_TimerID) entry;
+ }
+ else
+ {
+ ICall_CSState key;
+
+ entry = (ICall_ScheduleEntry *) args->timerid;
+
+ /* Critical section is entered to disable interrupts that might cause call
+ * to callback due to race condition */
+ key = ICall_enterCriticalSection();
+ Clock_stop(entry->clock);
+ entry->arg = args->arg;
+ ICall_leaveCriticalSection(key);
+ }
+
+ Clock_setTimeout(entry->clock, args->timeout);
+ Clock_start(entry->clock);
+
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal
+ * Set up or restart a timer.
+ *
+ * @param args arguments corresponding to those of ICall_setTimerMSecs()
+ * @return @ref ICALL_ERRNO_SUCCESS when successful;
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when msecs is greater than
+ * maximum value supported.
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ * Check ICall heap size and OS heap size if this happens.
+ */
+static ICall_Errno ICall_primSetTimerMSecs(ICall_SetTimerArgs * args)
+{
+ uint32_t ticks;
+ /* Convert to tick time */
+ ICall_Errno errno = ICall_msecs2Ticks(args->timeout, &ticks);
+
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return errno;
+ }
+ args->timeout = ticks;
+ return ICall_primSetTimer(args);
+}
+
+/**
+ * @internal
+ * Stops a timer.
+ *
+ * @param args arguments corresponding to those of ICall_stopTimer()
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when successful;
+ * @ref ICALL_ERRNO_INVALID_PARAMETER
+ * if id is @ref ICALL_INVALID_TIMER_ID.
+ */
+static ICall_Errno ICall_primStopTimer(ICall_StopTimerArgs * args)
+{
+ ICall_ScheduleEntry * entry = (ICall_ScheduleEntry *) args->timerid;
+
+ if (args->timerid == ICALL_INVALID_TIMER_ID)
+ {
+ return ICALL_ERRNO_INVALID_PARAMETER;
+ }
+
+ Clock_stop(entry->clock);
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Gets tick period
+ * @param args arguments corresponding to those of ICall_getTickPeriod()
+ * @return return values corresponding to those of ICall_getTickPeriod()
+ */
+static ICall_Errno ICall_primGetTickPeriod(ICall_Getuint32_tArgs * args)
+{
+ args->value = Clock_tickPeriod;
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal Gets maximum period supported
+ * @param args arguments corresponding to those of ICall_getMaxMSecs()
+ * @return return values corresponding to those of ICall_getMaxMSecs()
+ */
+static ICall_Errno ICall_primGetMaxMSecs(ICall_Getuint32_tArgs * args)
+{
+ uint_fast64_t tmp = ((uint_fast64_t) 0x7ffffffful) * Clock_tickPeriod;
+ tmp /= 1000;
+ if (tmp >= 0x80000000ul)
+ {
+ tmp = 0x7ffffffful;
+ }
+ args->value = (uint_least32_t) tmp;
+ return ICALL_ERRNO_SUCCESS;
+}
+
+/**
+ * @internal
+ * Waits for a message that matches comparison
+ *
+ * @param args arguments corresponding to those of ICall_waitMatch().
+ * @return @ref ICALL_ERRNO_SUCCESS when the synchronization object is
+ * signaled.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the semaphore being signaled.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when the milliseconds
+ * is greater than the value of ICall_getMaxMSecs().
+ */
+static ICall_Errno ICall_primWaitMatch(ICall_WaitMatchArgs * args)
+{
+ Task_Handle taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ ICall_MsgQueue prependQueue = NULL;
+#ifndef ICALL_EVENTS
+ uint_fast16_t consumedCount = 0;
+#endif
+ uint32_t timeout;
+ uint_fast32_t timeoutStamp;
+ ICall_Errno errno;
+
+ {
+ BIOS_ThreadType threadtype = BIOS_getThreadType();
+
+ if (threadtype == BIOS_ThreadType_Hwi || threadtype == BIOS_ThreadType_Swi)
+ {
+ /* Blocking call is not allowed from Hwi or Swi.
+ * Note that though theoretically, Swi or lower priority Hwi may block
+ * on an event to be generated by a higher priority Hwi, it is not a
+ * safe practice and hence it is disabled.
+ */
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ }
+
+ if (!taskentry)
+ {
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ /* Successful */
+ if (args->milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ /* Convert milliseconds to number of ticks */
+ errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return errno;
+ }
+ }
+
+ errno = ICALL_ERRNO_TIMEOUT;
+ timeoutStamp = Clock_getTicks() + timeout;
+ while (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
+ {
+ ICall_FetchMsgArgs fetchArgs;
+ ICall_ServiceEnum servId;
+ errno = ICall_primFetchMsg(&fetchArgs);
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ if (ICall_primEntityId2ServiceId(fetchArgs.src.entityId, &servId) == ICALL_ERRNO_SUCCESS)
+ {
+ if (args->matchFn(servId, fetchArgs.dest, fetchArgs.msg))
+ {
+ /* Matching message found*/
+ args->servId = servId;
+ args->dest = fetchArgs.dest;
+ args->msg = fetchArgs.msg;
+ errno = ICALL_ERRNO_SUCCESS;
+ break;
+ }
+ }
+ /* Message was received but it wasn't expected one.
+ * Add to the prepend queue */
+ ICall_msgEnqueue(&prependQueue, fetchArgs.msg);
+#ifdef ICALL_EVENTS
+ /* Event are binary semaphore, so if several messsages are posted while
+ * we are processing one, it's possible that some of them are 'missed' and
+ * not processed. Sending a event to ourself force this loop to run until
+ * all the messages in the queue are processed.
+ */
+ ICALL_SYNC_HANDLE_POST(taskentry->syncHandle);
+#endif
+ }
+
+ /* Prepare for timeout exit */
+ errno = ICALL_ERRNO_TIMEOUT;
+
+#ifndef ICALL_EVENTS
+ /* Keep the decremented semaphore count */
+ consumedCount++;
+#endif /* ICALL_EVENTS */
+ if (timeout != BIOS_WAIT_FOREVER && timeout != BIOS_NO_WAIT)
+ {
+ /* Readjust timeout */
+ uint32_t newTimeout = timeoutStamp - Clock_getTicks();
+ if (newTimeout == 0 || newTimeout > timeout)
+ {
+ break;
+ }
+ timeout = newTimeout;
+ }
+ }
+
+#ifdef ICALL_EVENTS
+ /*
+ * Because Events are binary semaphores, the task's queue must be checked for
+ * any remaining messages. If there are, the ICall event flag must be
+ * re-posted due to it being cleared on the last pend.
+ */
+ ICall_primRepostSync();
+#endif // ICALL_EVENTS
+
+ /* Prepend retrieved irrelevant messages */
+ ICall_msgPrepend(&taskentry->queue, prependQueue);
+#ifndef ICALL_EVENTS
+ /* Re-increment the consumed semaphores */
+ for (; consumedCount > 0; consumedCount--)
+ {
+ Semaphore_post(taskentry->syncHandle);
+ }
+#endif /* ICALL_EVENTS */
+ return errno;
+}
+
+/**
+ * @internal
+ * Retrieves an entity ID of an entity associated with the calling thread.
+ *
+ * @param args arguments corresponding to those of ICall_getEntityId().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when no entity was associated
+ * with the calling thread.
+ */
+static ICall_Errno ICall_primGetEntityId(ICall_GetEntityIdArgs * args)
+{
+ Task_Handle taskhandle = Task_self();
+ ICall_CSState key;
+ size_t i;
+
+ {
+ BIOS_ThreadType threadtype = BIOS_getThreadType();
+
+ if (threadtype == BIOS_ThreadType_Hwi || threadtype == BIOS_ThreadType_Swi)
+ {
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ }
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Not found */
+ break;
+ }
+ if (ICall_entities[i].task->task == taskhandle)
+ {
+ /* Found */
+ args->entity = i;
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_SUCCESS;
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+}
+
+/**
+ * @internal
+ * Checks whether the calling thread provides the designated service.
+ *
+ * @param args arguments corresponding to those of ICall_threadServes().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread is
+ * unrecognized.
+ * @ref ICALL_ERRNO_INVALID_SERVICE if the service id is not enrolled
+ * by any thread.
+ */
+static ICall_Errno ICall_primThreadServes(ICall_ThreadServesArgs * args)
+{
+ Task_Handle taskhandle;
+ ICall_CSState key;
+ size_t i;
+
+ {
+ BIOS_ThreadType threadtype = BIOS_getThreadType();
+
+ if (threadtype == BIOS_ThreadType_Hwi || threadtype == BIOS_ThreadType_Swi)
+ {
+ return ICALL_ERRNO_UNKNOWN_THREAD;
+ }
+ }
+
+ taskhandle = Task_self();
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Not found */
+ break;
+ }
+ else if (ICall_entities[i].service == args->servId)
+ {
+ args->result = (uint_fast8_t) (ICall_entities[i].task->task == taskhandle);
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_SUCCESS;
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_INVALID_SERVICE;
+}
+
+/**
+ * @internal
+ * Creates an RTOS task.
+ *
+ * @param args arguments corresponding to those of ICall_createTask().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
+ */
+static ICall_Errno ICall_primCreateTask(ICall_CreateTaskArgs * args)
+{
+ /* Task_Params is a huge structure.
+ * To reduce stack usage, heap is used instead.
+ * This implies that ICall_createTask() must be called before heap
+ * space may be exhausted.
+ */
+ Task_Params * params = (Task_Params *) ICall_heapMalloc(sizeof(Task_Params));
+ Task_Handle task;
+
+ if (params == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+
+ Task_Params_init(params);
+ params->priority = args->priority;
+ params->stackSize = args->stacksize;
+ params->arg0 = args->arg;
+
+ task = Task_create((Task_FuncPtr) args->entryfn, params, NULL);
+ ICall_heapFree(params);
+
+ if (task == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_JT */
+
+#ifdef ICALL_RTOS_EVENT_API
+/**
+ * @internal
+ * Creates an event.
+ *
+ * @param args arguments corresponding to those of ICall_createEvent().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
+ */
+static ICall_Errno ICall_primCreateEvent(ICall_CreateEventArgs * args)
+{
+ args->event = Event_create(NULL, NULL);
+
+ if (args->event == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_RTOS_EVENT_API */
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * @internal
+ * Creates a semaphore.
+ *
+ * @param args arguments corresponding to those of ICall_createSemaphore().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when task creation failed.
+ */
+static ICall_Errno ICall_primCreateSemaphore(ICall_CreateSemaphoreArgs * args)
+{
+ /* Semaphore_Params is a huge structure.
+ * To reduce stack usage, heap is used instead.
+ * This implies that ICall_createSemaphore() must be called before heap
+ * space may be exhausted.
+ */
+ Semaphore_Params * semParams = (Semaphore_Params *) ICall_heapMalloc(sizeof(Semaphore_Params));
+
+ if (semParams == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+
+ Semaphore_Params_init(semParams);
+ if (args->mode == ICALL_SEMAPHORE_MODE_BINARY)
+ {
+ semParams->mode = Semaphore_Mode_BINARY;
+ }
+
+ args->sem = Semaphore_create(args->initcount, semParams, NULL);
+ ICall_heapFree(semParams);
+
+ if (args->sem == NULL)
+ {
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_RTOS_SEMAPHORE_API */
+#ifdef ICALL_RTOS_EVENT_API
+/**
+ * @internal
+ * Waits on a ICALL_MSG_EVENT_ID.
+ *
+ * @param args arguments corresponding to those of ICall_waitEvent().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_TIMEOUT when timeout occurred.
+ */
+static ICall_Errno ICall_primWaitEvent(ICall_WaitEventArgs * args)
+{
+ uint32_t timeout;
+
+ if (args->milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return errno;
+ }
+ }
+
+ if (Event_pend(args->event, 0, ICALL_MSG_EVENT_ID, timeout))
+ {
+ return ICALL_ERRNO_SUCCESS;
+ }
+ return ICALL_ERRNO_TIMEOUT;
+}
+#endif /* ICALL_RTOS_EVENT_API */
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * @internal
+ * Waits on a semaphore.
+ *
+ * @param args arguments corresponding to those of ICall_waitSemaphore().
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_TIMEOUT when timeout occurred.
+ */
+static ICall_Errno ICall_primWaitSemaphore(ICall_WaitSemaphoreArgs * args)
+{
+ uint32_t timeout;
+
+ if (args->milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (args->milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ ICall_Errno errno = ICall_msecs2Ticks(args->milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return errno;
+ }
+ }
+ if (Semaphore_pend(args->sem, timeout))
+ {
+ return ICALL_ERRNO_SUCCESS;
+ }
+ return ICALL_ERRNO_TIMEOUT;
+}
+#endif /* ICALL_RTOS_SEMAPHORE_API */
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * @internal signals a semaphore
+ * @param args arguments corresponding to those of ICall_signal()
+ * @return return value corresponding to those of ICall_signal()
+ */
+static ICall_Errno ICall_primPostSemaphore(ICall_SignalArgs * args)
+{
+ Semaphore_post(args->syncHandle);
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_RTOS_EVENT_API */
+#ifdef ICALL_RTOS_EVENT_API
+/**
+ * @internal signals an event
+ * @param args arguments corresponding to those of ICall_signal()
+ * @return return value corresponding to those of ICall_signal()
+ */
+static ICall_Errno ICall_primPostEvent(ICall_SignalEventsArgs * args)
+{
+ Event_post(args->syncHandle, args->events);
+ return ICALL_ERRNO_SUCCESS;
+}
+#endif /* ICALL_RTOS_EVENT_API */
+/**
+ * @internal Primitive service function ID to handler function map
+ */
+#ifndef ICALL_JT
+static const struct _icall_primsvcfunc_map_entry_t
+{
+#ifdef COVERAGE_TEST
+ size_t id;
+#endif /* COVERAGE_TEST */
+ ICall_PrimSvcFunc func;
+} ICall_primSvcFuncs[] = {
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_ENROLL,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primEnroll },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_REGISTER_APP,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primRegisterApp },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_MSG_ALLOC,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primAllocMsg },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_MSG_FREE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primFreeMsg },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_MALLOC,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primMalloc },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_FREE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primFree },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SEND_MSG,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primSend },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_FETCH_MSG,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primFetchMsg },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SEND_SERV_MSG,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primSendServiceMsg },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_FETCH_SERV_MSG,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primFetchServiceMsg },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primWait },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SIGNAL,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primSignal },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_ABORT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primAbort },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_ENABLE_int,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primEnableint },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_DISABLE_int,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primDisableint },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_ENABLE_Mint,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primEnableMint },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_DISABLE_Mint,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primDisableMint },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_REGISTER_ISR,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primRegisterISR },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_GET_TICKS,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primGetTicks },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SET_TIMER_MSECS,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primSetTimerMSecs },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_GET_TICK_PERIOD,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primGetTickPeriod },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_GET_MAX_MILLISECONDS,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primGetMaxMSecs },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_ENTITY2SERVICE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primE2S },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_UPD_ACTIVITY_COUNTER,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrUpdActivityCounter },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_REGISTER_NOTIFY,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrRegisterNotify },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_MATCH,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primWaitMatch },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_GET_ENTITY_ID,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primGetEntityId },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SET_TIMER,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primSetTimer },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_STOP_TIMER,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primStopTimer },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_CONFIG_AC_ACTION,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrConfigACAction },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_REQUIRE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrRequire },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_DISPENSE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrDispense },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_THREAD_SERVES,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primThreadServes },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_IS_STABLE_XOSC_HF,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrIsStableXOSCHF },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_GET_TRANSITION_STATE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrGetTransitionState },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_CREATE_TASK,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primCreateTask },
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_CREATE_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primCreateSemaphore },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primWaitSemaphore },
+
+#else /* ICALL_RTOS_SEMAPHORE_API */
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ NULL },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ NULL },
+#endif /* ICALL_RTOS_SEMAPHORE_API */
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_SWITCH_XOSC_HF,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrSwitchXOSCHF },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_PWR_GET_XOSC_STARTUP_TIME,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICallPlatform_pwrGetXOSCStartupTime },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_REGISTER_ISR_EXT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primRegisterISR_Ext },
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_POST_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primPostSemaphore },
+#else /*ICALL_RTOS_SEMAPHORE_API */
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_POST_SEMAPHORE,
+#endif /* COVERAGE_TEST */
+ NULL }, /* ICALL_RTOS_SEMAPHORE_API */
+#endif
+
+#ifdef ICALL_RTOS_EVENT_API
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_CREATE_EVENT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primCreateEvent },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_EVENT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primWaitEvent },
+
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_POST_EVENT,
+#endif /* COVERAGE_TEST */
+ (ICall_PrimSvcFunc) ICall_primPostEvent },
+#else /*ICALL_RTOS_EVENT_API */
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_CREATE_EVENT,
+#endif /* COVERAGE_TEST */
+ NULL },
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_WAIT_EVENT,
+#endif /* COVERAGE_TEST */
+ NULL }, /* ICALL_RTOS_EVENT_API */
+ {
+#ifdef COVERAGE_TEST
+ ICALL_PRIMITIVE_FUNC_POST_EVENT,
+#endif /* COVERAGE_TEST */
+ NULL }, /* ICALL_RTOS_EVENT_API */
+#endif /* ICALL_RTOS_EVENT_API */
+};
+/**
+ * @internal
+ * Primitive service registered handler function
+ * @param args arguments
+ * @return error code
+ */
+static ICall_Errno ICall_primService(ICall_FuncArgsHdr * args)
+{
+ if (args->func >= sizeof(ICall_primSvcFuncs) / sizeof(ICall_primSvcFuncs[0]))
+ {
+ return ICALL_ERRNO_INVALID_FUNCTION;
+ }
+ return ICall_primSvcFuncs[args->func].func(args);
+}
+
+/**
+ * @internal Enrolls primitive service
+ */
+static void ICall_initPrim(void)
+{
+ ICall_entities[0].service = ICALL_SERVICE_CLASS_PRIMITIVE;
+ ICall_entities[0].fn = ICall_primService;
+
+ /* Initialize heap */
+ ICall_heapInit();
+
+ /* TODO: Think about freezing permanently allocated memory blocks
+ * for optimization.
+ * Now that multiple stack images may share the same heap.
+ * kick cannot be triggered by a single stack image.
+ * Hence, maybe there should be an alternative API to
+ * permanently allocate memory blocks, such as
+ * by allocating the blocks at the end of the heap space. */
+}
+#endif /* ICALL_JT */
+
+#ifdef COVERAGE_TEST
+/**
+ * @internal
+ * Verification function for ICall implementation
+ */
+void ICall_verify(void)
+{
+ size_t i;
+ for (i = 0; i < sizeof(ICall_primSvcFuncs) / sizeof(ICall_primSvcFuncs[0]); i++)
+ {
+ if (i != ICall_primSvcFuncs[i].id)
+ {
+ ICall_abort();
+ }
+ }
+}
+#endif /* COVERAGE_TEST */
+
+#ifdef ICALL_JT
+/**
+ * Registers an application.
+ * Note that this function must be called from the thread
+ * from which ICall_wait() function will be called.
+ *
+ * @param entity pointer to a variable to store entity id assigned
+ * to the application.
+ * @param msgsem pointer to a variable to store the synchronous object handle
+ * associated with the calling thread.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ */
+ICall_Errno ICall_registerApp(ICall_EntityID * entity, ICall_SyncHandle * msgSyncHdl)
+{
+
+ size_t i;
+ ICall_TaskEntry * taskentry = ICall_newTask(Task_self());
+ ICall_CSState key;
+
+ if (!taskentry)
+ {
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ return ICALL_ERRNO_NO_RESOURCE;
+ }
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Use this entry */
+ ICall_entities[i].service = ICALL_SERVICE_CLASS_APPLICATION;
+ ICall_entities[i].task = taskentry;
+ ICall_entities[i].fn = NULL;
+ *entity = (ICall_EntityID) i;
+ *msgSyncHdl = taskentry->syncHandle;
+ ICall_leaveCSImpl(key);
+ return ICALL_ERRNO_SUCCESS;
+ }
+ }
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_NO_RESOURCE);
+}
+
+/**
+ * Allocates memory block for a message.
+ * @param size size of the message body in bytes.
+ * @return pointer to the start of the message body of the newly
+ * allocated memory block, or NULL if the allocation
+ * failed.
+ */
+void * ICall_allocMsg(size_t size)
+{
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) ICall_heapMalloc(sizeof(ICall_MsgHdr) + size);
+
+ if (!hdr)
+ {
+ return NULL;
+ }
+ hdr->len = size;
+ hdr->next = NULL;
+ hdr->dest_id = ICALL_UNDEF_DEST_ID;
+ return ((void *) (hdr + 1));
+}
+
+/**
+ * Frees the memory block allocated for a message.
+ * @param msg pointer to the start of the message body
+ * which was returned from ICall_allocMsg().
+ */
+void ICall_freeMsg(void * msg)
+{
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) msg - 1;
+ ICall_heapFree(hdr);
+}
+
+/**
+ * Sends a message to a registered server.
+ * @param src Entity id of the sender of the message
+ * @param dest Service id
+ * @param format Message format:
+ * @ref ICALL_MSG_FORMAT_KEEP,
+ * @ref ICALL_MSG_FORMAT_1ST_CHAR_TASK_ID or
+ * @ref ICALL_MSG_FORMAT_3RD_CHAR_TASK_ID.
+ * Message format indicates whether and which
+ * field of the message must be transformed
+ * into a implementation specific sender
+ * identity for an external image.
+ * When a service message interface is defined,
+ * it may contain a field that is not understood
+ * by the client but only understood by
+ * the system on the server's side.
+ * The format provides an information to the
+ * messaging system on such a server
+ * so that it can generically tag necessary
+ * information to the message.
+ * @param msg pointer to the message body to send.
+ * Note that if message is successfully sent,
+ * the caller should not reference the message any
+ * longer.
+ * However, if the function fails, the caller
+ * still owns the reference to the message.
+ * That is, caller may attempt another send,
+ * or may free the memory block, etc.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_SERVICE when the 'dest'
+ * is unregistered service.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when the 'src'
+ * is an out of range entity id or when 'dest' is
+ * is a service that does not receive a message
+ * (such as ICall primitive service).
+ * Note that as far as 'src' is within the range,
+ * this function won't notice the 'src' entity id
+ * as invalid.
+ */
+
+ICall_Errno ICall_sendServiceMsg(ICall_EntityID src, ICall_ServiceEnum dest, ICall_MSGFormat format, void * msg)
+{
+ ICall_EntityID dstentity = ICall_searchServiceEntity(dest);
+
+ if (dstentity == ICALL_INVALID_ENTITY_ID)
+ {
+ return ICALL_ERRNO_INVALID_SERVICE;
+ }
+ return (ICall_send(src, dstentity, format, msg));
+}
+
+/**
+ * Retrieves a message received at the message queue
+ * associated with the calling thread.
+ *
+ * Note that this function should be used by an application
+ * which does not expect any message from non-server entity.
+ *
+ * @param src pointer to a variable to store the service id
+ * of the registered server which sent the retrieved
+ * message
+ * @param dest pointer to a variable to store the entity id
+ * of the destination of the message.
+ * @param msg pointer to a pointer variable to store the
+ * starting address of the message body being
+ * retrieved.
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ * and a message was retrieved.
+ * @ref ICALL_ERRNO_NOMSG when there is no queued message
+ * at the moment.
+ * @ref ICALL_ERRNO_CORRUPT_MSG when a message queued in
+ * front of the thread's receive queue was not sent by
+ * a server. Note that in this case, the message is
+ * not retrieved but thrown away.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
+ * called from a thread which has not registered
+ * an entity, either through ICall_enrollService()
+ * or through ICall_registerApp().
+ */
+ICall_Errno ICall_fetchServiceMsg(ICall_ServiceEnum * src, ICall_EntityID * dest, void ** msg)
+{
+ ICall_ServiceEnum servId;
+ ICall_Errno errno = ICall_fetchMsg((ICall_EntityID *) src, dest, msg);
+
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ if (ICall_primEntityId2ServiceId(*src, &servId) != ICALL_ERRNO_SUCCESS)
+ {
+ /* Source entity ID cannot be translated to service id */
+ ICall_freeMsg(*msg);
+ return ICALL_ERRNO_CORRUPT_MSG;
+ }
+ *src = servId;
+ }
+ return (errno);
+}
+#if 0
+void convertMilliToTimepec(struct timespec *timeoutPosix,uint32_t timeout)
+{
+ timeoutPosix->tv_sec = (timeout / 1000);
+ timeout = timeout % 1000;
+
+ /* 1 millisecond = 1 000 000 nanoseconds */
+ timeoutPosix->tv_nsec = timeout * 1000000;
+}
+#endif
+
+/**
+ * Waits for a signal to the semaphore associated with the calling thread.
+ *
+ * Note that the semaphore associated with a thread is signaled
+ * when a message is queued to the message receive queue of the thread
+ * or when ICall_signal() function is called onto the semaphore.
+ *
+ * @param milliseconds timeout period in milliseconds.
+ * @return @ref ICALL_ERRNO_SUCCESS when the semaphore is signaled.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the semaphore being signaled.
+ */
+ICall_Errno ICall_wait(uint_fast32_t milliseconds)
+{
+ TaskHandle_t taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ uint32_t timeout;
+ uint32_t event;
+
+ int16_t retVal = 0;
+
+ if (!taskentry)
+ {
+ return (ICALL_ERRNO_UNKNOWN_THREAD);
+ }
+ /* Successful */
+ if (milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ /* Convert milliseconds to number of ticks */
+ ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return (errno);
+ }
+ }
+
+#ifdef FREERTOS
+ if (HwiP_inISR())
+ {
+ xQueueReceiveFromISR(taskentry->syncHandle, (char *) &event, NULL);
+ }
+ else
+ {
+ xQueueReceive(taskentry->syncHandle, (char *) &event, milliseconds * 100);
+ }
+#endif
+ if (retVal != (-1))
+ {
+ return (ICALL_ERRNO_SUCCESS);
+ }
+
+ return (ICALL_ERRNO_TIMEOUT);
+}
+
+/**
+ * Signals a semaphore.
+ * @param msgsem handle of a synchronous object to signal
+ * @return @ref ICALL_ERRNO_SUCCESS
+ */
+ICall_Errno ICall_signal(ICall_SyncHandle msgSyncHdl)
+{
+ /* 0x80000000 is an internal Event_ID */
+ uint32_t msg_ptr = 0x80000000;
+ ICall_Errno status = ICALL_ERRNO_NO_RESOURCE;
+
+#ifdef FREERTOS
+ uint8_t statusQ;
+ if (HwiP_inISR())
+ {
+ statusQ = xQueueSendFromISR(msgSyncHdl, (char *) &msg_ptr, NULL);
+ }
+ else
+ {
+ statusQ = xQueueSend(msgSyncHdl, (char *) &msg_ptr, 0);
+ }
+
+ if (statusQ == pdTRUE)
+ {
+ status = ICALL_ERRNO_SUCCESS;
+ }
+#endif
+ return (status);
+}
+
+/**
+ * Registers a service entity
+ * @param service service id of the enrolling service
+ * @param fn handler function which handles function
+ * calls to the service.
+ * @param entity pointer to a variable to store the assigned entity id
+ * @param msgsem pointer to a variable to store the synchronous object handle
+ * associated with the calling thread.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when service id is already
+ * registered by another entity.
+ * @ref ICALL_ERRNO_NO_RESOURCE when maximum number of services
+ * are already registered.
+ */
+ICall_Errno ICall_enrollService(ICall_ServiceEnum service, ICall_ServiceFunc fn, ICall_EntityID * entity,
+ ICall_SyncHandle * msgSyncHdl)
+{
+ size_t i;
+ ICall_TaskEntry * taskentry = ICall_newTask(Task_self());
+ ICall_CSState key;
+
+ /* Note that certain service does not handle a message
+ * and hence, taskentry might be NULL.
+ */
+ if (taskentry == NULL)
+ {
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Use this entry */
+ ICall_entities[i].service = service;
+ ICall_entities[i].task = taskentry;
+ ICall_entities[i].fn = fn;
+ *entity = (ICall_EntityID) i;
+ *msgSyncHdl = taskentry->syncHandle;
+
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_SUCCESS);
+ }
+ else if (service == ICall_entities[i].service)
+ {
+ /* Duplicate service enrollment */
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+ }
+ /* abort */
+ ICALL_HOOK_ABORT_FUNC();
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_NO_RESOURCE);
+}
+#ifdef FREERTOS
+
+/**
+ * Allocates a memory block.
+ * @param size size of the block in bytes.
+ * @return address of the allocated memory block or NULL
+ * if allocation fails.
+ */
+
+void * ICall_heapMalloc(uint32_t size)
+{
+ void * ret = NULL;
+ ret = malloc(size);
+ return ret;
+}
+
+/**
+ * Frees an allocated memory block.
+ * @param msg pointer to a memory block to free.
+ */
+void ICall_heapFree(void * msg)
+{
+ free(msg);
+}
+
+/**
+ * Allocates a memory block, but check if enough memory will be left after the allocation.
+ * @param size size of the block in bytes.
+ * @return address of the allocated memory block or NULL
+ * if allocation fails.
+ */
+
+void * ICall_heapMallocLimited(uint_least16_t size)
+{
+ return malloc(size);
+}
+
+/**
+ * Get Statistic on Heap.
+ * @param stats pointer to a heapStats_t structure.
+ */
+
+/* Statistics currently are not supported via ICall apis.
+ * Please consider to use bget statistics (or any of your internal heap statistics) */
+void ICall_heapGetStats(ICall_heapStats_t * pStats) {}
+
+#endif // FREERTOS
+/**
+ * Allocates a memory block.
+ * @param size size of the block in bytes.
+ * @return address of the allocated memory block or NULL
+ * if allocation fails.
+ */
+void * ICall_malloc(uint_least16_t size)
+{
+ return (ICall_heapMalloc(size));
+}
+
+/**
+ * Frees an allocated memory block.
+ * @param msg pointer to a memory block to free.
+ */
+void ICall_free(void * msg)
+{
+ ICall_heapFree(msg);
+}
+
+/**
+ * Allocates a memory block, but check if enough memory will be left after the allocation.
+ * @param size size of the block in bytes.
+ * @return address of the allocated memory block or NULL
+ * if allocation fails.
+ */
+
+void * ICall_mallocLimited(uint_least16_t size)
+{
+ return (ICall_heapMallocLimited(size));
+}
+
+/**
+ * Get Statistic on Heap.
+ * @param stats pointer to a heapStats_t structure.
+ */
+void ICall_getHeapStats(ICall_heapStats_t * pStats)
+{
+ ICall_heapGetStats(pStats);
+}
+
+#ifdef HEAPMGR_METRICS
+/**
+ * @brief obtain heap usage metrics
+ * @param pBlkMax pointer to a variable to store max cnt of all blocks ever seen at once
+ * @param pBlkCnt pointer to a variable to store current cnt of all blocks
+ * @param pBlkFree pointer to a variable to store current cnt of free blocks
+ * @param pMemAlo pointer to a variable to store current total memory allocated
+ * @param pMemMax pointer to a variable to store max total memory ever allocated at once
+ * @param pMemUB pointer to a variable to store the upper bound of memory usage
+ */
+void ICall_getHeapMgrGetMetrics(uint32_t * pBlkMax, uint32_t * pBlkCnt, uint32_t * pBlkFree, uint32_t * pMemAlo, uint32_t * pMemMax,
+ uint32_t * pMemUB)
+{
+ ICall_heapMgrGetMetrics(pBlkMax, pBlkCnt, pBlkFree, pMemAlo, pMemMax, pMemUB);
+}
+
+#endif
+/**
+ * Sends a message to an entity.
+ * @param src entity id of the sender
+ * @param dest entity id of the destination of the message.
+ * @param format message format. See ICall_sendServiceMsg().
+ * @param msg pointer to the message body.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful.
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when either src
+ * or dest is not a valid entity id or when
+ * dest is an entity id of an entity that does
+ * not receive a message
+ * (e.g., ICall primitive service entity).
+ */
+ICall_Errno ICall_send(ICall_EntityID src, ICall_EntityID dest, ICall_MSGFormat format, void * msg)
+{
+ ICall_CSState key;
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) msg - 1;
+
+ if (dest >= ICALL_MAX_NUM_ENTITIES || src >= ICALL_MAX_NUM_ENTITIES)
+ {
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+ key = ICall_enterCSImpl();
+ if (!ICall_entities[dest].task)
+ {
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+
+ ICall_leaveCSImpl(key);
+ /* Note that once the entry is valid,
+ * the value does not change and hence it is OK
+ * to leave the critical section.
+ */
+
+ hdr->srcentity = src;
+ hdr->dstentity = dest;
+ hdr->format = format;
+
+ ICall_msgEnqueue(&ICall_entities[dest].task->queue, msg);
+ /* 0x80000000 is an internal event number */
+ uint32_t msg_ptr = 0x80000000;
+#ifdef FREERTOS
+ uint8_t status;
+
+ if (HwiP_inISR())
+ {
+ status = xQueueSendFromISR(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, NULL);
+ }
+ else
+ {
+ status = xQueueSend(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, 0);
+ }
+
+ if (status != pdPASS)
+ {
+ return status;
+ }
+#endif
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Retrieves a message, queued to receive queue of the calling thread.
+ *
+ * @param src pointer to a variable to store the sender entity id
+ * of the received message.
+ * @param dest pointer to a variable to store the destination entity id
+ * of the received message.
+ * @param msg pointer to a pointer variable to store the starting
+ * address of a received message body.
+ * @return @ref ICALL_ERRNO_SUCCESS when a message was successfully
+ * retrieved.
+ * @ref ICALL_ERRNO_NOMSG when no message was queued to
+ * the receive queue at the moment.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when the calling thread
+ * does not have a received queue associated with it.
+ * This happens when neither ICall_enrollService() nor
+ * ICall_registerApp() was ever called from the calling
+ * thread.
+ */
+ICall_Errno ICall_fetchMsg(ICall_EntityID * src, ICall_EntityID * dest, void ** msg)
+{
+ void * msgTemp;
+ TaskHandle_t taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ ICall_MsgHdr * hdr;
+
+ if (!taskentry)
+ {
+ return (ICALL_ERRNO_UNKNOWN_THREAD);
+ }
+ /* Successful */
+ msgTemp = ICall_msgDequeue(&taskentry->queue);
+
+ if (msgTemp == NULL)
+ {
+ return (ICALL_ERRNO_NOMSG);
+ }
+ hdr = (ICall_MsgHdr *) msgTemp - 1;
+ *src = hdr->srcentity;
+ *dest = hdr->dstentity;
+ *msg = msgTemp;
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Transforms and entityId into a serviceId.
+ * Note that this function is useful in case an application
+ * waits for messages from both a server and another application,
+ * in which case, the application can only use ICall_fetchMsg(),
+ * not ICall_fetchServiceMsg() because the latter will return
+ * @ref ICALL_ERRNO_CORRUPT_MSG when a message sent by the other
+ * application is about to be fetched.
+ * This function, then, is useful to retrieve service id
+ * matching the source entity id in case the source entity
+ * id is not that of the other application.
+ *
+ * @param entityId entity id
+ * @param servId pointer to a variable to store
+ * the resultant service id
+ * @return @ref ICALL_ERRNO_SUCCESS if the transformation was successful.
+ * @ref ICALL_ERRNO_INVALID_SERVICE if no matching service
+ * is found for the entity id.
+ */
+ICall_Errno ICall_entityId2ServiceId(ICall_EntityID entityId, ICall_ServiceEnum * servId)
+{
+ return ICall_primEntityId2ServiceId(entityId, servId);
+}
+
+/**
+ * Aborts.
+ *
+ * This is preferred over C runtime abort() function,
+ * in an external image since the C runtime abort() is only
+ * guaranteed in a root image which contains the C runtime
+ * entry function that is executed upon startup.
+ */
+ICall_Errno ICall_abort(void)
+{
+#ifdef HALNODEBUG
+#elif defined(EXT_HAL_ASSERT)
+ HAL_ASSERT(HAL_ASSERT_CAUSE_ICALL_ABORT);
+#else
+ {
+ volatile uint8_t j = 1;
+ while (j)
+ ;
+ }
+#endif /* EXT_HAL_ASSERT */
+ ICALL_HOOK_ABORT_FUNC();
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Enables interrupt.
+ * @param intnum interrupt number
+ * @return @ref ICALL_ERRNO_SUCCESS.
+ */
+ICall_Errno ICall_enableint(int intnum)
+{
+ Hwi_enableinterrupt(intnum);
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Disables interrupt
+ * @param intnum interrupt number
+ * @return @ref ICALL_ERRNO_SUCCESS
+ */
+ICall_Errno ICall_disableint(int intnum)
+{
+ Hwi_disableinterrupt(intnum);
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Gets the current tick counter value.
+ * @return current tick counter value
+ */
+uint_fast32_t ICall_getTicks(void)
+{
+ return (ClockP_getSystemTicks());
+}
+
+/**
+ * Gets the tick period.
+ * @return tick period in microseconds.
+ */
+uint_fast32_t ICall_getTickPeriod(void)
+{
+ return CLOCK_TICKS_PERIOD;
+}
+
+/**
+ * Gets the maximum timeout period supported by
+ * ICall_setTimerMSecs() function.
+ *
+ * @return maximum timeout period in milliseconds
+ */
+uint_fast32_t ICall_getMaxMSecs(void)
+{
+
+ uint_fast64_t tmp = ((uint_fast64_t) 0x7ffffffful) * (ICall_getTickPeriod());
+ tmp /= 1000;
+ if (tmp >= 0x80000000ul)
+ {
+ tmp = 0x7ffffffful;
+ }
+ return ((uint_least32_t) tmp);
+}
+
+/**
+ * Set up or restart a timer.
+ * Note that the timer setup initially by this function may be restarted
+ * using ICall_setTimer() function as well.
+ *
+ * @param msecs timeout period in milliseconds after which callback function
+ * shall be called.
+ * @param cback callback function pointer
+ * @param arg argument to pass to the callback function
+ * @param id pointer to the timer ID.
+ * If a new timer must be set up, the value of the timer ID
+ * must be set to @ref ICALL_INVALID_TIMER_ID when making this
+ * call and when the function returns successfully, the variable
+ * will be assigned a new timer ID value.
+ * The value other than @ref ICALL_INVALID_TIMER_ID shall be
+ * regarded as a request to restart the earlier set timer.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful;
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when msecs is greater than
+ * maximum value supported;
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ * Check ICall heap size and OS heap size if this happens.
+ *
+ * @see ICall_getMaxMSecs()
+ */
+ICall_Errno ICall_setTimerMSecs(uint_fast32_t msecs, ICall_TimerCback cback, void * arg, ICall_TimerID * id)
+{
+ uint32_t ticks;
+ uint32_t timeout;
+ /* Convert to tick time */
+ ICall_Errno errno = ICall_msecs2Ticks(msecs, &ticks);
+
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return (errno);
+ }
+ timeout = ticks;
+ ICall_setTimer(timeout, cback, arg, id);
+
+ return (errno);
+}
+
+/**
+ * Set up or restart a timer.
+ * Note that the timer setup initially by this function may be restarted
+ * using ICall_setTimerMSecs() function as well.
+ *
+ * @param ticks timeout period in ticks after which the callback function
+ * shall be called.
+ * @param cback callback function pointer
+ * @param arg argument to pass to the callback function
+ * @param id pointer to the timer ID.
+ * If a new timer must be set up, the value of the timer ID
+ * must be set to @ref ICALL_INVALID_TIMER_ID when making this
+ * call and when the function returns successfully, the variable
+ * will be assigned a new timer ID value.
+ * The value other than @ref ICALL_INVALID_TIMER_ID shall be
+ * regarded as a request to restart the earlier set timer.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful;
+ * @ref ICALL_ERRNO_NO_RESOURCE when ran out of resource.
+ * Check ICall heap size and OS heap size if this happens.
+ *
+ * @see ICall_getTickPeriod()
+ */
+
+ICall_Errno ICall_setTimer(uint32_t ticks, ICall_TimerCback cback, void * arg, ICall_TimerID * id)
+{
+
+ ICall_ScheduleEntry * entry;
+
+ if (*id == ICALL_INVALID_TIMER_ID)
+ {
+ ClockP_Params params;
+
+ /* Create a new timer */
+ entry = ICall_heapMalloc(sizeof(ICall_ScheduleEntry));
+ if (entry == NULL)
+ {
+ /* allocation failed */
+ return (ICALL_ERRNO_NO_RESOURCE);
+ }
+ ClockP_Params_init(¶ms);
+ params.startFlag = FALSE;
+ params.period = 0;
+ params.arg = (uintptr_t) entry;
+
+ entry->clockP = ClockP_create(ICall_clockFunc, ticks, ¶ms);
+ if (!entry->clockP)
+ {
+ /* abort */
+ ICall_abort();
+ ICall_heapFree(entry);
+ return (ICALL_ERRNO_NO_RESOURCE);
+ }
+ entry->cback = cback;
+ entry->arg = arg;
+ *id = (ICall_TimerID) entry;
+ }
+ else
+ {
+ ICall_CSState key;
+
+ entry = (ICall_ScheduleEntry *) *id;
+
+ /* Critical section is entered to disable interrupts that might cause call
+ * to callback due to race condition */
+ key = ICall_enterCriticalSection();
+ ClockP_stop(entry->clockP);
+ entry->arg = arg;
+ ICall_leaveCriticalSection(key);
+ }
+ ClockP_setTimeout(entry->clockP, ticks);
+
+ ClockP_start(entry->clockP);
+
+ return (ICALL_ERRNO_SUCCESS);
+}
+
+/**
+ * Stops a timer.
+ *
+ * @param id timer ID.
+ */
+void ICall_stopTimer(ICall_TimerID id)
+{
+ ICall_ScheduleEntry * entry = (ICall_ScheduleEntry *) id;
+
+ if (id == ICALL_INVALID_TIMER_ID)
+ {
+ return;
+ }
+
+ ClockP_stop(entry->clockP);
+}
+
+/**
+ * Increments or decrements power activity counter.
+ *
+ * When power activity counter is greater than zero,
+ * the device shall stay in the active power state.
+ * The caller has to make sure that it decrements the counter
+ * as many times as it has incremented the counter
+ * when there is no activity that requires the active power state.
+ * It is recommended that each client increments the counter by just one,
+ * but it is not mandated to be so.
+ *
+ * @param incFlag TRUE to indicate incrementing the counter.
+ * FALSE to indicate decrementing the counter.
+ * @return @ref TRUE if power is required.
+ * @ref FALSE if power is not required.
+ */
+bool ICall_pwrUpdActivityCounter(bool incFlag)
+{
+ ICall_PwrUpdActivityCounterArgs args;
+ args.incFlag = incFlag;
+ ICallPlatform_pwrUpdActivityCounter(&args);
+ return (args.pwrRequired);
+}
+
+/**
+ * Configures power constraint/dependency set/release actions upon
+ * activity counter change.
+ *
+ * When activity counter value drops to zero, all constraints and
+ * dependencies configured by this function shall be released.
+ * When activity counter value increments to one, all constraints
+ * and dependencies configured by this function shall be set.
+ *
+ * @param bitmap a bitmap of constraint or dependency flags.
+ * The flag definition is specific to each platform.
+ * For instance, see ICallCC26xxDefs.h.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
+ * flag in the bitmap is detected.
+ */
+ICall_Errno ICall_pwrConfigACAction(ICall_PwrBitmap_t bitmap)
+{
+ ICall_PwrBitmapArgs args;
+ args.bitmap = bitmap;
+ return (ICallPlatform_pwrConfigACAction(&args));
+}
+
+/**
+ * Sets power constraints and dependencies.
+ *
+ * @param bitmap a bitmap of constraint or dependency flags.
+ * The flag definition is specific to each platform.
+ * For instance, see ICallCC26xxDefs.h.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
+ * flag in the bitmap is detected.
+ */
+ICall_Errno ICall_pwrRequire(ICall_PwrBitmap_t bitmap)
+{
+ ICall_PwrBitmapArgs args;
+ args.bitmap = bitmap;
+ return (ICallPlatform_pwrRequire(&args));
+}
+
+/**
+ * Releases power constraints and dependencies.
+ *
+ * @param bitmap a bitmap of constraint or dependency flags.
+ * The flag definition is specific to each platform.
+ * For instance, see ICallCC26xxDefs.h.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_INVALID_PARAMETER when an invalid
+ * flag in the bitmap is detected.
+ */
+ICall_Errno ICall_pwrDispense(ICall_PwrBitmap_t bitmap)
+{
+ ICall_PwrBitmapArgs args;
+ args.bitmap = bitmap;
+ return (ICallPlatform_pwrDispense(&args));
+}
+
+/**
+ * Checks whether HF XOSC is stable.
+ * This function must be called after HF XOSC is turned on
+ * (through power dependency).
+ *
+ * @return TRUE when HF XOSC is stable.
+ * FALSE when HF XOSC is not stable.
+ */
+bool ICall_pwrIsStableXOSCHF(void)
+{
+ ICall_GetBoolArgs args;
+ (void) ICallPlatform_pwrIsStableXOSCHF(&args);
+ return (args.value);
+}
+
+/**
+ * Switch clock source to HF XOSC.
+ * This function must be called after HF XOSC is stable.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS
+ */
+ICall_Errno ICall_pwrSwitchXOSCHF(void)
+{
+ ICall_FuncArgsHdr args;
+ return (ICallPlatform_pwrSwitchXOSCHF(&args));
+}
+
+/**
+ * Gets the estimated crystal oscillator startup time.
+ *
+ * @return estimated crystal oscillator startup time
+ */
+uint32_t ICall_pwrGetXOSCStartupTime(uint_fast32_t timeUntilWakeupInMs)
+{
+ ICall_PwrGetXOSCStartupTimeArgs args;
+ args.timeUntilWakeupInMs = timeUntilWakeupInMs;
+ (void) ICallPlatform_pwrGetXOSCStartupTime(&args);
+ return (args.value);
+}
+
+/**
+ * Registers a power state transition notify function.
+ *
+ * The registered notify function shall be called when the power state
+ * changes.
+ *
+ * @param fn notify function pointer
+ * @param obj pointer to data object to be passed to notify function.
+ * This pointer must not be NULL and can point to an aggregate type
+ * containing the @ref ICall_PwrNotifyData.
+ * The object must not be released.
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_NO_RESOURCE when registration failed
+ */
+ICall_Errno ICall_pwrRegisterNotify(ICall_PwrNotifyFn fn, ICall_PwrNotifyData * obj)
+{
+ ICall_PwrRegisterNotifyArgs args;
+ args.hdr.service = ICALL_SERVICE_CLASS_PRIMITIVE;
+ args.hdr.func = ICALL_PRIMITIVE_FUNC_PWR_REGISTER_NOTIFY;
+ args.fn = fn;
+ args.obj = obj;
+ return (ICallPlatform_pwrRegisterNotify(&args));
+}
+
+/**
+ * Retrieves power transition state.
+ *
+ * @return Implementation specific transition state when successful
+ * Zero when the function is not implemented.
+ */
+uint_fast8_t ICall_pwrGetTransitionState(void)
+{
+ ICall_PwrGetTransitionStateArgs args;
+ ICall_Errno errno;
+
+ errno = ICallPlatform_pwrGetTransitionState(&args);
+
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ return (args.state);
+ }
+ return (0);
+}
+
+/**
+ * Creates a new RTOS task.
+ *
+ * @param entryfn task entry function.
+ * @param priority task priority as understood by the underlying RTOS
+ * @param stacksize stack size as understood by the underlying RTOS
+ * @param arg argument to pass to the task entry function
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when successful
+ * @ref ICALL_ERRNO_NO_RESOURCE when creation failed
+ */
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * Creates a semaphore.
+ *
+ * @param mode Semaphore mode
+ * @ref ICALL_SEMAPHORE_MODE_COUNTING, or
+ * @ref ICALL_SEMAPHORE_MODE_BINARY
+ * @param initcount initial count value
+ * @return created semaphore when successful
+ * NULL when creation failed
+ */
+ICall_Semaphore ICall_createSemaphore(uint_fast8_t mode, int initcount)
+{
+ /* Semaphore_Params is a huge structure.
+ * To reduce stack usage, heap is used instead.
+ * This implies that ICall_createSemaphore() must be called before heap
+ * space may be exhausted.
+ */
+ ICall_Semaphore sem;
+ Semaphore_Params * semParams = (Semaphore_Params *) ICall_heapMalloc(sizeof(Semaphore_Params));
+
+ if (semParams == NULL)
+ {
+ return (NULL);
+ }
+
+ Semaphore_Params_init(semParams);
+ if (mode == ICALL_SEMAPHORE_MODE_BINARY)
+ {
+ semParams->mode = Semaphore_Mode_BINARY;
+ }
+
+ sem = Semaphore_create(args->initcount, semParams, NULL);
+ ICall_heapFree(semParams);
+
+ return (sem);
+}
+#endif
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * Post on a semaphore
+ *
+ * @param sem semaphore.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ */
+ICall_Errno ICall_postSemaphore(ICall_Semaphore sem)
+{
+ Semaphore_post(sem);
+ return (ICALL_ERRNO_SUCCESS);
+}
+#endif /* ICALL_RTOS_SEMAPHORE_API */
+
+#ifdef ICALL_RTOS_EVENTS_API
+/**
+ * Creates a event.
+ *
+ * @return created event when successful
+ * NULL when creation failed
+ */
+ICall_Event ICall_createEvent(void)
+{
+ ICall_Event event = Event_create(NULL, NULL);
+ return (event);
+
+ ICall_CreateEventArgs args;
+ ICall_Errno errno;
+
+ args.hdr.service = ICALL_SERVICE_CLASS_PRIMITIVE;
+ args.hdr.func = ICALL_PRIMITIVE_FUNC_CREATE_EVENT;
+ errno = ICall_dispatcher(&args.hdr);
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ return (args.event);
+ }
+ return (NULL);
+}
+
+/**
+ * Post on an event
+ *
+ * @param event event.
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ */
+ICall_Errno ICall_postEvent(ICall_Event event, uint32_t events)
+{
+ Event_post(event, events);
+ return (ICALL_ERRNO_SUCCESS);
+}
+/**
+ * Waits on a event for ICALL_MSG_EVENT_ID
+ *
+ * @param event event.
+ * @param milliseconds timeout in milliseconds
+ * or @ref ICALL_TIMEOUT_FOREVER to wait forever
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ * and event was received.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the event being signaled.
+ */
+ICall_Errno ICall_waitEvent(ICall_Event event, uint_fast32_t milliseconds)
+{
+ uint32_t timeout;
+
+ if (milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return (errno);
+ }
+ }
+
+ if (Event_pend(event, 0, ICALL_MSG_EVENT_ID, timeout))
+ {
+ return (ICALL_ERRNO_SUCCESS);
+ }
+ return (ICALL_ERRNO_TIMEOUT);
+}
+#endif /* ICALL_RTOS_EVENTS_API */
+
+#ifdef ICALL_RTOS_SEMAPHORE_API
+/**
+ * Waits on a semaphore
+ *
+ * @param sem semaphore.
+ * @param milliseconds timeout in milliseconds
+ * or @ref ICALL_TIMEOUT_FOREVER to wait forever
+ *
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ * and semaphore was acquired.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the semaphore being signaled.
+ */
+ICall_Errno ICall_waitSemaphore(ICall_Semaphore sem, uint_fast32_t milliseconds)
+{
+ uint32_t timeout;
+
+ if (milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ ICall_Errno errno = ICall_msecs2Ticks(milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return (errno);
+ }
+ }
+ if (Semaphore_pend(sem, timeout))
+ {
+ return (ICALL_ERRNO_SUCCESS);
+ }
+ return (ICALL_ERRNO_TIMEOUT);
+}
+#endif /* ICALL_RTOS_SEMAPHORE_API */
+
+#if 0
+/* Util function that take time in ticks and convert it into ms - relate to system clock (returns system clock + converted ms) */
+static void AbsoluteTimeInMilliPlusTimer(uint_least32_t timeout,struct timespec *tsTimer)
+{
+
+ clock_gettime(CLOCK_REALTIME, tsTimer);
+
+ tsTimer->tv_sec += (timeout / 1000);
+ tsTimer->tv_nsec += (timeout % 1000) * 1000000;
+}
+#endif
+
+/**
+ * Waits for and retrieves a message received at the message queue
+ * associated with the calling thread, which matches a certain condition.
+ *
+ * @param milliseconds timeout period in milliseconds.
+ * @param matchFn pointer to a function that would return TRUE when
+ * the message matches its condition.
+ * @param src pointer to a variable to store the service id
+ * of the registered server which sent the retrieved
+ * message, or NULL if not interested in storing service id.
+ * @param dest pointer to a variable to store the entity id
+ * of the destination of the message,
+ * of NULL if not interested in storing the destination entity id.
+ * @param msg pointer to a pointer variable to store the
+ * starting address of the message body being
+ * retrieved. The pointer must not be NULL.
+ * @return @ref ICALL_ERRNO_SUCCESS when the operation was successful
+ * and a message was retrieved.
+ * @ref ICALL_ERRNO_TIMEOUT when designated timeout period
+ * has passed since the call of the function without
+ * the semaphore being signaled.
+ * @ref ICALL_ERRNO_UNKNOWN_THREAD when this function is
+ * called from a thread which has not registered
+ * an entity, either through ICall_enrollService()
+ * or through ICall_registerApp().
+ */
+ICall_Errno ICall_waitMatch(uint_least32_t milliseconds, ICall_MsgMatchFn matchFn, ICall_ServiceEnum * src, ICall_EntityID * dest,
+ void ** msg)
+{
+ TaskHandle_t taskhandle = Task_self();
+ ICall_TaskEntry * taskentry = ICall_searchTask(taskhandle);
+ ICall_MsgQueue prependQueue = NULL;
+#ifndef ICALL_EVENTS
+ uint_fast16_t consumedCount = 0;
+#endif
+ uint32_t timeout;
+ uint_fast32_t timeoutStamp;
+ ICall_Errno errno;
+
+ if (!taskentry)
+ {
+ return (ICALL_ERRNO_UNKNOWN_THREAD);
+ }
+ /* Successful */
+ if (milliseconds == 0)
+ {
+ timeout = BIOS_NO_WAIT;
+ }
+ else if (milliseconds == ICALL_TIMEOUT_FOREVER)
+ {
+ timeout = BIOS_WAIT_FOREVER;
+ }
+ else
+ {
+ /* Convert milliseconds to number of ticks */
+ errno = ICall_msecs2Ticks(milliseconds, &timeout);
+ if (errno != ICALL_ERRNO_SUCCESS)
+ {
+ return (errno);
+ }
+ }
+
+ errno = ICALL_ERRNO_TIMEOUT;
+
+ timeoutStamp = ICall_getTicks() + timeout;
+
+#ifdef ICALL_LITE
+
+ uint32_t events;
+
+#ifdef FREERTOS
+ // TODO: Investigate ICALL Wait tick period (Last parameter)
+ while (xQueueReceive(taskentry->syncHandle, (char *) &events, milliseconds * 1000) == pdPASS)
+#endif
+#else /* !ICALL_LITE */
+ while (ICALL_SYNC_HANDLE_PEND(taskentry->syncHandle, timeout))
+#endif /* ICALL_LITE */
+ {
+ ICall_EntityID fetchSrc;
+ ICall_EntityID fetchDst;
+ ICall_ServiceEnum servId;
+ void * fetchMsg;
+ errno = ICall_fetchMsg(&fetchSrc, &fetchDst, &fetchMsg);
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ if (ICall_primEntityId2ServiceId(fetchSrc, &servId) == ICALL_ERRNO_SUCCESS)
+ {
+ if (matchFn(servId, fetchDst, fetchMsg))
+ {
+ /* Matching message found*/
+ if (src != NULL)
+ {
+ *src = servId;
+ }
+ if (dest != NULL)
+ {
+ *dest = fetchDst;
+ }
+ *msg = fetchMsg;
+ errno = ICALL_ERRNO_SUCCESS;
+ break;
+ }
+ }
+ /* Message was received but it wasn't expected one.
+ * Add to the prepend queue */
+ ICall_msgEnqueue(&prependQueue, fetchMsg);
+#ifdef ICALL_EVENTS
+ /* Event are binary semaphore, so if several messsages are posted while
+ * we are processing one, it's possible that some of them are 'missed' and
+ * not processed. Sending a event to ourself force this loop to run until
+ * all the messages in the queue are processed.
+ */
+#ifdef ICALL_LITE
+ /* 0x20000000 is an internal Event_ID */
+ uint32_t msg_ptr = (0x20000000); // Event_Id_29;
+
+#ifdef FREERTOS
+
+ uint8_t status;
+ if (HwiP_inISR())
+ {
+ status = xQueueSendFromISR(taskentry->syncHandle, (char *) &msg_ptr, NULL);
+ }
+ else
+ {
+ status = xQueueSend(taskentry->syncHandle, (char *) &msg_ptr, 0);
+ }
+
+ if (status != pdTRUE)
+ {
+ return status;
+ }
+#endif
+
+#else /* !ICALL_LITE */
+ ICALL_SYNC_HANDLE_POST(taskentry->syncHandle);
+#endif /* ICALL_LITE*/
+#endif /* ICALL_EVENTS */
+ }
+
+ /* Prepare for timeout exit */
+ errno = ICALL_ERRNO_TIMEOUT;
+
+#ifndef ICALL_EVENTS
+ /* Keep the decremented semaphore count */
+ consumedCount++;
+#endif /* ICALL_EVENTS */
+ if (timeout != BIOS_WAIT_FOREVER && timeout != BIOS_NO_WAIT)
+ {
+ /* Readjust timeout */
+ uint32_t newTimeout = timeoutStamp - ICall_getTicks();
+
+ if (newTimeout == 0 || newTimeout > timeout)
+ {
+ break;
+ }
+ timeout = newTimeout;
+ }
+ }
+
+ /* Prepend retrieved irrelevant messages */
+ ICall_msgPrepend(&taskentry->queue, prependQueue);
+#ifndef ICALL_EVENTS
+ /* Re-increment the consumed semaphores */
+ for (; consumedCount > 0; consumedCount--)
+ {
+ Semaphore_post(taskentry->syncHandle);
+ }
+#endif /* ICALL_EVENTS */
+ return (errno);
+}
+
+/**
+ * Retrieves an entity ID of (arbitrary) one of the entities registered
+ * from the calling thread.
+ *
+ * Note that, if multiple entities were registered from the same thread,
+ * this function shall arbitrarily pick one of the entities.
+ *
+ * @return A valid entity ID or @ref ICALL_INVALID_ENTITY_ID
+ * when no entity was registered from the calling thread.
+ */
+ICall_EntityID ICall_getEntityId(void)
+{
+ ICall_EntityID id;
+ TaskHandle_t taskhandle = Task_self();
+ ICall_CSState key;
+ size_t i;
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Not found */
+ break;
+ }
+ if (ICall_entities[i].task->task == (TaskHandle_t) taskhandle)
+ {
+ /* Found */
+ id = i;
+ ICall_leaveCSImpl(key);
+ return (id);
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return ICALL_INVALID_ENTITY_ID;
+}
+
+/**
+ * Checks whether the calling thread provides the designated service.
+ *
+ * @param service Service enumeration value for the service.
+ *
+ * @return Non-zero if the current thread provides the designated service.
+ * Zero, otherwise.
+ */
+uint_fast8_t ICall_threadServes(ICall_ServiceEnum service)
+{
+ uint_fast8_t res = 0;
+ TaskHandle_t taskhandle;
+ ICall_CSState key;
+ size_t i;
+ taskhandle = Task_self();
+
+ key = ICall_enterCSImpl();
+ for (i = 0; i < ICALL_MAX_NUM_ENTITIES; i++)
+ {
+ if (ICall_entities[i].service == ICALL_SERVICE_CLASS_INVALID_ENTRY)
+ {
+ /* Not found */
+ break;
+ }
+ else if (ICall_entities[i].service == service)
+ {
+ res = (uint_fast8_t) (ICall_entities[i].task->task == taskhandle);
+ }
+ }
+ ICall_leaveCSImpl(key);
+ return (res);
+}
+
+/**
+ * Retrieves an internal ID understood only by a service entity,
+ * corresponding to an ICall entity ID.
+ *
+ * This function is used when a message body includes a field indicating a
+ * software entity and the destination of the message has its own internal
+ * message routing mechanism with its own entity enumeration system.
+ *
+ * @param service Service enumeration value for the service.
+ * Currently @ref ICALL_SERVICE_CLASS_BLE_MSG is supported.
+ * @param entity ICall entity ID.
+ *
+ * @return Stack specific 8 bit ID or 0xFF when failed.
+ */
+uint_fast8_t ICall_getLocalMsgEntityId(ICall_ServiceEnum service, ICall_EntityID entity)
+{
+ ICall_GetLocalMsgEntityIdArgs args;
+ ICall_Errno errno;
+ args.hdr.service = service;
+ args.hdr.func = ICALL_MSG_FUNC_GET_LOCAL_MSG_ENTITY_ID;
+ args.entity = entity;
+ errno = ICall_dispatcher(&args.hdr);
+ if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ return (args.localId);
+ }
+ return (0xFF);
+}
+
+#endif /* ICALL_JT */
+
+#ifdef ICALL_LITE
+/*******************************************************************************
+ * @fn matchLiteCS
+ */
+static bool matchLiteCS(ICall_ServiceEnum src, ICall_EntityID dest, const void * msg)
+{
+ (void) src;
+ (void) dest;
+ ICall_LiteCmdStatus * pMsg = (ICall_LiteCmdStatus *) msg;
+ return (pMsg->cmdId == ICALL_LITE_DIRECT_API_DONE_CMD_ID);
+}
+/*******************************************************************************
+ * @fn icall_directAPI
+ * see headers for details.
+ */
+uint32_t icall_directAPI(uint8_t service, icall_lite_id_t id, ...)
+{
+ va_list argp;
+ uint32_t res;
+ icallLiteMsg_t liteMsg;
+
+ // The following will push all parameter in the runtime stack.
+ // This need to be call before any other local declaration of variable....
+ va_start(argp, id);
+
+ // Todo - add string for every icall API function, instead of printing function address
+ BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : icall_directAPI to BLE func=0x%x, status=%d\n", id, 0);
+ // Create the message that will be send to the requested service..
+ liteMsg.hdr.len = sizeof(icallLiteMsg_t);
+ liteMsg.hdr.next = NULL;
+ liteMsg.hdr.dest_id = ICALL_UNDEF_DEST_ID;
+ liteMsg.msg.directAPI = id;
+ liteMsg.msg.pointerStack = (uint32_t *) (*((uint32_t *) (&argp)));
+ ICall_sendServiceMsg(ICall_getEntityId(), service, ICALL_MSG_FORMAT_DIRECT_API_ID, &(liteMsg.msg));
+
+ // Since stack needs to always have a higher priority than the thread calling
+ // the API, when we reach this point the API has been executed by the stack.
+ // This implies the following:
+ // - API are not called in critical section or in section where task
+ // switching is disabled
+ // It is possible that the stack is blocking on this API, in this case a
+ // sync object needs to be used in order for this call to resume only when
+ // the API has been process in full.
+ {
+ ICall_Errno errno;
+ void * pCmdStatus = NULL;
+
+ errno = ICall_waitMatch(ICALL_TIMEOUT_PREDEFINE, matchLiteCS, NULL, NULL, (void **) &pCmdStatus);
+ if (errno == ICALL_ERRNO_TIMEOUT)
+ {
+#ifdef HALNODEBUG
+#elif defined(EXT_HAL_ASSERT)
+ HAL_ASSERT(HAL_ASSERT_CAUSE_ICALL_TIMEOUT);
+#else /* !EXT_HAL_ASSERT */
+ ICall_abort();
+#endif /* EXT_HAL_ASSERT */
+ }
+ else if (errno == ICALL_ERRNO_SUCCESS)
+ {
+ if (pCmdStatus)
+ {
+ ICall_freeMsg(pCmdStatus);
+ }
+ }
+ else
+ {
+#ifdef HALNODEBUG
+#else /* ! HALNODEBUG */
+ ICall_abort();
+#endif /* HALNODEBUG */
+ }
+ }
+
+ // The return parameter is set in the runtime stack, at the location of the
+ // first parameter.
+ res = liteMsg.msg.pointerStack[0];
+
+ va_end(argp);
+
+ return (res);
+}
+
+/*******************************************************************************
+ * @fn ICall_sendServiceComplete
+ * see headers for details.
+ */
+ICall_Errno ICall_sendServiceComplete(ICall_EntityID src, ICall_EntityID dest, ICall_MSGFormat format, void * msg)
+{
+ ICall_CSState key;
+ ICall_MsgHdr * hdr = (ICall_MsgHdr *) msg - 1;
+
+ if (dest >= ICALL_MAX_NUM_ENTITIES || src >= ICALL_MAX_NUM_ENTITIES)
+ {
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+ key = ICall_enterCSImpl();
+ if (!ICall_entities[dest].task)
+ {
+ ICall_leaveCSImpl(key);
+ return (ICALL_ERRNO_INVALID_PARAMETER);
+ }
+
+ ICall_leaveCSImpl(key);
+ /* Note that once the entry is valid,
+ * the value does not change and hence it is OK
+ * to leave the critical section.
+ */
+
+ hdr->srcentity = src;
+ hdr->dstentity = dest;
+ hdr->format = format;
+ ICall_msgEnqueue(&ICall_entities[dest].task->queue, msg);
+
+ /* 0x20000000 is an internal Event_ID */
+ uint32_t msg_ptr = (0x20000000); // Event_Id_29;
+#ifdef FREERTOS
+ uint8_t status;
+ if (HwiP_inISR())
+ {
+ status = xQueueSendFromISR(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, NULL);
+ }
+ else
+ {
+ status = xQueueSend(ICall_entities[dest].task->syncHandle, (char *) &msg_ptr, 0);
+ }
+
+ if (status != pdTRUE)
+ {
+ return status;
+ }
+#endif
+ return (ICALL_ERRNO_SUCCESS);
+}
+#endif /* ICALL_LITE*/