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
  • Seems like this is a error in the documentation. It should say:

    Delay between CSN low to first SCK edge and last SCK edge to CSN high. Also used as CSN high time between two transfers, but only when the short is enabled (END_START).

  • 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