Skip to end of banner
Go to start of banner

CifX API Configuration

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

The cifX Toolkit configuration can use newlib and FreeRTOS functions/ objects. The changes are:

CifXToolkit_OS_freeRTOS.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.
*
*/

/*****************************************************************************/
/*! 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                                           */
/*****************************************************************************/
void OS_DeleteLock(void* pvLock)
{
  UNREFERENCED_PARAMETER(pvLock);
}


/*****************************************************************************/
/*****************************************************************************/
/*!<             Event functions (signalled from DSR)                        */
/*****************************************************************************/
/*****************************************************************************/

/*****************************************************************************/
/*! Create event
*     \return Handle to created event                                        */
/*****************************************************************************/
void* OS_CreateEvent(void)
{
  SemaphoreHandle_t tSem = xSemaphoreCreateBinary();
  return (void*)tSem;
}

/*****************************************************************************/
/*! Signal event
*     \param pvEvent Handle to event                                         */
/*****************************************************************************/
void OS_SetEvent(void* pvEvent)
{
  (void)xSemaphoreGive((SemaphoreHandle_t)pvEvent);
}

/*****************************************************************************/
/*! Reset event
*     \param pvEvent Handle to event                                         */
/*****************************************************************************/
void OS_ResetEvent(void* pvEvent)
{
  /* no equivalent available and not used by toolkit (currently) */
  UNREFERENCED_PARAMETER(pvEvent);
}

/*****************************************************************************/
/*! Delete event
*     \param pvEvent Handle to event                                         */
/*****************************************************************************/
void OS_DeleteEvent(void* pvEvent)
{
  vSemaphoreDelete((SemaphoreHandle_t)pvEvent);
}

/*****************************************************************************/
/*! Wait for event
*     \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;
}
  • No labels