osif_freertos.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 
57 #include <stdbool.h>
58 #include "device_registers.h"
59 #include "osif.h"
60 #include "FreeRTOS.h"
61 #include "task.h"
62 #include "devassert.h"
63 
64 #if !defined (USING_OS_FREERTOS)
65 #error "Wrong OSIF selected. Please define symbol USING_OS_FREERTOS in project settings or change the OSIF variant"
66 #endif
67 
68 /*******************************************************************************
69  * Variables
70  ******************************************************************************/
71 
72 /*******************************************************************************
73  * Private Functions
74  ******************************************************************************/
75 
79 #define MSEC_TO_TICK(msec) (pdMS_TO_TICKS(msec))
80 
81 /*FUNCTION**********************************************************************
82  *
83  * Function Name : osif_IsIsrContext
84  * Description : This function returns true if the current execution context
85  * is from an ISR and false if execution is in normal thread mode.
86  *
87  *END**************************************************************************/
88 #if FEATURE_OSIF_FREERTOS_ISR_CONTEXT_METHOD == 1
89 /* Cortex M device - read ICSR[IPSR] value */
90 static inline bool osif_IsIsrContext(void)
91 {
92  bool is_isr = false;
93  uint32_t ipsr_code = (uint32_t)( (S32_SCB->ICSR & S32_SCB_ICSR_VECTACTIVE_MASK) >> S32_SCB_ICSR_VECTACTIVE_SHIFT );
94  if (ipsr_code != 0u)
95  {
96  is_isr = true;
97  }
98 
99  return is_isr;
100 }
101 #elif FEATURE_OSIF_FREERTOS_ISR_CONTEXT_METHOD == 2
102 /* PowerPC device, for FreeRTOS 9.0.0 read the SPRG0 reg that denotes the interrupt nesting level */
103 #define SPRG0_ADDR (272)
104 static inline bool osif_IsIsrContext(void)
105 {
106  uint32_t interrupt_level = MFSPR(SPRG0_ADDR);
107  bool is_isr = (bool)(interrupt_level > 0u);
108  return is_isr;
109 }
110 #else
111  #error "No method to check ISR Context"
112 #endif /* FEATURE_OSIF_FREERTOS_ISR_CONTEXT_METHOD */
113 
115 /*******************************************************************************
116  * Code
117  ******************************************************************************/
118 
119 /*FUNCTION**********************************************************************
120  *
121  * Function Name : OSIF_TimeDelay
122  * Description : This function blocks (sleep) the current thread for a number
123  * of milliseconds.
124  *
125  * Implements : OSIF_TimeDelay_freertos_Activity
126  *END**************************************************************************/
127 void OSIF_TimeDelay(uint32_t delay)
128 {
129  /* One dependency for FreeRTOS config file */
130  /* INCLUDE_vTaskDelay */
131  vTaskDelay(MSEC_TO_TICK(delay));
132 }
133 
134 
135 /*FUNCTION**********************************************************************
136  *
137  * Function Name : OSIF_GetMilliseconds
138  * Description : This function returns the number of miliseconds elapsed since
139  * starting the internal timer (since scheduler was started).
140  *
141  * Implements : OSIF_GetMilliseconds_freertos_Activity
142  *END**************************************************************************/
143 uint32_t OSIF_GetMilliseconds(void)
144 {
145  /*
146  * Return the tick count in miliseconds
147  * Note: if configTICK_RATE_HZ is less than 1000, the return value will be truncated
148  * to 32-bit wide for large values of the tick count.
149  */
150  return (uint32_t)((((uint64_t) xTaskGetTickCount()) * 1000u) / configTICK_RATE_HZ);
151 }
152 
153 /*FUNCTION**********************************************************************
154  *
155  * Function Name : OSIF_MutexLock
156  * Description : This function obtains the mutex lock or returns error if timeout.
157  *
158  * Implements : OSIF_MutexLock_freertos_Activity
159  *END**************************************************************************/
160 status_t OSIF_MutexLock(const mutex_t * const pMutex,
161  const uint32_t timeout)
162 {
163  /* The (pMutex == NULL) case is a valid option, signaling that the mutex does
164  * not need to be locked - do not use DEV_ASSERT in this case */
165 
166  uint32_t timeoutTicks;
167  status_t osif_ret_code = STATUS_SUCCESS;
168  TaskHandle_t mutex_holder_handle;
169  TaskHandle_t current_task_handle;
170  BaseType_t operation_status = pdFAIL;
171 
172  if (pMutex != NULL)
173  {
174  /* Two dependencies for FreeRTOS config file */
175  /* INCLUDE_xQueueGetMutexHolder */
176  /* INCLUDE_xTaskGetCurrentTaskHandle */
177  mutex_holder_handle = xSemaphoreGetMutexHolder(*pMutex);
178  current_task_handle = xTaskGetCurrentTaskHandle();
179 
180  /* If pMutex has been locked by current task, return error. */
181  if (mutex_holder_handle == current_task_handle)
182  {
183  osif_ret_code = STATUS_ERROR;
184  }
185  else
186  {
187  /* Convert timeout from millisecond to tick. */
188  if (timeout == OSIF_WAIT_FOREVER)
189  {
190  timeoutTicks = portMAX_DELAY;
191  }
192  else
193  {
194  timeoutTicks = MSEC_TO_TICK(timeout);
195  }
196 
197  /* Try to take the semaphore */
198  operation_status = xSemaphoreTake(*pMutex, timeoutTicks);
199 
200  osif_ret_code = (operation_status == pdPASS) ? STATUS_SUCCESS : STATUS_TIMEOUT;
201  }
202  }
203 
204  return osif_ret_code;
205 }
206 
207 /*FUNCTION**********************************************************************
208  *
209  * Function Name : OSIF_MutexUnlock
210  * Description : This function unlocks the mutex, fails if the current thread
211  * is not the mutex holder.
212  *
213  * Implements : OSIF_MutexUnlock_freertos_Activity
214  *END**************************************************************************/
215 status_t OSIF_MutexUnlock(const mutex_t * const pMutex)
216 {
217  /* The (pMutex == NULL) case is a valid option, signaling that the mutex does
218  * not need to be unlocked - do not use DEV_ASSERT in this case */
219 
220  status_t osif_ret_code = STATUS_SUCCESS;
221  TaskHandle_t mutex_holder_handle;
222  TaskHandle_t current_task_handle;
223  BaseType_t operation_status = pdFAIL;
224 
225  if (pMutex != NULL)
226  {
227  /* Two dependencies for FreeRTOS config file */
228  /* INCLUDE_xQueueGetMutexHolder */
229  /* INCLUDE_xTaskGetCurrentTaskHandle */
230  mutex_holder_handle = xSemaphoreGetMutexHolder(*pMutex);
231  current_task_handle = xTaskGetCurrentTaskHandle();
232 
233  /* If pMutex is not locked by current task, return error. */
234  if (mutex_holder_handle != current_task_handle)
235  {
236  osif_ret_code = STATUS_ERROR;
237  }
238  else
239  {
240  operation_status = xSemaphoreGive(*pMutex);
241  osif_ret_code = (operation_status == pdPASS) ? STATUS_SUCCESS : STATUS_ERROR;
242  }
243  }
244 
245  return osif_ret_code;
246 }
247 
248 /*FUNCTION**********************************************************************
249  *
250  * Function Name : OSIF_MutexCreate
251  * Description : This function creates (registers) a mutex object to the OS.
252  *
253  * Implements : OSIF_MutexCreate_freertos_Activity
254  *END**************************************************************************/
255 status_t OSIF_MutexCreate(mutex_t * const pMutex)
256 {
257  /* The (pMutex == NULL) case is a valid option, signaling that the mutex does
258  * not need to be created - do not use DEV_ASSERT in this case */
259 
260  status_t osif_ret_code = STATUS_SUCCESS;
261 
262  if (pMutex != NULL)
263  {
264  *pMutex = xSemaphoreCreateMutex();
265  if (*pMutex == NULL)
266  {
267  osif_ret_code = STATUS_ERROR; /* mutex not created successfully */
268  }
269  }
270 
271  return osif_ret_code;
272 }
273 
274 /*FUNCTION**********************************************************************
275  *
276  * Function Name : OSIF_MutexDestroy
277  * Description : This function removes the mutex from the OS (and frees memory).
278  *
279  * Implements : OSIF_MutexDestroy_freertos_Activity
280  *END**************************************************************************/
281 status_t OSIF_MutexDestroy(const mutex_t * const pMutex)
282 {
283  /* The (pMutex == NULL) case is a valid option, signaling that the mutex does
284  * not need to be destroyed - do not use DEV_ASSERT in this case */
285 
286  if (pMutex != NULL)
287  {
288  DEV_ASSERT(*pMutex);
289  vSemaphoreDelete(*pMutex);
290  }
291 
292  return STATUS_SUCCESS;
293 }
294 
295 /*FUNCTION**********************************************************************
296  *
297  * Function Name : OSIF_SemaWait
298  * Description : This function performs the 'wait' (decrement) operation on a semaphore,
299  * returns error if operation times out.
300  *
301  * Implements : OSIF_SemaWait_freertos_Activity
302  *END**************************************************************************/
303 status_t OSIF_SemaWait(semaphore_t * const pSem,
304  const uint32_t timeout)
305 {
306  DEV_ASSERT(pSem);
307 
308  uint32_t timeoutTicks;
309  BaseType_t operation_status;
310  status_t osif_ret_code;
311 
312  /* Convert timeout from millisecond to ticks. */
313  if (timeout == OSIF_WAIT_FOREVER)
314  {
315  timeoutTicks = portMAX_DELAY;
316  }
317  else
318  {
319  timeoutTicks = MSEC_TO_TICK(timeout);
320  }
321 
322  /* Try to take the semaphore */
323  operation_status = xSemaphoreTake(*pSem, timeoutTicks);
324 
325  osif_ret_code = (operation_status == pdPASS) ? STATUS_SUCCESS : STATUS_TIMEOUT;
326 
327  return osif_ret_code;
328 }
329 
330 /*FUNCTION**********************************************************************
331  *
332  * Function Name : OSIF_SemaPost
333  * Description : This function performs the 'post' (increment) operation on a semaphore.
334  *
335  * Implements : OSIF_SemaPost_freertos_Activity
336  *END**************************************************************************/
337 status_t OSIF_SemaPost(semaphore_t * const pSem)
338 {
339  DEV_ASSERT(pSem);
340 
341  BaseType_t operation_status = pdFAIL;
342  status_t osif_ret_code;
343 
344  /* Check if the post operation is executed from ISR context */
345  bool is_isr = osif_IsIsrContext();
346  if (is_isr)
347  {
348  /* Execution from exception handler (ISR) */
349  BaseType_t taskWoken = pdFALSE;
350  operation_status = xSemaphoreGiveFromISR(*pSem, &taskWoken);
351 
352  if (operation_status == pdPASS)
353  {
354  /* Perform a context switch if necessary */
355  portYIELD_FROM_ISR(taskWoken);
356  }
357  }
358  else
359  {
360  /* Execution from task */
361  operation_status = xSemaphoreGive(*pSem);
362  }
363 
364  /* pdFAIL in case that the semaphore is full */
365  osif_ret_code = (operation_status == pdPASS) ? STATUS_SUCCESS : STATUS_ERROR;
366 
367  return osif_ret_code;
368 }
369 
370 /*FUNCTION**********************************************************************
371  *
372  * Function Name : OSIF_SemaCreate
373  * Description : This function creates (registers) a semaphore object to the OS.
374  *
375  * Implements : OSIF_SemaCreate_freertos_Activity
376  *END**************************************************************************/
377 status_t OSIF_SemaCreate(semaphore_t * const pSem,
378  const uint8_t initValue)
379 {
380  DEV_ASSERT(pSem);
381 
382  status_t osif_ret_code = STATUS_SUCCESS;
383 
384  *pSem = xSemaphoreCreateCounting(0xFFu, initValue);
385 
386  if (*pSem == NULL)
387  {
388  osif_ret_code = STATUS_ERROR; /* semaphore not created successfully */
389  }
390 
391  return osif_ret_code;
392 }
393 
394 /*FUNCTION**********************************************************************
395  *
396  * Function Name : OSIF_SemaDestroy
397  * Description : This function removes a semaphore object from the OS (frees memory).
398  *
399  * Implements : OSIF_SemaDestroy_freertos_Activity
400  *END**************************************************************************/
401 status_t OSIF_SemaDestroy(const semaphore_t * const pSem)
402 {
403  DEV_ASSERT(pSem);
404  DEV_ASSERT(*pSem);
405 
406  vSemaphoreDelete(*pSem);
407 
408  return STATUS_SUCCESS;
409 }
410 
411 /*******************************************************************************
412  * EOF
413  ******************************************************************************/
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.
void OSIF_TimeDelay(uint32_t delay)
Delays execution for a number of milliseconds.
status_t OSIF_MutexUnlock(const mutex_t *const pMutex)
Unlocks a previously locked mutex.
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.
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t OSIF_MutexCreate(mutex_t *const pMutex)
Create an unlocked mutex.
#define S32_SCB
Definition: S32K118.h:9048
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
#define S32_SCB_ICSR_VECTACTIVE_SHIFT
Definition: S32K118.h:9082
status_t OSIF_SemaWait(semaphore_t *const pSem, const uint32_t timeout)
Decrement a semaphore with timeout.
#define OSIF_WAIT_FOREVER
Definition: osif.h:65
status_t OSIF_SemaPost(semaphore_t *const pSem)
Increment a semaphore.
#define S32_SCB_ICSR_VECTACTIVE_MASK
Definition: S32K118.h:9081