I have nrf5340 DK board with NrfConnectSDK with zephyr. I have built it using the Nrfxpwm driver because I want to get to all four channel in the first pmw instance. I have trouble sending the PWM signals out pins P0.23 and P0.22

I started with the pwm_led example and merged some code from the SDK17 Pwm driver and it comiples and runs fine.  I have a 16 khz period and a 50% duty cycle and if I put it on pins

4,5,6,7  things work just fine.  but when i try to put it on p0.23 the processor starts rebooting.  I know P0.23 is a push button but I do not care about the button.  If i put the pwm output on P0.22 it goes from 3.0 to 1.3 volts.  it will not go to ground.  now on the nrf5340 DK board it says UART2  RX is using p0.22 .  I tried to disable uart2 in my .overlay file with

&uart2 {
status = "disabled";
};

but there was no change on p0.22.

Any help would be much appreciated.

thanks

phil

Parents
  •   but when i try to put it on p0.23 the processor starts rebooting. 

    Processor rebooting makes me think that it could either be a hardfault or an error handler in the application. Can you grep the whole project for sys_reboot and put breakpoints on all of them. Run your code in debug mode and see if any breakpoint hits. You will then get the context of the issue and it would be easier to get a workaround for that. If no breakpoint is hit, then I am not sure why PWM configuring to a certain pin would cause the core to reboot.

  • I decided to send you a simple version of my project.  If you can run it on the nrf5340 DK board and check to see if P0.22 goes all the way ground. this makes the question pretty simple.  load my application on the nrf5340 DK board and see if all four PWM channels reach ground.

    thanks, 

    phil

    
    #include <stdio.h>
    #include <string.h>
    #include <nrfx_pwm.h>
    //#include <zephyr.h>
    
    
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <errno.h>
    #include <zephyr/drivers/led.h>
    #include <zephyr/sys/util.h>
    #include <zephyr/kernel.h>
    
    // Use Zephyr macro to get access to the LED0 on the board
    #define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
    
    // Use nrfx to create a PWM instance which we will connect to the LED0 later
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    nrf_pwm_values_individual_t seq_values[] = {0, 0, 0, 0};
    nrf_pwm_sequence_t const seq =
    {
        .values.p_individual = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };
    
    static void demo1_handler(nrfx_pwm_evt_type_t event_type)
    {
        if (event_type == NRFX_PWM_EVT_FINISHED)
        {
            uint8_t channel    = 1;
            
    
            uint16_t * p_channels = (uint16_t *)&seq_values;
            uint16_t value = p_channels[channel];
            
            p_channels[channel] = 500 | 1 <<15;
    
            
        }
    }
    // Set duty cycle between 0 and 100%
    void pwm_update_duty_cycle(uint16_t duty_cycle)
    {
        
        // Check if value is outside of range. If so, set to 100%
        if(duty_cycle >= 1000)
        {
            seq_values->channel_0 = 1000;
        }
        else
        {
            printf("duty cycle %d\n",duty_cycle);
            seq_values->channel_0 = duty_cycle;
    		seq_values->channel_1 = duty_cycle/2;
    		seq_values->channel_2 = duty_cycle/4;
    		seq_values->channel_3 = duty_cycle/8;
        }
        
        nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP);
    }
    
    static void pwm_init(void)
    {
        nrfx_pwm_config_t const config0 =
        {
            .output_pins =
            {
                9,             // channel 0 now connected to LED0
                8,      
                4,    // channel 2
        //       22            // channel 3
                5
            },
            .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
            .base_clock   = NRF_PWM_CLK_16MHz,
            .count_mode   = NRF_PWM_MODE_UP,        ///< Up counter (edge-aligned PWM duty cycle).,
            .top_value    = 1000,
            .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
    
    	//uint32_t out_pins={28,8,21,4};
    	//nrf_pwm_pins_set	(&m_pwm0,out_pins);
    
        // Init PWM without error handler
        //nrfx_pwm_init(&m_pwm0, &config0, demo1_handler, NULL);
        nrfx_pwm_init(&m_pwm0, &config0, NULL, NULL);
    	
    
        
    }
    
    
    int main(void)
    {
    
        // Start clock for accurate frequencies
        NRF_CLOCK->TASKS_HFCLKSTART = 1; 
        // Wait for clock to start
        while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) 
            ;
        
        pwm_init();
    
    
    #if 0
        for (;;)
        {
            for(int i = 0; i <= 100; i++)
            {
      //          k_msleep(10);
                k_sleep(K_MSEC(10));
                pwm_update_duty_cycle(i);
            }
        }
    	#endif 
           printf("duty cycle\n");
    	   pwm_update_duty_cycle(500);
    }
    
    
    /** @} */
    phil_led_pwm.zip

