Skip to content

drivers: pwm: mcux_sctimer: counter stranded when device resumes before first channel config #111888

Description

@jacob-wienecke-nxp

Describe the bug

On frdm_rw612 (NXP RW612 SoC), using the MCUX SCTimer PWM driver
(drivers/pwm/pwm_mcux_sctimer.c), the SCTimer counter
can be left in a state where PWM output does not toggle for ~2 minutes after the
device resumes.

mcux_sctimer_pwm_pm_action() handles PM_DEVICE_ACTION_RESUME by
unconditionally starting the unified counter:

case PM_DEVICE_ACTION_RESUME:
#ifdef CONFIG_PM_DEVICE
    SCTIMER_StartTimer(config->base, kSCTIMER_Counter_U);
#endif

If a resume occurs before any channel has been configured (i.e. before the
first pwm_set_cycles() call), no period match register and no counter-limit
event have been set up yet. The freshly started unified counter therefore
free-runs across its entire 32-bit range with nothing to reset it. A resume happens
at the start of the app even with CONFIG_PM=n

When a channel is subsequently configured, mcux_sctimer_new_channel() programs
the period match via the MCUX SDK (SCTIMER_SetupPwm) but does not clear the
current COUNT value. The SCTimer counter-limit only fires on exact equality
(COUNT == match). If the free-running counter has already advanced past the
newly programmed match value, the limit condition is missed and the counter must
climb all the way to 0xFFFFFFFF and wrap back to 0 before it can hit the
match. Until that wrap occurs the period/pulse events do not fire, so the PWM
output is stuck at its inactive level. On frdm_rw612 the 32-bit counter wraps
after roughly 2 minutes, at which point PWM output resumes normally.

  • Target platform: frdm_rw612 (NXP RW612 SoC). This is the only platform on
    which the failure has been confirmed.
  • Diagnosis: the stall window opens PM_DEVICE_ACTION_RESUME is
    delivered ahead of the first channel configuration.

Regression

  • This is a regression.

Steps to reproduce

Use the in-tree
samples/basic/blinky_pwm
sample. frdm_rw612 enables the &sctimer controller and defines a
pwm-0 = &sctimer alias, but it has no pwm-leds node and no pwm-led0 alias,
and the sample ships no frdm_rw612 overlay — so a consumer must be supplied to
exercise the driver at all (and to create the resume-before-first-channel
ordering).

  1. Add samples/basic/blinky_pwm/boards/frdm_rw612.overlay:

    / {
        pwmleds {
            compatible = "pwm-leds";
            pwm_led0: pwm_led0 {
                pwms = <&sctimer 0 PWM_USEC(100) PWM_POLARITY_NORMAL>;
            };
        };
    
        aliases {
            pwm-led0 = &pwm_led0;
        };
    };
    
  2. Build and flash the sample with PM enabled:

    west build -b frdm_rw612 samples/basic/blinky_pwm -- -DCONFIG_PM=y -DCONFIG_PM_DEVICE=y
    west flash
    
  3. The SCTimer device resumes before the sample issues its first
    pwm_set_cycles(). Observe (scope/logic analyzer on the PWM output) that the
    output is held at its inactive level and does not toggle for ~2 minutes,
    after which the 32-bit counter wraps and PWM output begins normally.

Relevant log output

Impact

Functional Limitation – Some features not working as expected, but system usable.

Environment

  • OS: Windows
  • Toolchain: Zephyr SDK
  • Commit SHA or Version used: Zephyr v4.4

Additional Context

Fixed upstream by guarding the resume-path start so the counter only runs once at
least one channel is active:

case PM_DEVICE_ACTION_RESUME:
#ifdef CONFIG_PM_DEVICE
    if (data->pwm_channel_active) {
        SCTIMER_StartTimer(config->base, kSCTIMER_Counter_U);
    }
#endif

Metadata

Metadata

Labels

BackportBackport PR and backport failure issuesplatform: NXPNXP

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions