diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c index 759aeded46..c79b1a56bb 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c @@ -23,12 +23,13 @@ #include "fsl_pwm.h" #include "PeripheralPins.h" -static float pwm_clock_mhz; +static float pwm_clock_mhz = 0; + /* Array of PWM peripheral base address. */ static PWM_Type *const pwm_addrs[] = PWM_BASE_PTRS; -extern void pwm_setup_clock(); +extern void pwm_setup(); extern uint32_t pwm_get_clock(); void pwmout_init(pwmout_t* obj, PinName pin) @@ -36,48 +37,57 @@ void pwmout_init(pwmout_t* obj, PinName pin) PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); MBED_ASSERT(pwm != (PWMName)NC); - pwm_setup_clock(); + uint32_t pwm_base_clock; + uint32_t instance = (pwm >> PWM_SHIFT) & 0x7; + uint32_t module = (pwm >> PWM_MODULE_SHIFT) & 0x3; + uint32_t pwmchannel = pwm & 0x1; + pwm_config_t pwmInfo; + static uint32_t clkdiv; obj->pwm_name = pwm; - - uint32_t pwm_base_clock; pwm_base_clock = pwm_get_clock(); - float clkval = (float)pwm_base_clock / 1000000.0f; - uint32_t clkdiv = 0; - while (clkval > 1) { - clkdiv++; - clkval /= 2.0f; - if (clkdiv == 7) { - break; + + if (pwm_clock_mhz == 0) { + float clkval = (float)pwm_base_clock / 1000000.0f; + + while (clkval > 1) { + clkdiv++; + clkval /= 2.0f; + if (clkdiv == 7) { + break; + } } + pwm_clock_mhz = clkval; } - pwm_clock_mhz = clkval; - uint32_t instance = (pwm >> PWM_SHIFT) & 0x3; - uint32_t module = pwm >> PWM_MODULE_SHIFT; - uint8_t pwmchannel = pwm & 0x1; - pwm_config_t pwmInfo; + pwm_setup(instance); + /* Initialize PWM module */ PWM_GetDefaultConfig(&pwmInfo); pwmInfo.prescale = (pwm_clock_prescale_t)clkdiv; - /* Initialize PWM module */ + PWM_Init(pwm_addrs[instance], (pwm_submodule_t)module, &pwmInfo); - pwm_signal_param_t config = { + pwm_signal_param_t channel_config = { .level = kPWM_HighTrue, .dutyCyclePercent = 0, .deadtimeValue = 0 }; + if (pwmchannel == 0) { - config.pwmChannel = kPWM_PwmA; + channel_config.pwmChannel = kPWM_PwmA; } else { - config.pwmChannel = kPWM_PwmB; + channel_config.pwmChannel = kPWM_PwmB; } - // default to 20ms: standard for servos, and fine for e.g. brightness control - PWM_SetupPwm(pwm_addrs[instance], (pwm_submodule_t)module, &config, 1, kPWM_EdgeAligned, 50, pwm_base_clock); + // Setup the module signals to be low + PWM_SetupPwm(pwm_addrs[instance], (pwm_submodule_t)module, &channel_config, 1, kPWM_EdgeAligned, 50, pwm_base_clock); - PWM_StartTimer(pwm_addrs[instance], module); + /* Set the load okay bit for all submodules to load registers from their buffer */ + PWM_SetPwmLdok(pwm_addrs[instance], (1 << module), true); + + /* Start the timer for the sub-module */ + PWM_StartTimer(pwm_addrs[instance], (1 << module)); // Wire pinout pinmap_pinout(pin, PinMap_PWM); @@ -85,10 +95,10 @@ void pwmout_init(pwmout_t* obj, PinName pin) void pwmout_free(pwmout_t* obj) { - uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x3; - uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT; + uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x7; + uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3; - PWM_Deinit(pwm_addrs[instance], (pwm_submodule_t)module); + PWM_StopTimer(pwm_addrs[instance], (1 << module)); } void pwmout_write(pwmout_t* obj, float value) @@ -99,9 +109,9 @@ void pwmout_write(pwmout_t* obj, float value) value = 1.0f; } - PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3]; - uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT; - uint32_t pwmchannel = obj->pwm_name & 0xF; + PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7]; + uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3; + uint32_t pwmchannel = obj->pwm_name & 0x1; uint16_t pulseCnt = 0; pulseCnt = base->SM[module].VAL1; @@ -117,15 +127,14 @@ void pwmout_write(pwmout_t* obj, float value) } /* Set the load okay bit */ - PWM_SetPwmLdok(base, module, true); - + PWM_SetPwmLdok(base, (1 << module), true); } float pwmout_read(pwmout_t* obj) { - PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3]; - uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT; - uint32_t pwmchannel = obj->pwm_name & 0xF; + PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7]; + uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3; + uint32_t pwmchannel = obj->pwm_name & 0x1; uint16_t count; uint16_t mod = (base->SM[module].VAL1) & PWM_VAL1_VAL1_MASK; @@ -157,12 +166,30 @@ void pwmout_period_ms(pwmout_t* obj, int ms) // Set the PWM period, keeping the duty cycle the same. void pwmout_period_us(pwmout_t* obj, int us) { - PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3]; - uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT; + PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7]; + uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3; float dc = pwmout_read(obj); + uint32_t pwm_base_clock; + + pwm_base_clock = pwm_get_clock(); + uint32_t clkdiv = 0; + + pwm_clock_mhz = (float) pwm_base_clock / 1000000.0f; + uint32_t mod = (pwm_clock_mhz * (float) us) - 1; + while (mod > 0xFFFF) { + ++clkdiv; + pwm_clock_mhz /= 2.0f; + mod = (pwm_clock_mhz * (float) us) - 1; + if (clkdiv == 7) { + break; + } + } + uint32_t PRSC = base->SM[module].CTRL & ~PWM_CTRL_PRSC_MASK; + PRSC |= PWM_CTRL_PRSC(clkdiv); + base->SM[module].CTRL = PRSC; /* Indicates the end of the PWM period */ - base->SM[module].VAL1 = PWM_VAL1_VAL1((pwm_clock_mhz * (float)us) - 1); + base->SM[module].VAL1 = PWM_VAL1_VAL1(mod); pwmout_write(obj, dc); } @@ -179,9 +206,9 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) void pwmout_pulsewidth_us(pwmout_t* obj, int us) { - PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3]; - uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT; - uint32_t pwmchannel = obj->pwm_name & 0xF; + PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7]; + uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3; + uint32_t pwmchannel = obj->pwm_name & 0x1; uint32_t value = (uint32_t)(pwm_clock_mhz * (float)us); /* Setup the PWM dutycycle */ @@ -193,7 +220,7 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) base->SM[module].VAL5 = value; } /* Set the load okay bit */ - PWM_SetPwmLdok(base, module, true); + PWM_SetPwmLdok(base, (1 << module), true); } #endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralNames.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralNames.h index cda975898e..93dce23ac9 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralNames.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralNames.h @@ -52,14 +52,38 @@ typedef enum { #define PWM_SHIFT 8 typedef enum { - PWM_1 = (0 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 0 PWMA - PWM_2 = (0 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 0 PWMB - PWM_3 = (0 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 1 PWMA - PWM_4 = (0 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 1 PWMB - PWM_5 = (0 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 2 PWMA - PWM_6 = (0 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 2 PWMB - PWM_7 = (0 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 3 PWMA - PWM_8 = (0 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 3 PWMB + PWM_1 = (1 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 0 PWMA + PWM_2 = (1 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 0 PWMB + PWM_3 = (1 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 1 PWMA + PWM_4 = (1 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 1 PWMB + PWM_5 = (1 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 2 PWMA + PWM_6 = (1 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 2 PWMB + PWM_7 = (1 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 3 PWMA + PWM_8 = (1 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 3 PWMB + PWM_9 = (2 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 0 PWMA + PWM_10 = (2 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 0 PWMB + PWM_11 = (2 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 1 PWMA + PWM_12 = (2 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 1 PWMB + PWM_13 = (2 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 2 PWMA + PWM_14 = (2 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 2 PWMB + PWM_15 = (2 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 3 PWMA + PWM_16 = (2 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 3 PWMB + PWM_17 = (3 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 0 PWMA + PWM_18 = (3 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 0 PWMB + PWM_19 = (3 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 1 PWMA + PWM_20 = (3 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 1 PWMB + PWM_21 = (3 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 2 PWMA + PWM_22 = (3 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 2 PWMB + PWM_23 = (3 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 3 PWMA + PWM_24 = (3 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 3 PWMB + PWM_25 = (4 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 0 PWMA + PWM_26 = (4 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 0 PWMB + PWM_27 = (4 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 1 PWMA + PWM_28 = (4 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 1 PWMB + PWM_29 = (4 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 2 PWMA + PWM_30 = (4 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 2 PWMB + PWM_31 = (4 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 3 PWMA + PWM_32 = (4 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1) // PWM4 Submodule 3 PWMB } PWMName; #define ADC_INSTANCE_SHIFT 8 diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralPins.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralPins.c index fb5889835d..e155041366 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralPins.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralPins.c @@ -88,6 +88,9 @@ const PinMap PinMap_SPI_SSEL[] = { const PinMap PinMap_PWM[] = { {GPIO_AD_B0_10, PWM_7, ((3U << DAISY_REG_VALUE_SHIFT) | (0x454 << DAISY_REG_SHIFT) | 1)}, {GPIO_AD_B0_11, PWM_8, ((3U << DAISY_REG_VALUE_SHIFT) | (0x464 << DAISY_REG_SHIFT) | 1)}, + {GPIO_AD_B1_08, PWM_25, ((1U << DAISY_REG_VALUE_SHIFT) | (0x494 << DAISY_REG_SHIFT) | 1)}, + {GPIO_SD_B0_00, PWM_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x458 << DAISY_REG_SHIFT) | 1)}, + {GPIO_SD_B0_01, PWM_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x468 << DAISY_REG_SHIFT) | 1)}, {NC , NC , 0} }; diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c index d27ee85a34..a71d79604f 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c @@ -16,6 +16,7 @@ #include "pinmap.h" #include "fsl_clock_config.h" #include "fsl_clock.h" +#include "fsl_xbara.h" #include "lpm.h" #define LPSPI_CLOCK_SOURCE_DIVIDER (7U) @@ -217,9 +218,35 @@ uint32_t i2c_get_clock() return ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U)); } -void pwm_setup_clock() +void pwm_setup(uint32_t instance) { - /* Use default settings */ + /* Use default clock settings */ + /* Set the PWM Fault inputs to a low value */ + XBARA_Init(XBARA1); + + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2); + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3); + + switch (instance) { + case 1: + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0); + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1); + break; + case 2: + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault0); + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault1); + break; + case 3: + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault0); + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault1); + break; + case 4: + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault0); + XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault1); + break; + default: + break; + } } uint32_t pwm_get_clock()