Hello NXP Team,
I am using S32K396 with RTD 5.0.0 and the FlexIO PWM driver.
My configuration is:
Generated configuration:
const Flexio_Pwm_Ip_ChannelConfigType Flexio_Pwm_Ip_I0_Ch0 =
{
/* TimerId */ 0U,
/* PinId */ 1U,
#if (defined(FLEXIO_PWM_IP_HAS_PRESCALER) && (FLEXIO_PWM_IP_HAS_PRESCALER == STD_ON))
/* Prescaler */ FLEXIO_PWM_IP_CLK_DIV_16,
#endif
/* Period */ 400U,
/* DutyCycle */ 0U,
#if (defined(FLEXIO_PWM_IP_HAS_LOW_MODE) && (FLEXIO_PWM_IP_HAS_LOW_MODE == STD_ON))
/* Polarity */ FLEXIO_PWM_IP_ACTIVE_HIGH,
#endif
/* IrqMode */ FLEXIO_PWM_IP_IRQ_DISABLED,
/* IPL callback */ {
/* CbFunction */ NULL_PTR,
/* CbParameter */ NULL_PTR
},
/* HLD callback */ {
/* CbFunction */ NULL_PTR,
/* CbParameter */ 0
}
};
I am trying to understand the exact relationship between:
My measurements are:
| 200 | 100 | 20 kHz | 50% |
| 300 | 100 | 13.3 kHz | 33.3% |
| 400 | 100 | 27.7 kHz | 69.4% |
| 500 | 100 | 16.3 kHz | 40% |
The first two measurements seem to indicate:
Duty (%) = DutyTicks / PeriodTicks × 100However, I am unable to derive the exact PWM frequency formula used internally by the FlexIO PWM RTD driver.
Could you please clarify:
Any clarification on the internal timing equation would be greatly appreciated.
Thank you.
Hi @Esakki,
1.
Your formula is correct.
2.
For Period = 200 and Duty = 100 ticks, in Dual 8-bit counters PWM high mode (TIMCTL[TIMOD]):
TIMCMP = 0x00006363
High byte = 0x63 = 99 → decremented while the output is low
Low byte = 0x63 = 99 → decremented while the output is high
3.
Yes, the driver should prevent writing values greater than 256 to either byte when FLEXIO_PWM_IP_DEV_ERROR_DETECT = STD_ON.
If this check is disabled, the field will overflow, which is likely the root cause of the issue you are observing.
4.
Period in ticks − duty in ticks ≤ 256.
It is not possible to achieve 10 kHz with the given input clock in this mode. You need to increase the prescaler.
5.
Only the Reference Manual covers this.
Regards,
Daniel
Any support, information, and technology (“Materials”) provided by NXP are provided AS IS, without any warranty express or implied, and NXP disclaims all direct and indirect liability and damages in connection with the Material to the maximum extent permitted by the applicable law.
NXP accepts no liability for any assistance with applications or product design. Materials may only be used in connection with NXP products. Any feedback provided to NXP regarding the Materials may be used by NXP without restriction.
Hello Daniel,
Thank you for the explanation.
I have one follow-up question regarding the Period calculation.
From your explanation, I understand that in Dual 8-bit counters PWM high mode:
TIMCMP[15:8] = Period - Duty - 1
TIMCMP[7:0] = Duty - 1
and that both fields are limited to 256 counts.
Could you please clarify the exact formula used to calculate the output PWM frequency from:
FlexIO input clock frequency
Prescaler
Period value
For example, if:
FlexIO clock = 160 MHz
Prescaler = 256
Period = 63 ticks
What should be the expected PWM frequency?
Using the formula:
PWM Frequency = FlexIO Clock / (Prescaler × Period)
I would expect approximately 9.92 kHz.
However, when measuring the PWM output, I observe approximately 3.9 kHz.
Similarly, with:
Prescaler = 16
Period = 200
I measure approximately 20 kHz, which corresponds to an effective PWM clock of about 64 MHz rather than 160 MHz.
Could you please explain:
The exact PWM frequency equation for FlexIO PWM Dual 8-bit mode.
Whether any additional divider or timer scaling is applied internally by the FlexIO PWM driver.
Which runtime register or clock source should be checked to determine the actual clock used by the PWM timer.
Thank you for your help.
Hi @Esakki,
You can derive the equation directly from the driver implementation — see Flexio_Pwm_Ip_UpdatePeriodDuty():
Flexio_Pwm_Ip_SetLowerValue(Base, Channel, (uint8)(DutyCycle - 1U));
Flexio_Pwm_Ip_SetUpperValue(Base, Channel, (uint8)(Period - DutyCycle - 1U));
So the mapping to TIMCMP is:
Lower 8 bits = DutyCycle - 1
Upper 8 bits = Period - DutyCycle - 1
From Flexio_Pwm_Ip_GetPeriod():
Period = Upper + Lower + 2
Period = (DutyCycle - 1) + (Period - DutyCycle - 1) + 2
f_pwm = Input_FlexIO_CLK (prescalled) / Period
Duty(%) = DutyCycle / Period × 100
Example (FLEXIO clock = 160 MHz, prescaler = 16 → 10 MHz timer clock):
Period = 200 ticks -- f_pwm = 10 MHz / 200 = 50 kHz
Regards,
Daniel
Hello Daniel,
Thank you for the detailed explanation and the frequency formula.
According to the formula:
f_pwm = FlexIO_Input_Clock (after prescaler) / Period
For my configuration:
FlexIO Clock = 160 MHz
Prescaler = 256
Period = 63
I would expect:
f_pwm = 160 MHz / (256 × 63)
= 9.92 kHz
However, when measured on the oscilloscope, the PWM frequency is approximately 3.9 kHz.
Similarly, with:
Prescaler = 16
Period = 200
I measure approximately 20 kHz, whereas the formula predicts 50 kHz if the FlexIO clock is 160 MHz.
Could you please advise:
Is the FlexIO PWM driver using a clock source different from the configured FLEXIO0_CLK?
Is there any additional divider or clock scaling applied internally?
What is the recommended method to verify the actual runtime clock frequency used by the FlexIO PWM timer?
I would like to understand why the measured PWM frequency does not match the frequency calculated using the configured 160 MHz FlexIO clock.
Thank you for your support.
Regards,
Esakki