Hi,
I want to produce a pulse with 4 seconds length from p0.25, but i am failed.

Hi,
I want to produce a pulse with 4 seconds length from p0.25, but i am failed.
Hi,
I do not imediately see the problem as you play the sequence 100 times, and that works. Based on that and taht you get 1 second, it seems nrfx_pwm_simple_playback() is only called once from the init functions, but not from the pwm_handler()? Can you confirm by logging or debugging?
PS: There are samples here that can be used as a reference: https://github.com/zephyrproject-rtos/hal_nordic/blob/13ac55b5b52c905642e9c54f069109d188aa5840/nrfx/samples/src/nrfx_pwm
No, From the log you can see nrfx_pwm_simple_playback is called for four times,
p0.25 output sequences[[0] for 100 times only,
But it don`t output sequences[[1~3] .
Hi,
The finished event comes after the first secuence, so you are effectively starting the new before the previous has completed, and this fails. The driver lacks a good way to solve this with this approach, so I woudl instead suggest that you alternate between sequeces as shown in this sample (and update in between). This also has the benefit that interrupt latency does not matter that much, as you prepare for the switch before it actually happens.
PS: there were some issues with this test code that prevented it from running that was easily catched with asserts, so I on a generic basis recommend testing with asserts (CONFIG_ASSERT=y). With that addressed, I the modified code I tested looks like this:
#include <zephyr/sys/printk.h> #include <nrfx_pwm.h> #include <hal/nrf_gpio.h> #include <zephyr/kernel.h> static nrfx_pwm_t m_pwm = NRFX_PWM_INSTANCE(0); static volatile uint8_t current_seq = 0; #define motor_pwr_ctrl NRF_GPIO_PIN_MAP(0, 25) // PWM sequence nrf_pwm_values_individual_t seq_data[4] = { {.channel_0 = 250}, // 20% duty (250/1250) {.channel_0 = 625}, // 50% duty {.channel_0 = 875}, // 70% duty {.channel_0 = 1125} // 90% duty }; static nrf_pwm_sequence_t sequences[4] = { { // sequence0 .values.p_individual = &seq_data[0], .length = NRF_PWM_VALUES_LENGTH(seq_data[0]), .repeats = 0, .end_delay = 0 }, { // sequence1 .values.p_individual = &seq_data[1], .length = NRF_PWM_VALUES_LENGTH(seq_data[1]), .repeats = 0, .end_delay = 0 }, { // sequence2 .values.p_individual = &seq_data[2], .length = NRF_PWM_VALUES_LENGTH(seq_data[2]), .repeats = 0, .end_delay = 0 }, { // sequence3 .values.p_individual = &seq_data[3], .length = NRF_PWM_VALUES_LENGTH(seq_data[3]), .repeats = 0, .end_delay = 0 } }; // PWM handler static void pwm_handler(nrfx_pwm_evt_type_t event_type, void* pContext) { static int count = 0; if (event_type != 0) { printk("count: %i, evt: %i\n", count, event_type); } if (event_type == NRFX_PWM_EVT_FINISHED) { current_seq++; if (current_seq < 4) { printk("pwm_handler,current_seq=%d.\n", current_seq); nrfx_pwm_simple_playback(&m_pwm, &sequences[current_seq], 100, NRFX_PWM_FLAG_STOP);//repeat 100 times =1 second } else { //stop and relese pwm nrfx_pwm_stop(&m_pwm, false); nrfx_pwm_uninit(&m_pwm); printk("nrfx_pwm_uninit.\n"); } } } // PWM initial void init_pwm(void) { nrfx_pwm_config_t config = { .output_pins = { motor_pwr_ctrl, // channel 0 }, .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY, .base_clock = NRF_PWM_CLK_125kHz, .count_mode = NRF_PWM_MODE_UP, .top_value = 1250, // 10ms (1250/125kHz) .load_mode = NRF_PWM_LOAD_INDIVIDUAL, .step_mode = NRF_PWM_STEP_AUTO }; nrfx_pwm_init(&m_pwm, &config, (nrfx_pwm_handler_t)pwm_handler, NULL); current_seq = 0; //play the sequence0 nrfx_pwm_simple_playback(&m_pwm, &sequences[0], 100, NRFX_PWM_FLAG_STOP); //repeat 100 times =1 second } void PWM_Go(void) { #if defined(__ZEPHYR__) IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_PWM0), IRQ_PRIO_LOWEST, pwm_handler, 0, 0); #endif init_pwm(); } int main(void) { PWM_Go(); while (1) { k_sleep(K_FOREVER); } return 0; }
Hi,
The finished event comes after the first secuence, so you are effectively starting the new before the previous has completed, and this fails. The driver lacks a good way to solve this with this approach, so I woudl instead suggest that you alternate between sequeces as shown in this sample (and update in between). This also has the benefit that interrupt latency does not matter that much, as you prepare for the switch before it actually happens.
PS: there were some issues with this test code that prevented it from running that was easily catched with asserts, so I on a generic basis recommend testing with asserts (CONFIG_ASSERT=y). With that addressed, I the modified code I tested looks like this:
#include <zephyr/sys/printk.h> #include <nrfx_pwm.h> #include <hal/nrf_gpio.h> #include <zephyr/kernel.h> static nrfx_pwm_t m_pwm = NRFX_PWM_INSTANCE(0); static volatile uint8_t current_seq = 0; #define motor_pwr_ctrl NRF_GPIO_PIN_MAP(0, 25) // PWM sequence nrf_pwm_values_individual_t seq_data[4] = { {.channel_0 = 250}, // 20% duty (250/1250) {.channel_0 = 625}, // 50% duty {.channel_0 = 875}, // 70% duty {.channel_0 = 1125} // 90% duty }; static nrf_pwm_sequence_t sequences[4] = { { // sequence0 .values.p_individual = &seq_data[0], .length = NRF_PWM_VALUES_LENGTH(seq_data[0]), .repeats = 0, .end_delay = 0 }, { // sequence1 .values.p_individual = &seq_data[1], .length = NRF_PWM_VALUES_LENGTH(seq_data[1]), .repeats = 0, .end_delay = 0 }, { // sequence2 .values.p_individual = &seq_data[2], .length = NRF_PWM_VALUES_LENGTH(seq_data[2]), .repeats = 0, .end_delay = 0 }, { // sequence3 .values.p_individual = &seq_data[3], .length = NRF_PWM_VALUES_LENGTH(seq_data[3]), .repeats = 0, .end_delay = 0 } }; // PWM handler static void pwm_handler(nrfx_pwm_evt_type_t event_type, void* pContext) { static int count = 0; if (event_type != 0) { printk("count: %i, evt: %i\n", count, event_type); } if (event_type == NRFX_PWM_EVT_FINISHED) { current_seq++; if (current_seq < 4) { printk("pwm_handler,current_seq=%d.\n", current_seq); nrfx_pwm_simple_playback(&m_pwm, &sequences[current_seq], 100, NRFX_PWM_FLAG_STOP);//repeat 100 times =1 second } else { //stop and relese pwm nrfx_pwm_stop(&m_pwm, false); nrfx_pwm_uninit(&m_pwm); printk("nrfx_pwm_uninit.\n"); } } } // PWM initial void init_pwm(void) { nrfx_pwm_config_t config = { .output_pins = { motor_pwr_ctrl, // channel 0 }, .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY, .base_clock = NRF_PWM_CLK_125kHz, .count_mode = NRF_PWM_MODE_UP, .top_value = 1250, // 10ms (1250/125kHz) .load_mode = NRF_PWM_LOAD_INDIVIDUAL, .step_mode = NRF_PWM_STEP_AUTO }; nrfx_pwm_init(&m_pwm, &config, (nrfx_pwm_handler_t)pwm_handler, NULL); current_seq = 0; //play the sequence0 nrfx_pwm_simple_playback(&m_pwm, &sequences[0], 100, NRFX_PWM_FLAG_STOP); //repeat 100 times =1 second } void PWM_Go(void) { #if defined(__ZEPHYR__) IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_PWM0), IRQ_PRIO_LOWEST, pwm_handler, 0, 0); #endif init_pwm(); } int main(void) { PWM_Go(); while (1) { k_sleep(K_FOREVER); } return 0; }