This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

using spi_write() & spi_read() not behaving the same as spi_transceive() for spi data in provided spi sample

Hi,

I tried running an spi sample program with code as in below, shorted the MOSI and MISO pins and data was visibly received in print statement:

#include <zephyr.h>

#include <sys/printk.h>
#include <drivers/spi.h>
#include <drivers/gpio.h>



uint32_t freq = 4000000;
static const struct spi_config spi_cfg = {freq,(SPI_WORD_SET(8) | SPI_TRANSFER_MSB),0,nullptr};




const device * spi_dev;



static void spi_init(void)
{
const char* spiName = "SPI_1";
//const char* const spiName = "spi1";
spi_dev = device_get_binding(spiName);



if (spi_dev == NULL) {
printk("Could not get %s device\n", spiName);
return;
}
}



void spi_test_send(void)
{
int err;
static uint32_t tx_buffer[1]={0x05};
//static uint8_t tx_buffer = 128;
//static char tx_buffer[3]={'D','s','s'};
static uint32_t rx_buffer[1];
//static uint8_t rx_buffer;



const struct spi_buf tx_buf = {
.buf = tx_buffer,
.len = sizeof(tx_buffer)
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};



struct spi_buf rx_buf = {
.buf = rx_buffer,
.len = sizeof(rx_buffer),
};
const struct spi_buf_set rx = {
.buffers = &rx_buf,
.count = 1
};


err = spi_transceive(spi_dev, &spi_cfg, &tx, &rx);

if (err) {
printk("SPI error: %d\n", err);
} else {
/* Connect MISO to MOSI for loopback */
printk("TX sent: %d\n", tx_buffer[0]);
printk("RX recv: %d\n", rx_buffer[0]);

}
}



void main(void)
{
printk("SPIM Example\n");
spi_init();



while (1) {
spi_test_send();
k_sleep(K_SECONDS(1));
}
}

While in the same code if i use spi_write( ) & spi_read( ) apis, which inturn call spi transceive, I am not receiving any data, code as in below:

#include <zephyr.h>

#include <sys/printk.h>
#include <drivers/spi.h>
#include <drivers/gpio.h>



uint32_t freq = 4000000;
static const struct spi_config spi_cfg = {freq,(SPI_WORD_SET(8) | SPI_TRANSFER_MSB),0,nullptr};




const device * spi_dev;



static void spi_init(void)
{
const char* spiName = "SPI_1";
//const char* const spiName = "spi1";
spi_dev = device_get_binding(spiName);



if (spi_dev == NULL) {
printk("Could not get %s device\n", spiName);
return;
}
}



void spi_test_send(void)
{
int err;
static uint32_t tx_buffer[1]={0x05};
//static uint8_t tx_buffer = 128;
//static char tx_buffer[3]={'D','s','s'};
static uint32_t rx_buffer[1];
//static uint8_t rx_buffer;



const struct spi_buf tx_buf = {
.buf = tx_buffer,
.len = sizeof(tx_buffer)
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};



struct spi_buf rx_buf = {
.buf = rx_buffer,
.len = sizeof(rx_buffer),
};
const struct spi_buf_set rx = {
.buffers = &rx_buf,
.count = 1
};



err = spi_write(spi_dev, &spi_cfg, &tx);
err = spi_read(spi_dev, &spi_cfg, &rx);

if (err) {
printk("SPI error: %d\n", err);
} else {
/* Connect MISO to MOSI for loopback */
printk("TX sent: %d\n", tx_buffer[0]);
printk("RX recv: %d\n", rx_buffer[0]);

}
}



void main(void)
{
printk("SPIM Example\n");
spi_init();



while (1) {
spi_test_send();
k_sleep(K_SECONDS(1));
}
}

I am getting just -1 in receive buffer.

