nRF54L15 PDM clock runs at ~1/32 of expected (PCLK1M instead of PCLK32M) on a custom board works on DK

nRF54L15 PDM clock runs at ~1/32 of expected (PCLK1M instead of PCLK32M) on a custom board - works on DK

Summary

On a custom nRF54L15 board, the PDM peripheral clock (PDM_CLK) comes out at 20 kHz measured on a logic analyzer, where I expect 1.28 MHz (fs = 16 kHz, RATIO = 80). The PDM PRESCALER register reads 25 (correct), so the divider is right - but the clock source feeding the PDM is ~32x too low: it behaves as if the PDM is sourced from PCLK1M (~1 MHz) instead of PCLK32M (32 MHz).

The same application/driver path works on the nRF54L15-DK. Critically, the stock "known-good" firmware that works on the DK shows the identical ~1/32 clock on this custom board, so this is not specific to my application code.

I'm looking for: what determines whether the PDM gets PCLK32M vs a much lower peripheral clock, and how do I force the 32 MHz peripheral clock (PCLK32M) to the PERI domain / the PDM on a custom board?

Environment

  • nRF Connect SDK v3.3.0 (Zephyr 4.3.99)
  • SoC: nRF54L15 (cpuapp), custom board
  • Zephyr DMIC API → dmic_nrfx_pdm driver, nodes pdm20 and pdm21
  • Mics: Infineon IM72D128V PDM. pdm20 = P1.12 (CLK) / P1.09 (DIN); pdm21 = P1.11 (CLK) / P1.10 (DIN)
  • Requested config: pcm_rate = 16000, 16-bit, min/max_pdm_clk_freq bracket = 1.17–1.70 MHz

Measurements / evidence

