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

Control of SS pin of SPI with ppi.

Hi.

Development platform : nRF52833-DK, s113, SDK 16.0.0, IAR 8.31.1

I am making an example of periodically reading sensor data using SPI. 

The SPI is triggered through PPI.

static const nrf_drv_spi_t heater_volt_spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE_ID);  /**< SPI instance. */



void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
   // Get spi data...
}


static ret_code_t spi_init(void)
{

  nrf_drv_spi_config_t spi_config =
  {
      .sck_pin        = SPI_SCK_RVAC,
      .mosi_pin       = NRF_DRV_SPI_PIN_NOT_USED,
      .miso_pin       = SPI_MISO_RVAC,
      .ss_pin         = NRF_DRV_SPI_PIN_NOT_USED,
      .irq_priority   = APP_IRQ_PRIORITY_HIGH,
      .orc            = 0xFF,
      .frequency      = NRF_DRV_SPI_FREQ_8M,
      .mode           = NRF_DRV_SPI_MODE_0,
      .bit_order      = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
  };

  APP_ERROR_CHECK(nrf_drv_spi_init(&heater_volt_spi, &spi_config, spi_event_handler, NULL));

 nrf_drv_spi_xfer_desc_t xfer = NRF_DRV_SPI_XFER_TRX(NULL, 0, m_volt_rx_buf, 2);
 
 uint32_t flags = NRF_DRV_SPI_FLAG_HOLD_XFER           |
//              NRF_DRV_SPI_FLAG_RX_POSTINC          |
//              NRF_DRV_SPI_FLAG_NO_XFER_EVT_HANDLER |
              NRF_DRV_SPI_FLAG_REPEATED_XFER;
              
 nrf_drv_spi_xfer(&heater_volt_spi, &xfer, flags);


// Set PPI

    ret_code_t err_code;
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);


    uint32_t timer2_compare_event_addr = nrf_drv_timer_event_address_get(&m_timer2, NRF_TIMER_EVENT_COMPARE0);
    uint32_t start_tsk_addr = nrf_drv_spi_start_task_get(&heater_volt_spi);

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_voltage_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_voltage_channel, timer2_compare_event_addr, start_tsk_addr);
    APP_ERROR_CHECK(err_code);


 return NRF_SUCCESS;
}



static void timer2_init(void)
{
    // Check TIMER2 configuration for details.
    nrf_drv_timer_config_t timer_cfg =     {                                                                                    \
        .frequency          = (nrf_timer_frequency_t)NRF_TIMER_FREQ_16MHz,
        .mode               = (nrf_timer_mode_t)NRF_TIMER_MODE_TIMER,          
        .bit_width          = (nrf_timer_bit_width_t)NRF_TIMER_BIT_WIDTH_32,
        .interrupt_priority = 0,                    
        .p_context          = NULL                                                       
    };
    
    ret_code_t err_code = nrf_drv_timer_init(&m_timer2, &timer_cfg, empty_timer_handler);
    APP_ERROR_CHECK(err_code);


nrf_drv_timer_extended_compare(&m_timer2,
                               NRF_TIMER_CC_CHANNEL0,
                               nrf_drv_timer_us_to_ticks(&m_timer2,
                                                         500),  // #####
                               NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                               false);
}



void heater_driver_init(void)
{

  spi_init();

  timer2_init();

    err_code = nrf_drv_ppi_channel_enable(m_ppi_voltage_channel);
    APP_ERROR_CHECK(err_code);


  nrf_drv_timer_enable(&m_timer2);


}


timer2 operates at 500us cycle.

Transmission of spi is started by NRF_TIMER_EVENT_COMPARE0 of timer2.

My problem is to control the SS pin of SPI.

I think SS pin high can be done in spi_event_handler().

How can I set the SS pin low?

Thanks...

Parents
  • Hi,

    You can use GPIOTE to toggle the SS pin, see the GPIOTE example on how to set that up. If the slave does not require any time between SS and SCK, you can trigger the GPIOTE task on the same NRF_TIMER_EVENT_COMPARE0 event (using PPI fork), or alternatively a separate TIMER COMPARE event set to trigger a given time before the SPI transfer triggering event.

    Similarly, you can use the SPI END event to toggle the SS pin automatically again using GPIOTE after the transfer.

    Best regards,
    Jørgen

  • Hi. 

    I solved it by using GPIOTE as below.
    Thank you for your advice.

    void power_sampling_event_init(void)
    {
    {
        nrfx_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    
        uint32_t start_task_addr = nrf_drv_spi_start_task_get(&heater_volt_spi);
        uint32_t gpiote_task_addr;
    
        err_code = nrf_drv_gpiote_out_init(SPI_nCS_RVAC, &config);
        APP_ERROR_CHECK(err_code);
    
        gpiote_task_addr = nrfx_gpiote_clr_task_addr_get(SPI_nCS_RVAC);
    
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_voltage_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_voltage_channel, timer2_compare_event_addr, start_task_addr);
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_drv_ppi_channel_fork_assign(m_ppi_voltage_channel, gpiote_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    {
      uint32_t start_event_addr = nrf_drv_spi_end_event_get(&heater_volt_spi);
      uint32_t gpiote_task_addr;
      
      gpiote_task_addr = nrfx_gpiote_set_task_addr_get(SPI_nCS_RVAC);
    
      err_code = nrf_drv_ppi_channel_alloc(&m_ppi_voltage_nCS_channel);
      APP_ERROR_CHECK(err_code);
      
      err_code = nrf_drv_ppi_channel_assign(m_ppi_voltage_nCS_channel, start_event_addr, gpiote_task_addr);
      APP_ERROR_CHECK(err_code);
    
    }
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_voltage_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_voltage_nCS_channel);
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_gpiote_out_task_enable(SPI_nCS_RVAC);
    
    }
    

Reply
  • Hi. 

    I solved it by using GPIOTE as below.
    Thank you for your advice.

    void power_sampling_event_init(void)
    {
    {
        nrfx_gpiote_out_config_t config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    
        uint32_t start_task_addr = nrf_drv_spi_start_task_get(&heater_volt_spi);
        uint32_t gpiote_task_addr;
    
        err_code = nrf_drv_gpiote_out_init(SPI_nCS_RVAC, &config);
        APP_ERROR_CHECK(err_code);
    
        gpiote_task_addr = nrfx_gpiote_clr_task_addr_get(SPI_nCS_RVAC);
    
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_voltage_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_voltage_channel, timer2_compare_event_addr, start_task_addr);
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_drv_ppi_channel_fork_assign(m_ppi_voltage_channel, gpiote_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    {
      uint32_t start_event_addr = nrf_drv_spi_end_event_get(&heater_volt_spi);
      uint32_t gpiote_task_addr;
      
      gpiote_task_addr = nrfx_gpiote_set_task_addr_get(SPI_nCS_RVAC);
    
      err_code = nrf_drv_ppi_channel_alloc(&m_ppi_voltage_nCS_channel);
      APP_ERROR_CHECK(err_code);
      
      err_code = nrf_drv_ppi_channel_assign(m_ppi_voltage_nCS_channel, start_event_addr, gpiote_task_addr);
      APP_ERROR_CHECK(err_code);
    
    }
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_voltage_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_voltage_nCS_channel);
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_gpiote_out_task_enable(SPI_nCS_RVAC);
    
    }
    

Children
No Data
Related