Reply
  • I decided to send you a simple version of my project.  If you can run it on the nrf5340 DK board and check to see if P0.22 goes all the way ground. this makes the question pretty simple.  load my application on the nrf5340 DK board and see if all four PWM channels reach ground.

    thanks, 

    phil

    
    #include <stdio.h>
    #include <string.h>
    #include <nrfx_pwm.h>
    //#include <zephyr.h>
    
    
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <errno.h>
    #include <zephyr/drivers/led.h>
    #include <zephyr/sys/util.h>
    #include <zephyr/kernel.h>
    
    // Use Zephyr macro to get access to the LED0 on the board
    #define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
    
    // Use nrfx to create a PWM instance which we will connect to the LED0 later
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    nrf_pwm_values_individual_t seq_values[] = {0, 0, 0, 0};
    nrf_pwm_sequence_t const seq =
    {
        .values.p_individual = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };
    
    static void demo1_handler(nrfx_pwm_evt_type_t event_type)
    {
        if (event_type == NRFX_PWM_EVT_FINISHED)
        {
            uint8_t channel    = 1;
            
    
            uint16_t * p_channels = (uint16_t *)&seq_values;
            uint16_t value = p_channels[channel];
            
            p_channels[channel] = 500 | 1 <<15;
    
            
        }
    }
    // Set duty cycle between 0 and 100%
    void pwm_update_duty_cycle(uint16_t duty_cycle)
    {
        
        // Check if value is outside of range. If so, set to 100%
        if(duty_cycle >= 1000)
        {
            seq_values->channel_0 = 1000;
        }
        else
        {
            printf("duty cycle %d\n",duty_cycle);
            seq_values->channel_0 = duty_cycle;
    		seq_values->channel_1 = duty_cycle/2;
    		seq_values->channel_2 = duty_cycle/4;
    		seq_values->channel_3 = duty_cycle/8;
        }
        
        nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP);
    }
    
    static void pwm_init(void)
    {
        nrfx_pwm_config_t const config0 =
        {
            .output_pins =
            {
                9,             // channel 0 now connected to LED0
                8,      
                4,    // channel 2
        //       22            // channel 3
                5
            },
            .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
            .base_clock   = NRF_PWM_CLK_16MHz,
            .count_mode   = NRF_PWM_MODE_UP,        ///< Up counter (edge-aligned PWM duty cycle).,
            .top_value    = 1000,
            .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
    
    	//uint32_t out_pins={28,8,21,4};
    	//nrf_pwm_pins_set	(&m_pwm0,out_pins);
    
        // Init PWM without error handler
        //nrfx_pwm_init(&m_pwm0, &config0, demo1_handler, NULL);
        nrfx_pwm_init(&m_pwm0, &config0, NULL, NULL);
    	
    
        
    }
    
    
    int main(void)
    {
    
        // Start clock for accurate frequencies
        NRF_CLOCK->TASKS_HFCLKSTART = 1; 
        // Wait for clock to start
        while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) 
            ;
        
        pwm_init();
    
    
    #if 0
        for (;;)
        {
            for(int i = 0; i <= 100; i++)
            {
      //          k_msleep(10);
                k_sleep(K_MSEC(10));
                pwm_update_duty_cycle(i);
            }
        }
    	#endif 
           printf("duty cycle\n");
    	   pwm_update_duty_cycle(500);
    }
    
    
    /** @} */
    phil_led_pwm.zip

