476 lines
12 KiB
C
476 lines
12 KiB
C
/**
|
|
* Copyright (c) 2015, Realsil Semiconductor Corporation. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _OS_SYNC_H_
|
|
#define _OS_SYNC_H_
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* \addtogroup OS OSIF APIs
|
|
* \defgroup Synchronization Inter-Task Communication
|
|
*
|
|
* \brief Manage Inter-task communication functions.
|
|
* \details Tasks need to communicate with each other or access shared resources together.
|
|
* There are many ways to exchange data between tasks, for example using shared
|
|
* data, polling loops and message passing.\n
|
|
* Many resources can be considered as serially-reusable. This means that they
|
|
* can be used repeatedly by different tasks, but only by one task at a time.\n
|
|
* The following mechanisms are available to the user:\n
|
|
* \arg <b>Lock</b>
|
|
* \arg <b>Semaphore</b>
|
|
* \arg <b>Mutex</b>
|
|
*
|
|
* \ingroup OS
|
|
*/
|
|
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Enter the critical region. Disable preemptive context switch and interrupts.
|
|
*
|
|
* \param None
|
|
*
|
|
* \return Interrupt mask flag.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* uint32_t s;
|
|
*
|
|
* // Enter the critical section.
|
|
* s = os_lock();
|
|
* // Allow only one task or ISR to operate the list.
|
|
* list_add(p_list, &item);
|
|
* // Exit the critical section and restore ISR mask flag.
|
|
* os_unlock(s);
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
uint32_t os_lock(void);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Exit the critical region. Enable preemptive context switch and interrupts.
|
|
*
|
|
* \param[in] s Interrupt mask flag to be restored.
|
|
*
|
|
* \return None.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* uint32_t s;
|
|
*
|
|
* // Enter the critical section.
|
|
* s = os_lock();
|
|
* // Allow only one task or ISR to operate the list.
|
|
* list_add(p_list, &item);
|
|
* // Exit the critical section and restore ISR mask flag.
|
|
* os_unlock(s);
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
void os_unlock(uint32_t s);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Create a counting semaphore.
|
|
*
|
|
* \details Semaphores are used to manage and protect access to shared resources. A semaphore
|
|
* can be used to permit a fixed number of task to access a pool of shared resources.
|
|
* Using semaphores.\n
|
|
* A semaphore object should be initialized to the maximum number of available tokens.
|
|
* This number of available resources is specified as parameter of the os_sem_create()
|
|
* function. Each time a semaphore token is obtained with os_sem_take(), the semaphore
|
|
* count is decremented. When the semaphore count is 0, no semaphore token can be obtained.
|
|
* The task that tries to obtain the semaphore token needs to wait until the next token
|
|
* is free. Semaphores are released with os_sem_give() incrementing the semaphore count.
|
|
*
|
|
* \image html OS-semaphore-overview.jpg "Semaphore Overview" width=496px height=346px
|
|
*
|
|
* \param[out] pp_handle Used to pass back the created semaphore handle.
|
|
*
|
|
* \param[in] init_count The count value assigned to the semaphore when created.
|
|
*
|
|
* \param[in] max_count The maximum count value that can be reached. If the max_count is 1,
|
|
* a binary semaphore is being created.
|
|
*
|
|
* \return The status of the semaphore creation.
|
|
* \retval true Semaphore was created successfully.
|
|
* \retval false Semaphore was failed to create.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* void *p_handle;
|
|
*
|
|
* // Create a semaphore with initial value 0 and maximum value 10.
|
|
* if (os_sem_create(&p_handle, 0, 10) == true)
|
|
* {
|
|
* // Semaphore created successfully.
|
|
* }
|
|
* else
|
|
* {
|
|
* // Semaphore failed to create.
|
|
* return -1;
|
|
* }
|
|
*
|
|
* return 0;
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_sem_create(void **pp_handle, uint32_t init_count, uint32_t max_count);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Delete a semaphore.
|
|
*
|
|
* \param[in] p_handle The handle of the semaphore to be deleted.
|
|
*
|
|
* \return The status of the semaphore deletion.
|
|
* \retval true Semaphore was deleted successfully.
|
|
* \retval false Semaphore was failed to delete.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* void *p_handle;
|
|
*
|
|
* // Create a semaphore with initial value 0 and maximum value 10.
|
|
* if (os_sem_create(&p_handle, 0, 10) == true)
|
|
* {
|
|
* // Semaphore created successfully.
|
|
* }
|
|
* else
|
|
* {
|
|
* // Semaphore failed to create.
|
|
* return -1;
|
|
* }
|
|
*
|
|
* // Delete the created semaphore.
|
|
* os_sem_delete(p_handle);
|
|
*
|
|
* return 0;
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_sem_delete(void *p_handle);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Take a semaphore.
|
|
*
|
|
* \param[in] p_handle The handle of the semaphore to be taken.
|
|
*
|
|
* \param[in] wait_ms The time in milliseconds to wait for the semaphore to become
|
|
* available.
|
|
* \arg \c 0 No blocking and return immediately.
|
|
* \arg \c 0xFFFFFFFF Block infinitely until the semaphore taken.
|
|
* \arg \c others The timeout value in milliseconds.
|
|
*
|
|
* \return The status of the semaphore taking.
|
|
* \retval true Semaphore was taken successfully.
|
|
* \retval false Semaphore was failed to take.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* void *p_handle = NULL;
|
|
*
|
|
* // One task creates a semaphore.
|
|
* void task1(void *p_param)
|
|
* {
|
|
* // Create a full binary semaphore.
|
|
* os_sem_create(&p_handle, 1, 1);
|
|
* }
|
|
*
|
|
* // Anohter task uses the semaphore.
|
|
* void task2(void *p_param)
|
|
* {
|
|
* // See if we can obtain the semaphore. If the semaphore is
|
|
* // not available, wait for 100ms.
|
|
* if (os_sem_take(p_handle, 100) == true)
|
|
* {
|
|
* // Access the share resource.
|
|
*
|
|
* // Finish accessing the share resource, then release the semaphore.
|
|
* os_sem_give(p_handle);
|
|
* }
|
|
* else
|
|
* {
|
|
* // Could not access the share resource.
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_sem_take(void *p_handle, uint32_t wait_ms);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Give a semaphore.
|
|
*
|
|
* \param[in] p_handle The handle of the semaphore to be given.
|
|
*
|
|
* \return The status of the semaphore giving.
|
|
* \retval true Semaphore was given successfully.
|
|
* \retval false Semaphore was failed to give.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* void *p_handle = NULL;
|
|
*
|
|
* // Create an empty binary semaphore.
|
|
* os_sem_create(&p_handle, 0, 1);
|
|
*
|
|
* // Obtaining the empty semaphore immediately will be failed.
|
|
* if (os_sem_take(p_handle, 0) == false)
|
|
* {
|
|
* // Failed.
|
|
* }
|
|
*
|
|
* // Give the sempahore
|
|
* if (os_sem_give(p_hanel) == true)
|
|
* {
|
|
* // Now we can take the semaphore.
|
|
* os_sem_take(p_handle, 0);
|
|
*
|
|
* // Again taking the binary semaphore will be failed.
|
|
* os_sem_take(p_handle, 0);
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_sem_give(void *p_handle);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Create a mutex.
|
|
*
|
|
* \details Mutex (Mutual Exclusion) is used to protect a shared resource that can be accessed
|
|
* only by one task at a time.\n
|
|
* A mutex is a special version of a binary empty semaphore. The advantage of a mutex
|
|
* is that it introduces task ownership. When a task acquires a mutex and becomes its
|
|
* owner, subsequent mutex acquires from that task will succeed immediately. Thus, mutex
|
|
* acquires/releases can be nested.\n
|
|
*
|
|
* \image html OS-mutex-overview.jpg "Mutex Overview" width=451px height=196px
|
|
*
|
|
* \param[out] pp_handle Used to pass back the created mutex handle.
|
|
*
|
|
* \return The status of the mutex creation.
|
|
* \retval true Mutex was created successfully.
|
|
* \retval false Mutex was failed to create.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* void *p_handle = NULL;
|
|
*
|
|
* // Create a mutex.
|
|
* if (os_mutex_create(&p_handle) == true)
|
|
* {
|
|
* // The mutex created successfully.
|
|
* // Now it can be used.
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_mutex_create(void **pp_handle);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Delete a mutex.
|
|
*
|
|
* \param[in] p_handle The handle of the mutex to be deleted.
|
|
*
|
|
* \return The status of the Mutex deletion.
|
|
* \retval true Mutex was deleted successfully.
|
|
* \retval false Mutex was failed to delete.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* int test(void)
|
|
* {
|
|
* void *p_handle;
|
|
*
|
|
* // Create a mutex.
|
|
* if (os_mutex_create(&p_handle) == true)
|
|
* {
|
|
* // Mutex created successfully.
|
|
* }
|
|
* else
|
|
* {
|
|
* // Mutex failed to create.
|
|
* return -1;
|
|
* }
|
|
*
|
|
* // Delete the created mutex.
|
|
* os_mutex_delete(p_handle);
|
|
*
|
|
* return 0;
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_mutex_delete(void *p_handle);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Take a mutex.
|
|
*
|
|
* \param[in] p_handle The handle of the mutex to be taken.
|
|
*
|
|
* \param[in] wait_ms The time in milliseconds to wait for the mutex to become
|
|
* available.
|
|
* \arg \c 0 No blocking and return immediately.
|
|
* \arg \c 0xFFFFFFFF Block infinitely until the mutex taken.
|
|
* \arg \c others The timeout value in milliseconds.
|
|
*
|
|
* \return The status of the mutex taking.
|
|
* \retval true Mutex was taken successfully.
|
|
* \retval false Mutex was failed to take.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* void *p_handle = NULL;
|
|
*
|
|
* // One task creates a mutex.
|
|
* void task1(void *p_param)
|
|
* {
|
|
* // Create a mutex.
|
|
* os_mutex_create(&p_handle);
|
|
* }
|
|
*
|
|
* // Anohter task uses the mutex.
|
|
* void task2(void *p_param)
|
|
* {
|
|
* // See if we can obtain the mutex. If the mutex is
|
|
* // not available, wait for 100ms.
|
|
* if (os_mutex_take(p_handle, 100) == true)
|
|
* {
|
|
* // Access the share resource.
|
|
*
|
|
* // In real code, recursive calls of mutex may occur.
|
|
* os_mutex_take(p_handle, 100);
|
|
* os_mutex_take(p_handle, 200);
|
|
*
|
|
* // The mutex has now been 'taken' three times, so will not be
|
|
* // available to another task until it has also been given back
|
|
* // three times.
|
|
* os_mutex_give(p_handle);
|
|
* os_mutex_give(p_handle);
|
|
* os_mutex_give(p_handle);
|
|
*
|
|
* // Finish accessing the share resource, then release the semaphore.
|
|
* // Now the mutex can be taken by other tasks.
|
|
* }
|
|
* else
|
|
* {
|
|
* // Could not access the share resource.
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_mutex_take(void *p_handle, uint32_t wait_ms);
|
|
|
|
/**
|
|
* os_sync.h
|
|
*
|
|
* \brief Give a mutex.
|
|
*
|
|
* \param[in] p_handle The handle of the mutex to be given.
|
|
*
|
|
* \return The status of the mutex giving.
|
|
* \retval true Mutex was given successfully.
|
|
* \retval false Mutex was failed to give.
|
|
*
|
|
* <b>Example usage</b>
|
|
* \code{.c}
|
|
* void *p_handle = NULL;
|
|
*
|
|
* // One task creates a mutex.
|
|
* void task1(void *p_param)
|
|
* {
|
|
* // Create a mutex.
|
|
* os_mutex_create(&p_handle);
|
|
* }
|
|
*
|
|
* // Anohter task uses the mutex.
|
|
* void task2(void *p_param)
|
|
* {
|
|
* // See if we can obtain the mutex. If the mutex is
|
|
* // not available, wait for 100ms.
|
|
* if (os_mutex_take(p_handle, 100) == true)
|
|
* {
|
|
* // Access the share resource.
|
|
*
|
|
* // In real code, recursive calls of mutex may occur.
|
|
* os_mutex_take(p_handle, 100);
|
|
* os_mutex_take(p_handle, 200);
|
|
*
|
|
* // The mutex has now been 'taken' three times, so will not be
|
|
* // available to another task until it has also been given back
|
|
* // three times.
|
|
* os_mutex_give(p_handle);
|
|
* os_mutex_give(p_handle);
|
|
* os_mutex_give(p_handle);
|
|
*
|
|
* // Finish accessing the share resource, then release the semaphore.
|
|
* // Now the mutex can be taken by other tasks.
|
|
* }
|
|
* else
|
|
* {
|
|
* // Could not access the share resource.
|
|
* }
|
|
* }
|
|
* \endcode
|
|
*
|
|
* \ingroup Synchronization
|
|
*/
|
|
bool os_mutex_give(void *p_handle);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _OS_SYNC_H_ */
|