Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

need example for nrfx_gpiote_*

I'm trying to get acquainted with the NRFX_GPIOTE driver by writing a program to do the following:

initialize TIMER to generate three compare events:

  • channel0 compare event triggers a set event on a gpio pin
  • channel1 compare event triggers a clear event on the same gpio pin
  • channel2 compare events reset the timer

...all done via the PPI, of course.  And since the migration document recommends it, I'd like to use nrfx_ functions wherever possible.

My stumbling blocks:

  • The led_blinking gpiote example in the nRF5_SDK_15.0.0 shows how to toggle a GPIO pin, but not how to set it using one PPI channel and clear it using another.  Do you use the nrfx_gpiote_out_init() function for this?  If so, do you initialize the same GPIO with two different configurations?
  • It's not clear where I can use nrfx_ methods and where I should (or must) use nrf_drv_ methods.  
  • In the sketch that I've started, the linker complains that all the nrfx_xxx functions are undefined.  What must I do to get them loaded?

A code example, updated for nrfx_ methods, would be super useful!  Here's the framework I'm using for my main() function:

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
const int m_gpio_pin = 13;

int main() {
  uint32_t err_code;
  
  err_code = NRF_LOG_INIT(NULL);
  APP_ERROR_CHECK(err_code);
  NRF_LOG_DEFAULT_BACKENDS_INIT();

  err_code = nrf_pwr_mgmt_init();
  APP_ERROR_CHECK(err_code);

  peripherals_init();            // ready, set...
  nfrx_timer_enable(&m_timer);   // ... go!
  
  while(1) {
    nrf_pwr_mgmt_run();
    NRF_LOG_FLUSH();
  }
}

I'd be happy to show what I've got for peripherals_init(), but chances are good that I'm overthinking it.

Parents
  • Hi,

    The led_blinking gpiote example in the nRF5_SDK_15.0.0 shows how to toggle a GPIO pin, but not how to set it using one PPI channel and clear it using another.  Do you use the nrfx_gpiote_out_init() function for this?  If so, do you initialize the same GPIO with two different configurations?

    Yes, you use nrf_drv_gpiote_out_init() for this. No, we don't initialize the same GPIO with two different configurations.

    If you take a look at the GPIOTE register overview, you can see that we have 3 different types of tasks we can trigger, OUT, SET and CLEAR. So we can use nrf_drv_gpiote_set_task_addr_get() for the SET address, and nrf_drv_gpiote_clr_task_addr_get() for the CLEAR address.

    Snippet:

    int32_t compare_evt_addr_clear = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE1);
    uint32_t gpiote_task_addr_clear = nrfx_gpiote_clr_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
    err_code = nrfx_ppi_channel_assign(ppi_channel_clear, compare_evt_addr_clear, gpiote_task_addr_clear);
    APP_ERROR_CHECK(err_code);

    It's not clear where I can use nrfx_ methods and where I should (or must) use nrf_drv_ methods.  

    Almost all nrf_drv_ methods has been replaced by nrfx. Take a look in the components/drivers_nrf folder in SDK 15 to see what drivers that are not replaced with nrfx yet. To find the corresponding nrfx function, you can in SDK 15 in your IDE just right-click on the nrf_drv function, click on 'Go to definition', and if there is an nrfx implementation, you will see the macro for forwarding to the new implementation there.

    In the sketch that I've started, the linker complains that all the nrfx_xxx functions are undefined.  What must I do to get them loaded?

    What IDE/Toolchain are you using? Make sure that path to the nrfx folder is included in your toolchain, and that sdk_config.h is configured correctly. Take a look at some of the peripheral example in SDK 15, to see how it's done there.

    NRFX_GPIOTE driver by writing a program to do the following:

    Here is some example code that should do what you describe. You can copy-paste it into the peripheral\template_project in SDK 15 to test it.

    /**
     * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /** @file
    * @brief Example template project.
    * @defgroup nrf_templates_example Example Template
    *
    */
    
    #include <stdbool.h>
    #include <stdint.h>
    
    #include "nrf.h"
    #include "nordic_common.h"
    #include "boards.h"
    #include "nrfx_timer.h"
    #include "app_error.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrfx_ppi.h"
    #include "nrfx_gpiote.h"
    
    
    
    static const nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(0);
    
    #define GPIO_OUTPUT_PIN_NUMBER LED_2
    
    //const int m_gpio_pin = 13; 
    
    
    /**
     * @brief Handler for timer events.
     */
    void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
    
    
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE2:
            nrf_gpio_pin_toggle(LED_4);  // Led indicating that we have "reset the timer"
                
                break;
    
            default:
                //Do nothing.
                break;
        }
    }
    
    static void led_blinking_ppi_setup()
    {
        nrf_ppi_channel_t ppi_channel_set;
        nrf_ppi_channel_t ppi_channel_clear;
    
        ret_code_t err_code;
        nrfx_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    
        err_code = nrfx_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER, &config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_ppi_channel_alloc(&ppi_channel_set);
        APP_ERROR_CHECK(err_code);
      
        err_code = nrfx_ppi_channel_alloc(&ppi_channel_clear);
        APP_ERROR_CHECK(err_code);
    
    
        uint32_t compare_evt_addr_set = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE0);
        uint32_t gpiote_task_addr_set = nrfx_gpiote_set_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
        uint32_t compare_evt_addr_clear = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE1);
        uint32_t gpiote_task_addr_clear = nrfx_gpiote_clr_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
    
    
        err_code = nrfx_ppi_channel_assign(ppi_channel_set, compare_evt_addr_set, gpiote_task_addr_set);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_ppi_channel_assign(ppi_channel_clear, compare_evt_addr_clear, gpiote_task_addr_clear);
        APP_ERROR_CHECK(err_code);
    
    
    
        err_code = nrfx_ppi_channel_enable(ppi_channel_set);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_ppi_channel_enable(ppi_channel_clear);
        APP_ERROR_CHECK(err_code);
    
    
        nrfx_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER);
    }
    
    static void configure_timer()
    {
        ret_code_t err_code;
    
        uint32_t time_ms_trigger_set_event   = 3000; // Time(in miliseconds) after start
        uint32_t time_ms_trigger_clear_event = 7000; // Time(in miliseconds) after start
        uint32_t time_ms_reset_event         = 12000; //Time(in miliseconds) after start
    
    
        //Configure Timer
        nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrfx_timer_init(&m_timer, &timer_cfg, timer_led_event_handler);
        APP_ERROR_CHECK(err_code);
    
        uint32_t time_ticks_set_event   = nrfx_timer_ms_to_ticks(&m_timer, time_ms_trigger_set_event);
        uint32_t time_ticks_clear_event = nrfx_timer_ms_to_ticks(&m_timer, time_ms_trigger_clear_event);
        uint32_t time_ticks_reset_event = nrfx_timer_ms_to_ticks(&m_timer, time_ms_reset_event);
       
        nrfx_timer_compare(
             &m_timer, NRF_TIMER_CC_CHANNEL0, time_ticks_set_event, false);
    
        nrfx_timer_compare(
             &m_timer, NRF_TIMER_CC_CHANNEL1, time_ticks_clear_event, false); 
                
        nrfx_timer_extended_compare( //Set true to trigger interrupt for the event.
             &m_timer, NRF_TIMER_CC_CHANNEL2, time_ticks_reset_event, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, false);
    
        nrfx_timer_enable(&m_timer);
    
    }
    
    
    
    /**@brief Application main function.
     */
    int main(void)
    {
        uint32_t err_code;
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
      
        nrf_gpio_cfg_output(LED_4);
      
        err_code = nrfx_gpiote_init();
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    
        led_blinking_ppi_setup();
        configure_timer();
        
        while(1)
        {
          NRF_LOG_FLUSH();
          nrf_pwr_mgmt_run();
        }
    }
    

