PWM Spike on starting/stopping on all channels

Hello there,
we're using multiple pwm-channels of one module of the nRF54L15 for different purposes (multiple motors, h-bridge control; depending on the project).
When the first channel is being turned on or the last channel is being turned off we're seeing spikes on all configured channels - which seems to be unexpected behaviour to us.
We are currently able to work around this (in the h-bridge case just by the correct disable-sequence, in the other case by using different pwm-modules), but still it would be great to have a clean solution here.
Btw - the off spike looks like it changes the drive-mode of the pin, since it's not a clean edge to GND but looks like a discharge curve.
Here is a screenshot of this (I can measure the exact spike width, if needed):
C1 is the inactive pwm-channel, c2 the active one. C3 and C4 are the statically driven gpio's of the h-bridge.
We're on sdk-nrf 3.0.2 and have the following setup:
dts:
/ {
    motor_hbridge_static{
    	compatible = "gpio-leds";
    	motor_common_lowside: motor_common_lowside {
    		gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
    		label = "motor common lowside";
    	};
    	motor1_minus_lowside: motor1_minus_lowside {
    		gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
    		label = "motor1 minus lowside";
    	};
    };
    
    motor_hbridge_pwm{
    	compatible = "pwm-leds";
    	motor_common_highside: motor_common_highside{
    		pwms = <&pwm20 0 PWM_USEC(40) PWM_POLARITY_NORMAL>;
    	};
    	motor1_minus_highside: motor1_minus_highside{
    		pwms = <&pwm20 1 PWM_USEC(40) PWM_POLARITY_NORMAL>;
    	};
    };
};

&pinctrl {
	pwm20_default: pwm20_default {
		group1 {
			psels = <NRF_PSEL(PWM_OUT0, 1, 0)>,
					<NRF_PSEL(PWM_OUT1, 1, 1)>;
			nordic,drive-mode = <NRF_DRIVE_H0H1>;
		};
	};
	pwm20_sleep: pwm20_sleep {
		group1 {
			psels = <NRF_PSEL(PWM_OUT0, 1, 0)>,
					<NRF_PSEL(PWM_OUT1, 1, 1)>;
			low-power-enable;
			nordic,drive-mode = <NRF_DRIVE_H0H1>;
		};
	};
};

&pwm20 {
	status = "okay";
	pinctrl-0 = <&pwm20_default>;
	pinctrl-1 = <&pwm20_sleep>;
	pinctrl-names = "default", "sleep";
	zephyr,pm-device-runtime-auto;
};

Test-code:
void test_fn(void)
{
    motor_start(MOTOR_DRIVE_LEFT, MOTOR_PWM_FREQUENCY_LOW, 5000, 8000);
    k_sleep(K_MSEC(50));
    motor_stop();
    k_sleep(K_SECONDS(2));
}

int motor_start(enum motor_drive drive, enum motor_pwm_frequency freq, uint16_t target_voltage_mv, uint16_t voltage_mv)
{
    motor_stop();
    m_motor.drive                                       = drive;
    motor_set_target_voltage(target_voltage_mv);
    motor_set_pwm_frequency(freq);
    motor_update(voltage_mv, 0);
    return 0;
}

int motor_update(uint16_t voltage_mv, uint16_t current_ma)
{
    uint32_t period = PWM_MSEC(10); // 100 Hz
    if (m_motor.frequency == MOTOR_PWM_FREQUENCY_HIGH) {
        period = PWM_USEC(40); // 25 kHz
    }

    uint32_t pulse = (uint32_t)((uint64_t)((uint64_t)period * (uint64_t)m_motor.target_voltage_mv) / voltage_mv); //) / m_motor.target_voltage_mv;

    enum motor_drive drv = m_motor.drive;
    if (drv != MOTOR_DRIVE_RIGHT && drv != MOTOR_DRIVE_LEFT) {
        LOG_ERR("Wrong drive mode. Not driving...");
        return -ENOTSUP;
    }

    pwm_set_dt(m_bridge_pairs[drv].inactive_pwm, period, 0);
    k_sleep(K_USEC(10));
    pwm_set_dt(m_bridge_pairs[drv].active_pwm, period, pulse);
    k_sleep(K_USEC(10));
    gpio_pin_set_dt(m_bridge_pairs[drv].active_gpio, 1);
    gpio_pin_set_dt(m_bridge_pairs[drv].inactive_gpio, 0);

    LOG_DBG("%s: pulse/period: %d / %d", __FUNCTION__, pulse, period);
    return 0;
}

void motor_stop(void)
{

    gpio_pin_set_dt(m_bridge_pairs[drv].active_gpio, 0);
    gpio_pin_set_dt(m_bridge_pairs[drv].inactive_gpio, 0);  
    k_sleep(K_USEC(10));
    pwm_set_dt(m_bridge_pairs[drv].inactive_pwm, period, 0);
    pwm_set_dt(m_bridge_pairs[drv].active_pwm, period, 0);
}

test_fn is called inside a loop in main.
If you need any further information feel free to ask!
I'll also try to make a minimal test-project to test this with different mcu-targets to see if it's a nRF54L problem or also present on the nRF52840 which we use in our older projects.
Thanks and best regards
Marco
Parents Reply Children
Related