/* * Copyright (c) 2013 - 2015, Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_device_registers.h" #include "fsl_debug_console.h" #include "fsl_flexio.h" #include "board.h" #include "fsl_pit.h" #include "pin_mux.h" #include "clock_config.h" /******************************************************************************* * Definitions ******************************************************************************/ #define DEMO_TIME_DELAY_FOR_DUTY_CYCLE_UPDATE (2000000U) #define DEMO_FLEXIO_BASEADDR FLEXIO1 #define DEMO_FLEXIO_OUTPUTPIN (5U) /* Select FLEXIO1_FLEXIO05 as PWM output */ #define DEMO_FLEXIO_TIMER_CH (0U) /* Flexio timer0 used */ /* Select USB1 PLL (480 MHz) as flexio clock source */ #define FLEXIO_CLOCK_SELECT (3U) /* Clock pre divider for flexio clock source */ #define FLEXIO_CLOCK_PRE_DIVIDER (4U) /* Clock divider for flexio clock source */ #define FLEXIO_CLOCK_DIVIDER (7U) #define DEMO_FLEXIO_CLOCK_FREQUENCY \ (CLOCK_GetFreq(kCLOCK_Usb1PllClk) / (FLEXIO_CLOCK_PRE_DIVIDER + 1U) / (FLEXIO_CLOCK_DIVIDER + 1U)) /* FLEXIO output PWM frequency */ #define DEMO_FLEXIO_FREQUENCY (48000U) #define FLEXIO_MAX_FREQUENCY (DEMO_FLEXIO_CLOCK_FREQUENCY / 2U) #define FLEXIO_MIN_FREQUENCY (DEMO_FLEXIO_CLOCK_FREQUENCY / 256U) /******************************************************************************* * Prototypes ******************************************************************************/ /*! * @brief Configures the timer as a 8-bits PWM mode to generate the PWM waveform * * @param freq_Hz PWM frequency in hertz, range is [FLEXIO_MIN_FREQUENCY, FLEXIO_MAX_FREQUENCY] * @param duty Specified duty in unit of %, with a range of [1, 99] */ static void flexio_pwm_init(uint32_t freq_Hz, uint32_t duty); /*! * @brief Enables the timer by setting TIMOD to 8-bits PWM and start generating the PWM */ static void flexio_pwm_start(void); /******************************************************************************* * Variables *******************************************************************************/ /******************************************************************************* * Code ******************************************************************************/ static void flexio_pwm_init(uint32_t freq_Hz, uint32_t duty) { assert((freq_Hz < FLEXIO_MAX_FREQUENCY) && (freq_Hz > FLEXIO_MIN_FREQUENCY)); uint32_t lowerValue = 0; /* Number of clock cycles in high logic state in one period */ uint32_t upperValue = 0; /* Number of clock cycles in low logic state in one period */ uint32_t sum = 0; /* Number of clock cycles in one period */ flexio_timer_config_t fxioTimerConfig; /* Check parameter */ if ((duty > 99) || (duty == 0)) { duty = 50; } /* Configure the timer DEMO_FLEXIO_TIMER_CH for generating PWM */ fxioTimerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0U); fxioTimerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal; fxioTimerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow; fxioTimerConfig.pinConfig = kFLEXIO_PinConfigOutput; fxioTimerConfig.pinPolarity = kFLEXIO_PinActiveHigh; fxioTimerConfig.pinSelect = DEMO_FLEXIO_OUTPUTPIN; /* Set pwm output */ fxioTimerConfig.timerMode = kFLEXIO_TimerModeDisabled; fxioTimerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset; fxioTimerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput; fxioTimerConfig.timerDisable = kFLEXIO_TimerDisableNever; fxioTimerConfig.timerEnable = kFLEXIO_TimerEnabledAlways; fxioTimerConfig.timerReset = kFLEXIO_TimerResetNever; fxioTimerConfig.timerStart = kFLEXIO_TimerStartBitDisabled; fxioTimerConfig.timerStop = kFLEXIO_TimerStopBitDisabled; /* Calculate timer lower and upper values of TIMCMP */ /* Calculate the nearest integer value for sum, using formula round(x) = (2 * floor(x) + 1) / 2 */ /* sum = DEMO_FLEXIO_CLOCK_FREQUENCY / freq_H */ sum = (DEMO_FLEXIO_CLOCK_FREQUENCY * 2 / freq_Hz + 1) / 2; /* Calculate the nearest integer value for lowerValue, the high period of the pwm output */ /* lowerValue = sum * duty / 100 */ lowerValue = (sum * duty / 50 + 1) / 2; /* Calculate upper value, the low period of the pwm output */ upperValue = sum - lowerValue; fxioTimerConfig.timerCompare = ((upperValue - 1) << 8U) | (lowerValue - 1); FLEXIO_SetTimerConfig(DEMO_FLEXIO_BASEADDR, DEMO_FLEXIO_TIMER_CH, &fxioTimerConfig); } static void flexio_pwm_start(void) { /* Set Timer mode to kFLEXIO_TimerModeDual8BitPWM to start timer */ DEMO_FLEXIO_BASEADDR->TIMCTL[DEMO_FLEXIO_TIMER_CH] |= FLEXIO_TIMCTL_TIMOD(kFLEXIO_TimerModeDual8BitPWM); } /*! * @brief Main function */ int main(void) { uint32_t i; flexio_config_t fxioUserConfig; /* Init board hardware */ BOARD_ConfigMPU(); BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); /* Clock setting for Flexio */ CLOCK_SetMux(kCLOCK_Flexio1Mux, FLEXIO_CLOCK_SELECT); CLOCK_SetDiv(kCLOCK_Flexio1PreDiv, FLEXIO_CLOCK_PRE_DIVIDER); CLOCK_SetDiv(kCLOCK_Flexio1Div, FLEXIO_CLOCK_DIVIDER); /* Init flexio, use default configure * Disable doze and fast access mode * Enable in debug mode */ FLEXIO_GetDefaultConfig(&fxioUserConfig); fxioUserConfig.enableFastAccess = true; FLEXIO_Init(DEMO_FLEXIO_BASEADDR, &fxioUserConfig); // Init Timer CLOCK_SetMux(kCLOCK_PerclkMux, 1U); // Take the osc clock source 24MHz CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U); // divide the clock by 1 pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); PIT_Init(PIT, &pitConfig); PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, (24000000 / 10) - 1); PIT_EnableInterrupts(PIT, kPIT_Chnl_1, kPIT_TimerInterruptEnable); EnableIRQ(PIT_IRQn); PIT_StartTimer(PIT, kPIT_Chnl_1); PRINTF("\r\nFLEXIO_PWM demo start.\r\n"); while (1) { //flexio_pwm_init(DEMO_FLEXIO_FREQUENCY, --duty); //flexio_pwm_start(); for (i = 0; i < DEMO_TIME_DELAY_FOR_DUTY_CYCLE_UPDATE; i++) { __NOP(); } //if (duty == 0) // { // duty = 100; //} } } unsigned int idx = 0; unsigned int freq[] = {50000, 300000, 48000, 400000}; void PIT_IRQHandler(void) { flexio_pwm_init(freq[idx], 50); idx = (idx + 1) % 4; flexio_pwm_start(); PIT_ClearStatusFlags(PIT, kPIT_Chnl_1, kPIT_TimerFlag); }