Reply
  • Hi,

    The led_blinking gpiote example in the nRF5_SDK_15.0.0 shows how to toggle a GPIO pin, but not how to set it using one PPI channel and clear it using another.  Do you use the nrfx_gpiote_out_init() function for this?  If so, do you initialize the same GPIO with two different configurations?

    Yes, you use nrf_drv_gpiote_out_init() for this. No, we don't initialize the same GPIO with two different configurations.

    If you take a look at the GPIOTE register overview, you can see that we have 3 different types of tasks we can trigger, OUT, SET and CLEAR. So we can use nrf_drv_gpiote_set_task_addr_get() for the SET address, and nrf_drv_gpiote_clr_task_addr_get() for the CLEAR address.

    Snippet:

    int32_t compare_evt_addr_clear = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE1);
    uint32_t gpiote_task_addr_clear = nrfx_gpiote_clr_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
    err_code = nrfx_ppi_channel_assign(ppi_channel_clear, compare_evt_addr_clear, gpiote_task_addr_clear);
    APP_ERROR_CHECK(err_code);

    It's not clear where I can use nrfx_ methods and where I should (or must) use nrf_drv_ methods.  

    Almost all nrf_drv_ methods has been replaced by nrfx. Take a look in the components/drivers_nrf folder in SDK 15 to see what drivers that are not replaced with nrfx yet. To find the corresponding nrfx function, you can in SDK 15 in your IDE just right-click on the nrf_drv function, click on 'Go to definition', and if there is an nrfx implementation, you will see the macro for forwarding to the new implementation there.

    In the sketch that I've started, the linker complains that all the nrfx_xxx functions are undefined.  What must I do to get them loaded?

    What IDE/Toolchain are you using? Make sure that path to the nrfx folder is included in your toolchain, and that sdk_config.h is configured correctly. Take a look at some of the peripheral example in SDK 15, to see how it's done there.

    NRFX_GPIOTE driver by writing a program to do the following:

    Here is some example code that should do what you describe. You can copy-paste it into the peripheral\template_project in SDK 15 to test it.

    /**
     * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /** @file
    * @brief Example template project.
    * @defgroup nrf_templates_example Example Template
    *
    */
    
    #include <stdbool.h>
    #include <stdint.h>
    
    #include "nrf.h"
    #include "nordic_common.h"
    #include "boards.h"
    #include "nrfx_timer.h"
    #include "app_error.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrfx_ppi.h"
    #include "nrfx_gpiote.h"
    
    
    
    static const nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(0);
    
    #define GPIO_OUTPUT_PIN_NUMBER LED_2
    
    //const int m_gpio_pin = 13; 
    
    
    /**
     * @brief Handler for timer events.
     */
    void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
    
    
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE2:
            nrf_gpio_pin_toggle(LED_4);  // Led indicating that we have "reset the timer"
                
                break;
    
            default:
                //Do nothing.
                break;
        }
    }
    
    static void led_blinking_ppi_setup()
    {
        nrf_ppi_channel_t ppi_channel_set;
        nrf_ppi_channel_t ppi_channel_clear;
    
        ret_code_t err_code;
        nrfx_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    
        err_code = nrfx_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER, &config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_ppi_channel_alloc(&ppi_channel_set);
        APP_ERROR_CHECK(err_code);
      
        err_code = nrfx_ppi_channel_alloc(&ppi_channel_clear);
        APP_ERROR_CHECK(err_code);
    
    
        uint32_t compare_evt_addr_set = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE0);
        uint32_t gpiote_task_addr_set = nrfx_gpiote_set_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
        uint32_t compare_evt_addr_clear = nrfx_timer_event_address_get(&m_timer, NRF_TIMER_EVENT_COMPARE1);
        uint32_t gpiote_task_addr_clear = nrfx_gpiote_clr_task_addr_get(GPIO_OUTPUT_PIN_NUMBER);
    
    
    
        err_code = nrfx_ppi_channel_assign(ppi_channel_set, compare_evt_addr_set, gpiote_task_addr_set);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_ppi_channel_assign(ppi_channel_clear, compare_evt_addr_clear, gpiote_task_addr_clear);
        APP_ERROR_CHECK(err_code);
    
    
    
        err_code = nrfx_ppi_channel_enable(ppi_channel_set);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_ppi_channel_enable(ppi_channel_clear);
        APP_ERROR_CHECK(err_code);
    
    
        nrfx_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER);
    }
    
    static void configure_timer()
    {
        ret_code_t err_code;
    
        uint32_t time_ms_trigger_set_event   = 3000; // Time(in miliseconds) after start
        uint32_t time_ms_trigger_clear_event = 7000; // Time(in miliseconds) after start
        uint32_t time_ms_reset_event         = 12000; //Time(in miliseconds) after start
    
    
        //Configure Timer
        nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrfx_timer_init(&m_timer, &timer_cfg, timer_led_event_handler);
        APP_ERROR_CHECK(err_code);
    
        uint32_t time_ticks_set_event   = nrfx_timer_ms_to_ticks(&m_timer, time_ms_trigger_set_event);
        uint32_t time_ticks_clear_event = nrfx_timer_ms_to_ticks(&m_timer, time_ms_trigger_clear_event);
        uint32_t time_ticks_reset_event = nrfx_timer_ms_to_ticks(&m_timer, time_ms_reset_event);
       
        nrfx_timer_compare(
             &m_timer, NRF_TIMER_CC_CHANNEL0, time_ticks_set_event, false);
    
        nrfx_timer_compare(
             &m_timer, NRF_TIMER_CC_CHANNEL1, time_ticks_clear_event, false); 
                
        nrfx_timer_extended_compare( //Set true to trigger interrupt for the event.
             &m_timer, NRF_TIMER_CC_CHANNEL2, time_ticks_reset_event, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, false);
    
        nrfx_timer_enable(&m_timer);
    
    }
    
    
    
    /**@brief Application main function.
     */
    int main(void)
    {
        uint32_t err_code;
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_DEFAULT_BACKENDS_INIT();
      
        nrf_gpio_cfg_output(LED_4);
      
        err_code = nrfx_gpiote_init();
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    
        led_blinking_ppi_setup();
        configure_timer();
        
        while(1)
        {
          NRF_LOG_FLUSH();
          nrf_pwr_mgmt_run();
        }
    }
    

Children
No Data
Related