S32 SDK
osif_baremetal.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
50 #include "osif.h"
51 #include <stddef.h>
52 
53 #include "device_registers.h"
54 
55 #include "devassert.h"
56 
57 #if defined (USING_OS_FREERTOS)
58 #error "Wrong OSIF selected. Please define symbol USING_OS_BAREMETAL (or no OS define) in project settings or change the OSIF variant"
59 #endif
60 
61 /*******************************************************************************
62  * Variables
63  ******************************************************************************/
64 
65 /*******************************************************************************
66  * Private Functions
67  ******************************************************************************/
68 
72 #define MSEC_TO_TICK(msec) (msec)
73 
74 #if (FEATURE_OSIF_USE_SYSTICK != 0) || (FEATURE_OSIF_USE_PIT != 0)
75 /* Only include headers for configurations that need them. */
76 #include "interrupt_manager.h"
77 #include "clock_manager.h"
78 
79 #endif /* (FEATURE_OSIF_USE_SYSTICK != 0) || (FEATURE_OSIF_USE_PIT != 0) */
80 
81 static volatile uint32_t s_osif_tick_cnt = 0u;
82 
83 static inline void osif_Tick(void)
84 {
85  s_osif_tick_cnt++;
86 }
87 
88 static inline uint32_t osif_GetCurrentTickCount(void)
89 {
90  return s_osif_tick_cnt;
91 }
92 
93 #if FEATURE_OSIF_USE_SYSTICK
94 
95 void SysTick_Handler(void);
96 
97 void SysTick_Handler(void)
98 {
99  osif_Tick();
100 }
101 
102 static inline void osif_UpdateTickConfig(void)
103 {
104  uint32_t core_freq = 0u;
105  /* Get the correct name of the core clock */
106  clock_names_t coreclk = CORE_CLK;
107  status_t clk_status = CLOCK_SYS_GetFreq(coreclk, &core_freq);
108  DEV_ASSERT(clk_status == STATUS_SUCCESS);
109  DEV_ASSERT(core_freq > 0u);
110  (void)clk_status;
111 
112  S32_SysTick->RVR = S32_SysTick_RVR_RELOAD(core_freq / 1000u);
114 }
115 
116 static inline void osif_DisableIrqGlobal(void)
117 {
119 }
120 
121 static inline void osif_EnableIrqGlobal(void)
122 {
124 }
125 
126 #elif FEATURE_OSIF_USE_PIT
127 
128 #define PIT_CHAN_ID (15u)
129 
130 void PIT_Ch15_IRQHandler(void);
131 
132 void PIT_Ch15_IRQHandler(void)
133 {
134  PIT->TIMER[PIT_CHAN_ID].TFLG = PIT_TFLG_TIF(1u);
135 
136  osif_Tick();
137 }
138 
139 static inline void osif_UpdateTickConfig(void)
140 {
141  uint32_t tick_freq = 0u;
142  PIT_Type * base = PIT;
143 
144  /* get the clock frequency for the timer and compute ticks for 1 ms */
145  status_t clk_status = CLOCK_SYS_GetFreq(PITRTI0_CLK, &tick_freq);
146  DEV_ASSERT(clk_status == STATUS_SUCCESS);
147  DEV_ASSERT(tick_freq > 0u);
148  (void)clk_status;
149  uint32_t tick_1ms = tick_freq / 1000u;
150 
151  /* setup timer and enable interrupt */
152  base->MCR &= ~PIT_MCR_MDIS(1u); /* make sure module is started */
153  base->TIMER[PIT_CHAN_ID].LDVAL = tick_1ms;
154  base->TIMER[PIT_CHAN_ID].TCTRL |= PIT_RTI_TCTRL_TEN(1u) | PIT_RTI_TCTRL_TIE(1u);
155  const IRQn_Type pitIrqId[] = PIT_IRQS;
156  INT_SYS_EnableIRQ(pitIrqId[PIT_CHAN_ID]);
157 }
158 
159 static inline void osif_DisableIrqGlobal(void)
160 {
162 }
163 
164 static inline void osif_EnableIrqGlobal(void)
165 {
167 }
168 
169 #else /* FEATURE_OSIF_USE_SYSTICK == 0, FEATURE_OSIF_USE_PIT == 0 */
170 
171 static inline uint32_t osif_GetCurrentTickCount(void)
172 {
173  return 0u;
174 }
175 
176 static inline void osif_UpdateTickConfig(void)
177 {
178  /* do not update systick */
179 }
180 
181 #define osif_DisableIrqGlobal() (void)0;
182 
183 #define osif_EnableIrqGlobal() (void)0;
184 
185 #endif /* FEATURE_OSIF_USE_SYSTICK */
186 
189 /*******************************************************************************
190  * Code
191  ******************************************************************************/
192 
193 /*FUNCTION**********************************************************************
194  *
195  * Function Name : OSIF_TimeDelay
196  * Description : This function blocks execution for a number of milliseconds.
197  *
198  * Implements : OSIF_TimeDelay_baremetal_Activity
199  *END**************************************************************************/
200 void OSIF_TimeDelay(const uint32_t delay)
201 {
202  osif_UpdateTickConfig();
203  uint32_t start = osif_GetCurrentTickCount();
204  uint32_t crt_ticks = osif_GetCurrentTickCount();
205  uint32_t delta = crt_ticks - start;
206  uint32_t delay_ticks = MSEC_TO_TICK(delay);
207  while (delta < delay_ticks)
208  {
209  crt_ticks = osif_GetCurrentTickCount();
210  delta = crt_ticks - start;
211  }
212 }
213 
214 /*FUNCTION**********************************************************************
215  *
216  * Function Name : OSIF_GetMilliseconds
217  * Description : This function returns the number of miliseconds elapsed since
218  * starting the internal timer. To initialize the internal timer
219  * (Systick) in bare-metal, call either OSIF_TimeDelay or
220  * OSIF_SemaWait functions. Calling OSIF_TimeDelay(0) will initialize
221  * the timer without any side-effects (no delay).
222  *
223  * Implements : OSIF_GetMilliseconds_baremetal_Activity
224  *END**************************************************************************/
225 uint32_t OSIF_GetMilliseconds(void)
226 {
227  /*
228  * Please make sure the timer is initialized before calling this function.
229  * For example, calling OSIF_TimeDelay(0) ensures that the timer is initialized
230  * without any other side-effects. If OSIF_TimeDelay or OSIF_SemaWait functions
231  * have been called, the timer is already initialized.
232  */
233  return osif_GetCurrentTickCount(); /* This assumes that 1 tick = 1 millisecond */
234 }
235 
236 /*FUNCTION**********************************************************************
237  *
238  * Function Name : OSIF_MutexLock
239  * Description : This function locks a mutex (mock operation in baremetal case).
240  *
241  * Implements : OSIF_MutexLock_baremetal_Activity
242  *END**************************************************************************/
243 status_t OSIF_MutexLock(const mutex_t * const pMutex,
244  const uint32_t timeout)
245 {
246  (void)pMutex;
247  (void)timeout;
248 
249  return STATUS_SUCCESS;
250 }
251 
252 /*FUNCTION**********************************************************************
253  *
254  * Function Name : OSIF_MutexUnlock
255  * Description : This function unlocks a mutex (mock operation in baremetal case).
256  *
257  * Implements : OSIF_MutexUnlock_baremetal_Activity
258  *END**************************************************************************/
259 status_t OSIF_MutexUnlock(const mutex_t * const pMutex)
260 {
261  (void)pMutex;
262 
263  return STATUS_SUCCESS;
264 }
265 
266 /*FUNCTION**********************************************************************
267  *
268  * Function Name : OSIF_MutexCreate
269  * Description : This function creates a mutex (mock operation in baremetal case).
270  *
271  * Implements : OSIF_MutexCreate_baremetal_Activity
272  *END**************************************************************************/
273 status_t OSIF_MutexCreate(mutex_t * const pMutex)
274 {
275  (void)pMutex;
276 
277  return STATUS_SUCCESS;
278 }
279 
280 /*FUNCTION**********************************************************************
281  *
282  * Function Name : OSIF_MutexDestroy
283  * Description : This function destroys a mutex (mock operation in baremetal case).
284  *
285  * Implements : OSIF_MutexDestroy_baremetal_Activity
286  *END**************************************************************************/
287 status_t OSIF_MutexDestroy(const mutex_t * const pMutex)
288 {
289  (void)pMutex;
290 
291  return STATUS_SUCCESS;
292 }
293 
294 /*FUNCTION**********************************************************************
295  *
296  * Function Name : OSIF_SemaWait
297  * Description : This function performs the 'wait' (decrement) operation on a semaphore.
298  *
299  * Implements : OSIF_SemaWait_baremetal_Activity
300  *END**************************************************************************/
301 status_t OSIF_SemaWait(semaphore_t * const pSem,
302  const uint32_t timeout)
303 {
304  DEV_ASSERT(pSem != NULL);
305 
306  uint32_t timeoutTicks;
307  status_t osif_ret_code = STATUS_SUCCESS;
308 
309  osif_UpdateTickConfig();
310  /* Convert timeout from milliseconds to ticks. */
311  if (timeout == OSIF_WAIT_FOREVER)
312  {
313  timeoutTicks = OSIF_WAIT_FOREVER;
314  }
315  else
316  {
317  timeoutTicks = MSEC_TO_TICK(timeout);
318  }
319 
320  uint32_t start = osif_GetCurrentTickCount();
321  uint32_t end = (uint32_t)(start + timeoutTicks);
322  uint32_t max = end - start;
323  while (*pSem == 0u)
324  {
325  uint32_t crt_ticks = osif_GetCurrentTickCount();
326  uint32_t delta = crt_ticks - start;
327  if ((timeoutTicks != OSIF_WAIT_FOREVER) && (delta > max))
328  {
329  /* Timeout occured, stop waiting and return fail code */
330  osif_ret_code = STATUS_TIMEOUT;
331  break;
332  }
333  }
334 
335  if (osif_ret_code == STATUS_SUCCESS)
336  {
337  osif_DisableIrqGlobal();
338  --(*pSem);
339  osif_EnableIrqGlobal();
340  }
341 
342  return osif_ret_code;
343 }
344 
345 /*FUNCTION**********************************************************************
346  *
347  * Function Name : OSIF_SemaPost
348  * Description : This function performs the 'post' (increment) operation on a semaphore.
349  *
350  * Implements : OSIF_SemaPost_baremetal_Activity
351  *END**************************************************************************/
352 status_t OSIF_SemaPost(semaphore_t * const pSem)
353 {
354  DEV_ASSERT(pSem != NULL);
355 
356  status_t osif_ret_code = STATUS_SUCCESS;
357  osif_DisableIrqGlobal();
358  if (*pSem != 255u)
359  {
360  ++(*pSem);
361  }
362  else
363  {
364  osif_ret_code = STATUS_ERROR;
365  }
366 
367  osif_EnableIrqGlobal();
368 
369  return osif_ret_code;
370 }
371 
372 /*FUNCTION**********************************************************************
373  *
374  * Function Name : OSIF_SemaCreate
375  * Description : This function creates (initializes) a semaphore.
376  *
377  * Implements : OSIF_SemaCreate_baremetal_Activity
378  *END**************************************************************************/
379 status_t OSIF_SemaCreate(semaphore_t * const pSem,
380  const uint8_t initValue)
381 {
382  DEV_ASSERT(pSem != NULL);
383  osif_DisableIrqGlobal();
384  *pSem = initValue;
385  osif_EnableIrqGlobal();
386 
387  return STATUS_SUCCESS;
388 }
389 
390 /*FUNCTION**********************************************************************
391  *
392  * Function Name : OSIF_SemaDestroy
393  * Description : This function destroys a semaphore object (mock operation in baremetal case).
394  *
395  * Implements : OSIF_SemaDestroy_baremetal_Activity
396  *END**************************************************************************/
397 status_t OSIF_SemaDestroy(const semaphore_t * const pSem)
398 {
399  DEV_ASSERT(pSem != NULL);
400 
401  (void)pSem;
402 
403  return STATUS_SUCCESS;
404 }
405 
406 /*******************************************************************************
407  * EOF
408  ******************************************************************************/
#define S32_SysTick
Definition: S32K142.h:10203
status_t OSIF_MutexDestroy(const mutex_t *const pMutex)
Destroys a previously created mutex.
status_t OSIF_SemaDestroy(const semaphore_t *const pSem)
Destroys a previously created semaphore.
#define S32_SysTick_RVR_RELOAD(x)
Definition: S32K142.h:10245
void OSIF_TimeDelay(const uint32_t delay)
Delays execution for a number of milliseconds.
status_t OSIF_MutexUnlock(const mutex_t *const pMutex)
Unlocks a previously locked mutex.
#define S32_SysTick_CSR_ENABLE(x)
Definition: S32K142.h:10228
status_t OSIF_MutexLock(const mutex_t *const pMutex, const uint32_t timeout)
Waits for a mutex and locks it.
uint32_t OSIF_GetMilliseconds(void)
Returns the number of miliseconds elapsed since starting the internal timer or starting the scheduler...
status_t OSIF_SemaCreate(semaphore_t *const pSem, const uint8_t initValue)
Creates a semaphore with a given value.
void INT_SYS_DisableIRQGlobal(void)
Disable system interrupt.
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t OSIF_MutexCreate(mutex_t *const pMutex)
Create an unlocked mutex.
clock_names_t
Clock names.
status_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency)
Gets the clock frequency for a specific clock name.
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
void INT_SYS_EnableIRQGlobal(void)
Enables system interrupt.
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
#define S32_SysTick_CSR_TICKINT(x)
Definition: S32K142.h:10232
#define OSIF_WAIT_FOREVER
Definition: osif.h:65
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192