Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The cifX Toolkit configuration can use newlib and FreeRTOS functions/ objects. The changes arechanged cifX Toolkit OS Abstraction is:

Code Block
languagecpp
titleCifXToolkit_OS_freeRTOSFreeRTOS.c
/*
*
* cifX Toolkit API is working with millisecond increments and thus requires a timer resolution of at least 1kHz.
*
* This implementation excepts the kernel tick to be set appropriately, otherwise
* custom implementation is needed facilitating a hardware clock or similar.
*
* If FreeRTOS' configuration configTICK_RATE_HZ is set to 1000, FreeRTOS ticks may be used.
* In case this value exceeds 1000Hz, limitation of macro pdMS_TO_TICKS() need
* to be considered and the calculation to convert timer ticks to ms needs updating.
*
* vTaskDelay( requires INCLUDE_vTaskDelay to be set.
*
* xTaskGetTickCount()
* As the toolkit operates on 32bit timeout values, 16bit timer resolutions
* should be avoided in the first place.
* In case configUSE_16_BIT_TICKS is set, casting and overflow handling needs to added
* to guarantee expected handling.
*
*/

/**************************************************************************************
 Exclusion of Liability for this demo software:
 The following software is intended for and must only be used for reference and in an
 evaluation laboratory environment. It is provided without charge and is subject to
 alterations. There is no warranty for the software, to the extent permitted by
 applicable law. Except when otherwise stated in writing the copyright holders and/or
 other parties provide the software "as is" without warranty of any kind, either
 expressed or implied.
 Please refer to the Agreement in README_DISCLAIMER.txt, provided together with this file!
 By installing or otherwise using the software, you accept the terms of this Agreement.
 If you do not agree to the terms of this Agreement, then do not install or use the
 Software!
 *******************************************************************************/
/*! Get Millisecond counter value (used for timeout handling)
*     \return Counter value with a resolution of 1ms                         */
/****/

/**************************************************************************************/
uint32_t OS_GetMilliSecCounter(void)
{

#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  TickType_t tTicks = xTaskGetTickCount();
  return (uint32_t)tTicks;
#else
  #error OS_Sleep(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

}

/
Copyright (c) Hilscher Gesellschaft fuer Systemautomation mbH. All Rights Reserved.

***************************************************************************************/

/*! Sleep for the given time
*     \param ulSleepTimeMs Time in ms to sleep (0 will sleep for 50us)       */
/*****************$Id: cifXToolkit_OS-freeRTOS.c 14146 2021-07-27 13:25:12Z LContreras $:

  Description:
    OS abstraction function implementation for FreeRTOS on netX90 APP

  Changes:
    Date        Description
    -----------------------------------------------------------------------------------
    2021-06-18  initial port for FreeRTOS 10.2.0 running netX90 APP CPU

************************************************************/
void OS_Sleep(uint32_t ulSleepTimeMs)
{
#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  vTaskDelay(pdMS_TO_TICKS(ulSleepTimeMs));
#else
  #error OS_Sleep(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */
}

/********************************/

#include <stdlib.h>
#include <stdio.h>

#include "OS_Includes.h"

#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>


#include "cifXToolkit.h"
#include "cifXErrors.h"
//#include "OS_Dependent.h"

/* netX90 APP CPU */
#include "netx90_app.h" /* NVIC_* helpers, idpm_com_host_IRQn */

/* OS kernel includes */
#include "FreeRTOS.h"
#include "task.h"     /* Sleep, kernel tick, critical section */
#include "semphr.h"   /* Mutex, binary semaphore for Event */

static int s_fOSInitDone = 0; /*<! Status initialisation flag of this module */


/* Interrupt members (static variables sufficient as only one DPM is handled) */
static DEVICEINSTANCE* s_ptIrqDevInst = NULL; /*<! Interrupt context */
static TaskHandle_t    s_xDsrTask     = NULL; /*<! DSR task handle, notified by DPM IRQ */
static bool            s_fDSRActive   = false;


/*
* NOTE: The type of BaseType_t is set by the port, hence it may differ.
* This module only uses this type internally and thus should be compatible with different types.
*  The netX90 APP CPI port defines it as 'long' (see portmacro.h of FreeRTOS).
*/

