void Timer_A_configureUpDownMode(uint32_t timer, const Timer_A_UpDownModeConfig *config) { ASSERT( (TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_ACLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_SMCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK == config->clockSource)); ASSERT( (TIMER_A_DO_CLEAR == config->timerClear) || (TIMER_A_SKIP_CLEAR == config->timerClear)); ASSERT( (TIMER_A_DO_CLEAR == config->timerClear) || (TIMER_A_SKIP_CLEAR == config->timerClear)); privateTimer_AProcessClockSourceDivider(timer, config->clockSourceDivider); TIMER_A_CMSIS(timer)->rCTL.r &= ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + TIMER_A_UPDOWN_MODE + TIMER_A_DO_CLEAR + TIMER_A_TAIE_INTERRUPT_ENABLE); TIMER_A_CMSIS(timer)->rCTL.r |= (config->clockSource + TIMER_A_STOP_MODE + config->timerClear + config->timerInterruptEnable_TAIE); if (TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE == config->captureCompareInterruptEnable_CCR0_CCIE) BITBAND_PERI(TIMER_A_CMSIS(timer)->rCCTL0.r,CCIE_OFS) = 1; else BITBAND_PERI(TIMER_A_CMSIS(timer)->rCCTL0.r,CCIE_OFS) = 0; TIMER_A_CMSIS(timer)->rCCR0 = config->timerPeriod; }
void Timer_A_generatePWM(uint32_t timer, const Timer_A_PWMConfig *config) { ASSERT( (TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_ACLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_SMCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK == config->clockSource)); ASSERT( (TIMER_A_CAPTURECOMPARE_REGISTER_0 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_1 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_2 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_3 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_4 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_5 == config->compareRegister) || (TIMER_A_CAPTURECOMPARE_REGISTER_6 == config->compareRegister)); ASSERT( (TIMER_A_OUTPUTMODE_OUTBITVALUE == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_SET == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_TOGGLE_RESET == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_SET_RESET == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_TOGGLE == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_RESET == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_TOGGLE_SET == config->compareOutputMode) || (TIMER_A_OUTPUTMODE_RESET_SET == config->compareOutputMode)); privateTimer_AProcessClockSourceDivider(timer, config->clockSourceDivider); TIMER_A_CMSIS(timer)->rCTL.r &= ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + TIMER_A_UPDOWN_MODE + TIMER_A_DO_CLEAR + TIMER_A_TAIE_INTERRUPT_ENABLE); TIMER_A_CMSIS(timer)->rCTL.r |= (config->clockSource + TIMER_A_UP_MODE + TIMER_A_DO_CLEAR); TIMER_A_CMSIS(timer)->rCCR0 = config->timerPeriod; HWREG16(timer + OFS_TA0CCTL0) &= ~(TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE + TIMER_A_OUTPUTMODE_RESET_SET); HWREG16(timer + config->compareRegister) |= config->compareOutputMode; HWREG16(timer + config->compareRegister + OFS_TA0R) = config->dutyCycle; }
void Timer_A_startCounter(uint32_t timer, uint_fast16_t timerMode) { ASSERT( (TIMER_A_UPDOWN_MODE == timerMode) || (TIMER_A_CONTINUOUS_MODE == timerMode) || (TIMER_A_UP_MODE == timerMode)); TIMER_A_CMSIS(timer)->rCTL.r |= timerMode; }
uint32_t Timer_A_getEnabledInterruptStatus(uint32_t timer) { if (TIMER_A_CMSIS(timer)->rCTL.r & TAIE) { return Timer_A_getInterruptStatus(timer); } else { return 0; } }
uint16_t Timer_A_getCounterValue(uint32_t timer) { uint16_t voteOne, voteTwo, res; voteTwo = TIMER_A_CMSIS(timer)->rR; do { voteOne = voteTwo; voteTwo = TIMER_A_CMSIS(timer)->rR; if (voteTwo > voteOne) res = voteTwo - voteOne; else if (voteOne > voteTwo) res = voteOne - voteTwo; else res = 0; } while (res > TIMER_A_THRESHOLD); return voteTwo; }
/* * ======== PWMTimerMSP432_open ======== * @pre Function assumes that the handle is not NULL */ PWM_Handle PWMTimerMSP432_open(PWM_Handle handle, PWM_Params *params) { uintptr_t key; bool timerIsRunning; uint8_t cyclesPerMicroSec; uint32_t clockFreq; uint32_t tempPeriod; Timer_A_PWMConfig pwmConfig; PowerMSP432_Freqs powerFreqs; PWMTimerMSP432_Object *object = handle->object; PWMTimerMSP432_HWAttrs const *hwAttrs = handle->hwAttrs; if(params == NULL) { params = (PWM_Params *) &PWM_defaultParams; } key = HwiP_disable(); /* * Before opening the PWM instance, we must verify that the Timer is not * already open or being used by another source (possibly the Kernel). * Additionally, the Timer peripheral could have already been initialized * by another PWM instance, so we must verify if any other PWM driver * (on the same Timer) is initialized. */ timerIsRunning = (TIMER_A_CMSIS(hwAttrs->baseAddr)->rCTL.b.bMC != TIMER_A_STOP_MODE); if (object->isOpen || (timerIsRunning && (object->pwmTimerStatus)->activeOutputsMask == 0)) { /* Timer already opened or used by source other than PWM driver */ HwiP_restore(key); DebugP_log1("PWM:(%p) timer used by another source.", (uintptr_t) handle); return (NULL); } /* * Timer capture/compare register 0 is used as the period. It cannot be * used to generate PWM output. */ DebugP_assert(hwAttrs->compareRegister != TIMER_A_CAPTURECOMPARE_REGISTER_0); /* * Add power management support - PWM driver does not allow performance * level changes, low power modes or shutdown while open. */ Power_setConstraint(PowerMSP432_DISALLOW_PERF_CHANGES); Power_setConstraint(PowerMSP432_DISALLOW_DEEPSLEEP_0); Power_setConstraint(PowerMSP432_DISALLOW_SHUTDOWN_0); Power_setConstraint(PowerMSP432_DISALLOW_SHUTDOWN_1); PowerMSP432_getFreqs(Power_getPerformanceLevel(), &powerFreqs); clockFreq = powerFreqs.SMCLK; cyclesPerMicroSec = clockFreq / 1000000; /* Assert if period is too large for peripheral */ tempPeriod = params->period * cyclesPerMicroSec; DebugP_assert(tempPeriod <= maxPrescalarValue * maxDutyValue); /* * Verify if timer has been initialized by another PWM instance. If so, * make sure PWM periods are the same, do not open driver if otherwise. */ if ((object->pwmTimerStatus)->period && (object->pwmTimerStatus)->period != params->period) { HwiP_restore(key); DebugP_log1("PWM:(%p) differing PWM periods, cannot open driver.", (uintptr_t) handle); PWMTimerMSP432_close(handle); return (NULL); } else { /* PWM timer has not been initialized */ (object->pwmTimerStatus)->cyclesPerMicroSec = cyclesPerMicroSec; (object->pwmTimerStatus)->prescalar = PWMTimerMSP432_calculatePrescalar(tempPeriod); (object->pwmTimerStatus)->period = params->period; } /* Mark driver as being used */ object->isOpen = true; (object->pwmTimerStatus)->activeOutputsMask |= object->pwmCompareOutputBit; HwiP_restore(key); /* Store PWM instance parameters */ object->dutyMode = params->dutyMode; /* Configure PWM output & start timer */ pwmConfig.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; pwmConfig.clockSourceDivider = (object->pwmTimerStatus)->prescalar; pwmConfig.timerPeriod = tempPeriod / (object->pwmTimerStatus)->prescalar; pwmConfig.compareRegister = hwAttrs->compareRegister; pwmConfig.compareOutputMode = outputPolarity[params->polarity]; pwmConfig.dutyCycle = 0; MAP_Timer_A_generatePWM(hwAttrs->baseAddr, &pwmConfig); MAP_Timer_A_startCounter(hwAttrs->baseAddr, TIMER_A_UP_MODE); DebugP_log2("PWM:(%p) opened; period set to: %d", (uintptr_t) handle, params->period); return (handle); }
uint32_t Timer_A_getInterruptStatus(uint32_t timer) { return TIMER_A_CMSIS(timer)->rCTL.b.bIFG; }
void Timer_A_disableInterrupt(uint32_t timer) { BITBAND_PERI(TIMER_A_CMSIS(timer)->rCTL.r,TAIE_OFS) = 0; }
void Timer_A_clearInterruptFlag(uint32_t timer) { BITBAND_PERI(TIMER_A_CMSIS(timer)->rCTL.r,TAIFG_OFS) = 0; }
void Timer_A_stopTimer(uint32_t timer) { TIMER_A_CMSIS(timer)->rCTL.r &= ~MC_3; }
void Timer_A_clearTimer(uint32_t timer) { BITBAND_PERI(TIMER_A_CMSIS(timer)->rCTL.r , TACLR_OFS) = 1; }
static void privateTimer_AProcessClockSourceDivider(uint32_t timer, uint16_t clockSourceDivider) { TIMER_A_CMSIS(timer)->rCTL.r &= ~ID__8; TIMER_A_CMSIS(timer)->rEX0.r &= ~TAIDEX_7; switch (clockSourceDivider) { case TIMER_A_CLOCKSOURCE_DIVIDER_1: case TIMER_A_CLOCKSOURCE_DIVIDER_2: TIMER_A_CMSIS(timer)->rCTL.r |= ((clockSourceDivider - 1) << 6); TIMER_A_CMSIS(timer)->rEX0.r = TAIDEX_0; break; case TIMER_A_CLOCKSOURCE_DIVIDER_4: TIMER_A_CMSIS(timer)->rCTL.r |= ID__4; TIMER_A_CMSIS(timer)->rEX0.r = TAIDEX_0; break; case TIMER_A_CLOCKSOURCE_DIVIDER_8: TIMER_A_CMSIS(timer)->rCTL.r |= ID__8; TIMER_A_CMSIS(timer)->rEX0.r = TAIDEX_0; break; case TIMER_A_CLOCKSOURCE_DIVIDER_3: case TIMER_A_CLOCKSOURCE_DIVIDER_5: case TIMER_A_CLOCKSOURCE_DIVIDER_6: case TIMER_A_CLOCKSOURCE_DIVIDER_7: TIMER_A_CMSIS(timer)->rCTL.r |= ID__1; TIMER_A_CMSIS(timer)->rEX0.r = (clockSourceDivider - 1); break; case TIMER_A_CLOCKSOURCE_DIVIDER_10: case TIMER_A_CLOCKSOURCE_DIVIDER_12: case TIMER_A_CLOCKSOURCE_DIVIDER_14: case TIMER_A_CLOCKSOURCE_DIVIDER_16: TIMER_A_CMSIS(timer)->rCTL.r |= ID__2; TIMER_A_CMSIS(timer)->rEX0.r = (clockSourceDivider / 2 - 1); break; case TIMER_A_CLOCKSOURCE_DIVIDER_20: case TIMER_A_CLOCKSOURCE_DIVIDER_24: case TIMER_A_CLOCKSOURCE_DIVIDER_28: case TIMER_A_CLOCKSOURCE_DIVIDER_32: TIMER_A_CMSIS(timer)->rCTL.r |= ID__4; TIMER_A_CMSIS(timer)->rEX0.r = (clockSourceDivider / 4 - 1); break; case TIMER_A_CLOCKSOURCE_DIVIDER_40: case TIMER_A_CLOCKSOURCE_DIVIDER_48: case TIMER_A_CLOCKSOURCE_DIVIDER_56: case TIMER_A_CLOCKSOURCE_DIVIDER_64: TIMER_A_CMSIS(timer)->rCTL.r |= ID__8; TIMER_A_CMSIS(timer)->rEX0.r = (clockSourceDivider / 8 - 1); break; } }
void Timer_A_configureContinuousMode(uint32_t timer, const Timer_A_ContinuousModeConfig *config) { ASSERT( (TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_ACLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_SMCLK == config->clockSource) || (TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK == config->clockSource)); ASSERT( (TIMER_A_DO_CLEAR == config->timerClear) || (TIMER_A_SKIP_CLEAR == config->timerClear)); ASSERT( (TIMER_A_TAIE_INTERRUPT_ENABLE == config->timerInterruptEnable_TAIE) || (TIMER_A_TAIE_INTERRUPT_DISABLE == config->timerInterruptEnable_TAIE)); ASSERT( (TIMER_A_CLOCKSOURCE_DIVIDER_1 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_2 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_4 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_8 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_3 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_5 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_6 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_7 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_10 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_12 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_14 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_16 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_20 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_24 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_28 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_32 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_40 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_48 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_56 == config->clockSourceDivider) || (TIMER_A_CLOCKSOURCE_DIVIDER_64 == config->clockSourceDivider)); privateTimer_AProcessClockSourceDivider(timer, config->clockSourceDivider); TIMER_A_CMSIS(timer)->rCTL.r = (TIMER_A_CMSIS(timer)->rCTL.r & ~(TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK + TIMER_A_UPDOWN_MODE + TIMER_A_DO_CLEAR + TIMER_A_TAIE_INTERRUPT_ENABLE)) | (config->clockSource + config->timerClear + config->timerInterruptEnable_TAIE); }