175 lines
4.2 KiB
C
175 lines
4.2 KiB
C
/*
|
|
* Copyright (c) 2017, Texas Instruments Incorporated
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr.h>
|
|
#include <sys/__assert.h>
|
|
#include <kernel/zephyr/dpl/dpl.h>
|
|
#include <ti/drivers/dpl/SemaphoreP.h>
|
|
|
|
#include "stubs.h"
|
|
|
|
/*
|
|
* 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 as milliSeconds: */
|
|
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_MSEC(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: <simplelinksdk>/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);
|
|
}
|
|
}
|