Measurement Method Result
PDM_CLK pin frequency logic analyzer on P1.12 20.0 kHz (expected 1.28 MHz)
PDM PRESCALER register nrf_pdm_prescaler_get(NRF_PDM20) at runtime 25 (correct for 1.28 MHz from 32 MHz)
Implied PDM source clock 20 kHz × PRESCALER (×2 per datasheet formula) ~0.5–1.0 MHz (≈ PCLK1M; ~1/32 of PCLK32M)
CPU clock timed a fixed CPU loop against GRTC/k_uptime ~64 MHz (full speed)
HFXO start z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF) + onoff_request, spin-wait starts OK in ~5 ms
dmic_configure() return value 0 (success), blocks flow, no -EINVAL
PCM data drained blocks constant (mic not clocked in its operating range - consistent with a clock far below the IM72D128V's ~1 MHz minimum)

So: divider correct, CPU full speed, HFXO healthy - only the PDM's peripheral source clock is ~1/32 of PCLK32M. The nRF54L15 PDM has only a PRESCALER register (no CLKSELECT/MCLKCONFIG), i.e. it is hardwired to PCLK32M, so there is no DT clock-source to reroute.

What I have already tried (no change to the ~1/32 ratio)

DeviceTree / Kconfig (all matched to the nRF54L15-DK board files):

  • clock-source = "PCLK32M" and "PCLK32M_HFXO" (the latter raised it from ~6 kHz to ~20 kHz, but no further)
  • &clock { status = "okay"; }CONFIG_CLOCK_CONTROL_NRF=y
  • &hfxo { load-capacitors = "internal"; load-capacitance-femtofarad = <…>; }
  • &lfxo { load-capacitors = "internal"; … }
  • &regulators { status = "okay"; } + &vregmain { regulator-initial-mode = <NRF5X_REG_MODE_DCDC>; } + CONFIG_REGULATOR=y
  • &grtc identical to DK (owned-channels, status okay)
  • CONFIG_PM_DEVICE=y, CONFIG_PM_DEVICE_RUNTIME=y
  • PDM clock bracket variations (1.17–1.70 MHz → PRESCALER 25; 380–640 kHz → PRESCALER 63). The output scales exactly with PRESCALER, confirming the divider works and the source is fixed at ~1/32.

Application:

  • Held constant-latency: nrf_sys_event_request_global_constlat() (CONFIG_NRF_SYS_EVENT=y) for the lifetime of capture.
  • Verified CONFIG_CLOCK_CONTROL_NRF=y, CONFIG_REGULATOR=y, DCDC mode, PRESCALER value, HFXO start, CPU speed all in the flashed image.

The key data point

The proto firmware that runs correctly on the nRF54L15-DK (real PDM audio) produces the same ~1/32 PDM clock on this custom board. Same SoC, same SDK, equivalent DT - only the physical board differs.

Questions

  1. On the nRF54L15, what establishes PCLK32M (32 MHz) for a PERI-domain peripheral like the PDM, and under what condition would a PERI peripheral instead be clocked at ~PCLK1M (~1 MHz) - a clean ~1/32?
  2. Is there a board-level dependency (supply/decoupling, DCDC inductor, a specific clock or power-domain request) required for PCLK32M to reach the PERI domain that the DK satisfies but a custom board might not?
  3. The PDM PRESCALER reads 25 and the pin is 20 kHz - can you confirm the CLK = PCLK32M / (2 × PRESCALER) vs CLK = PCLK32M / PRESCALER formula for the nRF54L15, so I can back-compute the true source frequency exactly?
  4. Is there a register I can read at runtime to confirm the actual PCLK32M frequency / the PDM's clock source, to prove whether it is PCLK1M vs PCLK32M?

Minimal DT (PDM + clock/power), matched to the DK

&clock      { status = "okay"; };
&regulators { status = "okay"; };
&vregmain   { status = "okay"; regulator-initial-mode = <NRF5X_REG_MODE_DCDC>; };
&hfxo       { load-capacitors = "internal"; load-capacitance-femtofarad = <8000>; };
&lfxo       { load-capacitors = "internal"; load-capacitance-femtofarad = <17000>; };

&pdm20 {
    status = "okay";
    pinctrl-0 = <&pdm20_default_alt>;   /* CLK P1.12, DIN P1.09 */
    pinctrl-names = "default";
    clock-source = "PCLK32M";
    queue-size = <20>;
};

prj.conf (clock/power relevant):

CONFIG_AUDIO=y
CONFIG_AUDIO_DMIC=y
CONFIG_AUDIO_DMIC_NRFX_PDM=y
CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_REGULATOR=y
CONFIG_NRF_SYS_EVENT=y
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y
Parents
  • Hie,
    Thank you for the detailed information. Please find my responses to each of your questions below:

    On the nRF54L15, what establishes PCLK32M (32 MHz) for a PERI-domain peripheral like the PDM, and under what condition would a PERI peripheral instead be clocked at ~PCLK1M (~1 MHz) - a clean ~1/32?

    PCLK32M for a PERI-domain peripheral is derived from the high-frequency clock, which must be sourced from the HFXO (the 32 MHz crystal). When the peripheral requests its high-frequency clock and HFXO is running and locked, the peripheral is clocked at the full 32 MHz. If HFXO is not locked/available, the system can fall back to a degraded high-frequency source, which results in the peripheral effectively running at roughly 1/32 of the expected rate which is likely possible why you are seeing the PCLK1M equivalent behavior. I would recommened verifying the HFXO lock at runtime (code snippet after answer 4).

    Is there a board-level dependency (supply/decoupling, DCDC inductor, a specific clock or power-domain request) required for PCLK32M to reach the PERI domain that the DK satisfies but a custom board might not?

    Yes. PCLK32M ultimately depends on a correctly functioning HFXO and clean power delivery. On a custom board, please verify:

    • HFXO crystal value and load capacitors match the nRF54L15 requirements.
    • DCDC inductor value and placement are correct.
    • Decoupling capacitors near the power rails are present and correctly placed.

    A fault in the power domain, clock distribution, or HFXO circuit on the custom board can prevent HFXO from locking, which the DK would not exhibit.

    To isolate hardware vs. configuration, I would suggest:

    • Run the same firmware (compiled for the custom board) on a DK.
    • Compare the PDM CLK pin on a scope, DK vs. custom board, side-by-side.

    This will tell us quickly whether the issue is the board or the firmware/configuration.

    The PDM PRESCALER reads 25 and the pin is 20 kHz - can you confirm the CLK = PCLK32M / (2 × PRESCALER) vs CLK = PCLK32M / PRESCALER formula for the nRF54L15, so I can back-compute the true source frequency exactly?

    The correct formula for the nRF54L15 PDM is:

    CLK = PCLK32M / PRESCALER (not the ×2 variant).

    Back-computing your case: with PRESCALER = 25 and an observed PDM CLK of 20 kHz, the implied source is 20 kHz × 25 = 500 kHz. Since this maps to neither 32 MHz nor 1 MHz cleanly, I would recommend double-checking both the measured pin frequency and the PRESCALER value, as the numbers should resolve to a clean PCLK32M (1.28 MHz) or PCLK1M (40 kHz) figure once the source is correct.

    Is there a register I can read at runtime to confirm the actual PCLK32M frequency / the PDM's clock source, to prove whether it is PCLK1M vs PCLK32M?

    Unfortunately, there is no register which can read at runtime to confirm the actual PLK32M frequency or the PDMs clock source. However, you can confirm HFXO status at runtime, which is the most relevant check:

    nrf_clock_hfclk_t src;
    bool running = nrf_clock_is_running(NRF_CLOCK,
    NRF_CLOCK_DOMAIN_HFCLK,
    &src);
    printk("HF running=%d src=%d (0=RC 1=XTAL)\n", running, (int)src);

     
    Run this immediately before starting the PDM. If src is not XTAL, the peripheral is not on HFXO, which would explain the degraded clock.

    Request:

    Could you please share the example/firmware you are working on, so we can try to reproduce the behaviour on our end? That, together with the DK vs. custom board scope comparison, should let us pinpoint the root cause.

    Please feel free to reach out with any further questions.

    Best regards,
    Pallavi

Reply
  • Hie,
    Thank you for the detailed information. Please find my responses to each of your questions below:

    On the nRF54L15, what establishes PCLK32M (32 MHz) for a PERI-domain peripheral like the PDM, and under what condition would a PERI peripheral instead be clocked at ~PCLK1M (~1 MHz) - a clean ~1/32?

    PCLK32M for a PERI-domain peripheral is derived from the high-frequency clock, which must be sourced from the HFXO (the 32 MHz crystal). When the peripheral requests its high-frequency clock and HFXO is running and locked, the peripheral is clocked at the full 32 MHz. If HFXO is not locked/available, the system can fall back to a degraded high-frequency source, which results in the peripheral effectively running at roughly 1/32 of the expected rate which is likely possible why you are seeing the PCLK1M equivalent behavior. I would recommened verifying the HFXO lock at runtime (code snippet after answer 4).

    Is there a board-level dependency (supply/decoupling, DCDC inductor, a specific clock or power-domain request) required for PCLK32M to reach the PERI domain that the DK satisfies but a custom board might not?

    Yes. PCLK32M ultimately depends on a correctly functioning HFXO and clean power delivery. On a custom board, please verify:

    • HFXO crystal value and load capacitors match the nRF54L15 requirements.
    • DCDC inductor value and placement are correct.
    • Decoupling capacitors near the power rails are present and correctly placed.

    A fault in the power domain, clock distribution, or HFXO circuit on the custom board can prevent HFXO from locking, which the DK would not exhibit.

    To isolate hardware vs. configuration, I would suggest:

    • Run the same firmware (compiled for the custom board) on a DK.
    • Compare the PDM CLK pin on a scope, DK vs. custom board, side-by-side.

    This will tell us quickly whether the issue is the board or the firmware/configuration.

    The PDM PRESCALER reads 25 and the pin is 20 kHz - can you confirm the CLK = PCLK32M / (2 × PRESCALER) vs CLK = PCLK32M / PRESCALER formula for the nRF54L15, so I can back-compute the true source frequency exactly?

    The correct formula for the nRF54L15 PDM is:

    CLK = PCLK32M / PRESCALER (not the ×2 variant).

    Back-computing your case: with PRESCALER = 25 and an observed PDM CLK of 20 kHz, the implied source is 20 kHz × 25 = 500 kHz. Since this maps to neither 32 MHz nor 1 MHz cleanly, I would recommend double-checking both the measured pin frequency and the PRESCALER value, as the numbers should resolve to a clean PCLK32M (1.28 MHz) or PCLK1M (40 kHz) figure once the source is correct.

    Is there a register I can read at runtime to confirm the actual PCLK32M frequency / the PDM's clock source, to prove whether it is PCLK1M vs PCLK32M?

    Unfortunately, there is no register which can read at runtime to confirm the actual PLK32M frequency or the PDMs clock source. However, you can confirm HFXO status at runtime, which is the most relevant check:

    nrf_clock_hfclk_t src;
    bool running = nrf_clock_is_running(NRF_CLOCK,
    NRF_CLOCK_DOMAIN_HFCLK,
    &src);
    printk("HF running=%d src=%d (0=RC 1=XTAL)\n", running, (int)src);

     
    Run this immediately before starting the PDM. If src is not XTAL, the peripheral is not on HFXO, which would explain the degraded clock.

    Request:

    Could you please share the example/firmware you are working on, so we can try to reproduce the behaviour on our end? That, together with the DK vs. custom board scope comparison, should let us pinpoint the root cause.

    Please feel free to reach out with any further questions.

    Best regards,
    Pallavi

Children
No Data
Related