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

SPIM: MOSI line not consistent with Tx data buffer

I am using the SPIM example in the nRF52840 SDK.  It uses SPI_INSTANCE 3.  I am doing a simple SPI Write of 2 bytes.

I get SS, SCK, working properly.  MOSI is transitioning but it is not related to anything in the Tx buffer.  I have tried both NRFX_SPIM_XFER_TRX and NRFX_SPIM_XFER_TX function calls.

Any help would be appreciated.

Below is an excerpt of some of the relevant code: 

m_tx_buf[0] = 0x55; /**< TX buffer. */
m_tx_buf[1] = 0xAA; /**< TX buffer. */
m_tx_buf[2] = 0x55; /**< TX buffer. */

m_rx_buf[0] = 0x11; /**< TX buffer. */
m_rx_buf[1] = 0x66; /**< TX buffer. */
m_rx_buf[2] = 0x11; /**< TX buffer. */

tx_length = 2; /**< Transfer length. */
rx_length = 0; /**< Transfer length. */

// nrfx_spim_xfer_desc_t xfer_desc_WREN = NRFX_SPIM_XFER_TX(m_tx_buf, tx_length);
nrfx_spim_xfer_desc_t xfer_desc_WREN = NRFX_SPIM_XFER_TRX(m_tx_buf, tx_length, m_rx_buf, rx_length);

----------------------------

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
spi_config.frequency = NRF_SPIM_FREQ_1M;
spi_config.ss_pin = NRFX_SPIM_SS_PIN;
spi_config.miso_pin = NRFX_SPIM_MISO_PIN;
spi_config.mosi_pin = NRFX_SPIM_MOSI_PIN;
spi_config.sck_pin = NRFX_SPIM_SCK_PIN;
spi_config.mode = NRF_SPIM_MODE_3; // clk normally high, rising edge
spi_config.bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST;
// spi_config.dcx_pin = NRFX_SPIM_DCX_PIN;
spi_config.use_hw_ss = true;
spi_config.ss_active_high = false;
APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

----------------------------------

while (1)
{
     // Reset rx buffer and transfer done flag
     // memset(m_rx_buf, 0, rx_length);
    spi_xfer_done = false;

   APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc_WREN, 0));

   while (!spi_xfer_done)
   {
      _   _WFE();
    }

}

Parents Reply
  • Sure, no problem.  I only have a two channel scope but you can see CS and MOSI and CS and SCK. SPI is configured for mode3 so sck normally high and data clocked in on rising edge. It appears that the data on MOSI, is synchronous to SCK as it should be and it looks like it is 0b00000011 followed by 0b00000000.  This MOSI data does not change regardless of how I initialize the output or input buffers, and it doesn't even remotely match the data in the Tx or Rx buffers.

