@@ -164,19 +164,20 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t* self) {
164164
165165extern void common_hal_pwmio_pwmout_set_duty_cycle (pwmio_pwmout_obj_t * self , uint16_t duty ) {
166166 self -> duty_cycle = duty ;
167- uint16_t actual_duty = duty * self -> top / ((1 << 16 ) - 1 );
167+ // Do arithmetic in 32 bits to prevent overflow.
168+ uint16_t actual_duty = (uint32_t ) duty * self -> top / ((1 << 16 ) - 1 );
168169 pwm_set_chan_level (self -> slice , self -> channel , actual_duty );
169170}
170171
171172uint16_t common_hal_pwmio_pwmout_get_duty_cycle (pwmio_pwmout_obj_t * self ) {
172173 return self -> duty_cycle ;
173174}
174175
175- void pwmio_pwmout_set_top (pwmio_pwmout_obj_t * self , uint32_t top ) {
176+ void pwmio_pwmout_set_top (pwmio_pwmout_obj_t * self , uint16_t top ) {
176177 self -> actual_frequency = common_hal_mcu_processor_get_frequency () / top ;
177178 self -> top = top ;
178179 pwm_set_clkdiv_int_frac (self -> slice , 1 , 0 );
179- pwm_set_wrap (self -> slice , self -> top - 1 );
180+ pwm_set_wrap (self -> slice , self -> top );
180181}
181182
182183void common_hal_pwmio_pwmout_set_frequency (pwmio_pwmout_obj_t * self , uint32_t frequency ) {
@@ -187,7 +188,7 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
187188 target_slice_frequencies [self -> slice ] = frequency ;
188189
189190 // For low frequencies use the divider to give us full resolution duty_cycle.
190- if (frequency < (common_hal_mcu_processor_get_frequency () / (1 << 16 ))) {
191+ if (frequency <= (common_hal_mcu_processor_get_frequency () / (1 << 16 ))) {
191192 // Compute the divisor. It's an 8 bit integer and 4 bit fraction. Therefore,
192193 // we compute everything * 16 for the fractional part.
193194 // This is 1 << 12 because 4 bits are the * 16.
@@ -202,15 +203,15 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, uint32_t fr
202203 div16 = (1 << 12 ) - 1 ;
203204 }
204205 self -> actual_frequency = frequency16 / div16 ;
205- self -> top = 1 << 16 ;
206+ self -> top = ( 1 << 16 ) - 1 ;
206207 pwm_set_clkdiv_int_frac (self -> slice , div16 / 16 , div16 % 16 );
207- pwm_set_wrap (self -> slice , self -> top - 1 );
208+ pwm_set_wrap (self -> slice , self -> top );
208209 } else {
209210 uint32_t top = common_hal_mcu_processor_get_frequency () / frequency ;
210211 self -> actual_frequency = common_hal_mcu_processor_get_frequency () / top ;
211- self -> top = top ;
212+ self -> top = MIN ( UINT16_MAX , top - 1 ) ;
212213 pwm_set_clkdiv_int_frac (self -> slice , 1 , 0 );
213- pwm_set_wrap (self -> slice , self -> top - 1 );
214+ pwm_set_wrap (self -> slice , self -> top );
214215 }
215216 common_hal_pwmio_pwmout_set_duty_cycle (self , self -> duty_cycle );
216217}
0 commit comments