Skip to content

Commit 3661dc7

Browse files
committed
MIMXRT1050_EVK: Fix the PWM Hal driver
1. Add Pin defines for missing PWM pins 2. Update the hal to account for the number of PWM instances 3. Fix the register reload policy 4. Configure the XBAR to put the PWM fault inputs in inactive state Signed-off-by: Mahesh Mahadevan <[email protected]>
1 parent 920db63 commit 3661dc7

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)