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

NRF52840 SPIM3 extended config ss_duration not changing CSN inactive duration?

By changing ss_duration the duration CSN is high doesn't seem to be effected?

ss_duration = 2

CSN

SCK

ss_duration = 64

CSN

SCK

Setup

SPI Config

#define SS_DURATION_SHORT 2
#define SS_DURATION_LONG 64

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
spi_config.ss_pin = DEVICE_CS;
spi_config.miso_pin = SPI_MISO;
spi_config.mosi_pin = NRFX_SPIM_PIN_NOT_USED;
spi_config.sck_pin = SPI_SCK;
spi_config.ss_active_high = false;
spi_config.frequency = NRF_SPIM_FREQ_1M;
spi_config.mode = NRF_SPIM_MODE_0;
spi_config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
spi_config.dcx_pin = NRFX_SPIM_PIN_NOT_USED;
spi_config.use_hw_ss = true;
spi_config.ss_duration = SS_DURATION_SHORT;

nrfx_spim_init(&spi, &spi_config, NULL, NULL);

spi.p_reg->RXD.PTR = (uint32_t)sample_buffer;
spi.p_reg->RXD.MAXCNT = sizeof(sample_buffer[0]); //Size of transaction
spi.p_reg->RXD.LIST = 1; //Use ARRAY List

PPI

SPIM3 END EVENT -> SPIM3 START TASK

SPIM3 END EVENT -> TIMER2 COUNT TASK

Example Code Below

/**
 * Copyright (c) 2014 - 2020, 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
 *
 * @defgroup blinky_example_main main.c
 * @{
 * @ingroup blinky_example
 * @brief Blinky Example Application main file.
 *
 * This file contains the source code for a sample application to blink LEDs.
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"

//Nordic
#include "nrf_gpio.h"
#include "nrfx_spim.h"
#include "nrfx_timer.h"
#include "nrfx_ppi.h"
#include "nrf_drv_ppi.h"

#define SAMPLES 1001
#define SAMPLE_BUFFER_SIZE SAMPLES + 100

static uint8_t sample_buffer[SAMPLE_BUFFER_SIZE][3];
static volatile uint32_t sample_buffer_count = 0;

static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(3);
static const nrfx_timer_t count_timer = NRFX_TIMER_INSTANCE(2);

static nrf_ppi_channel_t spi_start_ppi_channel;
static nrf_ppi_channel_t spi_sample_ppi_channel;
static nrf_ppi_channel_t spi_count_ppi_channel;

#define DEVICE_CS NRF_GPIO_PIN_MAP(1,10)
#define SPI_MISO NRF_GPIO_PIN_MAP(1,11)
#define SPI_SCK NRF_GPIO_PIN_MAP(0,28)

#define SS_DURATION_SHORT 2
#define SS_DURATION_LONG 64

static void start() {
  //Enable sample looping channel
  nrf_drv_ppi_channel_enable(spi_sample_ppi_channel);

  //Reset pointer
  spi.p_reg->RXD.PTR = (uint32_t)sample_buffer;

  nrf_spim_task_trigger(spi.p_reg, NRF_SPIM_TASK_START);
}

static void timer_handler(nrf_timer_event_t event_type, void * p_context) {

}


static volatile uint32_t sample_buffer_count;

/**
 * @brief Function for application main entry.
 */
