NRF3540: Duty cycle accuracy

Hello,

I am working on a project using zephyr as well as the nrf5340 MCU. For this test, I am on the nrf5340dk.

My application requires I drive a PWM at 125khz. In my device tree, I setup the PWM as follows:

pwm0_default: pwm0_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 6)>;
nordic,drive-mode = <NRF_DRIVE_S0H1>;
};
};

pwm0_sleep: pwm0_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 6)>;
};
};

With:

&pwm0 {
pinctrl-0 = <&pwm0_default>;
pinctrl-1 = <&pwm0_sleep>;
pinctrl-names = "default", "sleep";
};

And:

The device application that uses it:

pwms = <&pwm0 0 PWM_USEC(8) PWM_POLARITY_NORMAL>;

Additionally, I have a 32MHz external crystal.

In this instance, I have an application that effectively just turns on this PWM and nothing else.


If I hook up a logic analyzer to the pin, and I analyze the PWM , there is a "very" slight oscillation in the duty cycle.

Effectively, I fall from 49.93% duty cycle to 50% duty cycle up to 51.07% duty cycle, and back down. It is not necessarily periodic.

I wouldn't expect the duty cycle to be 50% exactly at all times, but there is concern from our hardware team that this noise is causing problems down the line for our application.


I want to do my due diligence and ask, is there anything related to registers that I could be missing to make the duty cycle cleaner? Or, alternatively, if there is a drive-mode that could potentially make the signal cleaner? Not sure if there is much to do, here.

I can provide more information as needed.

  • I believe this ticket can be marked as resolved! I was able to find a different example in zephyr that fixed my issue. For others who may be experiencing a similar issue, the solution I found had to do with how the clock was being controlled. I found this solution to be my fix, but if you search for various parts of this solution through the zephyr library, you can find other examples.

    static int err;
    static int res;
    static struct onoff_manager *clk_mgr;
    static struct onoff_client clk_cli;

    static void clock_init(void)
    {

    clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
    if (!clk_mgr) {
    printk("Unable to get the Clock manager\n");
    return;
    }

    sys_notify_init_spinwait(&clk_cli.notify);

    err = onoff_request(clk_mgr, &clk_cli);
    if (err < 0) {
    printk("Clock request failed: %d\n", err);
    return;
    }

    do {
    err = sys_notify_fetch_result(&clk_cli.notify, &res);
    if (!err && res) {
    printk("Clock could not be started: %d\n", res);
    return;
    }
    } while (err);

    printk("Clock has started\n");
    }
Related