Using PPI to Generate 8MHZ Signal

Hi,

I'm using the PPI component to generate 8MHz GPIO signal. this signal is an input for power amplifier analog RF transmitter.

While the digital 8MHz signal looks fine, we are noticing some bumps every 40 us in the RF analog signal. when trying to use the SPI clock to create the 8MHz signal the bumps are eliminated and we get a clean signal.

As the PPI input clock is 16MHz, I was wondering if theoretically its capable to create a digital 8MHz signal? that means that the GPIO should be toggled every single clock, is that an overkill in terms of performance for the PPI or should it be able to handle this task?

The bumps were also reproduced with the DK evaluation board to generate the 8MHz signal, see bump in the image below:

Parents Reply Children
  • The slope of it seems even more odd to me, was that somehow intentional from you?

    Are you seeing the same bumps without it being turned off and on this frequently?

    Just noticed that you've added code here in a reply. I'll see if I can reproduce this on my side.

    Regards,

    Elfving

  • Hi,

    the slope is a side-effect of some HW current protection we have, its not a problem for us.

    Thanks 

  • levijo said:

    the slope is a side-effect of some HW current protection we have, its not a problem for us.

    I see. Did you try different frequencies and see if that made the bumps dissapear?

    Would you mind sending me the entire project that reproduces this for you?

    Regards,

    Elfving

  • the following code was isolated from the entire project, and it reproduced the problem. to see the bumps you would have to have our hardware with the RF analog path. We guess that in the digital path it reflects in some jitters or delays but it's hard for us to track with our HW debug tools.

    main.c:

    #include <zephyr/device.h>
    #include <zephyr/drivers/pwm.h>
    #include <zephyr/kernel.h>
    #if defined(CONFIG_CLOCK_CONTROL_NRF)
    #include <zephyr/drivers/clock_control.h>
    #include <zephyr/drivers/clock_control/nrf_clock_control.h>
    #endif /* defined(CONFIG_CLOCK_CONTROL_NRF) */
    #if defined(NRF54L15_XXAA)
    #include <hal/nrf_clock.h>
    #endif /* defined(NRF54L15_XXAA) */
    
    #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(main);
    
    static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));
    
    static int clock_init(void);
    static int setup_pwm(void);
    
    int main(void)
    {
    
    #if defined(CONFIG_CLOCK_CONTROL_NRF)
        clock_init();
    #endif
    
        setup_pwm();
    
        while (true) {
            k_sleep(K_MSEC(1000U));
        }
    
        return 0;
    }
    
    #if defined(CONFIG_CLOCK_CONTROL_NRF)
    static int clock_init(void)
    {
        int err;
        int res;
        struct onoff_manager *clk_mgr;
        struct onoff_client clk_cli;
    
        clk_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
        if (!clk_mgr) {
            LOG_ERR("unable to get the clock manager");
            return -1;
        }
    
        sys_notify_init_spinwait(&clk_cli.notify);
    
        err = onoff_request(clk_mgr, &clk_cli);
        if (err < 0) {
            LOG_ERR("clock request failed (error: %d)", err);
            return -1;
        }
    
        do {
            err = sys_notify_fetch_result(&clk_cli.notify, &res);
            if (!err && res) {
                LOG_ERR("clock could not be started (resone: %d)", res);
                return -1;
            }
        } while (err);
    
    #if defined(NRF54L15_XXAA)
        /* MLTPAN-20 */
        nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_PLLSTART);
    #endif /* defined(NRF54L15_XXAA) */
    
        LOG_INF("HF clock has started");
    
        return 0;
    }
    #endif /* CONFIG_CLOCK_CONTROL_NRF */
    
    static int setup_pwm(void)
    {
        LOG_INF("set PWM");
    
        if (!pwm_is_ready_dt(&pwm_led0)) {
            LOG_ERR("PWM device %s is not ready", pwm_led0.dev->name);
            return -1;
        }
    
        if (pwm_set_dt(&pwm_led0, PWM_NSEC(125U), PWM_NSEC(63U)) != 0) {
            LOG_ERR("failed to set PWM device %s", pwm_led0.dev->name);
            return -1;
        }
    
        return 0;
    }

    nrf5340dk_cpuapp.overlay:

    / {
    	aliases {
    	};
    };
    
    
    &sw_pwm {
    	status = "okay";
    	channel-gpios = <&gpio1 9 PWM_POLARITY_INVERTED>;
    };
    
    &pwm_led0 {
    	pwms = <& sw_pwm 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
    };
    

Related