int main(void)
{
  nrf_gpio_cfg_output(DEVICE_CS);
  nrf_gpio_cfg_output(SPI_SCK);
  nrf_gpio_cfg_input(SPI_MISO, NRF_GPIO_PIN_NOPULL);

  nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
  spi_config.ss_pin         = DEVICE_CS;
  spi_config.miso_pin       = SPI_MISO;
  spi_config.mosi_pin       = NRFX_SPIM_PIN_NOT_USED;
  spi_config.sck_pin        = SPI_SCK;
  spi_config.ss_active_high = false;
  spi_config.frequency      = NRF_SPIM_FREQ_1M;
  spi_config.mode           = NRF_SPIM_MODE_0;
  spi_config.bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST;
  spi_config.dcx_pin = NRFX_SPIM_PIN_NOT_USED;
  spi_config.use_hw_ss = true;
  spi_config.ss_duration = SS_DURATION_LONG;

  nrfx_spim_init(&spi, &spi_config, NULL, NULL);

  spi.p_reg->RXD.PTR = (uint32_t)sample_buffer;
  spi.p_reg->RXD.MAXCNT = sizeof(sample_buffer[0]); //Size of transaction
  spi.p_reg->RXD.LIST = 1; //Use ARRAY List

  uint32_t err_code = nrf_drv_ppi_init();


  //Sample
  err_code = nrf_drv_ppi_channel_alloc(&spi_sample_ppi_channel);
  APP_ERROR_CHECK(err_code);
  
  uint32_t spi_end_evt_addr        = nrfx_spim_end_event_get(&spi);
  uint32_t spi_start_task_addr       = nrfx_spim_start_task_get(&spi);

  //Trigger SPI start on a SPI end
  err_code = nrf_drv_ppi_channel_assign(spi_sample_ppi_channel, spi_end_evt_addr, spi_start_task_addr);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_ppi_channel_enable(spi_sample_ppi_channel);
  APP_ERROR_CHECK(err_code);



  //Count
  //Setup timer in counter mode
  nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
  timer_cfg.frequency = NRF_TIMER_FREQ_16MHz;
  timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
  timer_cfg.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER;

  err_code = nrfx_timer_init(&count_timer, &timer_cfg, timer_handler);

  

  //Count PPI
  err_code = nrf_drv_ppi_channel_alloc(&spi_count_ppi_channel);
  APP_ERROR_CHECK(err_code);

  uint32_t timer_count_evt_addr       = nrfx_timer_task_address_get(&count_timer, NRF_TIMER_TASK_COUNT);

  err_code = nrf_drv_ppi_channel_assign(spi_count_ppi_channel, spi_end_evt_addr, timer_count_evt_addr);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_ppi_channel_enable(spi_count_ppi_channel);
  APP_ERROR_CHECK(err_code);


  //Start Sampling
  start();


  while(true) {

    nrfx_timer_capture(&count_timer, NRF_TIMER_CC_CHANNEL1);
    sample_buffer_count = nrfx_timer_capture_get(&count_timer, NRF_TIMER_CC_CHANNEL1);

    if(sample_buffer_count >= SAMPLES) {
      //Stop SPI
      nrf_drv_ppi_channel_disable(spi_sample_ppi_channel);

      //Reset counter timer
      nrfx_timer_clear(&count_timer);

      nrf_delay_ms(100);

      //Start Again
      start();
    }

  }

}

/**
 *@}
 **/

Regards,

Jonathan