/*****************************************************************************/
/*! O/S Specific initialization
*     \return CIFX_NO_ERROR on success                                       */
/*****************************************************************************/
long OS_Init(void)
{
  s_fOSInitDone = 1;

  return CIFX_NO_ERROR;
}

/*****************************************************************************/
/*! O/S Specific de-initialization (de-initializes libpciaccess)             */
/*****************************************************************************/
void OS_Deinit(void)
{
  s_fOSInitDone = 0;
}


/*****************************************************************************/
/*****************************************************************************/
/*!<                          Memory functions                               */
/*****************************************************************************/
/*****************************************************************************/

/*
*  Although FreeRTOS provides dedicated functions for heap memory handling such
*  as vPortMalloc() and vPortFree(), there are different memory allocation schemes
*  available to choose from (not to mention custom implementations) each with
*  varying degree of properties and functionality.
*
*  Some ports do not supply a realloc() or memmove() function, which are expected
*  by cifX Toolkit. These are used in the scope of handling multiple devices
*  which this port does not support (1x iDPM only).
*
*  As such, the heap memory functions by the C library are used here.
*/
/*****************************************************************************/
/*! Memory allocation wrapper (standard malloc)
*     \param ulSize Size of block to allocate
*     \return NULL on failure                                                */
/*****************************************************************************/
void* OS_Memalloc(uint32_t ulSize)
{
  return malloc(ulSize);
}

/*****************************************************************************/
/*! Memory de-allocation wrapper (standard free)
*     \param pvMem  Block to free                                            */
/*****************************************************************************/
void OS_Memfree(void* pvMem)
{
  free(pvMem);
}

/*****************************************************************************/
/*! Memory resize wrapper (standard realloc)
*     \param pvMem      Block to resize
*     \param ulNewSize  New size of the block
*     \return NULL on error                                                  */
/*****************************************************************************/
void* OS_Memrealloc(void* pvMem, uint32_t ulNewSize)
{
  return realloc(pvMem, ulNewSize);
}

/*****************************************************************************/
/*! Memset wrapper
*     \param pvMem   Memory to set
*     \param bFill   Fill byte
*     \param ulSize  Size of the fill block                                  */
/*****************************************************************************/
void OS_Memset(void* pvMem, uint8_t bFill, uint32_t ulSize)
{
  memset(pvMem, bFill, ulSize);
}

/*****************************************************************************/
/*! Memcopy wrapper
*     \param pvDest  Destination pointer
*     \param pvSrc   Source pointer
*     \param ulSize  Size to copy                                            */
/*****************************************************************************/
void OS_Memcpy(void* pvDest, void* pvSrc, uint32_t ulSize)
{
  memcpy(pvDest, pvSrc, ulSize);
}

/*****************************************************************************/
/*! Memcompare wrapper
*     \param pvBuf1  First compare buffer
*     \param pvBuf2  Second compare buffer
*     \param ulSize  Size to compare
*     \return 0 if blocks are equal                                          */
/*****************************************************************************/
int OS_Memcmp(void* pvBuf1, void* pvBuf2, uint32_t ulSize)
{
  return memcmp(pvBuf1, pvBuf2, ulSize);
}

/*****************************************************************************/
/*! Memmove wrapper (Overlapping memory copy)
*     \param pvDest  Destination buffer
*     \param pvSrc   Source buffer
*     \param ulSize  Size to move                                            */
/*****************************************************************************/
void OS_Memmove(void* pvDest, void* pvSrc, uint32_t ulSize)
{
  memmove(pvDest, pvSrc, ulSize);
}


/*****************************************************************************/
/*****************************************************************************/
/*!<                         Timing functions                                */
/*****************************************************************************/
/*****************************************************************************/

/*
*
* cifX Toolkit API is working with millisecond increments and thus requires a timer resolution of at least 1kHz.
*
* This implementation excepts the kernel tick to be set appropriately, otherwise
* custom implementation is needed facilitating a hardware clock or similar.
*
* If FreeRTOS' configuration configTICK_RATE_HZ is set to 1000, FreeRTOS ticks may be used.
* In case this value exceeds 1000Hz, limitation of macro pdMS_TO_TICKS() need
* to be considered and the calculation to convert timer ticks to ms needs updating.
*
* vTaskDelay( requires INCLUDE_vTaskDelay to be set.
*
* xTaskGetTickCount()
* As the toolkit operates on 32bit timeout values, 16bit timer resolutions
* should be avoided in the first place.
* In case configUSE_16_BIT_TICKS is set, casting and overflow handling needs to added
* to guarantee expected handling.
*
*/

