PPI not initiating SPI

I've got an example code to turn on an LED with a button, it works. When I change it to send an spi command, it doesn't work anymore.

Could you check if you see something I did wrong with SPI? I've been around this issue for a day.

Thank you

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

#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "nordic_common.h"
#include "nrf.h"
//#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
//#include "SEGGER_RTT.h"

#include "nrf_drv_timer.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_spi.h"
#include "nrf_gpio.h"
#include "nrf_drv_gpiote.h"




//#define ACTIVE_CHANNEL     15

#define ACTIVE_CHANNEL   15

#define BYTES_PR_XFER_TX   4
// Number of bytes per transfer to receive from SPI slave
#define BYTES_PR_XFER_RX   4

// Number of SPI transfers to complete for one US frame
#define NUMBER_OF_XFERS 4
//#define DELAY_BETWEEN_TRANSFERS 1

// Max number of US frames to buffer
#define MAX_BUFFER_NUMBER_OF_US_FRAMES 35

#define LED_Pin1 3 // Pin connected with LED
#define Btn_Pin1 13 // Pin connected with Button



typedef struct ArrayList
    {
        uint8_t buffer[BYTES_PR_XFER_RX];
    } ArrayList_type;




static ArrayList_type m_rx_buf[NUMBER_OF_XFERS*MAX_BUFFER_NUMBER_OF_US_FRAMES];
//extern ArrayList_type m_tx_buf_1[NUMBER_OF_XFERS];


static uint8_t m_tx_buf2[4];



void buffer_init(void)
{
m_tx_buf2[0] = 0x00;
m_tx_buf2[1] = ACTIVE_CHANNEL & 0x3F;
m_tx_buf2[2] = 0x00;
m_tx_buf2[3] = 0x00;

//m_tx_buf2[0] = 0xFF;
//m_tx_buf2[1] = 0xFF;
//m_tx_buf2[2] = 0xFF;
//m_tx_buf2[3] = 0xFF;
}

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(0);




static nrf_ppi_channel_t ppi_channel; // A struct to hol ppi channel values


// Interrupt handler for GPIO button pin, we will not use it because we are directly routing
// the event to the pin, but you can use it in conjuction with the PPI
void intrrupt_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
 // Empty handler
}



// Task and event addresses for SPI transactions
uint32_t start_spi_task_addr;
uint32_t spi_end_evt_addr;
uint32_t timer0_timeout_cc0_evt_addr;
uint32_t counter1_count_task_addr;
uint32_t counter1_cc0_evt_addr;


void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    // Never called if NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER flag is used
}



// @brief Handler for timer events.
void timer_timeout_event_handler(nrf_timer_event_t event_type, void* p_context)
{
    // Handler must be declared and passed to nrf_drv_timer_init(), 
    // but is not used if nrf_drv_timer_extended_compare() is called with enable_int flag = false
}



/**@brief Function to initialize SPI
 *
 * @details This function initializes The SPI peripheral. It will also set up 
 * the SPI transfer with EasyDMA. The prepared SPI transfer can later be 
 * initiated with PPI.
 */
void spi_init()
{
    uint32_t err_code;
    nrf_drv_spi_config_t config = NRF_DRV_SPI_DEFAULT_CONFIG;
    config.ss_pin = SPI_SS_PIN;
    //LED_Pin1;
    //SPI_SS_PIN;
    config.miso_pin = SPI_MISO_PIN;
    config.mosi_pin = SPI_MOSI_PIN;
    config.sck_pin = SPI_SCK_PIN;
    config.frequency = NRF_DRV_SPI_FREQ_8M;
    config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
    config.mode = NRF_DRV_SPI_MODE_1;
    err_code = nrf_drv_spi_init(&spi, &config, spi_event_handler, NULL);
    APP_ERROR_CHECK(err_code);
    
    // Setting up an SPI transfer using EasyDMA
    nrf_drv_spi_xfer_desc_t xfer = NRF_DRV_SPI_XFER_TRX(m_tx_buf2, BYTES_PR_XFER_TX, (uint8_t *)m_rx_buf, BYTES_PR_XFER_RX);
    
    uint32_t flags = NRF_DRV_SPI_FLAG_HOLD_XFER           |
                     NRF_DRV_SPI_FLAG_RX_POSTINC          |
                     NRF_DRV_SPI_FLAG_REPEATED_XFER       |
                     NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER;
    
    err_code = nrf_drv_spi_xfer(&spi, &xfer, flags);
    APP_ERROR_CHECK(err_code);
    
    // Get SPI START task address and END event address
    start_spi_task_addr = nrf_drv_spi_start_task_get(&spi);
    spi_end_evt_addr = nrf_drv_spi_end_event_get(&spi);
}

