Add fsl_rtos_abstraction.c which I forgot to add.
This commit is contained in:
226
right/src/buspal/fsl_rtos_abstraction.c
Normal file
226
right/src/buspal/fsl_rtos_abstraction.c
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <assert.h>
|
||||
#include "fsl_rtos_abstraction.h"
|
||||
#include "microseconds/microseconds.h"
|
||||
|
||||
enum _sync_constants
|
||||
{
|
||||
kSyncUnlocked = 0,
|
||||
kSyncLocked = 1
|
||||
};
|
||||
|
||||
static lock_object_t lockObject;
|
||||
static uint64_t s_ticksPerMs = 0;
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : time_diff
|
||||
* Description : This function gets the difference between two time stamp,
|
||||
* time overflow is considered.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
static uint32_t ms_diff(uint64_t tickStart, uint64_t tickStop)
|
||||
{
|
||||
return ((tickStop - tickStart) / s_ticksPerMs);
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_SemaCreate
|
||||
* Description : This function is used to create a semaphore. Return
|
||||
* kStatus_OSA_Success if create successfully, otherwise return kStatus_OSA_Error.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
osa_status_t OSA_SemaCreate(semaphore_t *pSem, uint8_t initValue)
|
||||
{
|
||||
assert(pSem);
|
||||
|
||||
if (!s_ticksPerMs)
|
||||
{
|
||||
s_ticksPerMs = microseconds_convert_to_ticks(1000);
|
||||
}
|
||||
|
||||
pSem->semCount = initValue;
|
||||
pSem->isWaiting = false;
|
||||
pSem->tickStart = 0u;
|
||||
pSem->timeout = 0u;
|
||||
|
||||
return kStatus_OSA_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_SemaWait
|
||||
* Description : This function checks the semaphore's counting value, if it is
|
||||
* positive, decreases it and returns kStatus_OSA_Success, otherwise, timeout
|
||||
* will be used for wait. The parameter timeout indicates how long should wait
|
||||
* in milliseconds. Pass kSyncWaitForever to wait indefinitely, pass 0 will
|
||||
* return kStatus_OSA_Timeout immediately if semaphore is not positive.
|
||||
* This function returns kStatus_OSA_Success if the semaphore is received, returns
|
||||
* kStatus_OSA_Timeout if the semaphore is not received within the specified
|
||||
* 'timeout', returns kStatus_OSA_Error if any errors occur during waiting,
|
||||
* returns kStatus_OSA_Idle if the semaphore is not available and 'timeout' is
|
||||
* not exhausted, because wait functions should not block with bare metal.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
osa_status_t OSA_SemaWait(semaphore_t *pSem, uint32_t timeout)
|
||||
{
|
||||
uint64_t currentTicks;
|
||||
|
||||
assert(pSem);
|
||||
|
||||
/* Check the sem count first. Deal with timeout only if not already set */
|
||||
if (pSem->semCount)
|
||||
{
|
||||
__disable_irq();
|
||||
pSem->semCount--;
|
||||
pSem->isWaiting = false;
|
||||
__enable_irq();
|
||||
return kStatus_OSA_Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeout == 0)
|
||||
{
|
||||
/* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */
|
||||
return kStatus_OSA_Timeout;
|
||||
}
|
||||
else if (pSem->isWaiting)
|
||||
{
|
||||
/* Check for timeout */
|
||||
currentTicks = microseconds_get_ticks();
|
||||
if (pSem->timeout < ms_diff(pSem->tickStart, currentTicks))
|
||||
{
|
||||
__disable_irq();
|
||||
pSem->isWaiting = false;
|
||||
__enable_irq();
|
||||
return kStatus_OSA_Timeout;
|
||||
}
|
||||
}
|
||||
else if (timeout != kSyncWaitForever) /* If don't wait forever, start the timer */
|
||||
{
|
||||
/* Start the timeout counter */
|
||||
__disable_irq();
|
||||
pSem->isWaiting = true;
|
||||
__enable_irq();
|
||||
pSem->tickStart = microseconds_get_ticks();
|
||||
pSem->timeout = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
return kStatus_OSA_Idle;
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_SemaPost
|
||||
* Description : This function is used to wake up one task that wating on the
|
||||
* semaphore. If no task is waiting, increase the semaphore. The function returns
|
||||
* kStatus_OSA_Success if the semaphre is post successfully, otherwise returns
|
||||
* kStatus_OSA_Error.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
osa_status_t OSA_SemaPost(semaphore_t *pSem)
|
||||
{
|
||||
assert(pSem);
|
||||
/* The max value is 0xFF */
|
||||
if (pSem->semCount == 0xFF)
|
||||
{
|
||||
return kStatus_OSA_Error;
|
||||
}
|
||||
__disable_irq();
|
||||
++pSem->semCount;
|
||||
__enable_irq();
|
||||
|
||||
return kStatus_OSA_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_SemaDestroy
|
||||
* Description : This function is used to destroy a semaphore.
|
||||
* Return kStatus_OSA_Success if the semaphore is destroyed successfully, otherwise
|
||||
* return kStatus_OSA_Error.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
osa_status_t OSA_SemaDestroy(semaphore_t *pSem)
|
||||
{
|
||||
assert(pSem);
|
||||
|
||||
return kStatus_OSA_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_TimeDelay
|
||||
* Description : This function is used to delay for a number of milliseconds.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
void OSA_TimeDelay(uint32_t delay)
|
||||
{
|
||||
microseconds_delay(delay * 1000);
|
||||
}
|
||||
|
||||
void sync_init(sync_object_t *obj, bool state)
|
||||
{
|
||||
*obj = state ? kSyncLocked : kSyncUnlocked;
|
||||
}
|
||||
|
||||
bool sync_wait(sync_object_t *obj, uint32_t timeout)
|
||||
{
|
||||
// Increment the object so we can tell if it changes. Because the increment is not
|
||||
// atomic (load, add, store), we must disabled interrupts during it.
|
||||
__disable_irq();
|
||||
++(*obj);
|
||||
__enable_irq();
|
||||
|
||||
// Wait for the object to be unlocked.
|
||||
while (*obj != 0)
|
||||
{
|
||||
// Spin.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void sync_signal(sync_object_t *obj)
|
||||
{
|
||||
// Atomically unlock the object.
|
||||
__disable_irq();
|
||||
--(*obj);
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void sync_reset(sync_object_t *obj)
|
||||
{
|
||||
__disable_irq();
|
||||
(*obj) = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void lock_init(void)
|
||||
{
|
||||
__disable_irq();
|
||||
lockObject = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void lock_acquire(void)
|
||||
{
|
||||
// Disable global IRQ until lock_release() is called.
|
||||
__disable_irq();
|
||||
++lockObject;
|
||||
}
|
||||
|
||||
void lock_release(void)
|
||||
{
|
||||
// Restore previous state, enable global IRQ if all locks released.
|
||||
if (lockObject <= 1)
|
||||
{
|
||||
lockObject = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
else
|
||||
{
|
||||
--lockObject;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user