/*****************************************************************************/
/*! Get Millisecond counter value (used for timeout handling)
*     \return Counter value with a resolution of 1ms                         */
/*****************************************************************************/
uint32_t OS_GetMilliSecCounter(void)
{

#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  TickType_t tTicks = xTaskGetTickCount();
  return (uint32_t)tTicks;
#else
  #error OS_Sleep(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

}

/*****************************************************************************/
/*! Sleep for the given time
*     \param ulSleepTimeMs Time in ms to sleep (0 will sleep for 50us)       */
/*****************************************************************************/
void OS_Sleep(uint32_t ulSleepTimeMs)
{
#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  vTaskDelay(pdMS_TO_TICKS(ulSleepTimeMs));
#else
  #error OS_Sleep(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */
}

/*****************************************************************************/
/*****************************************************************************/
/*!<                         Interrupt handling                              */
/*****************************************************************************/
/*****************************************************************************/

/*****************************************************************************/
/*! DSR task evaluating DPM changes.
*   Function should be instantiated as a high priority task
*   (all cifX API calls should be lower that its priority).
*     \param pvParameters   User parameter (unused)                          */
/*****************************************************************************/
void CIFX_DSRHandler(void* pvParameters)
{
  while(s_ptIrqDevInst)
  {
    (void)ulTaskNotifyTake(pdTRUE, /* Clear the notification value on exit */
                           portMAX_DELAY);/* Block indefinitely */
    if(s_fDSRActive)
    {
      cifXTKitDSRHandler(s_ptIrqDevInst);
    }
    else
      break;
  }

  vTaskDelete(s_xDsrTask);
  s_xDsrTask = NULL;
}

