23
23
#include "fsl_pwm.h"
24
24
#include "PeripheralPins.h"
25
25
26
- static float pwm_clock_mhz ;
26
+ static float pwm_clock_mhz = 0 ;
27
+
27
28
28
29
/* Array of PWM peripheral base address. */
29
30
static PWM_Type * const pwm_addrs [] = PWM_BASE_PTRS ;
30
31
31
- extern void pwm_setup_clock ();
32
+ extern void pwm_setup ();
32
33
extern uint32_t pwm_get_clock ();
33
34
34
35
void pwmout_init (pwmout_t * obj , PinName pin )
35
36
{
36
37
PWMName pwm = (PWMName )pinmap_peripheral (pin , PinMap_PWM );
37
38
MBED_ASSERT (pwm != (PWMName )NC );
38
39
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 ;
40
46
41
47
obj -> pwm_name = pwm ;
42
-
43
- uint32_t pwm_base_clock ;
44
48
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
+ }
52
59
}
60
+ pwm_clock_mhz = clkval ;
53
61
}
54
62
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 );
60
64
65
+ /* Initialize PWM module */
61
66
PWM_GetDefaultConfig (& pwmInfo );
62
67
pwmInfo .prescale = (pwm_clock_prescale_t )clkdiv ;
63
- /* Initialize PWM module */
68
+
64
69
PWM_Init (pwm_addrs [instance ], (pwm_submodule_t )module , & pwmInfo );
65
70
66
- pwm_signal_param_t config = {
71
+ pwm_signal_param_t channel_config = {
67
72
.level = kPWM_HighTrue ,
68
73
.dutyCyclePercent = 0 ,
69
74
.deadtimeValue = 0
70
75
};
76
+
71
77
if (pwmchannel == 0 ) {
72
- config .pwmChannel = kPWM_PwmA ;
78
+ channel_config .pwmChannel = kPWM_PwmA ;
73
79
} else {
74
- config .pwmChannel = kPWM_PwmB ;
80
+ channel_config .pwmChannel = kPWM_PwmB ;
75
81
}
76
82
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 );
79
85
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 ));
81
91
82
92
// Wire pinout
83
93
pinmap_pinout (pin , PinMap_PWM );
84
94
}
85
95
86
96
void pwmout_free (pwmout_t * obj )
87
97
{
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 ;
90
100
91
- PWM_Deinit (pwm_addrs [instance ], (pwm_submodule_t ) module );
101
+ PWM_StopTimer (pwm_addrs [instance ], (1 << module ) );
92
102
}
93
103
94
104
void pwmout_write (pwmout_t * obj , float value )
@@ -99,9 +109,9 @@ void pwmout_write(pwmout_t* obj, float value)
99
109
value = 1.0f ;
100
110
}
101
111
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 ;
105
115
uint16_t pulseCnt = 0 ;
106
116
107
117
pulseCnt = base -> SM [module ].VAL1 ;
@@ -117,15 +127,14 @@ void pwmout_write(pwmout_t* obj, float value)
117
127
}
118
128
119
129
/* Set the load okay bit */
120
- PWM_SetPwmLdok (base , module , true);
121
-
130
+ PWM_SetPwmLdok (base , (1 << module ), true);
122
131
}
123
132
124
133
float pwmout_read (pwmout_t * obj )
125
134
{
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 ;
129
138
uint16_t count ;
130
139
uint16_t mod = (base -> SM [module ].VAL1 ) & PWM_VAL1_VAL1_MASK ;
131
140
@@ -157,12 +166,30 @@ void pwmout_period_ms(pwmout_t* obj, int ms)
157
166
// Set the PWM period, keeping the duty cycle the same.
158
167
void pwmout_period_us (pwmout_t * obj , int us )
159
168
{
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 ;
162
171
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 ;
163
190
164
191
/* 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 );
166
193
167
194
pwmout_write (obj , dc );
168
195
}
@@ -179,9 +206,9 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
179
206
180
207
void pwmout_pulsewidth_us (pwmout_t * obj , int us )
181
208
{
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 ;
185
212
uint32_t value = (uint32_t )(pwm_clock_mhz * (float )us );
186
213
187
214
/* Setup the PWM dutycycle */
@@ -193,7 +220,7 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
193
220
base -> SM [module ].VAL5 = value ;
194
221
}
195
222
/* Set the load okay bit */
196
- PWM_SetPwmLdok (base , module , true);
223
+ PWM_SetPwmLdok (base , ( 1 << module ) , true);
197
224
}
198
225
199
226
#endif
0 commit comments