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

nRF9160 SPI and spi_cs_control

Hi,

I got SPI working when writing to the CS pins directly. I thought however it might shorten the SPI acces when using spi_cs_control. When executing the code I will however get an error on the first spi_transceive:

Here is my code:

#include        <nrf9160.h>
#include        <drivers/spi.h>
#include        <drivers/gpio.h>
#include        <zephyr.h>
#include    "qlocx_digio.h"
#include        <logging/log.h>

//*************************** Definitions ***********************************

LOG_MODULE_REGISTER(app_qlocx_digio, CONFIG_APP_LOG_LEVEL);

#define CHECK_DELAY     2              // Check every 10 ms
#define TURN_OFF_DELAY  5
//#define AUTO_RESET

#define OLD_ON_OUT1     0x0100
#define OLD_ON_OUT2     0x0200
#define OLD_ON_OUT3     0x0400
#define OLD_ON_OUT4     0x0800
#define OLD_ON_OUT5     0x1000
#define OLD_ON_OUT6     0x2000
#define OLD_ON_OUT7     0x4000
#define OLD_ON_OUT8     0x8000

#define OPEN_LOAD_DETECT   (OLD_ON_OUT1 | OLD_ON_OUT2 | OLD_ON_OUT3 | OLD_ON_OUT4 | OLD_ON_OUT5 | OLD_ON_OUT6 | OLD_ON_OUT7 | OLD_ON_OUT8 )

static struct device * gpio_dev;
static struct device * spi_dev;

static uint16_t last_output = 0x0000;
static uint16_t last_status = 0x0000;


static bool out_state[MAX_OUTPUT];

//*************************** Internal functions ****************************
static struct spi_cs_control cs_pwr1 = {
        .delay = 1,
        .gpio_dev = NULL,
        .gpio_pin = 25,
        };


static struct spi_cs_control cs_pwr2 = {
        .delay = 1,
        .gpio_dev = NULL,
        .gpio_pin = 18,
        };

static struct spi_config spi_cfg_pwr1 = {
    .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
             SPI_MODE_CPHA,
    .frequency = 4000000,
    .slave = 0,
        .cs = &cs_pwr1,
};

static struct spi_config spi_cfg_pwr2 = {
    .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
             SPI_MODE_CPHA,
    .frequency = 4000000,
    .slave = 0,
        .cs = &cs_pwr2,
};



static void spi_init(void)
{
const char* spiName = "SPI_3";

      spi_dev = device_get_binding(spiName);

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


// Set output
// ch = 0 - 15; state = true or false
void    spi_Out(uint8_t ch, uint8_t state)
{
uint16_t output;
uint16_t data;
int err;
static uint8_t tx_buffer[2];
static uint8_t rx_buffer[2];

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
};
   
    gpio_pin_set(gpio_dev, 23, 1);            // EN_PWR
    /*
    if( ch < OPEN_DOOR9){
        gpio_pin_set(gpio_dev, 18, 0);        // CS_PWR2  passive
        gpio_pin_set(gpio_dev, 25, 1);        // CS_PWR1  active
    }
    else{
        gpio_pin_set(gpio_dev, 25, 0);        // CS_PWR1  passive
        gpio_pin_set(gpio_dev, 18, 1);        // CS_PWR2  active        
    }
    data = 1 << ch;
    
    if(state){        
        last_output |= data;        
    }
    else{
        last_output &= ~data;
    }
    if( ch < OPEN_DOOR9){
        output = last_output | OPEN_LOAD_DETECT;
    }
    else{
        output = (uint16_t)(last_output >> 8 ) | OPEN_LOAD_DETECT;
    }
    tx_buffer[1] = output & 0xFF;
    tx_buffer[0] = output >> 8;
    err = spi_transceive(spi_dev, &spi_cfg, &tx, &rx);

    if( ch < OPEN_DOOR9){
        last_status &= 0xFF00;
        last_status |= rx_buffer[0];
    }
    else{
        last_status &= 0x00FF;
        last_status |= rx_buffer[0] << 8;
    }
    gpio_pin_set(gpio_dev, 25, 0);        // CS_PWR1  passive
    gpio_pin_set(gpio_dev, 18, 0);        // CS_PWR2  passive
    //gpio_pin_set(gpio_dev, 23, 0);        // EN_PWR   passive
   */
   data = 1 << ch;
    
    if(state){        
        last_output |= data;        
    }
    else{
        last_output &= ~data;
    }
    if( ch < OPEN_DOOR9){
        output = last_output | OPEN_LOAD_DETECT;
    }
    else{
        output = (uint16_t)(last_output >> 8 ) | OPEN_LOAD_DETECT;
    }
    tx_buffer[1] = output & 0xFF;
    tx_buffer[0] = output >> 8;
    if( ch < OPEN_DOOR9){
        err = spi_transceive(spi_dev, &spi_cfg_pwr1, &tx, &rx);
    }
    else{
        err = spi_transceive(spi_dev, &spi_cfg_pwr2, &tx, &rx);
    }
    if( ch < OPEN_DOOR9){
        last_status &= 0xFF00;
        last_status |= rx_buffer[0];
    }
    else{
        last_status &= 0x00FF;
        last_status |= rx_buffer[0] << 8;
    }
}