/*****************************************************************************/
/*! IRQ handler for DPM interrupt.
*   Fixed location in NVIC (idpm_com_host_IRQn).                             */
/*****************************************************************************/
void IDPM_IRQHandler(void)
{
  /* Prohibit any call if toolkit is not fully configured */
  if(!s_fOSInitDone || !s_ptIrqDevInst || !s_xDsrTask)
  {
    /* Spurious IRQ, disable if detected */
    NVIC_DisableIRQ(idpm_com_host_IRQn);
  }
  else
  {
    int iResult = 0;
    iResult = cifXTKitISRHandler(s_ptIrqDevInst, 1); /* Ignore register block as we are netX90 APP */

    /* "The DSR is expected to be interruptible and will process the interrupt events in non-interrupt mode."
       -> Signal to DSR thread */
    if(CIFX_TKIT_IRQ_DSR_REQUESTED == iResult)
    {
      BaseType_t xHigherPriorityTaskWoken = pdFALSE;

      /* Unblock the handling task so the task can perform any processing necessitated
      by the interrupt. s_xDsrTask is the task's handle, which was obtained
      when the task was created. */
      vTaskNotifyGiveFromISR(s_xDsrTask, &xHigherPriorityTaskWoken);

      /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE. */
      portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
  }
}

/*****************************************************************************/
/*! Enable interrupts on the given device.
*   Achieved by creating an DSR service task which is called by ISR handler
*   (the latter is installed in NVIC).
*     \param pvOSDependent Pointer to internal device structure              */
/*****************************************************************************/
void OS_EnableInterrupts(void* pvOSDependent)
{
  s_fDSRActive = true;

  (void)xTaskCreate(CIFX_DSRHandler,
                    "CIFXDSR",
                    configMINIMAL_STACK_SIZE, /* Depending on the application usage, more Stack may be needed */
                    (void*) NULL,
                    CIFX_INTERRUPT_DSR_TASK_PRIORITY,
                    &s_xDsrTask);

  /* Store context locally of ISR/DSR */
  s_ptIrqDevInst = (DEVICEINSTANCE*)pvOSDependent;

  /* Only used the shared interrupt */
  NVIC_SetPriority(idpm_com_host_IRQn, NETX90_IDPM_IRQ_PRIORITY);
  NVIC_EnableIRQ(idpm_com_host_IRQn);
}

/*****************************************************************************/
/*! Disable interrupts on the given device
*     \param pvOSDependent Pointer to internal device structure              */
/*****************************************************************************/
void OS_DisableInterrupts(void* pvOSDependent)
{
  UNREFERENCED_PARAMETER(pvOSDependent);

  /* Disable physical interrupt of DPM */
  NVIC_DisableIRQ(idpm_com_host_IRQn);
  NVIC_SetPriority(idpm_com_host_IRQn, 0); /* Reset priority to default */

  /* Trigger deinit of DSR task */
  s_fDSRActive = false;
  (void)xTaskNotifyGive(s_xDsrTask);

  taskYIELD();

  /* Task handle is deleted in DSR epilogue */

  s_ptIrqDevInst = NULL;
}

/*****************************************************************************/
/*****************************************************************************/
/*!<                   Mutex functions (channel access)                      */
/*****************************************************************************/
/*****************************************************************************/

/*****************************************************************************/
/*! Create mutex
*     \return Handle to new created mutex                                    */
/*****************************************************************************/
void* OS_CreateMutex(void)
{
  return (void*) xSemaphoreCreateMutex();
}

/*****************************************************************************/
/*! Try to acquire mutex with timeout
*     \param pvMutex   Handle to mutex
*     \param ulTimeout Timeout in ms to wait for mutex
*     \return !=0 if mutex was acquired                                      */
/*****************************************************************************/
int OS_WaitMutex(void* pvMutex, uint32_t ulTimeout)
{
  BaseType_t tRes;

#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  tRes = xSemaphoreTake((SemaphoreHandle_t)pvMutex, (TickType_t)pdMS_TO_TICKS(ulTimeout));
#else
  #error OS_WaitMutex(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

  /* Map return value for cifX Toolkit */
  if(pdPASS == tRes)
    return 1;
  else
    return 0;

}

/*****************************************************************************/
/*! Release previously acquired mutex
*     \param pvMutex   Handle to mutex                                       */
/*****************************************************************************/
void OS_ReleaseMutex(void* pvMutex)
{
  (void)xSemaphoreGive((SemaphoreHandle_t)pvMutex);
}

/*****************************************************************************/
/*! Delete mutex
*     \param pvMutex   Handle to mutex                                       */
/*****************************************************************************/
void OS_DeleteMutex(void* pvMutex)
{
  vSemaphoreDelete((SemaphoreHandle_t)pvMutex);
}

/*****************************************************************************/
/*****************************************************************************/
/*!<                        Lock functions                                   */
/*****************************************************************************/
/*****************************************************************************/

/*****************************************************************************/
/*! Create Lock (Usually same as mutex, but does not support timed waiting)
*     \return Handle to created lock                                         */
/*****************************************************************************/
void* OS_CreateLock(void)
{
  /* Ideally, any task which calls cifX API functions requiring a lock (ultimately changes to HSK cells)
   * should be running in task mode.
   * While changing the implementation of OS_*Lock() functions to work in interrupt mode could be done,
   * it should be seen as application specific.
   * Special care needs to be taken to be fully IRQ safe (beware of e.g. configMAX_SYSCALL_INTERRUPT_PRIORITY
   * and other FreeRTOS/IRQ setting!).
   */

  /* For critical sections, no initialisation is needed, so return a valid placeholder. */
  return (void*)1;
}

/*****************************************************************************/
/*! Acquire a lock
*     \param pvLock Handle to lock                                           */
/*****************************************************************************/
void OS_EnterLock(void* pvLock)
{
  /* Taken from FreeRTOS 10.2. documentation (taskENTER_CRITICAL()):
   * "Preemptive context switches only occur inside an interrupt, so will not occur when interrupts are disabled.
   * Therefore, the task that called taskENTER_CRITICAL() is guaranteed to remain in the Running state until
   * the critical section is exited, unless the task explicitly attempts to block or yield
   * (which it should not do from inside a critical section)."
  */

  taskENTER_CRITICAL();
}

/*****************************************************************************/
/*! Release a lock
*     \param pvLock Handle to lock                                           */
/*****************************************************************************/
void OS_LeaveLock(void* pvLock)
{
  taskEXIT_CRITICAL();
}

/*****************************************************************************/
/*!< Delete a lock
*     \param pvLock Handle to lock            Interrupt handling                              */
/*****************************************************************************/
void OS_DeleteLock(void* pvLock)
{
  UNREFERENCED_PARAMETER(pvLock);
}


/*****************************************************************************/

/*****************************************************************************/
/*!< DSR task evaluating DPM changes. *   Function should be instantiated as a high priority task
*   (all cifX API calls should be lower that its priority).
*Event functions (signalled from DSR)      \param pvParameters   User parameter (unused)                          */
/*/
/*****************************************************************************/
/************************************************************************/
void CIFX_DSRHandler(void* pvParameters)
{
  while(s_ptIrqDevInst)
  {
    (void)ulTaskNotifyTake(pdTRUE, /* Clear the notification value on exit */
                           portMAX_DELAY);/* Block indefinitely */
    if(s_fDSRActive)
    {
      cifXTKitDSRHandler(s_ptIrqDevInst);
    }
    else
  

  break;
  }

  vTaskDelete(s_xDsrTask);
  s_xDsrTask = NULL;
}

/*****************************************************************************/
/*! IRQ handler for DPM interrupt.
*Create event
*     \return Handle to created event    Fixed location in NVIC (idpm_com_host_IRQn).                                 */
/*****************************************************************************/
void IDPM_IRQHandler(void)
{
  /* Prohibit any call if toolkit is not fully configured */
  if(!s_fOSInitDone || !s_ptIrqDevInst || !s_xDsrTask)
  {
    /* Spurious IRQ, disable if detected */
    NVIC_DisableIRQ(idpm_com_host_IRQn);
  }
  else
 ***/
void* OS_CreateEvent(void)
{
  SemaphoreHandle_t  inttSem iResult = 0xSemaphoreCreateBinary();
  return  iResult = cifXTKitISRHandler(s_ptIrqDevInst, 1); /* Ignore register block as we are netX90 APP */

    /* "The DSR is expected to be interruptible and will process the interrupt events in non-interrupt mode."
       -> Signal to DSR thread */
    if(CIFX_TKIT_IRQ_DSR_REQUESTED == iResult)
    {(void*)tSem;
}

/*****************************************************************************/
/*! Signal event
*     \param pvEvent Handle to event                     BaseType_t xHigherPriorityTaskWoken = pdFALSE; 
      /* Unblock the handling task so the task can perform any processing necessitated       by the interrupt. s_xDsrTask is the task's handle, which was obtained
      when the task was created. */
      vTaskNotifyGiveFromISR(s_xDsrTask, &xHigherPriorityTaskWoken);*/
/*****************************************************************************/
void OS_SetEvent(void* pvEvent)
{
  (void)xSemaphoreGive((SemaphoreHandle_t)pvEvent);
}

/*****************************************************************************/
/*! Reset event
*     \param pvEvent Handle to event            /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE. */       portYIELD_FROM_ISR(xHigherPriorityTaskWoken);     }   } } */
/*****************************************************************************/
/*! Enable interrupts on the given device.
*   Achieved by creating an DSR service task which is called by ISR handler
*   (the latter is installed in NVIC).
*     \param pvOSDependent Pointer to internal device structure              */
/***********void OS_ResetEvent(void* pvEvent)
{
  /* no equivalent available and not used by toolkit (currently) */
  UNREFERENCED_PARAMETER(pvEvent);
}

