Skip to content

Commit b3fe04f

Browse files
author
Cruz Monrreal
authored
Merge pull request #8099 from NXPmicro/Fix_MXRT_PWM
MIMXRT1050_EVK: Fix the PWM Hal driver
2 parents 37654e5 + 3661dc7 commit b3fe04f

File tree

4 files changed

+133
-52
lines changed

4 files changed

+133
-52
lines changed

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/pwmout_api.c

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,72 +23,82 @@
2323
#include "fsl_pwm.h"
2424
#include "PeripheralPins.h"
2525

26-
static float pwm_clock_mhz;
26+
static float pwm_clock_mhz = 0;
27+
2728

2829
/* Array of PWM peripheral base address. */
2930
static PWM_Type *const pwm_addrs[] = PWM_BASE_PTRS;
3031

31-
extern void pwm_setup_clock();
32+
extern void pwm_setup();
3233
extern uint32_t pwm_get_clock();
3334

3435
void pwmout_init(pwmout_t* obj, PinName pin)
3536
{
3637
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
3738
MBED_ASSERT(pwm != (PWMName)NC);
3839

39-
pwm_setup_clock();
40+
uint32_t pwm_base_clock;
41+
uint32_t instance = (pwm >> PWM_SHIFT) & 0x7;
42+
uint32_t module = (pwm >> PWM_MODULE_SHIFT) & 0x3;
43+
uint32_t pwmchannel = pwm & 0x1;
44+
pwm_config_t pwmInfo;
45+
static uint32_t clkdiv;
4046

4147
obj->pwm_name = pwm;
42-
43-
uint32_t pwm_base_clock;
4448
pwm_base_clock = pwm_get_clock();
45-
float clkval = (float)pwm_base_clock / 1000000.0f;
46-
uint32_t clkdiv = 0;
47-
while (clkval > 1) {
48-
clkdiv++;
49-
clkval /= 2.0f;
50-
if (clkdiv == 7) {
51-
break;
49+
50+
if (pwm_clock_mhz == 0) {
51+
float clkval = (float)pwm_base_clock / 1000000.0f;
52+
53+
while (clkval > 1) {
54+
clkdiv++;
55+
clkval /= 2.0f;
56+
if (clkdiv == 7) {
57+
break;
58+
}
5259
}
60+
pwm_clock_mhz = clkval;
5361
}
5462

55-
pwm_clock_mhz = clkval;
56-
uint32_t instance = (pwm >> PWM_SHIFT) & 0x3;
57-
uint32_t module = pwm >> PWM_MODULE_SHIFT;
58-
uint8_t pwmchannel = pwm & 0x1;
59-
pwm_config_t pwmInfo;
63+
pwm_setup(instance);
6064

65+
/* Initialize PWM module */
6166
PWM_GetDefaultConfig(&pwmInfo);
6267
pwmInfo.prescale = (pwm_clock_prescale_t)clkdiv;
63-
/* Initialize PWM module */
68+
6469
PWM_Init(pwm_addrs[instance], (pwm_submodule_t)module, &pwmInfo);
6570

66-
pwm_signal_param_t config = {
71+
pwm_signal_param_t channel_config = {
6772
.level = kPWM_HighTrue,
6873
.dutyCyclePercent = 0,
6974
.deadtimeValue = 0
7075
};
76+
7177
if (pwmchannel == 0) {
72-
config.pwmChannel = kPWM_PwmA;
78+
channel_config.pwmChannel = kPWM_PwmA;
7379
} else {
74-
config.pwmChannel = kPWM_PwmB;
80+
channel_config.pwmChannel = kPWM_PwmB;
7581
}
7682

77-
// default to 20ms: standard for servos, and fine for e.g. brightness control
78-
PWM_SetupPwm(pwm_addrs[instance], (pwm_submodule_t)module, &config, 1, kPWM_EdgeAligned, 50, pwm_base_clock);
83+
// Setup the module signals to be low
84+
PWM_SetupPwm(pwm_addrs[instance], (pwm_submodule_t)module, &channel_config, 1, kPWM_EdgeAligned, 50, pwm_base_clock);
7985

80-
PWM_StartTimer(pwm_addrs[instance], module);
86+
/* Set the load okay bit for all submodules to load registers from their buffer */
87+
PWM_SetPwmLdok(pwm_addrs[instance], (1 << module), true);
88+
89+
/* Start the timer for the sub-module */
90+
PWM_StartTimer(pwm_addrs[instance], (1 << module));
8191

8292
// Wire pinout
8393
pinmap_pinout(pin, PinMap_PWM);
8494
}
8595

8696
void pwmout_free(pwmout_t* obj)
8797
{
88-
uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x3;
89-
uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT;
98+
uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x7;
99+
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
90100

91-
PWM_Deinit(pwm_addrs[instance], (pwm_submodule_t)module);
101+
PWM_StopTimer(pwm_addrs[instance], (1 << module));
92102
}
93103

94104
void pwmout_write(pwmout_t* obj, float value)
@@ -99,9 +109,9 @@ void pwmout_write(pwmout_t* obj, float value)
99109
value = 1.0f;
100110
}
101111

102-
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3];
103-
uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT;
104-
uint32_t pwmchannel = obj->pwm_name & 0xF;
112+
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
113+
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
114+
uint32_t pwmchannel = obj->pwm_name & 0x1;
105115
uint16_t pulseCnt = 0;
106116

107117
pulseCnt = base->SM[module].VAL1;
@@ -117,15 +127,14 @@ void pwmout_write(pwmout_t* obj, float value)
117127
}
118128

