This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Timer0 and Timer 1, inconsistent operation

I am using Timer0 and Timer with GPIOTE and PPI to output 2 clocks on 2 pins.

Both timer settings are identical (for troubleshooting). Only timer-0 can be generated at the output pins (pin-1 and pin-2). While timer-1 does not produce any output.

(after spending 10+ hours of testing, and missing a deadline, and checking that both timers are enabled in the sdk_config.h)

any clue what can be the reason ?

/*
  Use Timer with PPI and GPIOTE
  Generates 4MHz timer on output pin
  Timer1 is not outputting
*/

#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "app_error.h"
#include "nrfx_gpiote.h"
#include "nrf_gpiote.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"
#include "nrf_ppi.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"

#include "boards.h"
#include "nrf_drv_gpiote.h"

#define I2S_SCK     NRF_GPIO_PIN_MAP(0,13)
#define I2S_LRCLK   NRF_GPIO_PIN_MAP(0,3)
#define LED_Power   NRF_GPIO_PIN_MAP(1,9)

// Create variable to hold error values
ret_code_t err_code;

// Create timer instance
const nrf_drv_timer_t Timer_0 = NRF_DRV_TIMER_INSTANCE(0);
const nrf_drv_timer_t Timer_1 = NRF_DRV_TIMER_INSTANCE(1);

// Create Timer ISR handler
void Timer_0_handler(nrf_timer_event_t event_type, void* p_context)
{
}

void Timer_1_handler(nrf_timer_event_t event_type, void* p_context)
{
}

// A function to initialize and set everything for the timers with PPI and GPIOTE
static void Initialize_Timer_PPI_GPIOTE(void)
{
//NRF_CLOCK->TASKS_HFCLKSTART = 1;
//    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
//    {
//        // Wait for clock to start
//    }

    // Configure timer as counter, 64 counts at 4MHz
    nrf_drv_timer_config_t Timer_0_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    Timer_0_cfg.frequency = NRF_TIMER_FREQ_8MHz;
    //Timer_0_cfg.mode = NRF_TIMER_MODE_COUNTER;
    //Timer_0_cfg.bit_width = TIMER_BITMODE_BITMODE_32Bit;
    // Set up timer
    NRF_TIMER0->PRESCALER = 1;
    NRF_TIMER0->CC[0] = 1; // Adjust the output frequency by adjusting the CC.
    //NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
    NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled;
    //NRF_TIMER0->TASKS_START = 1;

  // Configure timer as counter, 2 counts at 62.5KHz
    nrf_drv_timer_config_t Timer_1_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    Timer_1_cfg.frequency = NRF_TIMER_FREQ_4MHz;
    //Timer_1_cfg.mode = NRF_TIMER_MODE_COUNTER;
    //Timer_1_cfg.bit_width = TIMER_BITMODE_BITMODE_32Bit;
    // Set up timer
    NRF_TIMER1->PRESCALER = 0;
    NRF_TIMER1->CC[1] = 1; // Adjust the output frequency by adjusting the CC.
    //NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos;
    NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled;
    //NRF_TIMER1->TASKS_START = 1;
   
    // Initialize timers
    err_code = nrf_drv_timer_init(&Timer_0, &Timer_0_cfg, Timer_0_handler);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_timer_init(&Timer_1, &Timer_1_cfg, Timer_1_handler);
    APP_ERROR_CHECK(err_code);

    // Create variables to hold event and task addresses. They will connect with PPI TEP (Task End Point) and PPI EEP (Event End Point)
    uint32_t compare_event_addr_1;
    uint32_t compare_event_addr_2;
    uint32_t gpiote_task_addr_1;
    uint32_t gpiote_task_addr_2;

    // Create structure to hold PPI channel values
    nrf_ppi_channel_t ppi_channel_1;
    nrf_ppi_channel_t ppi_channel_2;
    
    // Initialize GPTIOTE module
    if(!nrf_drv_gpiote_is_init())
    {
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }
    
    // Initialize PPI module, make sure it is only enabled once in the code
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    // Allocate a channel from available PPI channels
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_2);
    APP_ERROR_CHECK(err_code);
    
    // Enable and configure the pin (high/low/toggle). True ? Initial high state, False ? Initial low state
    nrf_drv_gpiote_out_config_t out_config_1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    err_code = nrf_drv_gpiote_out_init(I2S_SCK, &out_config_1);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_out_config_t out_config_2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    err_code = nrf_drv_gpiote_out_init(I2S_LRCLK, &out_config_2);
    APP_ERROR_CHECK(err_code);

    // Get address of respective event and tasks from the respective peripherals
    compare_event_addr_1 = nrf_drv_timer_event_address_get(&Timer_0, NRF_TIMER_EVENT_COMPARE0);
    gpiote_task_addr_1 = nrf_drv_gpiote_out_task_addr_get(I2S_SCK);
    compare_event_addr_2 = nrf_drv_timer_event_address_get(&Timer_1, NRF_TIMER_EVENT_COMPARE1);
    gpiote_task_addr_2 = nrf_drv_gpiote_out_task_addr_get(I2S_LRCLK);
    
    // Connect EEP & TEP with Peripheral Events and Tasks using their addresses and assign them to an allocated channel
    err_code = nrf_drv_ppi_channel_assign(ppi_channel_1, compare_event_addr_1, gpiote_task_addr_1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel_2, compare_event_addr_2, gpiote_task_addr_2);
    APP_ERROR_CHECK(err_code);
    
    // Enable channel to start receiving events and route them to tasks
    err_code = nrf_drv_ppi_channel_enable(ppi_channel_1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel_2);
    APP_ERROR_CHECK(err_code);
    
    // Enable pin task to be executed when called by any event via PPI
    nrf_drv_gpiote_out_task_enable(I2S_SCK);
    nrf_drv_gpiote_out_task_enable(I2S_LRCLK);
}