//*************************** External functions ****************************
void    digio_Init(void)
{
uint8_t i;

    spi_init();
    gpio_dev = device_get_binding("GPIO_0");
    if (!gpio_dev) {
        LOG_ERR("Could not get GPIO_0 device.");
    }
    cs_pwr1.gpio_dev = gpio_dev;
    cs_pwr2.gpio_dev = gpio_dev;
    if(gpio_pin_configure(gpio_dev, 0, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.0.");
    }
    if(gpio_pin_configure(gpio_dev, 1, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.1.");
    }
    if(gpio_pin_configure(gpio_dev, 2, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.2.");
    }
    if(gpio_pin_configure(gpio_dev, 3, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.3.");
    }
    if(gpio_pin_configure(gpio_dev, 4, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.4.");
    }
    if(gpio_pin_configure(gpio_dev, 5, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.5.");
    }
    if(gpio_pin_configure(gpio_dev, 6, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.6.");
    }
    if(gpio_pin_configure(gpio_dev, 7, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.7.");
    }
    if(gpio_pin_configure(gpio_dev, 8, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.8.");
    }
    if(gpio_pin_configure(gpio_dev, 9, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.9.");
    }
    if(gpio_pin_configure(gpio_dev, 10, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.10.");
    }
    if(gpio_pin_configure(gpio_dev, 11, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.11.");
    }
    if(gpio_pin_configure(gpio_dev, 12, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.12.");
    }
    if(gpio_pin_configure(gpio_dev, 13, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.13.");
    }
    if(gpio_pin_configure(gpio_dev, 14, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.14.");
    }
    if(gpio_pin_configure(gpio_dev, 15, GPIO_INPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.15.");
    }
    if(gpio_pin_configure(gpio_dev, 18, GPIO_OUTPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.18.");
    }
    if(gpio_pin_configure(gpio_dev, 23, GPIO_OUTPUT | GPIO_ACTIVE_HIGH) < 0){
        LOG_ERR("Could not configure P0.23.");
    }
    if(gpio_pin_configure(gpio_dev, 24, GPIO_OUTPUT | GPIO_ACTIVE_HIGH) < 0){
        LOG_ERR("Could not configure P0.24.");
    }
    if(gpio_pin_configure(gpio_dev, 25, GPIO_OUTPUT | GPIO_ACTIVE_LOW) < 0){
        LOG_ERR("Could not configure P0.25.");
    }
for(i = 0;i <MAX_OUTPUT;i++){
        digio_Out(i, 0);
    }   
}

I can not find any documentation on gpio_dt_flags. Maybe spi_cs_control is just not supported for nRF9160??

Best regards

Dirk

Parents
  • Hi Dirk, 

    From the top of output log you have provided, it states:
    devicetree and spi_context CS levels are not equal

    Have you configured SPI in your devicetree?

    We have a simple (a little outdated) sample on SPI here


    The gpio_dt_flags are GPIO devicetree flags:

    /**
     * @brief SPI Chip Select control structure
     *
     * This can be used to control a CS line via a GPIO line, instead of
     * using the controller inner CS logic.
     *
     * @param gpio_dev is a valid pointer to an actual GPIO device. A NULL pointer
     *        can be provided to full inhibit CS control if necessary.
     * @param gpio_pin is a number representing the gpio PIN that will be used
     *    to act as a CS line
     * @param delay is a delay in microseconds to wait before starting the
     *    transmission and before releasing the CS line
     * @param gpio_dt_flags is the devicetree flags corresponding to how the CS
     *    line should be driven. GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
     *    equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
     *    spi_config.
     */
    struct spi_cs_control {
    	const struct device	*gpio_dev;
    	uint32_t		delay;
    	gpio_pin_t		gpio_pin;
    	gpio_dt_flags_t		gpio_dt_flags;
    };
    

    There are several examples of the usage in NCS, i.e. 

    More information on Device Tree can be found here.

    E.g. from nrf\boards\arm\thingy91_nrf9160\thingy91_nrf9160_common.dts you can see how the Thingy:91 has configured SPI3 CS pin. 



    Kind regards,
    Øyvind

  • Hi Öyvind,

     Q3IoT_201204.zip

    Even after adding the cs definitions to our board_common.dts I get similar errors. I attach our board definition files.

    Best regards

    Dirk

Reply Children
Related