119129
/* Set the load okay bit */
120-
PWM_SetPwmLdok(base, module, true);
121-
130+
PWM_SetPwmLdok(base, (1 << module), true);
122131
}
123132

124133
float pwmout_read(pwmout_t* obj)
125134
{
126-
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3];
127-
uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT;
128-
uint32_t pwmchannel = obj->pwm_name & 0xF;
135+
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
136+
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
137+
uint32_t pwmchannel = obj->pwm_name & 0x1;
129138
uint16_t count;
130139
uint16_t mod = (base->SM[module].VAL1) & PWM_VAL1_VAL1_MASK;
131140

@@ -157,12 +166,30 @@ void pwmout_period_ms(pwmout_t* obj, int ms)
157166
// Set the PWM period, keeping the duty cycle the same.
158167
void pwmout_period_us(pwmout_t* obj, int us)
159168
{
160-
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3];
161-
uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT;
169+
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
170+
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
162171
float dc = pwmout_read(obj);
172+
uint32_t pwm_base_clock;
173+
174+
pwm_base_clock = pwm_get_clock();
175+
uint32_t clkdiv = 0;
176+
177+
pwm_clock_mhz = (float) pwm_base_clock / 1000000.0f;
178+
uint32_t mod = (pwm_clock_mhz * (float) us) - 1;
179+
while (mod > 0xFFFF) {
180+
++clkdiv;
181+
pwm_clock_mhz /= 2.0f;
182+
mod = (pwm_clock_mhz * (float) us) - 1;
183+
if (clkdiv == 7) {
184+
break;
185+
}
186+
}
187+
uint32_t PRSC = base->SM[module].CTRL & ~PWM_CTRL_PRSC_MASK;
188+
PRSC |= PWM_CTRL_PRSC(clkdiv);
189+
base->SM[module].CTRL = PRSC;
163190

164191
/* Indicates the end of the PWM period */
165-
base->SM[module].VAL1 = PWM_VAL1_VAL1((pwm_clock_mhz * (float)us) - 1);
192+
base->SM[module].VAL1 = PWM_VAL1_VAL1(mod);
166193

167194
pwmout_write(obj, dc);
168195
}
@@ -179,9 +206,9 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
179206

180207
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
181208
{
182-
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x3];
183-
uint32_t module = obj->pwm_name >> PWM_MODULE_SHIFT;
184-
uint32_t pwmchannel = obj->pwm_name & 0xF;
209+
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
210+
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
211+
uint32_t pwmchannel = obj->pwm_name & 0x1;
185212
uint32_t value = (uint32_t)(pwm_clock_mhz * (float)us);
186213

187214
/* Setup the PWM dutycycle */
@@ -193,7 +220,7 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
193220
base->SM[module].VAL5 = value;
194221
}
195222
/* Set the load okay bit */
196-
PWM_SetPwmLdok(base, module, true);
223+
PWM_SetPwmLdok(base, (1 << module), true);
197224
}
198225

