/*FUNCTION********************************************************************** * * Function Name : OSA_MsgQGet * Description : This function checks the queue's status, if it is not empty, * get message from it and return kStatus_OSA_Success, otherwise, timeout will * be used for wait. The parameter timeout indicates how long should wait in * milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return * kStatus_OSA_Timeout immediately if queue is empty. * This function returns kStatus_OSA_Success if message is got successfully, * returns kStatus_OSA_Timeout if message queue is empty within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting, * returns kStatus_OSA_Idle if message queue is empty and 'timeout' is * not exhausted, because wait functions should not block with bare metal. * *END**************************************************************************/ osa_status_t OSA_MsgQGet(msg_queue_handler_t handler, void *pMessage, uint32_t timeout) { assert(handler); osa_status_t retVal = kStatus_OSA_Error; uint32_t *from_ptr, *to_ptr; uint16_t msgSize; INT_SYS_DisableIRQGlobal(); /* Check if the queue is not empty */ if(!handler->isEmpty) { from_ptr = &handler->queueMem[handler->head * handler->size]; to_ptr = (uint32_t*)(pMessage); /* Copy entire message into the queue, based on the size configured at creation */ msgSize = handler->size; while(msgSize--) { *to_ptr++ = *from_ptr++; } /* Adjust head pointer and wrap in case the end of the buffer is reached */ ++handler->head; if(handler->head == handler->number) { handler->head = 0; } /* If queue is empty, clear the semaphore. */ if(handler->head == handler->tail) { handler->isEmpty = true; /* Set semapohre to 0 because the queue is empty. */ (void)OSA_SemaWait(&handler->queueSem, 0); } INT_SYS_EnableIRQGlobal(); retVal = kStatus_OSA_Success; } else { INT_SYS_EnableIRQGlobal(); /* Wait for the semaphore if the queue was empty */ retVal = OSA_SemaWait(&handler->queueSem, timeout); } return retVal; }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexLock * Description : This function checks the mutex's status, if it is unlocked, * lock it and returns kStatus_OSA_Success, otherwise, timeout will be used for * wait. The parameter timeout indicates how long should wait in milliseconds. * Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value * kStatus_OSA_Timeout immediately if mutex is locked. * This function returns kStatus_OSA_Success if the mutex is obtained, returns * kStatus_OSA_Timeout if the mutex is not obtained within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting, * returns kStatus_OSA_Idle if the mutex is not available and 'timeout' is * not exhausted, because wait functions should not block with bare metal. * *END**************************************************************************/ osa_status_t OSA_MutexLock(mutex_t *pMutex, uint32_t timeout) { uint32_t currentTime; assert(pMutex); /* Always check first. Deal with timeout only if not available. */ if (pMutex->isLocked == false) { /* Get the lock and return success */ INT_SYS_DisableIRQGlobal(); pMutex->isLocked = true; pMutex->isWaiting = false; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; } else { if (0 == timeout) { /* If timeout is 0 and mutex is not available, return kStatus_OSA_Timeout. */ return kStatus_OSA_Timeout; } #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) else if (pMutex->isWaiting) { /* Check for timeout */ currentTime = OSA_TimeGetMsec(); if (pMutex->timeout < OSA_TimeDiff(pMutex->time_start, currentTime)) { INT_SYS_DisableIRQGlobal(); pMutex->isWaiting = false; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Timeout; } } else if (timeout != OSA_WAIT_FOREVER) /* If dont't wait forever, start timer. */ { /* Start the timeout counter */ INT_SYS_DisableIRQGlobal(); pMutex->isWaiting = true; INT_SYS_EnableIRQGlobal(); pMutex->time_start = OSA_TimeGetMsec(); pMutex->timeout = timeout; } #endif } return kStatus_OSA_Idle; }
/*FUNCTION********************************************************************** * * Function Name : OSA_SemaWait * Description : This function checks the semaphore's counting value, if it is * positive, decreases it and returns kStatus_OSA_Success, otherwise, timeout * will be used for wait. The parameter timeout indicates how long should wait * in milliseconds. Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will * return kStatus_OSA_Timeout immediately if semaphore is not positive. * This function returns kStatus_OSA_Success if the semaphore is received, returns * kStatus_OSA_Timeout if the semaphore is not received within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting, * returns kStatus_OSA_Idle if the semaphore is not available and 'timeout' is * not exhausted, because wait functions should not block with bare metal. * *END**************************************************************************/ osa_status_t OSA_SemaWait(semaphore_t *pSem, uint32_t timeout) { uint32_t currentTime; assert(pSem); /* Check the sem count first. Deal with timeout only if not already set */ if (pSem->semCount) { INT_SYS_DisableIRQGlobal(); pSem->semCount --; pSem->isWaiting = false; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; } else { if (0 == timeout) { /* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */ return kStatus_OSA_Timeout; } #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) else if (pSem->isWaiting) { /* Check for timeout */ currentTime = OSA_TimeGetMsec(); if (pSem->timeout < OSA_TimeDiff(pSem->time_start, currentTime)) { INT_SYS_DisableIRQGlobal(); pSem->isWaiting = false; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Timeout; } } else if (timeout != OSA_WAIT_FOREVER) /* If don't wait forever, start the timer */ { /* Start the timeout counter */ INT_SYS_DisableIRQGlobal(); pSem->isWaiting = true; INT_SYS_EnableIRQGlobal(); pSem->time_start = OSA_TimeGetMsec(); pSem->timeout = timeout; } #endif } return kStatus_OSA_Idle; }
/*! * @brief Get inup from user about wakeup timeout */ uint8_t setWakeUpTimeOut(void) { uint8_t val0; uint8_t val1; while(1) { PRINTF("Select the wake up timeout in format DD. Possible decimal value is from range 01 - 60 seconds. Eg. 05 means 5 seconds delay"); PRINTF("\r\nWaiting for key press..\r\n\r\n"); val0 = GETCHAR(); if( (val0 >= '0') && (val0 <= '6') ) { val1 = GETCHAR(); if( (val1 >= '0') && (val1 <= '9') ) { val0 = (val0-'0')*10 + (val1-'0'); if( (val0!=0) && (val0<=60) ) { INT_SYS_DisableIRQGlobal(); LLWU_HAL_SetInternalModuleCmd(LLWU_BASE_PTR,kLlwuWakeupModule5,true); INT_SYS_EnableIRQGlobal(); cmd_alarm(val0); return val0; } } } PRINTF("Wrong value!\r\n"); } }
/*FUNCTION**************************************************************** * * Function Name : WDOG_DRV_Unlock * Description : Unlock watchdog register written * This function is used to unlock the WDOG register written because WDOG register * will lock automatically after 256 bus clock. Written while the register is * locked has no affect. * *END*********************************************************************/ static void WDOG_DRV_Unlock(void) { INT_SYS_DisableIRQGlobal(); WDOG_HAL_Unlock(g_wdogBaseAddr[0]); INT_SYS_EnableIRQGlobal(); }
/*FUNCTION**************************************************************** * * Function Name : WDOG_DRV_Refresh * Description : Refresh watchdog. * This function is used to feed the WDOG, it will set the WDOG timer count to zero and * should be called before watchdog timer is timeout, otherwise a RESET will assert. * *END*********************************************************************/ void WDOG_DRV_Refresh(void) { INT_SYS_DisableIRQGlobal(); WDOG_HAL_Refresh(g_wdogBaseAddr[0]); INT_SYS_EnableIRQGlobal(); }
/*FUNCTION********************************************************************** * * Function Name : OSA_MsgQPut * Description : This function is used to put a message to a message queue. * Return kStatus_OSA_Success if the message is put successfully, otherwise * return kStatus_OSA_Error. * *END**************************************************************************/ osa_status_t OSA_MsgQPut(msg_queue_handler_t handler, void* pMessage) { assert(handler); uint32_t *from_ptr, *to_ptr; uint16_t msgSize; /* Check that there is room in the queue */ INT_SYS_DisableIRQGlobal(); if((handler->tail != handler->head) || (handler->isEmpty)) { from_ptr = (uint32_t*)pMessage; to_ptr = &handler->queueMem[handler->tail * handler->size]; /* Copy entire message into the queue, based on the size configured at creation */ msgSize = handler->size; while(msgSize--) { *to_ptr++ = *from_ptr++; } /* Adjust tail pointer and wrap in case the end of the buffer is reached */ ++handler->tail; if(handler->tail == handler->number) { handler->tail = 0; } /* If queue was empty, clear the empty flag and signal that it is not empty anymore */ if(handler->isEmpty) { handler->isEmpty = false; OSA_SemaPost(&handler->queueSem); } INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; } else { INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Error; } }
/*FUNCTION********************************************************************** * * Function Name : OSA_EventClear * Description : Clear one or more event flags of an event object. * Return kStatus_OSA_Success if clear successfully, kStatus_OSA_Error if failed. * *END**************************************************************************/ osa_status_t OSA_EventClear(event_t *pEvent, event_flags_t flagsToClear) { assert(pEvent); /* Clear flags ensuring atomic operation */ INT_SYS_DisableIRQGlobal(); pEvent->flags &= ~flagsToClear; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; }
/*FUNCTION********************************************************************** * * Function Name : OSA_EventSet * Description : Set one or more event flags of an event object. * Return kStatus_OSA_Success if set successfully, kStatus_OSA_Error if failed. * *END**************************************************************************/ osa_status_t OSA_EventSet(event_t *pEvent, event_flags_t flagsToSet) { assert(pEvent); /* Set flags ensuring atomic operation */ INT_SYS_DisableIRQGlobal(); pEvent->flags |= flagsToSet; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexUnlock * Description : This function is used to unlock a mutex. * *END**************************************************************************/ osa_status_t OSA_MutexUnlock(mutex_t *pMutex) { assert(pMutex); INT_SYS_DisableIRQGlobal(); pMutex->isLocked = false; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; }
/*FUNCTION********************************************************************** * * Function Name : OSA_ExitCritical * Description : This function is used to exit critical section. * *END**************************************************************************/ void OSA_ExitCritical(osa_critical_section_mode_t mode) { if (kCriticalDisableInt == mode) { INT_SYS_EnableIRQGlobal(); } else { return; } }
/*FUNCTION********************************************************************** * * Function Name : OSA_SemaPost * Description : This function is used to wake up one task that wating on the * semaphore. If no task is waiting, increase the semaphore. The function returns * kStatus_OSA_Success if the semaphre is post successfully, otherwise returns * kStatus_OSA_Error. * *END**************************************************************************/ osa_status_t OSA_SemaPost(semaphore_t *pSem) { assert(pSem); /* The max value is 0xFF */ if (0xFF == pSem->semCount) { return kStatus_OSA_Error; } INT_SYS_DisableIRQGlobal(); ++pSem->semCount; INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; }
/*FUNCTION********************************************************************** * * Function Name : OSA_EventWait * Description : This function checks the event's status, if it meets the wait * condition, return kStatus_OSA_Success, otherwise, timeout will be used for * wait. The parameter timeout indicates how long should wait in milliseconds. * Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value * kStatus_OSA_Timeout immediately if wait condition is not met. The event flags * will be cleared if the event is auto clear mode. Flags that wakeup waiting * task could be obtained from the parameter setFlags. * This function returns kStatus_OSA_Success if wait condition is met, returns * kStatus_OSA_Timeout if wait condition is not met within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting, * returns kStatus_OSA_Idle if wait condition is not met and 'timeout' is * not exhausted, because wait functions should not block with bare metal. * *END**************************************************************************/ osa_status_t OSA_EventWait(event_t *pEvent, event_flags_t flagsToWait, bool waitAll, uint32_t timeout, event_flags_t *setFlags) { uint32_t currentTime; assert(pEvent); assert(setFlags); osa_status_t retVal = kStatus_OSA_Idle; *setFlags = pEvent->flags & flagsToWait; /* Check the event flag first, if does not meet wait condition, deal with timeout. */ if ((((!waitAll) && (*setFlags))) || (*setFlags == flagsToWait)) { INT_SYS_DisableIRQGlobal(); pEvent->isWaiting = false; if(kEventAutoClear == pEvent->clearMode) { pEvent->flags &= ~flagsToWait; } INT_SYS_EnableIRQGlobal(); return kStatus_OSA_Success; } else { if (0 == timeout) { /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */ return kStatus_OSA_Timeout; } #if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) else if (pEvent->isWaiting) { /* Check for timeout */ currentTime = OSA_TimeGetMsec(); if (pEvent->timeout < OSA_TimeDiff(pEvent->time_start, currentTime)) { INT_SYS_DisableIRQGlobal(); pEvent->isWaiting = false; INT_SYS_EnableIRQGlobal(); retVal = kStatus_OSA_Timeout; } } else if(timeout != OSA_WAIT_FOREVER) /* If no timeout, don't start the timer */ { /* Start the timeout counter */ INT_SYS_DisableIRQGlobal(); pEvent->isWaiting = true; INT_SYS_EnableIRQGlobal(); pEvent->time_start = OSA_TimeGetMsec(); pEvent->timeout = timeout; } #endif } return retVal; }
/*! * @brief Main demo function. */ int main (void) { ftm_pwm_param_t xAxisParams, yAxisParams; accel_dev_t accDev; accel_dev_interface_t accDevice; accel_sensor_data_t accelData; accel_i2c_interface_t i2cInterface; int16_t xData, yData; int16_t xAngle, yAngle; uint32_t ftmModulo; // Register callback func for I2C i2cInterface.i2c_init = I2C_DRV_MasterInit; i2cInterface.i2c_read = I2C_DRV_MasterReceiveDataBlocking; i2cInterface.i2c_write = I2C_DRV_MasterSendDataBlocking; accDev.i2c = &i2cInterface; accDev.accel = &accDevice; accDev.slave.baudRate_kbps = BOARD_ACCEL_BAUDRATE; accDev.slave.address = BOARD_ACCEL_ADDR; accDev.bus = BOARD_ACCEL_I2C_INSTANCE; // Initialize standard SDK demo application pins. hardware_init(); // Accel device driver utilizes the OSA, so initialize it. OSA_Init(); // Initialize the LEDs used by this application. LED2_EN; LED3_EN; // Print the initial banner. PRINTF("Bubble Level Demo!\r\n\r\n"); // Initialize the Accel. accel_init(&accDev); // Turn on the clock to the FTM. CLOCK_SYS_EnableFtmClock(BOARD_FTM_INSTANCE); // Initialize the FTM module. FTM_HAL_Init(BOARD_FTM_BASE); // Configure the sync mode to software. FTM_HAL_SetSyncMode(BOARD_FTM_BASE, kFtmUseSoftwareTrig); // Enable the overflow interrupt. FTM_HAL_EnableTimerOverflowInt(BOARD_FTM_BASE); // Set the FTM clock divider to /16. FTM_HAL_SetClockPs(BOARD_FTM_BASE, kFtmDividedBy16); // Configure the FTM channel used for the X-axis. Initial duty cycle is 0%. xAxisParams.mode = kFtmEdgeAlignedPWM; xAxisParams.edgeMode = kFtmHighTrue; FTM_HAL_EnablePwmMode(BOARD_FTM_BASE, &xAxisParams, BOARD_FTM_X_CHANNEL); FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL, 0); // Configure the FTM channel used for the Y-axis. Initial duty cycle is 0%. yAxisParams.mode = kFtmEdgeAlignedPWM; yAxisParams.edgeMode = kFtmHighTrue; FTM_HAL_EnablePwmMode(BOARD_FTM_BASE, &yAxisParams, BOARD_FTM_Y_CHANNEL); FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL, 0); // Get the FTM reference clock and calculate the modulo value. ftmModulo = (CLOCK_SYS_GetFtmSystemClockFreq(BOARD_FTM_INSTANCE) / (1 << FTM_HAL_GetClockPs(BOARD_FTM_BASE))) / (BOARD_FTM_PERIOD_HZ - 1); // Initialize the FTM counter. FTM_HAL_SetCounterInitVal(BOARD_FTM_BASE, 0); FTM_HAL_SetMod(BOARD_FTM_BASE, ftmModulo); // Set the clock source to start the FTM. FTM_HAL_SetClockSource(BOARD_FTM_BASE, kClock_source_FTM_SystemClk); // Enable the FTM interrupt at the NVIC level. INT_SYS_EnableIRQ(BOARD_FTM_IRQ_VECTOR); // Main loop. Get sensor data and update globals for the FTM timer update. while(1) { // Wait 5 ms in between samples (accelerometer updates at 200Hz). OSA_TimeDelay(5); // Get new accelerometer data. accDev.accel->accel_read_sensor_data(&accDev,&accelData); // Turn off interrupts (FTM) while updating new duty cycle values. INT_SYS_DisableIRQGlobal(); // Get the X and Y data from the sensor data structure. xData = (int16_t)((accelData.data.accelXMSB << 8) | accelData.data.accelXLSB); yData = (int16_t)((accelData.data.accelYMSB << 8) | accelData.data.accelYLSB); // Convert raw data to angle (normalize to 0-90 degrees). No negative // angles. xAngle = abs((int16_t)(xData * 0.011)); yAngle = abs((int16_t)(yData * 0.011)); // Set values for next FTM ISR udpate. Use 5 degrees as the threshold // for whether to turn the LED on or not. g_xValue = (xAngle > 5) ? (uint16_t)((xAngle / 90.0) * ftmModulo) : 0; g_yValue = (yAngle > 5) ? (uint16_t)((yAngle / 90.0) * ftmModulo) : 0; // Re-enable interrupts. INT_SYS_EnableIRQGlobal(); // Print out the raw accelerometer data. PRINTF("x= %d y = %d\r\n", xData, yData); } }