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