/******************************************************************/
void OS_EnableInterrupts(void* pvOSDependent)
{
  s_fDSRActive = true;

  (void)xTaskCreate(CIFX_DSRHandler,
                    "CIFXDSR",
                    configMINIMAL_STACK_SIZE, /* Depending on the application usage, more Stack may be needed */
                    (void*) NULL,
          ***********/
/*! Delete event
*     \param pvEvent Handle to event          CIFX_INTERRUPT_DSR_TASK_PRIORITY,
                    &s_xDsrTask);

  /* Store context locally of ISR/DSR */
  s_ptIrqDevInst = (DEVICEINSTANCE*)pvOSDependent;    /* Only used the shared interrupt */
/*****************************************************************************/
void NVICOS_SetPriority(idpm_com_host_IRQn, NETX90_IDPM_IRQ_PRIORITY);
  NVIC_EnableIRQ(idpm_com_host_IRQnDeleteEvent(void* pvEvent)
{
  vSemaphoreDelete((SemaphoreHandle_t)pvEvent);
}

/*****************************************************************************/
/*! Disable interrupts on the given device Wait for event
*     \param pvEvent   Handle to event
*     \param ulTimeout Timeout pvOSDependentin Pointerms to internalwait devicefor structureevent
*     \return CIFX_EVENT_SIGNALLED if event was set, CIFX_EVENT_TIMEOUT otherwise */
/*****************************************************************************/
voiduint32_t OS_DisableInterruptsWaitEvent(void* pvOSDependent pvEvent, uint32_t ulTimeout)
{
  UNREFERENCED_PARAMETER(pvOSDependent)BaseType_t tRes;

#if  /* Disable physical interrupt of DPM */
  NVIC_DisableIRQ(idpm_com_host_IRQn);
  NVIC_SetPriority(idpm_com_host_IRQn, 0); /* Reset priority to default */

  /* Trigger deinit of DSR task */
  s_fDSRActive = false;
  (void)xTaskNotifyGive(s_xDsrTask);

  taskYIELD();

  /* Task handle is deleted in DSR epilogue */

  s_ptIrqDevInst = NULL;((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  tRes = xSemaphoreTake((SemaphoreHandle_t)pvEvent, (TickType_t)pdMS_TO_TICKS(ulTimeout));
#else
  #error OS_WaitEvent(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

  /* Map return value for cifX Toolkit */
  if(pdPASS == tRes)
    return CIFX_EVENT_SIGNALLED;
  else
    return CIFX_EVENT_TIMEOUT;

}

/*****************************************************************************/
/*****************************************************************************/
/*!<                       Mutex functions (channel access)1:1 memory mapping                                 */
/*****************************************************************************/
/*****************************************************************************/

/******************************************************************************/
/*! Create mutex
*     \return Handle to new created mutex    /
/*! Map driver pointer to user space
*     \param pvDriverMem   Pointer to driver memory
*     \param ulMemSize     Size of the memory to map
*     \param ppvMappedMem  Returned mapped pointer
*     \param pvOSDependent OS Dependent parameter in DEVICEINSTANCE
*     \return Handle to mapping, NULL on error         */
/*****************************************************************************/
void* OS_CreateMutex(void)
{
  return (void*) xSemaphoreCreateMutex();
}

/*****                      */
/************************************************************************/
/*! Try to acquire mutex with timeout
*     \param pvMutex   Handle to mutex
*     \param ulTimeout Timeout in ms to wait for mutex
*     \return !=0 if mutex was acquired                                      */
/*****/
void* OS_MapUserPointer(void* pvDriverMem, uint32_t ulMemSize, void** ppvMappedMem, void* pvOSDependent)
{
  UNREFERENCED_PARAMETER(ulMemSize);
  UNREFERENCED_PARAMETER(pvOSDependent);

  /* No memory mapping needed (single address space) */
  *ppvMappedMem = pvDriverMem;

  return pvDriverMem;
}

/**********************************************************************************/
int OS_WaitMutex(void* pvMutex, uint32_t ulTimeout)
{
  BaseType_t tRes;

#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  tRes = xSemaphoreTake((SemaphoreHandle_t)pvMutex, (TickType_t)pdMS_TO_TICKS(ulTimeout));
#else
  #error OS_WaitMutex(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

  /* Map return value for cifX Toolkit */
  if(pdPASS == tRes)
 /
/*! Unmap previously mapped user space pointer
*     \param phMapping     Handle returned from OS_MapUserPointer
*     \param pvOSDependent OS Dependent parameter in DEVICEINSTANCE
*     \return 0 on error                                                     */
/*****************************************************************************/
int OS_UnmapUserPointer(void* phMapping, void* pvOSDependent)
{
  UNREFERENCED_PARAMETER(phMapping);
  UNREFERENCED_PARAMETER(pvOSDependent);

  /* No memory mapping needed (single address space) */
  return 1;
  else
    return 0;

}

}

/*****************************************************************************/
/*****************************************************************************/
/*! Release previously acquired mutex
*<                String operations from libc           \param pvMutex   Handle to mutex                                       */
/*****************************************************************************/
/*****************************************************************************/
void
OS_ReleaseMutex(void* pvMutex)
{
  (void)xSemaphoreGive((SemaphoreHandle_t)pvMutex);
}

/*****************************************************************************/
/*! Delete mutexCompare strings
*     \param pszBuf1  String buffer 1
*     \param pszBuf2  String buffer 2
*     \paramreturn 0 pvMutexif strings are Handleequal to mutex                                       */
/*****************************************************************************/
voidint OS_DeleteMutex(voidStrcmp(const char* pszBuf1, const char* pvMutexpszBuf2)
{
  return vSemaphoreDelete((SemaphoreHandle_t)pvMutex);
}

/*****************************************************************************/strcmp(pszBuf1, pszBuf2);
}

/*****************************************************************************/
/*!<   Compare strings case insensitive
*     \param pszBuf1  String buffer 1
*     \param pszBuf2  String buffer 2
*     \param ulLen    Maximum length to compare
*     \return 0 if strings are equal     Lock functions                                   */
/*****************************************************************************/
int OS_Strnicmp(const char* pszBuf1, const char* pszBuf2, uint32_t ulLen)
{
  return strncasecmp(pszBuf1, pszBuf2, ulLen);
}

/**************/
/***************************************************************/
/*! Get length of string
*************/

     \param szText  Text buffer
*     \return Length of given string                                         */
/*****************************************************************************/
/*! Create Lock (Usually same as mutex, but does not support timed waiting)
*     \return Handle to created lock                                         */
/**int OS_Strlen(const char* szText)
{
  return strlen(szText);
}

/***************************************************************************/
void* OS_CreateLock(void)
{
  /* Ideally, any task which calls cifX API functions requiring a lock (ultimately changes to HSK cells)
   * should be running in task mode.
   * While changing the implementation of OS_*Lock() functions to work in interrupt mode could be done,
   * it should be seen as application specific.
   * Special care needs to be taken to be fully IRQ safe (beware of e.g. configMAX_SYSCALL_INTERRUPT_PRIORITY
   * and other FreeRTOS/IRQ setting!).
   */

  /* For critical sections, no initialisation is needed, so return a valid placeholder. */
  return (void*)1;
}
****/
/*! Copy string to destination buffer
*     \param szText   Destination string
*     \param szSource Source string
*     \param ulLen    Maximum length to copy
*     \return Pointer to szDest                                              */
/*****************************************************************************/
/char*! Acquire a lock
*     \param pvLock Handle to lock                                           */ OS_Strncpy(char* szDest, const char* szSource, uint32_t ulLen)
{
  return strncpy(szDest, szSource, ulLen);
}

#ifdef CIFX_TOOLKIT_ENABLE_DSR_LOCK
/*****************************************************************************/
void OS_EnterLock(void* pvLock)
{
  /* Taken from FreeRTOS 10.2. documentation (taskENTER_CRITICAL()):
   * "Preemptive context switches only occur inside an interrupt, so will not occur when interrupts are disabled.
   * Therefore, the task that called taskENTER_CRITICAL() is guaranteed to remain in the Running state until
   * the critical section is exited, unless the task explicitly attempts to block or yield
   * (which it should not do from inside a critical section)."
  */

  taskENTER_CRITICAL(/*! This functions needs to provide a lock against the interrupt service
*   routine of the device. The easiest way is an IRQ lock but some operating
*   systems provide a way to lock against a specific interrupt
*     \param pvODDependent OS Dependent parameter in DEVICEINSTANCE          */
/*****************************************************************************/
void OS_IrqLock(void* pvOSDependent)
{
  UNREFERENCED_PARAMETER(pvOSDependent);

  /* Only mask DPM interrupt if it was configured */
  if(s_ptIrqDevInst)
    NVIC_DisableIRQ(idpm_com_host_IRQn);
}

/*****************************************************************************/
/*! ReleaseThis afunction lockre-enables *the device's interrupt service routine.
\param* pvLock Handle to lock                                  \param pvODDependent OS Dependent parameter in DEVICEINSTANCE          */
/*****************************************************************************/
void OS_LeaveLockIrqUnlock(void* pvLockpvOSDependent)
{
  UNREFERENCED_PARAMETER(pvOSDependent);

  if(s_ptIrqDevInst)
    taskEXITNVIC_CRITICAL(EnableIRQ(idpm_com_host_IRQn);
}
#endif


/*****************************************************************************/
/*! Delete a lock
*     \param pvLock Handle to lock                                           ***/
/*****************************************************************************/
void OS_DeleteLock(void* pvLock)
{
  UNREFERENCED_PARAMETER(pvLock);
}


/*****************************************************************************/
/***!<  Stubs needed to build, but not needed or available on netX90 APP CPU   */
/**************************************************************************/
/*!<             Event functions (signalled from DSR)                        ********/
/*****************************************************************************/
/*****************************************************************************/

/*****************************************************************************/
/*! CreateRead eventPCI *configuration area of specified card
\return* Handle to created event \param pvOSDependent OS Dependent parameter to identify card
*     \return Pointer to configuration data (passed to   WritePCIConfig)                 */
/*****************************************************************************/
void* OS_CreateEventReadPCIConfig(void* pvOSDependent)
{
  /* No PCI(e) hardware SemaphoreHandle_t*/
tSem = xSemaphoreCreateBinaryUNREFERENCED_PARAMETER(pvOSDependent);
  return (void*)tSemNULL;
}

/*****************************************************************************/
/*! SignalRestore PCI eventconfiguration
*     \param pvEvent Handle to event              pvOSDependent OS Dependent parameter to identify card
*     \param pvPCIConfig   Pointer returned from ReadPCIConfig               */
/*****************************************************************************/
void OS_SetEvent(WritePCIConfig(void* pvOSDependent, void* pvEventpvPCIConfig)
{
  (void)xSemaphoreGive((SemaphoreHandle_t)pvEvent)/* No PCI(e) hardware */
  UNREFERENCED_PARAMETER(pvOSDependent);
  UNREFERENCED_PARAMETER(pvPCIConfig);
}


/*****************************************************************************/
/*! Reset eventOpen file for reading
*     \param pvEvent Handle to event szFile       File to open (including path)
*     \param pulFileSize  Returned size of the file in bytes
*     \return Handle to the file, NULL on failure                            */
/*****************************************************************************/
void* OS_ResetEventFileOpen(voidchar* pvEvent)
{
  /* no equivalent available and not used by toolkit (currently) */
  szFile, uint32_t* pulFileLen)
{
  UNREFERENCED_PARAMETER(szFile);
  UNREFERENCED_PARAMETER(pvEvent)pulFileLen);
  return NULL;
}

/*****************************************************************************/
/*! DeleteClose open eventfile
*     \param pvEventpvFile Handle to event Handle to the file (acquired         by OS_FileOpen)                           */
/*****************************************************************************/
void OS_DeleteEventFileClose(void* pvEventpvFile)
{
  vSemaphoreDelete((SemaphoreHandle_t)pvEventUNREFERENCED_PARAMETER(pvFile);
}

/*****************************************************************************/
/*! Read data from file
*     \param pvFile    Handle to the file (acquired by OS_FileOpen)
*     \param ulOffset  Offset to read from
**/
/*! Wait for event
*     \param ulSize    Size to read
*     \param pvBuffer  Buffer to read data into
*     \return number of bytes read         \param pvEvent   Handle to event *     \param ulTimeout Timeout in ms to wait for event *     \return CIFX_EVENT_SIGNALLED if event was set, CIFX_EVENT_TIMEOUT otherwise */
/*****************************************************************************/
uint32_t OS_WaitEvent(void* pvEvent, uint32_t ulTimeout)
{
  BaseType_t tRes;

#if ((1000 == configTICK_RATE_HZ) && !configUSE_16_BIT_TICKS)
  tRes = xSemaphoreTake((SemaphoreHandle_t)pvEvent, (TickType_t)pdMS_TO_TICKS(ulTimeout));
#else
  #error OS_WaitEvent(): Custom timer needed
#endif /* configTICK_RATE_HZ, !configUSE_16_BIT_TICKS */

  /* Map return value for cifX Toolkit */
  if(pdPASS == tRes)
    return CIFX_EVENT_SIGNALLED;
  else
    return CIFX_EVENT_TIMEOUT;
}***************/
uint32_t OS_FileRead(void* pvFile, uint32_t ulOffset, uint32_t ulSize, void* pvBuffer)
{
  UNREFERENCED_PARAMETER(pvFile);
  UNREFERENCED_PARAMETER(ulOffset);
  UNREFERENCED_PARAMETER(ulSize);
  UNREFERENCED_PARAMETER(pvBuffer);
  return 0;
}

/*****************************************************************************/