2018-07-09 18:13:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2019-10-24 23:08:21 +08:00
|
|
|
#include <kernel.h>
|
2018-07-09 18:13:28 +08:00
|
|
|
#include <cmsis_os.h>
|
2019-10-24 23:08:21 +08:00
|
|
|
#include <string.h>
|
2018-07-09 18:13:28 +08:00
|
|
|
|
|
|
|
K_MEM_SLAB_DEFINE(cmsis_semaphore_slab, sizeof(struct k_sem),
|
|
|
|
CONFIG_CMSIS_SEMAPHORE_MAX_COUNT, 4);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create and Initialize a semaphore object.
|
|
|
|
*/
|
|
|
|
osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def,
|
|
|
|
int32_t count)
|
|
|
|
{
|
|
|
|
struct k_sem *semaphore;
|
|
|
|
|
|
|
|
if (semaphore_def == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-11-15 17:57:13 +08:00
|
|
|
if (k_is_in_isr()) {
|
2018-07-09 18:13:28 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k_mem_slab_alloc(&cmsis_semaphore_slab,
|
2019-10-03 08:26:14 +08:00
|
|
|
(void **)&semaphore, K_MSEC(100)) == 0) {
|
2018-09-12 10:09:03 +08:00
|
|
|
(void)memset(semaphore, 0, sizeof(struct k_sem));
|
2018-07-09 18:13:28 +08:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
k_sem_init(semaphore, count, count);
|
|
|
|
|
|
|
|
return (osSemaphoreId)semaphore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Wait until a semaphore becomes available.
|
|
|
|
*/
|
|
|
|
int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t timeout)
|
|
|
|
{
|
|
|
|
struct k_sem *semaphore = (struct k_sem *) semaphore_id;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
if (semaphore_id == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-11-15 17:57:13 +08:00
|
|
|
if (k_is_in_isr()) {
|
2018-07-09 18:13:28 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timeout == osWaitForever) {
|
|
|
|
status = k_sem_take(semaphore, K_FOREVER);
|
2019-03-27 09:57:45 +08:00
|
|
|
} else if (timeout == 0U) {
|
2018-07-09 18:13:28 +08:00
|
|
|
status = k_sem_take(semaphore, K_NO_WAIT);
|
|
|
|
} else {
|
2020-05-05 04:39:17 +08:00
|
|
|
status = k_sem_take(semaphore, K_MSEC(timeout));
|
2018-07-09 18:13:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If k_sem_take is successful, return the number of available
|
|
|
|
* tokens + 1. +1 is for accounting the currently acquired token.
|
|
|
|
* If it has timed out, return 0 (no tokens available).
|
|
|
|
*/
|
|
|
|
if (status == 0) {
|
|
|
|
return k_sem_count_get(semaphore) + 1;
|
2018-08-23 15:57:42 +08:00
|
|
|
} else {
|
2018-07-09 18:13:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Release a semaphore that was obtained by osSemaphoreWait.
|
|
|
|
*/
|
|
|
|
osStatus osSemaphoreRelease(osSemaphoreId semaphore_id)
|
|
|
|
{
|
|
|
|
struct k_sem *semaphore = (struct k_sem *) semaphore_id;
|
|
|
|
|
|
|
|
if (semaphore_id == NULL) {
|
|
|
|
return osErrorParameter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All tokens have already been released */
|
|
|
|
if (k_sem_count_get(semaphore) == semaphore->limit) {
|
|
|
|
return osErrorResource;
|
|
|
|
}
|
|
|
|
|
|
|
|
k_sem_give(semaphore);
|
|
|
|
|
|
|
|
return osOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Delete a semaphore that was created by osSemaphoreCreate.
|
|
|
|
*/
|
|
|
|
osStatus osSemaphoreDelete(osSemaphoreId semaphore_id)
|
|
|
|
{
|
|
|
|
struct k_sem *semaphore = (struct k_sem *) semaphore_id;
|
|
|
|
|
|
|
|
if (semaphore_id == NULL) {
|
|
|
|
return osErrorParameter;
|
|
|
|
}
|
|
|
|
|
2018-11-15 17:57:13 +08:00
|
|
|
if (k_is_in_isr()) {
|
2018-07-09 18:13:28 +08:00
|
|
|
return osErrorISR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The status code "osErrorResource" (the semaphore object
|
|
|
|
* could not be deleted) is not supported in Zephyr.
|
|
|
|
*/
|
|
|
|
|
|
|
|
k_mem_slab_free(&cmsis_semaphore_slab, (void *) &semaphore);
|
|
|
|
|
|
|
|
return osOK;
|
|
|
|
}
|