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