Kindly suggest what i can do to make spi_write & spi_read work..?

  • Clearly, for the above code, master board (BL653) is transmitting the data just fine, along with controlling the cs, as in channel-2, channel-1 is MOSI & channel 0 is clock.

    Hello  ,

    Clearly master board it is doing, I think something work with slave board or slave pin out config.

    Can you have a look at slave code, config and kindlu suggest.
     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CONFIG_DEBUG=y
    CONFIG_GPIO=y
    CONFIG_SPI=y
    #CONFIG_SPI_1=y
    CONFIG_PRINTK=y
    CONFIG_POLL=y
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    SLAVE:************************************

    Thanks.

  • Hi,

     

    P0.01 is default setup to be one of the inputs of the external 32k crystal:

    https://infocenter.nordicsemi.com/topic/ps_nrf52833/pin.html?cp=4_1_0_6_0_1#wlcsp

     

    I would recommend that you choose another GPIO for the CSN pin.

     

    There's a couple of samples available here with both SPIM and SPIS:

    https://github.com/sigurdnev/ncs-playground/tree/master/samples

     

    Kind regards,

    Håkon

  • Hello ,


    There's a couple of samples available here with both SPIM and SPIS:

    https://github.com/sigurdnev/ncs-playground/tree/master/samples

    This does not suffice my requirement as everywhere here only spi_transceive is being used, while I am supposed to evaluate spi_read & spi_write.

    And

    P0.01 is default setup to be one of the inputs of the external 32k crystal:

    Thank you for the kind suggestion, I used P0.11 and after a couple of resets I was able to print 0x1234(data sent via master)

    on slave as in below:

    Need your help in understanding why the -116 (-ETIMEOUT) error is still persistent with the call to SPI_Read( ).
    I need to eliminate this error.

    For your kind reference, attaching the master board code & slave board code with configs.

    Master (BL653):

    prj.conf:

    CONFIG_DEBUG=y
    
    CONFIG_GPIO=y
    
    CONFIG_SPI=y
    #CONFIG_SPI_1=y
    
    CONFIG_PRINTK=y
    
    CONFIG_POLL=y

    bl653_dvk.overlay:

    /*
     * Copyright (c) 2019 Callender-Consulting, LLC
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    &spi1 {
    	compatible = "nordic,nrf-spi";
    	status = "okay";
    	sck-pin = <41>;
    	mosi-pin = <40>;
    	miso-pin = <4>;
    	cs-gpios = <&gpio0 23 0>;
    };

    main.c:

    /**
     * Copyright (c) 2019 - Callender-Consulting. LLC
     *
     *   You should have received a copy of the GNU General Public License.
     *   see <https://www.gnu.org/licenses/>.
     * 
     */
    #include <string.h>
    #include <errno.h>
    #include <zephyr.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/spi.h>
    
    #define STACKSIZE 1024
    #define PRIORITY 99
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    
    #define SPI_MASTER_BUS_NAME     		DT_INST_0_NORDIC_NRF_SPI_LABEL
    #define SPI_MASTER_GPIOS_NAME    		DT_ALIAS_GPIO_0_LABEL
    #define SPI_MASTER_GPIO_IRQ_PIN  		DT_ALIAS_SPI_0_CSN_PIN
    
    /* Needs to be aligned with the SPI master buffer size */
    #define SPI_MAX_MSG_LEN         255
    
    typedef struct spi_master_msg {
    	uint32_t       length;
        uint8_t        data [SPI_MAX_MSG_LEN];
    } spi_master_msg_t;
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    int spi_master_write(struct device * spi, 
                         struct spi_config * spi_cfg,
                         uint16_t * data)
    {
        struct spi_buf bufs = {
                .buf = data,
                .len = 2
        };
        struct spi_buf_set tx = {
            .buffers = &bufs
        };
    
        tx.count = 1;
    
        return spi_write(spi, spi_cfg, &tx);
    }
    
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    int spi_master_read(struct device * spi, 
                        struct spi_config * spi_cfg,
                        uint16_t * data)
    {
        struct spi_buf bufs = {
                .buf = data,
                .len = 2
        };
        struct spi_buf_set rx = {
            .buffers = &bufs
        };
    
        rx.count = 1;
    
        return spi_read(spi, spi_cfg, &rx);
    }
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    void spi_master_init(void)
    {
        struct device * spi;
        struct spi_config spi_cfg;
        struct spi_cs_control cs_ctrl;
    
        uint16_t tx_data = 0x1234;
        uint16_t rx_data = 0;
    
        printk("SPI Master example application\n");
    
        printk("rx_data buffer at %p\n", &rx_data);
    
        spi = device_get_binding("SPI_1");
        if (!spi) {
            printk("Could not find SPI driver\n");
            return;
        }
    
        cs_ctrl.gpio_dev = device_get_binding("GPIO_0");
        cs_ctrl.gpio_pin = 23;
        cs_ctrl.delay = 0;
    
        /*
         *  SPI controller configuration structure for the nRF52 series.
         *
         *  param frequency is the bus frequency in hertz
         *  param operation is a bit field with the following parts:
         *
         *     operational mode  [ 0 ]       - master or slave.
         *     mode              [ 1 : 3 ]   - Polarity, phase and loop mode.
         *     transfer          [ 4 ]       - LSB or MSB first.
         *     word_size         [ 5 : 10 ]  - Size of a data frame in bits.
         *     lines             [ 11 : 12 ] - MISO lines: Single/Dual/Quad/Octal.
         *     cs_hold           [ 13 ]      - Hold on the CS line if possible.
         *     lock_on           [ 14 ]      - Keep resource locked for the caller.
         *     cs_active_high    [ 15 ]      - Active high CS logic.
         *
         *  param master is the master number from 0 to host controller master limit.
         *  param cs is a valid pointer on a struct spi_cs_control is CS line is
         *        emulated through a gpio line, or NULL otherwise.
         */
    
        /* Note: Implicid Mode-0; e.g. CPOL=0, CPHA=0 -- the only mode supported */
        /* Note: The nRF52 series doesn't support CS pin configuration */
    
        memset(&spi_cfg, 0, sizeof(spi_cfg));
    
        spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_MASTER 
        //                    | SPI_MODE_CPOL | SPI_MODE_CPHA 
                            | SPI_LINES_SINGLE; 
        spi_cfg.frequency = 1000000;
        spi_cfg.cs = &cs_ctrl;
    
        printk("%s: master config @ %p:"
                " wordsize(%u), mode(%u/%u/%u)\n", __func__, &spi_cfg,
                SPI_WORD_SIZE_GET(spi_cfg.operation),
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_CPOL) ? 1 : 0,
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_CPHA) ? 1 : 0,
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_LOOP) ? 1 : 0);
    
        while (1)  { //for (int i=0; i < 2; i++) {
    
            spi_master_write(spi, &spi_cfg, &tx_data);
    
            printk("Sent: 0x%02X\n", tx_data);
    
            spi_master_read(spi, &spi_cfg, &rx_data);
    
            printk("Received: 0x%02X\n", rx_data);
    
            printk("Response is %s\n",  (rx_data == 0x5678) ? "correct" : "incorrect");
    
            k_sleep(K_SECONDS(2));
        }
        printk("done\n");
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    void spi_master_thread(void * id, void * unused1, void * unused2)
    {
        printk("%s\n", __func__);
    
        spi_master_init();
    
        while(1) { /* spin */}
    }
    
    K_THREAD_DEFINE(spi_master_id, STACKSIZE, spi_master_thread,NULL, NULL, NULL, PRIORITY, 0, 0);
    

    Slave (nRF52833_dk):

    prj.conf:

    # nothing here
    CONFIG_DEBUG=y
    
    CONFIG_GPIO=y
    
    CONFIG_SPI=y
    CONFIG_SPI_SLAVE=y
    CONFIG_PRINTK=y
    

    nrf52833dk_nrf52833.overlay:

    /*
    * Copyright (c) 2019 Callender-Consulting, LLC
    *
    * SPDX-License-Identifier: Apache-2.0
    */
    
    &spi0 {
    compatible = "nordic,nrf-spis";
    status = "okay";
    sck-pin = <27>;
    mosi-pin = <26>;
    miso-pin = <29>;
    csn-pin = <11>;
    def-char = <0xFF>;
    };

    main.c:

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    #include <string.h>
    #include <errno.h>
    #include <zephyr.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/spi.h>
    
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    
    #define SPI_SLAVE_BUS_NAME     			DT_INST_0_NORDIC_NRF_SPIS_LABEL
    #define SPI_SLAVE_GPIOS_NAME    		DT_ALIAS_GPIO_0_LABEL
    #define SPI_SLAVE_GPIO_IRQ_PIN  		DT_ALIAS_SPI_0_CSN_PIN
    
    #define STACKSIZE 1024
    #define PRIORITY 99
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    void spi_slave_init(void);
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    int spi_slave_write(struct device * spi, 
                        struct spi_config * spi_cfg,
                        uint16_t * data)
    {
        struct spi_buf bufs = {
                .buf = data,
                .len = 2
        };
        struct spi_buf_set tx = {
            .buffers = &bufs
        };
        
        tx.count = 1;
    
        return spi_write(spi, spi_cfg, &tx);
    }
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    int spi_slave_read(struct device * spi, 
                       struct spi_config * spi_cfg,
                       uint16_t * data)
    {
        struct spi_buf bufs = {
                .buf = data,
                .len = 2
        };
        struct spi_buf_set rx = {
            .buffers = &bufs
        };
        
        rx.count = 1;
    
        return spi_read(spi, spi_cfg, &rx);
    }
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    void spi_slave_init(void)
    {
        struct device * spi;
        struct spi_config spi_cfg;
    
    
        uint16_t tx_data = 0x5678;
        uint16_t rx_data = 0;
    
        printk("SPI Slave example application\n");
    
        printk("rx_data buffer at %p\n", &rx_data);
    
        spi = device_get_binding("SPI_0");
        if (!spi) {
            printk("Could not find SPI driver\n");
            return;
        }
    
    
    
        /*
         *  SPI controller configuration structure for the nRF52 series.
         *
         *  param frequency is the bus frequency in hertz
         *  param operation is a bit field with the following parts:
         *
         *     operational mode  [ 0 ]       - master or slave.
         *     mode              [ 1 : 3 ]   - Polarity, phase and loop mode.
         *     transfer          [ 4 ]       - LSB or MSB first.
         *     word_size         [ 5 : 10 ]  - Size of a data frame in bits.
         *     lines             [ 11 : 12 ] - MISO lines: Single/Dual/Quad/Octal.
         *     cs_hold           [ 13 ]      - Hold on the CS line if possible.
         *     lock_on           [ 14 ]      - Keep resource locked for the caller.
         *     cs_active_high    [ 15 ]      - Active high CS logic.
         *
         *  param slave is the slave number from 0 to host controller slave limit.
         *  param cs is a valid pointer on a struct spi_cs_control is CS line is
         *        emulated through a gpio line, or NULL otherwise.
         */
    
        /* Note: Implicid Mode-0; e.g. CPOL=0, CPHA=0 -- the only mode supported */
        /* Note: The nRF52 series doesn't support CS pin configuration */
    
        memset(&spi_cfg, 0, sizeof(spi_cfg));
    
        spi_cfg.operation = SPI_WORD_SET(8) | SPI_OP_MODE_SLAVE; 
        spi_cfg.frequency = 1000000;
        spi_cfg.slave = 1;
    
        printk("%s: slave config @ %p:"
                " wordsize(%u), mode(%u/%u/%u)\n", __func__, &spi_cfg,
                SPI_WORD_SIZE_GET(spi_cfg.operation),
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_CPOL) ? 1 : 0,
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_CPHA) ? 1 : 0,
                (SPI_MODE_GET(spi_cfg.operation) & SPI_MODE_LOOP) ? 1 : 0);
    
        while (1) {
            int err = spi_slave_read(spi, &spi_cfg, &rx_data);
    
            if (rx_data == 0x1234) {
                spi_slave_write(spi, &spi_cfg, &tx_data);
            }
            printk("err: %d ,Received: 0x%04X -- %s \n",err, rx_data,
                   (rx_data == 0x1234) ? "ok" : "wrong"); 
        }
    }
    
    
    /*---------------------------------------------------------------------------*/
    /*                                                                           */
    /*---------------------------------------------------------------------------*/
    void spi_slave_thread(void * id, void * unused1, void * unused2)
    {
        printk("%s\n", __func__);
    
        spi_slave_init();
    
        while (1) { /* spin */}
    }
    
    K_THREAD_DEFINE(spi_slave_id, STACKSIZE, spi_slave_thread, 
                    NULL, NULL, NULL, PRIORITY, 0, 0);
    

    And also the master's captured waveforms:

    Kindly suggest,

    Thanks,

  • Ubaid_M said:
    This does not suffice my requirement as everywhere here only spi_transceive is being used, while I am supposed to evaluate spi_read & spi_write.

    Could you please test those examples for SPIM + SPIS to see if they work?

     

    Kind regards,

    Håkon

  • Hello Hakan,

    Could you please test those examples for SPIM + SPIS to see if they work?

    I mean to say, no where in those examples spi_read( ) & spi_write( ) are being used.

    And i need to work with spi_read( ) & spi_write( ), which I am able to currently with these example,

    Master (BL653):

    &

    Slave (nRF52833_dk):

    Except for this, towards which I need your help:

    Need your help in understanding why the -116 (-ETIMEOUT) error is still persistent with the call to SPI_Read( ).
    I need to eliminate this error.

    Do you suggest i lower the frequency and check again..?

    Thanks

     

Related