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

SPIM fun (not!)

Again, I'm having trouble with the driver library. Earlier when testing I had SPI working OK as a small standalone test , but now I want to add SPIM to my actual application. The application is based on the BLE sample template.

I've attached a cut down copy of my code and my sdk_config.h.. I'm guessing that the config file is screwed up as I had to hack it to remove some of the nrf legacy entries.

The test here is just trying to send some data over SPI. I toggle a debug gpio just to verify I'm looking in the right place. But I'm just seeing a handful of erratic pulses on the SCK line, and some regular clock-like pulses on the data line! (yes, the pinouts are correct)

So

Q1 Is there a sdk_config.h available with the old legacy drivers removed available?

Q2 What is the format of sdk_config.h?

Q3 I'm not sure what to do with the rx buffer? this is a tx only output

I've attached my config file and code, can you see anything fundamentally wrong with it? The end goal is to send 2-byte packets triggered by a timer via PPI. I already  have the timer & PPI working, at the moment the PPI is just toggling a gpio as a test.

#define PIN_DBG           3
#define DAC_CS_PIN        31
#define DAC_SCK_PIN       26
#define DAC_SDI_PIN       29
#define DAC_SPI_INSTANCE  1
#define DAC_BUF_SIZE      16

//SPI master
#define SPI_INSTANCE  1                                           /**< SPI instance index. */
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
static uint8_t dac_buf[DAC_BUF_SIZE];
static uint8_t m_rx_buf[8];  /**< dummy RX buffer. */

static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}

static void gpio_init(void)
{
    ret_code_t err_code;
    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false); 
    err_code = nrf_drv_gpiote_out_init(PIN_DBG, &out_config);
	APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    in_config.pull = NRF_GPIO_PIN_NOPULL;
    err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
	APP_ERROR_CHECK(err_code);
}

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    spi_xfer_done = true;
    NRF_LOG_INFO("Transfer completed.");
}

/**@brief Function for application main entry.
 */
int main(void)
{
    uint16_t n; //TEST
    uint32_t err_code = NRF_SUCCESS;
    log_init();
    gpio_init();
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.ss_pin   = DAC_CS_PIN;
    spi_config.miso_pin = NRFX_SPIM_PIN_NOT_USED;
    spi_config.mosi_pin = DAC_SDI_PIN;
    spi_config.sck_pin  = DAC_SCK_PIN;
    spi_config.frequency = NRF_SPIM_FREQ_8M;
    nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL);
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(&dac_buf, DAC_BUF_SIZE, m_rx_buf, 8);

    //SPI test
	// Fill the buffer and generate a waveform on the debug pin to check on the logic analyser
    for(n=0; n<16; n++)
    {
      dac_buf[n] = n;
      nrf_delay_us(1);
      nrfx_gpiote_out_clear(PIN_DBG);
      nrf_delay_us(1);
      nrfx_gpiote_out_set(PIN_DBG);
    }
    spi_xfer_done = false;
    APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
    while (!spi_xfer_done)
    {
        __WFE();
    }    
    nrfx_gpiote_out_clear(PIN_DBG);
    // Enter main loop.
    for (;;)
        idle_state_handle();
}

sdk_config.h

Parents
  • You may be seeing a 'scope alias issue, but even if not using the SPI at 8MHz really requires high drive outputs; these must be set after initialising the SPI:

      nrf_gpio_cfg(DAC_CS,  NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
      nrf_gpio_cfg(DAC_SDI, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
      nrf_gpio_cfg(DAC_SCK, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);

    The Rx stuff is redundant, just use null and 0 thus:

    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(&dac_buf, DAC_BUF_SIZE, NULL, 0);

    If there are still issues, try dropping to clock to 1MHz just to check the capacitance on the connecting leads are not too high, Leads more than a few inches (100mm) can cause transmission issues on the SCK at the DAC if it happens to be a high-speed DAC; in that case a damping or termination resistor will be required. Usually high-drive alone fixes that though.

  • OK - humble pie time! Yes it was aliasing as the sampling rate on my LA was sett too low for some reason Disappointed The drive rate will be useful though... It's working fine as-is but would be good to set it anyway so not a wasted exercise.

    Do you have any info on the sdk config? The one I'm using has been hacked about and may cause issues down the line. For example I can't see any option for setting EasyDMA, I may not need it as I'm only sending 2 bytes at a time but every little helps as the CPU can potentially get quite busy at times (I have a SoftDevice running, a SD card connected by SPI, this DAC output and a 5kbps Manchester decoder potentially all running concurrrently)

    Thanks

    Nick

Reply
  • OK - humble pie time! Yes it was aliasing as the sampling rate on my LA was sett too low for some reason Disappointed The drive rate will be useful though... It's working fine as-is but would be good to set it anyway so not a wasted exercise.

    Do you have any info on the sdk config? The one I'm using has been hacked about and may cause issues down the line. For example I can't see any option for setting EasyDMA, I may not need it as I'm only sending 2 bytes at a time but every little helps as the CPU can potentially get quite busy at times (I have a SoftDevice running, a SD card connected by SPI, this DAC output and a 5kbps Manchester decoder potentially all running concurrrently)

    Thanks

    Nick

Children
  • Ah, sdk_config.h - the bane of developers. I put stuff like this at the top of sdk_config.h:

    #if defined(FEATURE_NO_32_KHZ_CRYSTAL)
    #define NRFX_CLOCK_CONFIG_LF_SRC         0
    #define CLOCK_CONFIG_LF_SRC              0
    #define NRF_SDH_CLOCK_LF_SRC             0
    #define NRF_SDH_CLOCK_LF_RC_CTIV        16
    #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV    2
    #define NRF_SDH_CLOCK_LF_ACCURACY        1 // <1=> NRF_CLOCK_LF_ACCURACY_500_PPM
    #endif
    
    #if defined(FEATURE_SPIM2)
    #define SPIM_PRESENT               1
    #define NRF_SPI_ENABLED            1//0
    #define NRFX_SPI_ENABLED           1//0
    #define NRF_SPIM2_ENABLED          1//0
    #define NRFX_SPIM_ENABLED          1//0
    #define NRFX_SPIM2_ENABLED         1//0
    #endif
    
    #if defined(FEATURE_SPIM3)
    #define SPIM_PRESENT               1
    #define NRF_SPI_ENABLED            1//0
    #define NRFX_SPI_ENABLED           1//0
    #define NRF_SPIM3_ENABLED          1//0
    #define NRFX_SPIM_ENABLED          1//0
    #define NRFX_SPIM3_ENABLED         1//0
    #define NRFX_SPIM_EXTENDED_ENABLED 1//0
    #endif

    Then in project Preprocessro definitions FEATURE_SPIM2 etc; not pretty but it save lots of time trying to do it "properly" .. these settings give you DMA via the Nordic drivers

Related