osif_baremetal.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2018 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 static volatile uint32_t s_osif_tick_cnt = 0u;
80 
81 static inline void osif_Tick(void)
82 {
83  s_osif_tick_cnt++;
84 }
85 
86 static inline uint32_t osif_GetCurrentTickCount(void)
87 {
88  return s_osif_tick_cnt;
89 }
90 
91 #endif /* (FEATURE_OSIF_USE_SYSTICK != 0) || (FEATURE_OSIF_USE_PIT != 0) */
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  /* For Cortex-M0 devices the systick counter is initialized with an undefined
113  value, so make sure to initialize it to 0 before starting */
115  S32_SysTick->RVR = S32_SysTick_RVR_RELOAD(core_freq / 1000u);
118 }
119 
120 static inline void osif_DisableIrqGlobal(void)
121 {
123 }
124 
125 static inline void osif_EnableIrqGlobal(void)
126 {
128 }
129 
130 #elif FEATURE_OSIF_USE_PIT
131 
132 void OSIF_PIT_IRQHandler(void);
133 
134 void OSIF_PIT_IRQHandler(void)
135 {
136  OSIF_PIT->TIMER[OSIF_PIT_CHAN_ID].TFLG = PIT_TFLG_TIF(1u);
137 
138  osif_Tick();
139 }
140 
141 static inline void osif_UpdateTickConfig(void)
142 {
143  uint32_t tick_freq = 0u;
144  PIT_Type * base = OSIF_PIT;
145 
146  /* get the clock frequency for the timer and compute ticks for 1 ms */
147  status_t clk_status = CLOCK_SYS_GetFreq(PITRTI0_CLK, &tick_freq);
148  DEV_ASSERT(clk_status == STATUS_SUCCESS);
149  DEV_ASSERT(tick_freq > 0u);
150  (void)clk_status;
151  uint32_t tick_1ms = tick_freq / 1000u;
152 
153  /* setup timer and enable interrupt */
154  base->MCR &= ~PIT_MCR_MDIS(1u); /* make sure module is started */
155  base->MCR |= PIT_MCR_FRZ(1u); /* stop in Debug */
156  base->TIMER[OSIF_PIT_CHAN_ID].LDVAL = tick_1ms;
157  base->TIMER[OSIF_PIT_CHAN_ID].TCTRL |= PIT_TCTRL_TEN(1u) | PIT_TCTRL_TIE(1u);
158  const IRQn_Type pitIrqId[PIT_INSTANCE_COUNT][PIT_IRQS_CH_COUNT] = PIT_IRQS;
159 
160  INT_SYS_InstallHandler(pitIrqId[0U][OSIF_PIT_CHAN_ID], OSIF_PIT_IRQHandler, NULL);
161  INT_SYS_EnableIRQ(pitIrqId[0U][OSIF_PIT_CHAN_ID]);
162 }
163 
164 static inline void osif_DisableIrqGlobal(void)
165 {
167 }
168 
169 static inline void osif_EnableIrqGlobal(void)
170 {
172 }
173 
174 #else /* FEATURE_OSIF_USE_SYSTICK == 0, FEATURE_OSIF_USE_PIT == 0 */
175 
176 static inline uint32_t osif_GetCurrentTickCount(void)
177 {
178  return 0u;
179 }
180 
181 static inline void osif_UpdateTickConfig(void)
182 {
183  /* do not update tick */
184 }
185 
186 #define osif_DisableIrqGlobal() (void)0;
187 
188 #define osif_EnableIrqGlobal() (void)0;
189 
190 #endif /* FEATURE_OSIF_USE_SYSTICK */
191 
194 /*******************************************************************************
195  * Code
196  ******************************************************************************/
197 
198 /*FUNCTION**********************************************************************
199  *
200  * Function Name : OSIF_TimeDelay
201  * Description : This function blocks execution for a number of milliseconds.
202  *
203  * Implements : OSIF_TimeDelay_baremetal_Activity
204  *END**************************************************************************/
205 void OSIF_TimeDelay(const uint32_t delay)
206 {
207  osif_UpdateTickConfig();
208  uint32_t start = osif_GetCurrentTickCount();
209  uint32_t crt_ticks = osif_GetCurrentTickCount();
210  uint32_t delta = crt_ticks - start;
211  uint32_t delay_ticks = MSEC_TO_TICK(delay);
212  while (delta < delay_ticks)
213  {
214  crt_ticks = osif_GetCurrentTickCount();
215  delta = crt_ticks - start;
216  }
217 }
218 
219 /*FUNCTION**********************************************************************
220  *
221  * Function Name : OSIF_GetMilliseconds
222  * Description : This function returns the number of miliseconds elapsed since
223  * starting the internal timer. To initialize the internal timer
224  * (Systick) in bare-metal, call either OSIF_TimeDelay or
225  * OSIF_SemaWait functions. Calling OSIF_TimeDelay(0) will initialize
226  * the timer without any side-effects (no delay).
227  *
228  * Implements : OSIF_GetMilliseconds_baremetal_Activity
229  *END**************************************************************************/
230 uint32_t OSIF_GetMilliseconds(void)
231 {
232  /*
233  * Please make sure the timer is initialized before calling this function.
234  * For example, calling OSIF_TimeDelay(0) ensures that the timer is initialized
235  * without any other side-effects. If OSIF_TimeDelay or OSIF_SemaWait functions
236  * have been called, the timer is already initialized.
237  */
238  return osif_GetCurrentTickCount(); /* This assumes that 1 tick = 1 millisecond */
239 }
240 
241 /*FUNCTION**********************************************************************
242  *
243  * Function Name : OSIF_MutexLock
244  * Description : This function locks a mutex (mock operation in baremetal case).
245  *
246  * Implements : OSIF_MutexLock_baremetal_Activity
247  *END**************************************************************************/
248 status_t OSIF_MutexLock(const mutex_t * const pMutex,
249  const uint32_t timeout)
250 {
251  (void)pMutex;
252  (void)timeout;
253 
254  return STATUS_SUCCESS;
255 }
256 
257 /*FUNCTION**********************************************************************
258  *
259  * Function Name : OSIF_MutexUnlock
260  * Description : This function unlocks a mutex (mock operation in baremetal case).
261  *
262  * Implements : OSIF_MutexUnlock_baremetal_Activity
263  *END**************************************************************************/
264 status_t OSIF_MutexUnlock(const mutex_t * const pMutex)
265 {
266  (void)pMutex;
267 
268  return STATUS_SUCCESS;
269 }
270 
271 /*FUNCTION**********************************************************************
272  *
273  * Function Name : OSIF_MutexCreate
274  * Description : This function creates a mutex (mock operation in baremetal case).
275  *
276  * Implements : OSIF_MutexCreate_baremetal_Activity
277  *END**************************************************************************/
278 status_t OSIF_MutexCreate(mutex_t * const pMutex)
279 {
280  (void)pMutex;
281 
282  return STATUS_SUCCESS;
283 }
284 
285 /*FUNCTION**********************************************************************
286  *
287  * Function Name : OSIF_MutexDestroy
288  * Description : This function destroys a mutex (mock operation in baremetal case).
289  *
290  * Implements : OSIF_MutexDestroy_baremetal_Activity
291  *END**************************************************************************/
292 status_t OSIF_MutexDestroy(const mutex_t * const pMutex)
293 {
294  (void)pMutex;
295 
296  return STATUS_SUCCESS;
297 }
298 
299 /*FUNCTION**********************************************************************
300  *
301  * Function Name : OSIF_SemaWait
302  * Description : This function performs the 'wait' (decrement) operation on a semaphore.
303  *
304  * Implements : OSIF_SemaWait_baremetal_Activity
305  *END**************************************************************************/
306 status_t OSIF_SemaWait(semaphore_t * const pSem,
307  const uint32_t timeout)
308 {
309  DEV_ASSERT(pSem != NULL);
310 
311  uint32_t timeoutTicks;
312  status_t osif_ret_code = STATUS_SUCCESS;
313 
314  osif_UpdateTickConfig();
315  /* Convert timeout from milliseconds to ticks. */
316  if (timeout == OSIF_WAIT_FOREVER)
317  {
318  timeoutTicks = OSIF_WAIT_FOREVER;
319  }
320  else
321  {
322  timeoutTicks = MSEC_TO_TICK(timeout);
323  }
324 
325  uint32_t start = osif_GetCurrentTickCount();
326  uint32_t end = (uint32_t)(start + timeoutTicks);
327  uint32_t max = end - start;
328  while (*pSem == 0u)
329  {
330  uint32_t crt_ticks = osif_GetCurrentTickCount();
331  uint32_t delta = crt_ticks - start;
332  if ((timeoutTicks != OSIF_WAIT_FOREVER) && (delta > max))
333  {
334  /* Timeout occured, stop waiting and return fail code */
335  osif_ret_code = STATUS_TIMEOUT;
336  break;
337  }
338  }
339 
340  if (osif_ret_code == STATUS_SUCCESS)
341  {
342  osif_DisableIrqGlobal();
343  --(*pSem);
344  osif_EnableIrqGlobal();
345  }
346 
347  return osif_ret_code;
348 }
349 
350 /*FUNCTION**********************************************************************
351  *
352  * Function Name : OSIF_SemaPost
353  * Description : This function performs the 'post' (increment) operation on a semaphore.
354  *
355  * Implements : OSIF_SemaPost_baremetal_Activity
356  *END**************************************************************************/
357 status_t OSIF_SemaPost(semaphore_t * const pSem)
358 {
359  DEV_ASSERT(pSem != NULL);
360 
361  status_t osif_ret_code = STATUS_SUCCESS;
362  osif_DisableIrqGlobal();
363  if (*pSem != 255u)
364  {
365  ++(*pSem);
366  }
367  else
368  {
369  osif_ret_code = STATUS_ERROR;
370  }
371 
372  osif_EnableIrqGlobal();
373 
374  return osif_ret_code;
375 }
376 
377 /*FUNCTION**********************************************************************
378  *
379  * Function Name : OSIF_SemaCreate
380  * Description : This function creates (initializes) a semaphore.
381  *
382  * Implements : OSIF_SemaCreate_baremetal_Activity
383  *END**************************************************************************/
384 status_t OSIF_SemaCreate(semaphore_t * const pSem,
385  const uint8_t initValue)
386 {
387  DEV_ASSERT(pSem != NULL);
388  osif_DisableIrqGlobal();
389  *pSem = initValue;
390  osif_EnableIrqGlobal();
391 
392  return STATUS_SUCCESS;
393 }
394 
395 /*FUNCTION**********************************************************************
396  *
397  * Function Name : OSIF_SemaDestroy
398  * Description : This function destroys a semaphore object (mock operation in baremetal case).
399  *
400  * Implements : OSIF_SemaDestroy_baremetal_Activity
401  *END**************************************************************************/
402 status_t OSIF_SemaDestroy(const semaphore_t * const pSem)
403 {
404  DEV_ASSERT(pSem != NULL);
405 
406  (void)pSem;
407 
408  return STATUS_SUCCESS;
409 }
410 
411 /*******************************************************************************
412  * EOF
413  ******************************************************************************/
#define S32_SysTick
Definition: S32K118.h:9236
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: S32K118.h:9278
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: S32K118.h:9261
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.
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
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K118.h:188
void INT_SYS_EnableIRQGlobal(void)
Enables system interrupt.
#define S32_SysTick_CVR_CURRENT(x)
Definition: S32K118.h:9283
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
#define S32_SysTick_CSR_TICKINT(x)
Definition: S32K118.h:9265
#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.
#define S32_SysTick_CSR_CLKSOURCE(x)
Definition: S32K118.h:9269
clock_names_t
Clock names.
void INT_SYS_InstallHandler(IRQn_Type irqNumber, const isr_t newHandler, isr_t *const oldHandler)
Installs an interrupt handler routine for a given IRQ number.