Parents Reply Children
  • I have updated my code below to use short (END_START). But it the timing looks the same as with PPI.

    ss_duration = 2

    ss_duration = 64

    /**
     * Copyright (c) 2014 - 2020, 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
     *
     * @defgroup blinky_example_main main.c
     * @{
     * @ingroup blinky_example
     * @brief Blinky Example Application main file.
     *
     * This file contains the source code for a sample application to blink LEDs.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf_delay.h"
    
    //Nordic
    #include "nrf_gpio.h"
    #include "nrfx_spim.h"
    #include "nrfx_timer.h"
    #include "nrfx_ppi.h"
    #include "nrf_drv_ppi.h"
    
    #define SAMPLES 1001
    #define SAMPLE_BUFFER_SIZE SAMPLES + 100
    
    static uint8_t sample_buffer[SAMPLE_BUFFER_SIZE][3];
    static volatile uint32_t sample_buffer_count = 0;
    
    static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(3);
    static const nrfx_timer_t count_timer = NRFX_TIMER_INSTANCE(2);
    
    static nrf_ppi_channel_t spi_count_ppi_channel;
    
    #define DEVICE_CS NRF_GPIO_PIN_MAP(1,10)
    #define SPI_MISO NRF_GPIO_PIN_MAP(1,11)
    #define SPI_SCK NRF_GPIO_PIN_MAP(0,28)
    
    #define SS_DURATION_SHORT 2
    #define SS_DURATION_LONG 64
    
    static volatile uint32_t sample_buffer_count;
    
    static void enable_continuous_spi() {
      spi.p_reg->SHORTS = 1 << 17;
    }
    
    static void disable_continuous_spi() {
      spi.p_reg->SHORTS = 0;
    }
    
    static void start() {
      //Enable sample looping channel
      enable_continuous_spi();
    
      //Reset pointer
      spi.p_reg->RXD.PTR = (uint32_t)sample_buffer;
    
      nrf_spim_task_trigger(spi.p_reg, NRF_SPIM_TASK_START);
    }
    
    static void timer_handler(nrf_timer_event_t event_type, void * p_context) {
    
    }
    
    
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
      nrf_gpio_cfg_output(DEVICE_CS);
      nrf_gpio_cfg_output(SPI_SCK);
      nrf_gpio_cfg_input(SPI_MISO, NRF_GPIO_PIN_NOPULL);
    
      nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
      spi_config.ss_pin         = DEVICE_CS;
      spi_config.miso_pin       = SPI_MISO;
      spi_config.mosi_pin       = NRFX_SPIM_PIN_NOT_USED;
      spi_config.sck_pin        = SPI_SCK;
      spi_config.ss_active_high = false;
      spi_config.frequency      = NRF_SPIM_FREQ_1M;
      spi_config.mode           = NRF_SPIM_MODE_0;
      spi_config.bit_order      = NRF_SPIM_BIT_ORDER_MSB_FIRST;
      spi_config.dcx_pin = NRFX_SPIM_PIN_NOT_USED;
      spi_config.use_hw_ss = true;
      spi_config.ss_duration = SS_DURATION_SHORT;
    
      nrfx_spim_init(&spi, &spi_config, NULL, NULL);
    
      spi.p_reg->RXD.PTR = (uint32_t)sample_buffer;
      spi.p_reg->RXD.MAXCNT = sizeof(sample_buffer[0]); //Size of transaction
      spi.p_reg->RXD.LIST = 1; //Use ARRAY List
    
      uint32_t err_code = nrf_drv_ppi_init();
    
      //Count
      //Setup timer in counter mode
      nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
      timer_cfg.frequency = NRF_TIMER_FREQ_16MHz;
      timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
      timer_cfg.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER;
    
      err_code = nrfx_timer_init(&count_timer, &timer_cfg, timer_handler);
    
      
    
      //Count PPI
      err_code = nrf_drv_ppi_channel_alloc(&spi_count_ppi_channel);
      APP_ERROR_CHECK(err_code);
    
      uint32_t timer_count_evt_addr       = nrfx_timer_task_address_get(&count_timer, NRF_TIMER_TASK_COUNT);
      uint32_t spi_end_evt_addr        = nrfx_spim_end_event_get(&spi);
    
      err_code = nrf_drv_ppi_channel_assign(spi_count_ppi_channel, spi_end_evt_addr, timer_count_evt_addr);
      APP_ERROR_CHECK(err_code);
      
      err_code = nrf_drv_ppi_channel_enable(spi_count_ppi_channel);
      APP_ERROR_CHECK(err_code);
    
    
      //Start Sampling
      start();
    
    
      while(true) {
    
        nrfx_timer_capture(&count_timer, NRF_TIMER_CC_CHANNEL1);
        sample_buffer_count = nrfx_timer_capture_get(&count_timer, NRF_TIMER_CC_CHANNEL1);
    
        if(sample_buffer_count >= SAMPLES) {
          //Stop SPI
          disable_continuous_spi();
    
          //Reset counter timer
          nrfx_timer_clear(&count_timer);
    
          nrf_delay_ms(100);
    
          //Start Again
          start();
        }
    
      }
    
    }
    
    /**
     *@}
     **/
    

  • I will have to create an internal jira for it, for now I suggest you add a application delay between SPI transfers to ensure a minimum delay.

    Kenneth

Related