Hi,
I’m trying to generate a PWM signal directly using the nRF5340’s PWM peripheral registers (not using Zephyr’s pwm_dt_spec or driver API).
The LED turns ON correctly, so the PWM peripheral is initialized and running, but the duty cycle doesn’t change dynamically — it stays at the first value even though I update the sequence buffer in code.
Here’s the simplified code I’m using:
#include <zephyr/kernel.h>
#include <hal/nrf_pwm.h>
#include <hal/nrf_gpio.h>
static NRF_PWM_Type *pwm = NRF_PWM0;
static uint16_t seq_values[2];
static uint16_t duty = 0;
static int dir = 200;
void pwm_init(void)
{
pwm->ENABLE = 0;
pwm->PSEL.OUT[0] = 25; // P0.25
pwm->PSEL.OUT[1] = 26; // P0.26
pwm->MODE = PWM_MODE_UPDOWN_Up;
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1;
pwm->COUNTERTOP = 16000;
pwm->LOOP = 0;
pwm->DECODER = (PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) |
(PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
pwm->SEQ[0].PTR = (uint32_t)&seq_values[0];
pwm->SEQ[0].CNT = 2;
pwm->SEQ[0].REFRESH = 0;
pwm->SEQ[0].ENDDELAY = 0;
pwm->ENABLE = 1;
}
void pwm_update(uint16_t duty1, uint16_t duty2)
{
seq_values[0] = duty1;
seq_values[1] = duty2;
pwm->TASKS_SEQSTART[0] = 1; // restart sequence
}
int main(void)
{
pwm_init();
while (1)
{
duty += dir;
if (duty >= 16000) dir = -200;
if (duty <= 0) dir = 200;
pwm_update(duty, 16000 - duty);
k_msleep(20);
}
}
The LED stays ON continuously — it doesn’t fade in/out as expected.
I am using nRf5340 Audio DK and SDK version 2.9
Am I missing any register configuration (like SEQ[0].REFRESH or LOOP) for dynamic updates?