432 lines
14 KiB
C
432 lines
14 KiB
C
/*
|
|
* Copyright (c) 2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016-2020 NXP
|
|
* All rights reserved.
|
|
*
|
|
* NXP Confidential. This software is owned or controlled by NXP and may only be
|
|
* used strictly in accordance with the applicable license terms. By expressly
|
|
* accepting such terms or by downloading, installing, activating and/or otherwise
|
|
* using the software, you are agreeing that you have read, and that you agree to
|
|
* comply with and are bound by, such license terms. If you do not agree to be
|
|
* bound by the applicable license terms, then you may not retain, install,
|
|
* activate or otherwise use the software. The production use license in
|
|
* Section 2.3 is expressly granted for this software.
|
|
*/
|
|
|
|
/*!
|
|
* @file osif_baremetal.c
|
|
*
|
|
* @page misra_violations MISRA-C:2012 violations
|
|
*
|
|
* @section [global]
|
|
* Violates MISRA 2012 Required Rule 1.3, Taking address of near auto variable.
|
|
* The code is not dynamically linked. An absolute stack address is obtained
|
|
* when taking the address of the near auto variable. A source of error in
|
|
* writing dynamic code is that the stack segment may be different from the data
|
|
* segment.
|
|
*
|
|
* @section [global]
|
|
* Violates MISRA 2012 Advisory Directive 4.9, Function-like macro defined.
|
|
* The macros are used to validate input parameters to driver functions.
|
|
*
|
|
* @section [global]
|
|
* Violates MISRA 2012 Advisory Rule 8.7, External could be made static.
|
|
* Function is defined for usage by application code.
|
|
*
|
|
* @section [global]
|
|
* Violates MISRA 2012 Advisory Rule 11.4, Conversion between a pointer and integer type.
|
|
* The cast is required to initialize a pointer with an unsigned long define, representing an address.
|
|
*
|
|
* @section [global]
|
|
* Violates MISRA 2012 Required Rule 11.6, Cast from unsigned int to pointer.
|
|
* This is required for initializing pointers to the module's memory map, which is located at a
|
|
* fixed address.
|
|
*
|
|
*/
|
|
|
|
#include "osif.h"
|
|
#include <stddef.h>
|
|
|
|
#include "device_registers.h"
|
|
|
|
#include "devassert.h"
|
|
|
|
#if defined (USING_OS_FREERTOS)
|
|
#error "Wrong OSIF selected. Please define symbol USING_OS_BAREMETAL (or no OS define) in project settings or change the OSIF variant"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Private Functions
|
|
******************************************************************************/
|
|
|
|
/*! @cond DRIVER_INTERNAL_USE_ONLY */
|
|
|
|
/*! @brief Converts milliseconds to ticks - in this case, one tick = one millisecond */
|
|
#define MSEC_TO_TICK(msec) (msec)
|
|
|
|
#if (FEATURE_OSIF_USE_SYSTICK != 0) || (FEATURE_OSIF_USE_PIT != 0)
|
|
/* Only include headers for configurations that need them. */
|
|
#include "interrupt_manager.h"
|
|
#include "clock_manager.h"
|
|
|
|
static volatile uint32_t s_osif_tick_cnt = 0u;
|
|
|
|
static inline void osif_Tick(void)
|
|
{
|
|
s_osif_tick_cnt++;
|
|
}
|
|
|
|
static inline uint32_t osif_GetCurrentTickCount(void)
|
|
{
|
|
return s_osif_tick_cnt;
|
|
}
|
|
|
|
#endif /* (FEATURE_OSIF_USE_SYSTICK != 0) || (FEATURE_OSIF_USE_PIT != 0) */
|
|
|
|
#if FEATURE_OSIF_USE_SYSTICK
|
|
|
|
void SysTick_Handler(void);
|
|
|
|
void SysTick_Handler(void)
|
|
{
|
|
osif_Tick();
|
|
}
|
|
|
|
static inline void osif_UpdateTickConfig(void)
|
|
{
|
|
uint32_t core_freq = 0u;
|
|
static bool first_init = true;
|
|
/* Get the correct name of the core clock */
|
|
clock_names_t coreclk = CORE_CLK;
|
|
status_t clk_status = CLOCK_SYS_GetFreq(coreclk, &core_freq);
|
|
DEV_ASSERT(clk_status == STATUS_SUCCESS);
|
|
DEV_ASSERT(core_freq > 0u);
|
|
(void)clk_status;
|
|
|
|
/* For Cortex-M0 devices the systick counter is initialized with an undefined
|
|
value, so make sure to initialize it to 0 before starting */
|
|
S32_SysTick->CSR = S32_SysTick_CSR_ENABLE(0u);
|
|
S32_SysTick->RVR = S32_SysTick_RVR_RELOAD(core_freq / 1000u);
|
|
if (first_init)
|
|
{
|
|
/* only initialize CVR on the first entry, to not cause time drift */
|
|
S32_SysTick->CVR = S32_SysTick_CVR_CURRENT(0U);
|
|
first_init = false;
|
|
}
|
|
S32_SysTick->CSR = S32_SysTick_CSR_ENABLE(1u) | S32_SysTick_CSR_TICKINT(1u) | S32_SysTick_CSR_CLKSOURCE(1u);
|
|
}
|
|
|
|
static inline void osif_DisableIrqGlobal(void)
|
|
{
|
|
INT_SYS_DisableIRQGlobal();
|
|
}
|
|
|
|
static inline void osif_EnableIrqGlobal(void)
|
|
{
|
|
INT_SYS_EnableIRQGlobal();
|
|
}
|
|
|
|
#elif FEATURE_OSIF_USE_PIT
|
|
|
|
void OSIF_PIT_IRQHandler(void);
|
|
|
|
void OSIF_PIT_IRQHandler(void)
|
|
{
|
|
OSIF_PIT->TIMER[OSIF_PIT_CHAN_ID].TFLG = PIT_TFLG_TIF(1u);
|
|
|
|
osif_Tick();
|
|
}
|
|
|
|
static inline void osif_UpdateTickConfig(void)
|
|
{
|
|
uint32_t tick_freq = 0u;
|
|
PIT_Type * base = OSIF_PIT;
|
|
|
|
/* get the clock frequency for the timer and compute ticks for 1 ms */
|
|
status_t clk_status = CLOCK_SYS_GetFreq(PITRTI0_CLK, &tick_freq);
|
|
DEV_ASSERT(clk_status == STATUS_SUCCESS);
|
|
DEV_ASSERT(tick_freq > 0u);
|
|
(void)clk_status;
|
|
uint32_t tick_1ms = tick_freq / 1000u;
|
|
|
|
/* setup timer and enable interrupt */
|
|
base->MCR &= ~PIT_MCR_MDIS(1u); /* make sure module is started */
|
|
base->MCR |= PIT_MCR_FRZ(1u); /* stop in Debug */
|
|
base->TIMER[OSIF_PIT_CHAN_ID].LDVAL = tick_1ms;
|
|
base->TIMER[OSIF_PIT_CHAN_ID].TCTRL |= PIT_TCTRL_TEN(1u) | PIT_TCTRL_TIE(1u);
|
|
static const IRQn_Type pitIrqId[PIT_INSTANCE_COUNT][PIT_IRQS_CH_COUNT] = PIT_IRQS;
|
|
|
|
INT_SYS_InstallHandler(pitIrqId[0U][OSIF_PIT_CHAN_ID], OSIF_PIT_IRQHandler, NULL);
|
|
INT_SYS_EnableIRQ(pitIrqId[0U][OSIF_PIT_CHAN_ID]);
|
|
}
|
|
|
|
static inline void osif_DisableIrqGlobal(void)
|
|
{
|
|
INT_SYS_DisableIRQGlobal();
|
|
}
|
|
|
|
static inline void osif_EnableIrqGlobal(void)
|
|
{
|
|
INT_SYS_EnableIRQGlobal();
|
|
}
|
|
|
|
#else /* FEATURE_OSIF_USE_SYSTICK == 0, FEATURE_OSIF_USE_PIT == 0 */
|
|
|
|
static inline uint32_t osif_GetCurrentTickCount(void)
|
|
{
|
|
return 0u;
|
|
}
|
|
|
|
static inline void osif_UpdateTickConfig(void)
|
|
{
|
|
/* do not update tick */
|
|
}
|
|
|
|
#define osif_DisableIrqGlobal() (void)0;
|
|
|
|
#define osif_EnableIrqGlobal() (void)0;
|
|
|
|
#endif /* FEATURE_OSIF_USE_SYSTICK */
|
|
|
|
/*! @endcond */
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_TimeDelay
|
|
* Description : This function blocks execution for a number of milliseconds.
|
|
*
|
|
* Implements : OSIF_TimeDelay_baremetal_Activity
|
|
*END**************************************************************************/
|
|
void OSIF_TimeDelay(const uint32_t delay)
|
|
{
|
|
osif_UpdateTickConfig();
|
|
uint32_t start = osif_GetCurrentTickCount();
|
|
uint32_t crt_ticks = osif_GetCurrentTickCount();
|
|
uint32_t delta = crt_ticks - start;
|
|
uint32_t delay_ticks = MSEC_TO_TICK(delay);
|
|
while (delta < delay_ticks)
|
|
{
|
|
crt_ticks = osif_GetCurrentTickCount();
|
|
delta = crt_ticks - start;
|
|
}
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_GetMilliseconds
|
|
* Description : This function returns the number of miliseconds elapsed since
|
|
* starting the internal timer. To initialize the internal timer
|
|
* (Systick) in bare-metal, call either OSIF_TimeDelay or
|
|
* OSIF_SemaWait functions. Calling OSIF_TimeDelay(0) will initialize
|
|
* the timer without any side-effects (no delay).
|
|
*
|
|
* Implements : OSIF_GetMilliseconds_baremetal_Activity
|
|
*END**************************************************************************/
|
|
uint32_t OSIF_GetMilliseconds(void)
|
|
{
|
|
/*
|
|
* Please make sure the timer is initialized before calling this function.
|
|
* For example, calling OSIF_TimeDelay(0) ensures that the timer is initialized
|
|
* without any other side-effects. If OSIF_TimeDelay or OSIF_SemaWait functions
|
|
* have been called, the timer is already initialized.
|
|
*/
|
|
return osif_GetCurrentTickCount(); /* This assumes that 1 tick = 1 millisecond */
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_MutexLock
|
|
* Description : This function locks a mutex (mock operation in baremetal case).
|
|
*
|
|
* Implements : OSIF_MutexLock_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_MutexLock(const mutex_t * const pMutex,
|
|
const uint32_t timeout)
|
|
{
|
|
(void)pMutex;
|
|
(void)timeout;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_MutexUnlock
|
|
* Description : This function unlocks a mutex (mock operation in baremetal case).
|
|
*
|
|
* Implements : OSIF_MutexUnlock_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_MutexUnlock(const mutex_t * const pMutex)
|
|
{
|
|
(void)pMutex;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_MutexCreate
|
|
* Description : This function creates a mutex (mock operation in baremetal case).
|
|
*
|
|
* Implements : OSIF_MutexCreate_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_MutexCreate(mutex_t * const pMutex)
|
|
{
|
|
(void)pMutex;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_MutexDestroy
|
|
* Description : This function destroys a mutex (mock operation in baremetal case).
|
|
*
|
|
* Implements : OSIF_MutexDestroy_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_MutexDestroy(const mutex_t * const pMutex)
|
|
{
|
|
(void)pMutex;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_SemaWait
|
|
* Description : This function performs the 'wait' (decrement) operation on a semaphore.
|
|
* When timeout value is 0, it's the equivalent of TryWait - try to decrement but return
|
|
* immediately if it fails (counter is 0).
|
|
*
|
|
* Implements : OSIF_SemaWait_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_SemaWait(semaphore_t * const pSem,
|
|
const uint32_t timeout)
|
|
{
|
|
DEV_ASSERT(pSem != NULL);
|
|
|
|
status_t osif_ret_code = STATUS_SUCCESS;
|
|
|
|
osif_UpdateTickConfig();
|
|
if ((timeout == 0u))
|
|
{
|
|
/* when the timeout is 0 the wait operation is the equivalent of try_wait,
|
|
meaning that if the semaphore is 0 return immediately with an error code
|
|
*/
|
|
if (*pSem == 0u)
|
|
{
|
|
osif_ret_code = STATUS_TIMEOUT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* timeout is not 0 */
|
|
uint32_t timeoutTicks;
|
|
if (timeout == OSIF_WAIT_FOREVER)
|
|
{
|
|
timeoutTicks = OSIF_WAIT_FOREVER;
|
|
}
|
|
else
|
|
{
|
|
/* Convert timeout from milliseconds to ticks. */
|
|
timeoutTicks = MSEC_TO_TICK(timeout);
|
|
}
|
|
uint32_t start = osif_GetCurrentTickCount();
|
|
uint32_t end = (uint32_t)(start + timeoutTicks);
|
|
uint32_t max = end - start;
|
|
while (*pSem == 0u)
|
|
{
|
|
uint32_t crt_ticks = osif_GetCurrentTickCount();
|
|
uint32_t delta = crt_ticks - start;
|
|
if ((timeoutTicks != OSIF_WAIT_FOREVER) && (delta > max))
|
|
{
|
|
/* Timeout occured, stop waiting and return fail code */
|
|
osif_ret_code = STATUS_TIMEOUT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (osif_ret_code == STATUS_SUCCESS)
|
|
{
|
|
osif_DisableIrqGlobal();
|
|
--(*pSem);
|
|
osif_EnableIrqGlobal();
|
|
}
|
|
|
|
return osif_ret_code;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_SemaPost
|
|
* Description : This function performs the 'post' (increment) operation on a semaphore.
|
|
*
|
|
* Implements : OSIF_SemaPost_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_SemaPost(semaphore_t * const pSem)
|
|
{
|
|
DEV_ASSERT(pSem != NULL);
|
|
|
|
status_t osif_ret_code = STATUS_SUCCESS;
|
|
osif_DisableIrqGlobal();
|
|
if (*pSem != 255u)
|
|
{
|
|
++(*pSem);
|
|
}
|
|
else
|
|
{
|
|
osif_ret_code = STATUS_ERROR;
|
|
}
|
|
|
|
osif_EnableIrqGlobal();
|
|
|
|
return osif_ret_code;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_SemaCreate
|
|
* Description : This function creates (initializes) a semaphore.
|
|
*
|
|
* Implements : OSIF_SemaCreate_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_SemaCreate(semaphore_t * const pSem,
|
|
const uint8_t initValue)
|
|
{
|
|
DEV_ASSERT(pSem != NULL);
|
|
osif_DisableIrqGlobal();
|
|
*pSem = initValue;
|
|
osif_EnableIrqGlobal();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*FUNCTION**********************************************************************
|
|
*
|
|
* Function Name : OSIF_SemaDestroy
|
|
* Description : This function destroys a semaphore object (mock operation in baremetal case).
|
|
*
|
|
* Implements : OSIF_SemaDestroy_baremetal_Activity
|
|
*END**************************************************************************/
|
|
status_t OSIF_SemaDestroy(const semaphore_t * const pSem)
|
|
{
|
|
DEV_ASSERT(pSem != NULL);
|
|
|
|
(void)pSem;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* EOF
|
|
******************************************************************************/
|