/* * Copyright (c) 2017, Texas Instruments Incorporated * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include /* * Zephyr kernel object pools: * * This bit of code enables the simplelink host driver, which assumes dynamic * allocation of kernel objects (semaphores, mutexes, hwis), to be * more easily ported to Zephyr (which supports static allocation). * * It leverages the Zephyr memory slab, enabling us to define a semaphore * object pool for use by the SimpleLink host driver. */ #define DPL_MAX_SEMAPHORES 14 /* (user.h:MAX_CONCURRENT_ACTIONS+4) = 14 */ K_MEM_SLAB_DEFINE(sem_slab, sizeof(struct k_sem), DPL_MAX_SEMAPHORES,\ MEM_ALIGN); static struct k_sem *dpl_sem_pool_alloc() { struct k_sem *sem_ptr = NULL; if (k_mem_slab_alloc(&sem_slab, (void **)&sem_ptr, K_NO_WAIT) < 0) { /* * We assert, as this is a logic error, due to a change in # * of semaphores needed by the simplelink driver. In that case, * the sem pool must be increased programmatically to match. */ __ASSERT(0, "Increase size of DPL semaphore pool"); } return sem_ptr; } static SemaphoreP_Status dpl_sem_pool_free(struct k_sem *sem) { k_mem_slab_free(&sem_slab, (void **)&sem); return SemaphoreP_OK; } /* timeout comes in and out in ticks */ static k_timeout_t dpl_convert_timeout(uint32_t timeout) { switch(timeout) { case SemaphoreP_NO_WAIT: return K_NO_WAIT; case SemaphoreP_WAIT_FOREVER: return K_FOREVER; default: return K_TICKS(timeout); } } SemaphoreP_Handle SemaphoreP_create(unsigned int count, SemaphoreP_Params *params) { unsigned int limit = UINT_MAX; struct k_sem *sem; if (params) { limit = (params->mode == SemaphoreP_Mode_BINARY) ? 1 : UINT_MAX; } sem = dpl_sem_pool_alloc(); if (sem) { k_sem_init(sem, count, limit); } return (SemaphoreP_Handle)sem; } SemaphoreP_Handle SemaphoreP_createBinary(unsigned int count) { SemaphoreP_Params params; SemaphoreP_Params_init(¶ms); params.mode = SemaphoreP_Mode_BINARY; return (SemaphoreP_create(count, ¶ms)); } void SemaphoreP_delete(SemaphoreP_Handle handle) { k_sem_reset((struct k_sem *)handle); (void)dpl_sem_pool_free((struct k_sem *)handle); } void SemaphoreP_Params_init(SemaphoreP_Params *params) { params->mode = SemaphoreP_Mode_COUNTING; params->callback = NULL; } /* * The SimpleLink driver calls this function with a timeout of 0 to "clear" * the SyncObject, rather than calling dpl_SyncObjClear() directly. * See: /source/ti/drivers/net/wifi/source/driver.h * #define SL_DRV_SYNC_OBJ_CLEAR(pObj) * (void)sl_SyncObjWait(pObj,SL_OS_NO_WAIT); * * So, we claim (via simplelink driver code inspection), that SyncObjWait * will *only* be called with timeout == 0 if the intention is to clear the * semaphore: in that case, we just call k_sem_reset. */ SemaphoreP_Status SemaphoreP_pend(SemaphoreP_Handle handle, uint32_t timeout) { int retval; if (0 == timeout) { k_sem_reset((struct k_sem *)handle); retval = SemaphoreP_OK; } else { retval = k_sem_take((struct k_sem *)handle, dpl_convert_timeout(timeout)); __ASSERT_NO_MSG(retval != -EBUSY); retval = (retval >= 0) ? SemaphoreP_OK : SemaphoreP_TIMEOUT; } return retval; } void SemaphoreP_post(SemaphoreP_Handle handle) { k_sem_give((struct k_sem *)handle); } SemaphoreP_Handle SemaphoreP_construct(SemaphoreP_Struct *handle, unsigned int count, SemaphoreP_Params *params) { unsigned int limit = UINT_MAX; struct k_sem *sem; if (params) { limit = (params->mode == SemaphoreP_Mode_BINARY) ? 1 : UINT_MAX; } sem = (struct k_sem *)handle; if (sem) { k_sem_init(sem, count, limit); } return (SemaphoreP_Handle)sem; } SemaphoreP_Handle SemaphoreP_constructBinary(SemaphoreP_Struct *handle, unsigned int count) { SemaphoreP_Params params; SemaphoreP_Params_init(¶ms); params.mode = SemaphoreP_Mode_BINARY; return (SemaphoreP_construct(handle, count, ¶ms)); } void SemaphoreP_destruct(SemaphoreP_Struct *semP) { struct k_sem *sem; sem = (struct k_sem *)semP->data; if (sem) { k_sem_reset(sem); } }