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; }