//void spi_init()
//{
//}





// A function to initialize all the pins with all the configurations
static void gpiote_pins_init(void)
{
  // Variable to hold error values
  uint32_t error_code = NRF_SUCCESS;

  error_code = nrf_drv_gpiote_init(); // Initialize gpiote module
  APP_ERROR_CHECK(error_code);

  // create the configurations for input pin interrupt
  nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true); 
  // set the PULL UP resistor because the button gives logic zero so when
  // no button is being pressed the pullup resistors will pull the pin to logic high state
  in_config.pull = NRF_GPIO_PIN_PULLUP; 

 // initialize the interrupt pin for the button
    error_code = nrf_drv_gpiote_in_init(Btn_Pin1, &in_config, intrrupt_pin_handler);
    APP_ERROR_CHECK(error_code);


// enable and configure the task of LED pin with its function
// it can be:
// set high
// set low
// or toggle pin

    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    error_code = nrf_drv_gpiote_out_init(LED_Pin1, &out_config);
    APP_ERROR_CHECK(error_code);



// once everything is done

// enable LED Pin task so that it can be executed when ever called by any event via PPI
    nrf_drv_gpiote_out_task_enable(LED_Pin1);

// enable the interrupt event on button pin
    nrf_drv_gpiote_in_event_enable(Btn_Pin1, true);


  
}




// A function to initialize the PPI Module with all the configurations
static void ppi_init(void)
{
  // a variable to hold the error value
    uint32_t err_code = NRF_SUCCESS;

  // Variables to hold the event address and task address
  // they are needed to connect with the PPI TEP(Task End Point) & PPI EEP (Event End Point)
    uint32_t btn_evt_addr;
    uint32_t led_task_addr;



// Initialize the PPI module, only to be enabled once
   err_code =  nrf_drv_ppi_init();
   APP_ERROR_CHECK(err_code);


// Allocate the channel from the available PPI channels
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel);
    APP_ERROR_CHECK(err_code);


// Get the address of the respective event and tasks from the pins
    btn_evt_addr =  nrf_drv_gpiote_in_event_addr_get(Btn_Pin1);
    led_task_addr = nrf_drv_gpiote_out_task_addr_get(LED_Pin1);


// connect the EEP & TEP with Peripheral Events & Tasks using their addresses and assign them to an allocated channel
    //err_code = nrf_drv_ppi_channel_assign(ppi_channel, btn_evt_addr, led_task_addr);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel, btn_evt_addr, start_spi_task_addr);
    APP_ERROR_CHECK(err_code);

// Enable the channel so that it can start receiving events and then route them to tasks
    err_code = nrf_drv_ppi_channel_enable(ppi_channel);
    APP_ERROR_CHECK(err_code);

    
}




//void test_spi_manually()
//{
//    // Manually trigger the SPI START task
//    *((volatile uint32_t *)start_spi_task_addr) = 1;
//}





int main(void)
{

    buffer_init();
    

    spi_init();

    gpiote_pins_init();

    ppi_init();

    //test_spi_manually();


  
   
    while (true)
    {
       // Do nothing
    }
}


/** @} */

Related