mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_Cypress/TARGET_PSOC6/pwmout_api.c
- Revision:
- 189:f392fc9709a3
- Parent:
- 188:bcfe06ba3d64
--- a/targets/TARGET_Cypress/TARGET_PSOC6/pwmout_api.c Thu Nov 08 11:46:34 2018 +0000 +++ b/targets/TARGET_Cypress/TARGET_PSOC6/pwmout_api.c Wed Feb 20 22:31:08 2019 +0000 @@ -1,6 +1,8 @@ /* * mbed Microcontroller Library * Copyright (c) 2017-2018 Future Electronics + * Copyright (c) 2018-2019 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,10 +88,10 @@ period /= 2; prescaler += 1; } + if (period > MAX_16_BIT_PERIOD) { // We have reached the prescaler limit, set period to max value. error("Can't configure required PWM period."); - period = MAX_16_BIT_PERIOD; } obj->prescaler = prescaler; @@ -120,12 +122,12 @@ /* * Callback handler to restart the timer after deep sleep. */ -#if DEVICE_SLEEP && DEVICE_LOWPOWERTIMER -static cy_en_syspm_status_t pwm_pm_callback(cy_stc_syspm_callback_params_t *callback_params) +#if DEVICE_SLEEP && DEVICE_LPTICKER +static cy_en_syspm_status_t pwm_pm_callback(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode) { pwmout_t *obj = (pwmout_t *)callback_params->context; - switch (callback_params->mode) { + switch (mode) { case CY_SYSPM_BEFORE_TRANSITION: /* Disable timer before transition */ Cy_TCPWM_PWM_Disable(obj->base, obj->counter_id); @@ -145,7 +147,7 @@ return CY_SYSPM_SUCCESS; } -#endif // DEVICE_SLEEP && DEVICE_LOWPOWERTIMER +#endif // DEVICE_SLEEP && DEVICE_LPTICKER void pwmout_init(pwmout_t *obj, PinName pin) @@ -156,59 +158,75 @@ MBED_ASSERT(obj); MBED_ASSERT(pin != (PinName)NC); - // Allocate and setup clock. + + // Allocate and setup clock (same clock for all PWMs) if (pwm_clock_divider == CY_INVALID_DIVIDER) { + pwm_clock_divider = cy_clk_allocate_divider(CY_SYSCLK_DIV_8_BIT); if (pwm_clock_divider == CY_INVALID_DIVIDER) { error("PWM clock divider allocation failed."); - return; } - Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, - pwm_clock_divider, - (CY_CLK_PERICLK_FREQ_HZ / PWMOUT_BASE_CLOCK_HZ) - 1); + + /* Configure divider */ + Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, pwm_clock_divider, + (cy_PeriClkFreqHz / PWMOUT_BASE_CLOCK_HZ) - 1); Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, pwm_clock_divider); } + /* Find instance using pins */ pwm_cnt = pinmap_peripheral(pin, PinMap_PWM_OUT); if (pwm_cnt != (uint32_t)NC) { - if (cy_reserve_io_pin(pin)) { - error("PWMOUT pin reservation conflict."); - } - obj->base = (TCPWM_Type*)CY_PERIPHERAL_BASE(pwm_cnt); - obj->pin = pin; + + obj->pin = pin; + obj->base = (TCPWM_Type *)CY_PERIPHERAL_BASE(pwm_cnt); if (obj->base == TCPWM0) { + /* TCPWM0 is used */ obj->counter_id = ((PWMName)pwm_cnt - PWM_32b_0) / (PWM_32b_1 - PWM_32b_0); abs_cnt_num = obj->counter_id; } else { - // TCPWM1 is used. + /* TCPWM1 is used */ obj->counter_id = ((PWMName)pwm_cnt - PWM_16b_0) / (PWM_16b_1 - PWM_16b_0); abs_cnt_num = obj->counter_id + 8; } - if (cy_reserve_tcpwm(abs_cnt_num)) { - error("PWMOUT Timer/Counter reservation conflict."); + + /* Check if resource severed */ + if (0 != cy_reserve_tcpwm(abs_cnt_num)) { + Cy_TCPWM_PWM_Disable(obj->base, obj->counter_id); + Cy_TCPWM_PWM_DeInit(obj->base, obj->counter_id, &pwm_config); + } else { + if (cy_reserve_io_pin(pin)) { + error("PWMOUT pin reservation conflict."); + } + +#if DEVICE_SLEEP && DEVICE_LPTICKER + /* Register callback once */ + obj->pm_callback_handler.callback = pwm_pm_callback; + obj->pm_callback_handler.type = CY_SYSPM_DEEPSLEEP; + obj->pm_callback_handler.skipMode = 0; + obj->pm_callback_handler.callbackParams = &obj->pm_callback_params; + obj->pm_callback_params.base = obj->base; + obj->pm_callback_params.context = obj; + if (!Cy_SysPm_RegisterCallback(&obj->pm_callback_handler)) { + error("PM callback registration failed!"); + } +#endif // DEVICE_SLEEP && DEVICE_LPTICKER } - // Configure clock. + /* Configure pin */ pwm_function = pinmap_function(pin, PinMap_PWM_OUT); + pin_function(pin, pwm_function); + + /* Connect clock */ obj->clock = CY_PIN_CLOCK(pwm_function); Cy_SysClk_PeriphAssignDivider(obj->clock, CY_SYSCLK_DIV_8_BIT, pwm_clock_divider); + + /* Configure hardarwe */ Cy_TCPWM_PWM_Init(obj->base, obj->counter_id, &pwm_config); - pin_function(pin, pwm_function); + // These will be properly configured later on. - obj->period = 0; + obj->period = 0; obj->pulse_width = 0; - obj->prescaler = 0; -#if DEVICE_SLEEP && DEVICE_LOWPOWERTIMER - obj->pm_callback_handler.callback = pwm_pm_callback; - obj->pm_callback_handler.type = CY_SYSPM_DEEPSLEEP; - obj->pm_callback_handler.skipMode = CY_SYSPM_SKIP_CHECK_READY | CY_SYSPM_SKIP_CHECK_FAIL; - obj->pm_callback_handler.callbackParams = &obj->pm_callback_params; - obj->pm_callback_params.base = obj->base; - obj->pm_callback_params.context = obj; - if (!Cy_SysPm_RegisterCallback(&obj->pm_callback_handler)) { - error("PM callback registration failed!"); - } -#endif // DEVICE_SLEEP && DEVICE_LOWPOWERTIMER + obj->prescaler = 0; } else { error("PWM OUT pinout mismatch."); @@ -217,7 +235,9 @@ void pwmout_free(pwmout_t *obj) { - // TODO: Not implemented yet. + /* Does nothing because it is not called in the MBED PWMOUT driver + * destructor. The pwmout_init handles multiple calls of constructor. + */ } void pwmout_write(pwmout_t *obj, float percent)