Skip to content

MIMXRT1050_EVK: Fix the PWM Hal driver #8099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 69 additions & 42 deletions targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,72 +23,82 @@
#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)
{
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);
}

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)
Expand All @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}
Expand All @@ -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 */
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
};

Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down