Children
  • i found this note in the nordic documentation for the nrf5340 dk board.

    it says P0.22 is used by UART2.  maybe that is a problem if something in my devicetree is enabling UART 2 ???

    Some of the signals are also available on connectors P7, P8, P9, P10, P11, and P12, which are on the bottom side of the DK. By mounting pin lists on the connector footprints, the nRF5340 DK can be used as a shield for Arduino motherboards2 or other boards that follow the Arduino standard. For easy access to GPIO, power, and ground, the signals can also be found on the through-hole connectors P13–P17. Note: Some pins have default settings: • P0.00 and P0.01 are used for the 32.768 kHz crystal and are not available on the connectors. For more information, see 32.768 kHz crystal on page 24. • P0.19, P0.20, P0.21, and P0.22 are used by the UART connected to the interface MCU. For more information, see Virtual COM port on page 7. • P0.02 and P0.03 are by default used by NFC1 and NFC2. For more information, see NFC antenna interface on page 27. • P0.08–P0.09 and P0.23–P0.24 are by default connected to the buttons and P0.28–P0.31 are connected to the LEDs. For more information, see Buttons and LEDs on page 23. • P0.13–P0.18 are by default connected to the external memory. For more information, see External memory on page 20. When the nRF5340 DK is used as a shield together with an Arduino standard motherboard, the Arduino signals are routed as shown in the following figure. 2 Only 3.3 V Arduino boards.

  • Good point, but it is not uart2 in our case but instead uart0 that is connected to this pin.

    weightwatcherphil said:
    it says P0.22 is used by UART2.  maybe that is a problem if something in my devicetree is enabling UART 2 ???

    I can see it clearly that the UART2 is disabled in the devicetree in the final built. 

    I do not know what it says UART_2 instance is connected to those pins, but any UART instance can be connected to those pins but those pins are hardwired to the debugger chip that emulates VCOM port. Looking at the device tree.

    	chosen {
    		zephyr,console = &uart0;
    		zephyr,shell-uart = &uart0;
    		zephyr,uart-mcumgr = &uart0;
    		zephyr,bt-mon-uart = &uart0;
    		zephyr,bt-c2h-uart = &uart0;
    		zephyr,bt-hci-rpmsg-ipc = &ipc0;
    		nordic,802154-spinel-ipc = &ipc0;
    		zephyr,ieee802154 = &ieee802154;
    	};
    
    
    	&uart0 {
    		status = "okay";
    		current-speed = <115200>;
    		pinctrl-0 = <&uart0_default>;
    		pinctrl-1 = <&uart0_sleep>;
    		pinctrl-names = "default", "sleep";
    	};
    
    	uart0_default: uart0_default {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 0, 20)>,
    				<NRF_PSEL(UART_RTS, 0, 19)>;
    		};
    		group2 {
    			psels = <NRF_PSEL(UART_RX, 0, 22)>,
    				<NRF_PSEL(UART_CTS, 0, 21)>;
    			bias-pull-up;
    		};
    	};

    Which translates to using serial console and enabling logging will connect the UART0 to pins 19,20,21 and 22. Which might be the root cause in your case.

  • just to make sure I follow this.  you found the device tree information in the file

    C:\ncs\v2.4.0\zephyr\boards\arm\nrf5340dk_nrf5340\nrf5340_cpuapp_common-pinctrl.dtsi

    /*
    * Copyright (c) 2022 Nordic Semiconductor
    * SPDX-License-Identifier: Apache-2.0
    */

    &pinctrl {
    i2c1_default: i2c1_default {
    group1 {
    psels = <NRF_PSEL(TWIM_SDA, 1, 2)>,
    <NRF_PSEL(TWIM_SCL, 1, 3)>;
    };
    };

    i2c1_sleep: i2c1_sleep {
    group1 {
    psels = <NRF_PSEL(TWIM_SDA, 1, 2)>,
    <NRF_PSEL(TWIM_SCL, 1, 3)>;
    low-power-enable;
    };
    };

    uart0_default: uart0_default {
    group1 {
    psels = <NRF_PSEL(UART_TX, 0, 20)>,
    <NRF_PSEL(UART_RTS, 0, 19)>;
    };
    group2 {
    psels = <NRF_PSEL(UART_RX, 0, 22)>,
    <NRF_PSEL(UART_CTS, 0, 21)>;
    bias-pull-up;
    };
    };

    uart0_sleep: uart0_sleep {
    group1 {
    psels = <NRF_PSEL(UART_TX, 0, 20)>,
    <NRF_PSEL(UART_RX, 0, 22)>,
    <NRF_PSEL(UART_RTS, 0, 19)>,
    <NRF_PSEL(UART_CTS, 0, 21)>;
    low-power-enable;
    };
    };

    pwm0_default: pwm0_default {
    group1 {
    psels = <NRF_PSEL(PWM_OUT0, 0, 28)>;
    };
    };

    pwm0_sleep: pwm0_sleep {
    group1 {
    psels = <NRF_PSEL(PWM_OUT0, 0, 28)>;
    low-power-enable;
    };
    };

    qspi_default: qspi_default {
    group1 {
    psels = <NRF_PSEL(QSPI_SCK, 0, 17)>,
    <NRF_PSEL(QSPI_IO0, 0, 13)>,
    <NRF_PSEL(QSPI_IO1, 0, 14)>,
    <NRF_PSEL(QSPI_IO2, 0, 15)>,
    <NRF_PSEL(QSPI_IO3, 0, 16)>,
    <NRF_PSEL(QSPI_CSN, 0, 18)>;
    nordic,drive-mode = <NRF_DRIVE_H0H1>;
    };
    };

    qspi_sleep: qspi_sleep {
    group1 {
    psels = <NRF_PSEL(QSPI_SCK, 0, 17)>,
    <NRF_PSEL(QSPI_IO0, 0, 13)>,
    <NRF_PSEL(QSPI_IO1, 0, 14)>,
    <NRF_PSEL(QSPI_IO2, 0, 15)>,
    <NRF_PSEL(QSPI_IO3, 0, 16)>;
    low-power-enable;
    };
    group2 {
    psels = <NRF_PSEL(QSPI_CSN, 0, 18)>;
    low-power-enable;
    bias-pull-up;
    };
    };

    uart1_default: uart1_default {
    group1 {
    psels = <NRF_PSEL(UART_TX, 1, 1)>;
    };
    group2 {
    psels = <NRF_PSEL(UART_RX, 1, 0)>;
    bias-pull-up;
    };
    };

    uart1_sleep: uart1_sleep {
    group1 {
    psels = <NRF_PSEL(UART_TX, 1, 1)>,
    <NRF_PSEL(UART_RX, 1, 0)>;
    low-power-enable;
    };
    };

    spi4_default: spi4_default {
    group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    <NRF_PSEL(SPIM_MISO, 1, 14)>,
    <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    };
    };

    spi4_sleep: spi4_sleep {
    group1 {
    psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
    <NRF_PSEL(SPIM_MISO, 1, 14)>,
    <NRF_PSEL(SPIM_MOSI, 1, 13)>;
    low-power-enable;
    };
    };

    };

Related