/******************************************************************************* * Code for BOARD_BootClockRUN configuration ******************************************************************************/ void BOARD_BootClockRUN(void) { /* Setup the reference oscillator. */ BOARD_RfOscInit(); /* Set the system clock dividers in SIM to safe value. */ CLOCK_SetSimSafeDivs(); /* Enable RTC oscillator. */ CLOCK_CONFIG_EnableRtcOsc(RTC_OSC_CAP_LOAD_0PF); /* Initializes OSC0 according to Ref OSC needs. */ BOARD_InitOsc0(); /* Set MCG to FEE mode. */ CLOCK_BootToFeeMode(mcgConfig_BOARD_BootClockRUN.oscsel, mcgConfig_BOARD_BootClockRUN.frdiv, mcgConfig_BOARD_BootClockRUN.dmx32, mcgConfig_BOARD_BootClockRUN.drs, CLOCK_CONFIG_FllStableDelay); /* Configure the Internal Reference clock (MCGIRCLK). */ CLOCK_SetInternalRefClkConfig(mcgConfig_BOARD_BootClockRUN.irclkEnableMode, mcgConfig_BOARD_BootClockRUN.ircs, mcgConfig_BOARD_BootClockRUN.fcrdiv); /* Set the clock configuration in SIM module. */ CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN); /* Configure RTC clock. */ CLOCK_CONFIG_SetRtcClock(); /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; /* Set LPUART0 clock source. */ CLOCK_SetLpuartClock(SIM_LPUART_CLK_SEL_OSCERCLK_CLK); /* Set TPM clock source. */ CLOCK_SetTpmClock(SIM_TPM_CLK_SEL_OSCERCLK_CLK); }
void pwmout_init(pwmout_t* obj, PinName pin) { PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); obj->pwm_name = pwm; uint32_t pwm_base_clock; /* Set the TPM clock source to be IRC 48M */ CLOCK_SetTpmClock(1U); pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; while (clkval > 1) { clkdiv++; clkval /= 2.0f; if (clkdiv == 7) { break; } } pwm_clock_mhz = clkval; uint32_t channel = pwm & 0xF; uint32_t instance = pwm >> TPM_SHIFT; tpm_config_t tpmInfo; TPM_GetDefaultConfig(&tpmInfo); tpmInfo.prescale = (tpm_clock_prescale_t)clkdiv; /* Initialize TPM module */ TPM_Init(tpm_addrs[instance], &tpmInfo); tpm_chnl_pwm_signal_param_t config = { .chnlNumber = (tpm_chnl_t)channel, .level = kTPM_HighTrue, .dutyCyclePercent = 0, }; // default to 20ms: standard for servos, and fine for e.g. brightness control TPM_SetupPwm(tpm_addrs[instance], &config, 1, kTPM_EdgeAlignedPwm, 50, pwm_base_clock); TPM_StartTimer(tpm_addrs[instance], kTPM_SystemClock); // Wire pinout pinmap_pinout(pin, PinMap_PWM); } void pwmout_free(pwmout_t* obj) { TPM_Deinit(tpm_addrs[obj->pwm_name >> TPM_SHIFT]); }
/*! * @brief Main function */ int main(void) { tpm_config_t tpmInfo; tpm_chnl_pwm_signal_param_t tpmParam; tpm_pwm_level_select_t pwmLevel = kTPM_LowTrue; /* Configure tpm params with frequency 24kHZ */ tpmParam.chnlNumber = (tpm_chnl_t)BOARD_TPM_CHANNEL; tpmParam.level = pwmLevel; tpmParam.dutyCyclePercent = updatedDutycycle; /* Board pin, clock, debug console init */ BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); /* Select the clock source for the TPM counter as kCLOCK_PllFllSelClk */ CLOCK_SetTpmClock(1U); /* Print a note to terminal */ PRINTF("\r\nTPM example to output center-aligned PWM signal\r\n"); PRINTF("\r\nYou will see a change in LED brightness if an LED is connected to the TPM pin"); PRINTF("\r\nIf no LED is connected to the TPM pin, then probe the signal using an oscilloscope"); TPM_GetDefaultConfig(&tpmInfo); /* Initialize TPM module */ TPM_Init(BOARD_TPM_BASEADDR, &tpmInfo); TPM_SetupPwm(BOARD_TPM_BASEADDR, &tpmParam, 1U, kTPM_CenterAlignedPwm, 24000U, TPM_SOURCE_CLOCK); /* Enable channel interrupt flag.*/ TPM_EnableInterrupts(BOARD_TPM_BASEADDR, TPM_CHANNEL_INTERRUPT_ENABLE); /* Enable at the NVIC */ EnableIRQ(TPM_INTERRUPT_NUMBER); TPM_StartTimer(BOARD_TPM_BASEADDR, kTPM_SystemClock); while (1) { /* Use interrupt to update the PWM dutycycle */ if (true == tpmIsrFlag) { /* Disable interrupt to retain current dutycycle for a few seconds */ TPM_DisableInterrupts(BOARD_TPM_BASEADDR, TPM_CHANNEL_INTERRUPT_ENABLE); tpmIsrFlag = false; /* Disable channel output before updating the dutycycle */ TPM_UpdateChnlEdgeLevelSelect(BOARD_TPM_BASEADDR, (tpm_chnl_t)BOARD_TPM_CHANNEL, 0U); /* Update PWM duty cycle */ TPM_UpdatePwmDutycycle(BOARD_TPM_BASEADDR, (tpm_chnl_t)BOARD_TPM_CHANNEL, kTPM_CenterAlignedPwm, updatedDutycycle); /* Start channel output with updated dutycycle */ TPM_UpdateChnlEdgeLevelSelect(BOARD_TPM_BASEADDR, (tpm_chnl_t)BOARD_TPM_CHANNEL, pwmLevel); /* Delay to view the updated PWM dutycycle */ delay(); /* Enable interrupt flag to update PWM dutycycle */ TPM_EnableInterrupts(BOARD_TPM_BASEADDR, TPM_CHANNEL_INTERRUPT_ENABLE); } } }