199226
#endif

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralNames.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,38 @@ typedef enum {
5252
#define PWM_SHIFT 8
5353

5454
typedef enum {
55-
PWM_1 = (0 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 0 PWMA
56-
PWM_2 = (0 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 0 PWMB
57-
PWM_3 = (0 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 1 PWMA
58-
PWM_4 = (0 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 1 PWMB
59-
PWM_5 = (0 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 2 PWMA
60-
PWM_6 = (0 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 2 PWMB
61-
PWM_7 = (0 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 3 PWMA
62-
PWM_8 = (0 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 3 PWMB
55+
PWM_1 = (1 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 0 PWMA
56+
PWM_2 = (1 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 0 PWMB
57+
PWM_3 = (1 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 1 PWMA
58+
PWM_4 = (1 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 1 PWMB
59+
PWM_5 = (1 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 2 PWMA
60+
PWM_6 = (1 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 2 PWMB
61+
PWM_7 = (1 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM1 Submodule 3 PWMA
62+
PWM_8 = (1 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM1 Submodule 3 PWMB
63+
PWM_9 = (2 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 0 PWMA
64+
PWM_10 = (2 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 0 PWMB
65+
PWM_11 = (2 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 1 PWMA
66+
PWM_12 = (2 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 1 PWMB
67+
PWM_13 = (2 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 2 PWMA
68+
PWM_14 = (2 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 2 PWMB
69+
PWM_15 = (2 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM2 Submodule 3 PWMA
70+
PWM_16 = (2 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM2 Submodule 3 PWMB
71+
PWM_17 = (3 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 0 PWMA
72+
PWM_18 = (3 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 0 PWMB
73+
PWM_19 = (3 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 1 PWMA
74+
PWM_20 = (3 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 1 PWMB
75+
PWM_21 = (3 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 2 PWMA
76+
PWM_22 = (3 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 2 PWMB
77+
PWM_23 = (3 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM3 Submodule 3 PWMA
78+
PWM_24 = (3 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1), // PWM3 Submodule 3 PWMB
79+
PWM_25 = (4 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 0 PWMA
80+
PWM_26 = (4 << PWM_SHIFT) | (0 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 0 PWMB
81+
PWM_27 = (4 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 1 PWMA
82+
PWM_28 = (4 << PWM_SHIFT) | (1 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 1 PWMB
83+
PWM_29 = (4 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 2 PWMA
84+
PWM_30 = (4 << PWM_SHIFT) | (2 << PWM_MODULE_SHIFT) | (1), // PWM4 Submodule 2 PWMB
85+
PWM_31 = (4 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (0), // PWM4 Submodule 3 PWMA
86+
PWM_32 = (4 << PWM_SHIFT) | (3 << PWM_MODULE_SHIFT) | (1) // PWM4 Submodule 3 PWMB
6387
} PWMName;
6488

6589
#define ADC_INSTANCE_SHIFT 8

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/PeripheralPins.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ const PinMap PinMap_SPI_SSEL[] = {
8888
const PinMap PinMap_PWM[] = {
8989
{GPIO_AD_B0_10, PWM_7, ((3U << DAISY_REG_VALUE_SHIFT) | (0x454 << DAISY_REG_SHIFT) | 1)},
9090
{GPIO_AD_B0_11, PWM_8, ((3U << DAISY_REG_VALUE_SHIFT) | (0x464 << DAISY_REG_SHIFT) | 1)},
91+
{GPIO_AD_B1_08, PWM_25, ((1U << DAISY_REG_VALUE_SHIFT) | (0x494 << DAISY_REG_SHIFT) | 1)},
92+
{GPIO_SD_B0_00, PWM_1, ((1U << DAISY_REG_VALUE_SHIFT) | (0x458 << DAISY_REG_SHIFT) | 1)},
93+
{GPIO_SD_B0_01, PWM_2, ((1U << DAISY_REG_VALUE_SHIFT) | (0x468 << DAISY_REG_SHIFT) | 1)},
9194
{NC , NC , 0}
9295
};
9396

targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050/TARGET_EVK/mbed_overrides.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "pinmap.h"
1717
#include "fsl_clock_config.h"
1818
#include "fsl_clock.h"
19+
#include "fsl_xbara.h"
1920
#include "lpm.h"
2021

2122
#define LPSPI_CLOCK_SOURCE_DIVIDER (7U)
@@ -217,9 +218,35 @@ uint32_t i2c_get_clock()
217218
return ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U));
218219
}
219220

220-
void pwm_setup_clock()
221+
void pwm_setup(uint32_t instance)
221222
{
222-
/* Use default settings */
223+
/* Use default clock settings */
224+
/* Set the PWM Fault inputs to a low value */
225+
XBARA_Init(XBARA1);
226+
227+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2);
228+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3);
229+
230+
switch (instance) {
231+
case 1:
232+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0);
233+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1);
234+
break;
235+
case 2:
236+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault0);
237+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault1);
238+
break;
239+
case 3:
240+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault0);
241+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault1);
242+
break;
243+
case 4:
244+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault0);
245+
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault1);
246+
break;
247+
default:
248+
break;
249+
}
223250
}
224251

225252
uint32_t pwm_get_clock()

0 commit comments

Comments
 (0)