int main(void)
{
    nrf_gpio_cfg_output(I2S_SCK);
    nrf_gpio_cfg_output(I2S_LRCLK);
    nrf_gpio_cfg_output(LED_Power);
    nrf_gpio_pin_clear(I2S_SCK);
    nrf_gpio_pin_clear(I2S_LRCLK);
    nrf_gpio_pin_set(LED_Power);

    Initialize_Timer_PPI_GPIOTE();

      // Start timer
      nrf_drv_timer_enable(&Timer_0);
      nrf_drv_timer_enable(&Timer_1);

    while (1)
    {
//        __WFI();
    }
}

Parents
  • This line is incorrect:

    NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled;

    You mention that both timer settings are identical, but they are not as Compare 0 is used on Timer 0 but Compare 1 is used on Timer 1. The best solution is to use Compare 0 on both timers as each timer has independent compare registers. However a quick fix is to simply left shift the clear bit mentioned above by 1 place; that was what the line above in the original post was doing. The #defines can be somewhat confusing, and causes misunderstandings such as this.

    NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos;

  • This is my attempt to produce 2 events (clocks), first is a 4MHz clock on GPIO pin using GPIOTE and PPI, and another clock at 62.5KHz using a second PPI channel. Both PPI channels are reading the same clock (4MHz). I am not sure what I am doing wrong. I wish if you help me out with setting the configuration.

    thanks

    // Create timer instance
    const nrf_drv_timer_t Timer_0 = NRF_DRV_TIMER_INSTANCE(0);
    const nrf_drv_timer_t Timer_1 = NRF_DRV_TIMER_INSTANCE(1);
    
    static void Initialize_Timer_PPI_GPIOTE(void)
    {
        // Configure timer_0 at 4MHz
        nrf_drv_timer_config_t Timer_0_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        Timer_0_cfg.frequency = NRF_TIMER_FREQ_8MHz;
        Timer_0_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        // Set up timer
        NRF_TIMER0->PRESCALER = 1;
        NRF_TIMER0->CC[0] = 1;
        NRF_TIMER0->CC[1] = 64;
        nrfx_timer_compare(&Timer_0, NRF_TIMER_CC_CHANNEL0, 1, false);
        nrfx_timer_extended_compare(&Timer_0, NRF_TIMER_CC_CHANNEL1, 1, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
    
        // Initialize timer
        err_code = nrf_drv_timer_init(&Timer_0, &Timer_0_cfg, Timer_0_handler);
        APP_ERROR_CHECK(err_code);
        
        // Create variables to hold event and task addresses. They will connect with PPI TEP (Task End Point) and PPI EEP (Event End Point)
        uint32_t compare_event_addr_1;
        uint32_t gpiote_task_addr_1;
    
        // Initialize GPTIOTE module ///////////////////////////////////////////////////////////////////
        if(!nrf_drv_gpiote_is_init())
        {
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
        
        // Initialize PPI module ///////////////////////////////////////////////////////////////////////
        // Create structure to hold PPI channel values
        nrf_ppi_channel_t ppi_channel_1;
        nrf_ppi_channel_t ppi_channel_2;
    
        // Initialize PPI module, make sure it is only enabled once in the code
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        // Allocate a channel from available PPI channels
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable and configure the pin (high/low/toggle). True ? Initial high state, False ? Initial low state
        nrf_drv_gpiote_out_config_t out_config_1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_SCK, &out_config_1);
        APP_ERROR_CHECK(err_code);
        nrf_drv_gpiote_out_config_t out_config_2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_LRCLK, &out_config_2);
        APP_ERROR_CHECK(err_code);
    
        // Get address of respective event and tasks from the respective peripherals
        compare_event_addr_1 = nrf_drv_timer_event_address_get(&Timer_0, NRF_TIMER_EVENT_COMPARE0);
        gpiote_task_addr_1 = nrf_drv_gpiote_out_task_addr_get(I2S_SCK);
        compare_event_addr_2 = nrf_drv_timer_event_address_get(&Timer_0, NRF_TIMER_EVENT_COMPARE1);
        gpiote_task_addr_2 = nrf_drv_gpiote_out_task_addr_get(I2S_LRCLK);
        
        // Connect EEP & TEP with Peripheral Events and Tasks using their addresses and assign them to an allocated channel
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_1, compare_event_addr_1, gpiote_task_addr_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_2, compare_event_addr_2, gpiote_task_addr_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable channel to start receiving events and route them to tasks
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        // Initialize PPI END //////////////////////////////////////////////////////////////////////////
    
        // Enable pin task to be executed when called by any event via PPI
        nrf_drv_gpiote_out_task_enable(I2S_SCK);
        nrf_drv_gpiote_out_task_enable(I2S_LRCLK);
    }
    
    
    than in the main(), i call:
    
    Initialize_Timer_PPI_GPIOTE();
     nrf_drv_timer_enable(&Timer_0);
     nrf_drv_timer_enable(&Timer_1);

  • Hi,

    The following line is overwriting the CC register:

    nrfx_timer_extended_compare(&Timer_0, NRF_TIMER_CC_CHANNEL1, 1, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);

    This will set both CC[0] and CC[1] to 1, giving 4 MHz output on both signals. It would also not work as you intend to set CC[0] to 1 and CC[1] to 64, and expect different periods on the signals. The timer is only cleared after COMPARE_1 event, meaning the first GPIOTE/PPI channel will trigger when counter reaches 1, while second GPIOTE/PPI channel will trigger when counter reaches 64, then timer will be cleared and the cycle will repeat. This will give you the same (low frequency) period on both signals, just shifted a bit in time.

    You need to use separate timers to generate varying frequency. I would recommend you to avoid using multiple ways of accessing the timer (accessing registers, nrfx driver, nrf_drv drivers). Using the driver only will make the code easier to read, and make sure the error checks are correct and that you do not break any functionality used by the driver, leaving it in a bad state.

    Something like this should give you the desired functionality:

    static void Initialize_Timer_PPI_GPIOTE(void)
    {
        // Configure timer_0 at 4MHz
        nrf_drv_timer_config_t Timer_0_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        Timer_0_cfg.frequency = NRF_TIMER_FREQ_8MHz;
        Timer_0_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    
        // Configure timer_1 at 62.5kHz
        nrf_drv_timer_config_t Timer_1_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        Timer_1_cfg.frequency = NRF_TIMER_FREQ_125kHz;
        Timer_1_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        
        ret_code_t err_code;
    
        // Initialize timer
        err_code = nrf_drv_timer_init(&Timer_0, &Timer_0_cfg, Timer_0_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_timer_init(&Timer_1, &Timer_1_cfg, Timer_1_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_extended_compare(&Timer_0, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        nrf_drv_timer_extended_compare(&Timer_1, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        
        // Create variables to hold event and task addresses. They will connect with PPI TEP (Task End Point) and PPI EEP (Event End Point)
        uint32_t compare_event_addr_1;
        uint32_t gpiote_task_addr_1;
    
        // Initialize GPTIOTE module ///////////////////////////////////////////////////////////////////
        if(!nrf_drv_gpiote_is_init())
        {
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
        
        // Initialize PPI module ///////////////////////////////////////////////////////////////////////
        // Create structure to hold PPI channel values
        nrf_ppi_channel_t ppi_channel_1;
        nrf_ppi_channel_t ppi_channel_2;
    
        // Initialize PPI module, make sure it is only enabled once in the code
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        // Allocate a channel from available PPI channels
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable and configure the pin (high/low/toggle). True ? Initial high state, False ? Initial low state
        nrf_drv_gpiote_out_config_t out_config_1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_SCK, &out_config_1);
        APP_ERROR_CHECK(err_code);
        nrf_drv_gpiote_out_config_t out_config_2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_LRCLK, &out_config_2);
        APP_ERROR_CHECK(err_code);
    
        // Get address of respective event and tasks from the respective peripherals
        compare_event_addr_1 = nrf_drv_timer_event_address_get(&Timer_0, NRF_TIMER_EVENT_COMPARE0);
        gpiote_task_addr_1 = nrf_drv_gpiote_out_task_addr_get(I2S_SCK);
        uint32_t compare_event_addr_2 = nrf_drv_timer_event_address_get(&Timer_1, NRF_TIMER_EVENT_COMPARE0);
        uint32_t gpiote_task_addr_2 = nrf_drv_gpiote_out_task_addr_get(I2S_LRCLK);
        
        // Connect EEP & TEP with Peripheral Events and Tasks using their addresses and assign them to an allocated channel
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_1, compare_event_addr_1, gpiote_task_addr_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_2, compare_event_addr_2, gpiote_task_addr_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable channel to start receiving events and route them to tasks
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        // Initialize PPI END //////////////////////////////////////////////////////////////////////////
    
        // Enable pin task to be executed when called by any event via PPI
        nrf_drv_gpiote_out_task_enable(I2S_SCK);
        nrf_drv_gpiote_out_task_enable(I2S_LRCLK);
    }

    Best regards,
    Jørgen

Reply
  • Hi,

    The following line is overwriting the CC register:

    nrfx_timer_extended_compare(&Timer_0, NRF_TIMER_CC_CHANNEL1, 1, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);

    This will set both CC[0] and CC[1] to 1, giving 4 MHz output on both signals. It would also not work as you intend to set CC[0] to 1 and CC[1] to 64, and expect different periods on the signals. The timer is only cleared after COMPARE_1 event, meaning the first GPIOTE/PPI channel will trigger when counter reaches 1, while second GPIOTE/PPI channel will trigger when counter reaches 64, then timer will be cleared and the cycle will repeat. This will give you the same (low frequency) period on both signals, just shifted a bit in time.

    You need to use separate timers to generate varying frequency. I would recommend you to avoid using multiple ways of accessing the timer (accessing registers, nrfx driver, nrf_drv drivers). Using the driver only will make the code easier to read, and make sure the error checks are correct and that you do not break any functionality used by the driver, leaving it in a bad state.

    Something like this should give you the desired functionality:

    static void Initialize_Timer_PPI_GPIOTE(void)
    {
        // Configure timer_0 at 4MHz
        nrf_drv_timer_config_t Timer_0_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        Timer_0_cfg.frequency = NRF_TIMER_FREQ_8MHz;
        Timer_0_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    
        // Configure timer_1 at 62.5kHz
        nrf_drv_timer_config_t Timer_1_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        Timer_1_cfg.frequency = NRF_TIMER_FREQ_125kHz;
        Timer_1_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        
        ret_code_t err_code;
    
        // Initialize timer
        err_code = nrf_drv_timer_init(&Timer_0, &Timer_0_cfg, Timer_0_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_timer_init(&Timer_1, &Timer_1_cfg, Timer_1_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_extended_compare(&Timer_0, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        nrf_drv_timer_extended_compare(&Timer_1, NRF_TIMER_CC_CHANNEL0, 1, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        
        // Create variables to hold event and task addresses. They will connect with PPI TEP (Task End Point) and PPI EEP (Event End Point)
        uint32_t compare_event_addr_1;
        uint32_t gpiote_task_addr_1;
    
        // Initialize GPTIOTE module ///////////////////////////////////////////////////////////////////
        if(!nrf_drv_gpiote_is_init())
        {
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
        
        // Initialize PPI module ///////////////////////////////////////////////////////////////////////
        // Create structure to hold PPI channel values
        nrf_ppi_channel_t ppi_channel_1;
        nrf_ppi_channel_t ppi_channel_2;
    
        // Initialize PPI module, make sure it is only enabled once in the code
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        // Allocate a channel from available PPI channels
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable and configure the pin (high/low/toggle). True ? Initial high state, False ? Initial low state
        nrf_drv_gpiote_out_config_t out_config_1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_SCK, &out_config_1);
        APP_ERROR_CHECK(err_code);
        nrf_drv_gpiote_out_config_t out_config_2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        err_code = nrf_drv_gpiote_out_init(I2S_LRCLK, &out_config_2);
        APP_ERROR_CHECK(err_code);
    
        // Get address of respective event and tasks from the respective peripherals
        compare_event_addr_1 = nrf_drv_timer_event_address_get(&Timer_0, NRF_TIMER_EVENT_COMPARE0);
        gpiote_task_addr_1 = nrf_drv_gpiote_out_task_addr_get(I2S_SCK);
        uint32_t compare_event_addr_2 = nrf_drv_timer_event_address_get(&Timer_1, NRF_TIMER_EVENT_COMPARE0);
        uint32_t gpiote_task_addr_2 = nrf_drv_gpiote_out_task_addr_get(I2S_LRCLK);
        
        // Connect EEP & TEP with Peripheral Events and Tasks using their addresses and assign them to an allocated channel
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_1, compare_event_addr_1, gpiote_task_addr_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_assign(ppi_channel_2, compare_event_addr_2, gpiote_task_addr_2);
        APP_ERROR_CHECK(err_code);
        
        // Enable channel to start receiving events and route them to tasks
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_enable(ppi_channel_2);
        APP_ERROR_CHECK(err_code);
        // Initialize PPI END //////////////////////////////////////////////////////////////////////////
    
        // Enable pin task to be executed when called by any event via PPI
        nrf_drv_gpiote_out_task_enable(I2S_SCK);
        nrf_drv_gpiote_out_task_enable(I2S_LRCLK);
    }

    Best regards,
    Jørgen

Children
Related