@@ -415,11 +415,13 @@ void ap3_pwm_wait_for_pulse(uint32_t timer, uint32_t segment, uint32_t output, u
415415
416416 // Get the compare value
417417 cmpr0 = ((uint32_t )(*(pui32CompareReg)) & 0x0000FFFF );
418-
419- // Wait for the timer value to be less than the compare value so that it is safe to change
420- ctimer_val = am_hal_ctimer_read ( timer, segment);
421- while ( (ctimer_val + 0 ) > cmpr0 ){
418+
419+ if ( cmpr0 ){ // Only wait when cmpr0 is greater than 0 to avoid an infinite while loop
420+ // Wait for the timer value to be less than the compare value so that it is safe to change
422421 ctimer_val = am_hal_ctimer_read ( timer, segment);
422+ while ( (ctimer_val + 0 ) >= cmpr0 ){
423+ ctimer_val = am_hal_ctimer_read ( timer, segment);
424+ }
423425 }
424426 }
425427}
@@ -526,13 +528,16 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
526528 }
527529
528530 // Test for AM_HAL_CTIMER_OUTPUT_FORCE0 or AM_HAL_CTIMER_OUTPUT_FORCE1
531+ bool set_periods = true ;
529532 if ((th == 0 ) || (fw == 0 ))
530533 {
531534 output = AM_HAL_CTIMER_OUTPUT_FORCE0;
535+ set_periods = false ; // disable setting periods when going into a forced mode
532536 }
533537 else if (th == fw)
534538 {
535539 output = AM_HAL_CTIMER_OUTPUT_FORCE1;
540+ set_periods = false ; // disable setting periods when going into a forced mode
536541 }
537542
538543 // Wait until after high pulse to change the state (avoids inversion)
@@ -551,31 +556,33 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
551556 // (AM_HAL_CTIMER_FN_PWM_REPEAT | AP3_ANALOG_CLK | AM_HAL_CTIMER_INT_ENABLE) );
552557 (AM_HAL_CTIMER_FN_PWM_REPEAT | clk));
553558
554- // If this pad uses secondary output:
555- if (output == AM_HAL_CTIMER_OUTPUT_SECONDARY)
556- {
557- // Need to explicitly enable compare registers 2/3
558- uint32_t *pui32ConfigReg = NULL ;
559- pui32ConfigReg = (uint32_t *)CTIMERADDRn (CTIMER, timer, AUX0);
560- uint32_t ui32WriteVal = AM_REGVAL (pui32ConfigReg);
561- uint32_t ui32ConfigVal = (1 << CTIMER_AUX0_TMRA0EN23_Pos); // using CTIMER_AUX0_TMRA0EN23_Pos because for now this number is common to all CTimer instances
562- if (segment == AM_HAL_CTIMER_TIMERB)
559+ if (set_periods){
560+ // If this pad uses secondary output:
561+ if (output == AM_HAL_CTIMER_OUTPUT_SECONDARY)
562+ {
563+ // Need to explicitly enable compare registers 2/3
564+ uint32_t *pui32ConfigReg = NULL ;
565+ pui32ConfigReg = (uint32_t *)CTIMERADDRn (CTIMER, timer, AUX0);
566+ uint32_t ui32WriteVal = AM_REGVAL (pui32ConfigReg);
567+ uint32_t ui32ConfigVal = (1 << CTIMER_AUX0_TMRA0EN23_Pos); // using CTIMER_AUX0_TMRA0EN23_Pos because for now this number is common to all CTimer instances
568+ if (segment == AM_HAL_CTIMER_TIMERB)
569+ {
570+ ui32ConfigVal = ((ui32ConfigVal & 0xFFFF ) << 16 );
571+ }
572+ ui32WriteVal = (ui32WriteVal & ~(segment)) | ui32ConfigVal;
573+ AM_REGVAL (pui32ConfigReg) = ui32WriteVal;
574+
575+ // then set the duty cycle with the 'aux' function
576+ am_hal_ctimer_aux_period_set (timer, segment, fw, th);
577+ }
578+ else
563579 {
564- ui32ConfigVal = ((ui32ConfigVal & 0xFFFF ) << 16 );
580+ // Otherwise simply set the primary duty cycle
581+ am_hal_ctimer_period_set (timer, segment, fw, th);
565582 }
566- ui32WriteVal = (ui32WriteVal & ~(segment)) | ui32ConfigVal;
567- AM_REGVAL (pui32ConfigReg) = ui32WriteVal;
568583
569- // then set the duty cycle with the 'aux' function
570- am_hal_ctimer_aux_period_set (timer, segment, fw, th);
584+ am_hal_ctimer_start (timer, segment); // Start the timer only when there are periods to compare to
571585 }
572- else
573- {
574- // Otherwise simply set the primary duty cycle
575- am_hal_ctimer_period_set (timer, segment, fw, th);
576- }
577-
578- am_hal_ctimer_start (timer, segment);
579586
580587 return AP3_OK;
581588}
@@ -594,17 +601,17 @@ ap3_err_t analogWriteResolution(uint8_t res)
594601ap3_err_t analogWrite (uint8_t pin, uint32_t val)
595602{
596603 // Determine the high time based on input value and the current resolution setting
597- uint32_t fw = 0xFFFF ; // Choose the frame width in clock periods (32767 -> ~ 180 Hz)
598- if (val == ((0x01 << _analogWriteBits) - 1 ))
604+ uint32_t clk = AM_HAL_CTIMER_HFRC_12MHZ; // Use an Ambiq HAL provided value to select which clock
605+ uint32_t fw = 0xFFFF ; // Choose the frame width in clock periods (32767 -> ~ 180 Hz)
606+ if (val >= ((0x01 << _analogWriteBits) - 1 ))
599607 {
600608 val = fw; // Enable FORCE1
601609 }
602610 else
603611 {
604- val <<= (16 - _analogWriteBits); // Shift over the value to fill available resolution
612+ val <<= (16 - _analogWriteBits); // Shift over the value to fill available resolution
605613 }
606- uint32_t clk = AM_HAL_CTIMER_HFRC_12MHZ; // Use an Ambiq HAL provided value to select which clock
607-
614+
608615 return ap3_pwm_output (pin, val, fw, clk);
609616}
610617
0 commit comments