hal_ti/simplelink/kernel/zephyr/dpl/SemaphoreP_zephyr.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(&params);
params.mode = SemaphoreP_Mode_BINARY;
return (SemaphoreP_create(count, &params));
}
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(&params);
params.mode = SemaphoreP_Mode_BINARY;
return (SemaphoreP_construct(handle, count, &params));
}
void SemaphoreP_destruct(SemaphoreP_Struct *semP) {
struct k_sem *sem;
sem = (struct k_sem *)semP->data;
if (sem) {
k_sem_reset(sem);
}
}