Children
  • Hi,

    Which SDK version are you using? I implemented your code in the SPIM example with the exception of the length of the buffer. I changed the size of the tx and rx buffer to the length of the buffer instead of 2. I've included a screenshot of the MOSI and SCK line, which shows the correct TX data being sent. I've included the code for your comparison. 

    /**
     * Copyright (c) 2017 - 2019, 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.
     *
     */
    #include "nrfx_spim.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define NRFX_SPIM_SCK_PIN  3
    #define NRFX_SPIM_MOSI_PIN 4
    #define NRFX_SPIM_MISO_PIN 28
    #define NRFX_SPIM_SS_PIN   29
    #define NRFX_SPIM_DCX_PIN  30
    
    #define SPI_INSTANCE  3      
    #define TEST
                                         /**< 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. */
    #ifndef TEST
    
    #define TEST_STRING "Nordic123456789012345678901234567890"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];  /**< RX buffer. */
    #endif
    #ifdef TEST
    static uint8_t      m_tx_buf[]  =   {0x55, 0xAA, 0x55};
    static uint8_t      m_rx_buf[]  =   {0x11, 0x66, 0x11};
    #endif
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    
    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);
    
        nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
        spi_config.frequency      = NRF_SPIM_FREQ_1M;
        spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
        spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
        spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
        spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
        spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
        spi_config.use_hw_ss      = true;
        spi_config.ss_active_high = false;
    
        #ifdef TEST
        spi_config.mode = NRF_SPIM_MODE_3;
    
        #endif
        APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));
    
        NRF_LOG_INFO("NRFX SPIM example started.");
    
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
        }
    }
    

  • SEGGER Embedded Studio for ARM
    Release 4.20  Build 2019081500.39804
    Windows x64

    There are several differences:

    I assign pins differently:
    #define NRFX_SPIM_SCK_PIN 27 
    #define NRFX_SPIM_MOSI_PIN 7 
    #define NRFX_SPIM_MISO_PIN 8 
    #define NRFX_SPIM_SS_PIN NRF_GPIO_PIN_MAP(1,9) 
    //#define NRFX_SPIM_DCX_PIN 30 

    You define a DCX pin, I don't use DCX.

    Lastly, you do a DCX call:  APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));

    I use:   APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc_WREN, 0));

  • Hi,

    Sorry for the confusion, It wasn't clear from the limited code that you shared that you've used other pins then in the example. I changed the pins to the one that you use and changed to SPI call without DCX, I still see the correct output form MOSI. Is the pins only used for SPI? Pin 7 and 8 is often set as the UART TX and RX in many of our examples in the SDK. Here is the code that I've used and the trace from the MOSI line.

    /**
     * Copyright (c) 2017 - 2019, 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.
     *
     */
    #include "nrfx_spim.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define TEST
    
    
    #ifdef TEST
    #define NRFX_SPIM_SCK_PIN  27
    #define NRFX_SPIM_MOSI_PIN 7
    #define NRFX_SPIM_MISO_PIN 8
    #define NRFX_SPIM_SS_PIN   NRF_GPIO_PIN_MAP(1,9) 
    #else
    #define NRFX_SPIM_SCK_PIN  3
    #define NRFX_SPIM_MOSI_PIN 4
    #define NRFX_SPIM_MISO_PIN 28
    #define NRFX_SPIM_SS_PIN   29
    #define NRFX_SPIM_DCX_PIN  30
    #endif
    
    #define SPI_INSTANCE  3      
                                         /**< 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. */
    #ifndef TEST
    
    #define TEST_STRING "Nordic123456789012345678901234567890"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];  /**< RX buffer. */
    #else
    static uint8_t      m_tx_buf[]  =   {0x55, 0xAA, 0x55};
    static uint8_t      m_rx_buf[]  =   {0x11, 0x66, 0x11};
    #endif
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    
    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);
    
        nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
        spi_config.frequency      = NRF_SPIM_FREQ_1M;
        spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
        spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
        spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
        spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
        spi_config.use_hw_ss      = true;
        spi_config.ss_active_high = false;
        #ifndef TEST
        spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
        #else
        spi_config.mode = NRF_SPIM_MODE_3;
        #endif
        APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));
    
        NRF_LOG_INFO("NRFX SPIM example started.");
    
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
        #ifndef TEST
            APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));
    
        #else
             APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, 0));
        #endif
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
        }
    }
    

    regards

    Jared 

  • Ok, thank you for your help.  I can now get MOSI to work the way your example does. In the process however I found that part of my problem is my understanding of the following function:

    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length1, m_rx_buf, m_length2);

    My expectation is that this function transmits the number of bytes defined by m_length1.  However both m_length1 and m_length2 have an affect on the number of transmitted bytes in different ways. I don't understand this.

    Also, if I just want to transmit, why do I need to define m_rx_buf?  And what function would I use if I just want to receive bytes?  

  • Hi,

    NRFX_SPIM_XFER_TRX() as the name suggests, sends and receives data.  m_length1 (tx_length) and m_length2 (rx_length) is therefore the size of the buffer that the data is sent from and where it's received respectively. If you only want to send data then the correct function to use would be NRFX_SPIM_XFER_TX(), and NRFX_SPIM_XFER_RX() if you only want to receive data.

    regards 

    Jared

Related