Translating previously working code to NCS v2.2.0

I'm working on a project with the AD5940, and it looks like this case did the job.

 nrf52832+SPI+AD5940 cannot get ad5940id

 

However, I am using NCS v2.2.0 and not nRF5 v17.1 - so code translation is required.

My current code is as follows:

Overlay:

/ {
    gpio_custom {
        compatible = "gpio-keys";
        gpiocu0: gpiocu0 {
            label = "GPIO_D2";
            gpios = <&gpio1 4 0>;/* D2 */
        };
        gpiocu1: gpiocu1 {
            label = "GPIO_D5";
            gpios = <&gpio1 7 0>;/* D5 */
        };
        gpiocu2: gpiocu2 {
            label = "GPIO_D6";
            gpios = <&gpio1 8 0>;/* D6 */
        };
        ad5940reset: ad5940reset {
            label = "AD5940_RESET";
            gpios = <&gpio1 12 0>;/* D10 */
        };
    };
    aliases {
        gpiod2 = &gpiocu0;
        gpiod5 = &gpiocu1;
        gpiod6 = &gpiocu2;
        reset5940 = &ad5940reset;
    };
};


&arduino_spi {
    status = "okay";
    ad5940:ad5940@0{
        compatible = "adi,adxl345";
        // compatible = "adi,adxl372";
        reg = <0>;
        spi-max-frequency = <DT_FREQ_M(4)>;
        friendly-name = "ad5940";
        // int1-gpios = <&gpio1 8 0>;
    };
};

nRF adjustment(nRF_MCU_Port.c):

#include "ad5940.h"
#include "nRF_MCU_Port.h"
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#include <inttypes.h>
#include <dk_buttons_and_leds.h>

LOG_MODULE_REGISTER(BIA_AD5940);

volatile static uint32_t ucInterrupted = 0; /* Flag to indicate interrupt occurred */

#define AD5940_SPI DT_NODELABEL(ad5940)
static const struct spi_dt_spec dev_spi = SPI_DT_SPEC_GET(AD5940_SPI, SPI_WORD_SET(8) | SPI_MODE_GET(0), 0);

/* GPIO Configuration*/

#define D6 DT_ALIAS(gpiod6)
#if !DT_NODE_HAS_STATUS(D6, okay)
#error "Unsupported board: gpiod6 devicetree alias is not defined"
#endif

/*For the XXRst functions*/
#define R5940 DT_ALIAS(reset5940)
#if !DT_NODE_HAS_STATUS(R5940, okay)
#error "Unsupported board: reset_5940 devicetree alias is not defined"
#endif



uint8_t selector = 0;

static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(D6, gpios, {0});

/*AD5940 Reset Pin*/
static const struct gpio_dt_spec reset_dev = GPIO_DT_SPEC_GET_OR(R5940, gpios, {0});
/*Interrupt Special settings*/
static struct gpio_callback button_cb_data;

bool AD5940_SPI_SETUP(void)
{
    if (!device_is_ready(dev_spi.bus))
    {
        // LOG_ERR("Couldn't find %s\n", dev_spi.bus->name);
        printk("Couldn't find %s\n", dev_spi.bus->name);

        return false;
    }
    else
    {
        // LOG_WRN("SPI Initialized\n\r");
        bool success = (AD5940_ReadReg(REG_AFECON_ADIID) == AD5940_ADIID) ? true : false;
        if(success)
        printk("SPI Initialized\n\r");
        else
        // printk("SPI Initialization failed\n\r");
        return success;
    }
}

void Ext_Int0_Handler(const struct device *dev, struct gpio_callback *cb,
                      uint32_t pins)
{
    //    /* Clear interrupt flag */
    ucInterrupted = 1;
    // LOG_INF("Ext_Int0_Handler\n\r");
    // todo: ADD BLE and EMG interrupt handling here - or not - depends on the application
    /* This example just set the flag and deal with interrupt in AD5940Main function. It's your choice to choose how to process interrupt. */
}

//GPIO Free "interrupt"
void set_interrupt(void)
{
    ucInterrupted = 1;
}
void AD5940_INT_SETUP(void)
{
    int ret;
    if (!device_is_ready(button.port))
    {
        printk("Error: button device %s is not ready\n",
               button.port->name);
        return;
    }

    ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
    if (ret != 0)
    {
        printk("Error %d: failed to configure %s pin %d\n",
               ret, button.port->name, button.pin);
        return;
    }

    ret = gpio_pin_interrupt_configure_dt(&button,
                                          GPIO_INT_EDGE_TO_ACTIVE);
    if (ret != 0)
    {
        printk("Error %d: failed to configure interrupt on %s pin %d\n",
               ret, button.port->name, button.pin);
        return;
    }

    gpio_init_callback(&button_cb_data, Ext_Int0_Handler, BIT(button.pin));
    gpio_add_callback(button.port, &button_cb_data);
    printk("Set up button at %s pin %d\n", button.port->name, button.pin);
    // LOG_INF("Set up button at %s pin %d\n", button.port->name, button.pin);
}

// void AD5940_GUI_SETUP(void)
// {
//     if (!device_is_ready(dev_led0.port->name))
//     {
//         // LOG_ERR("Couldn't find %s\n", dev_led0.port->name);
//         printk("Couldn't find %s\n", dev_led0.port->name);
//         return;
//     }
//     else
//     {
//         // LOG_WRN("GPIO Initialized\n\r");
//         printk("GPIO Initialized\n\r");
//         gpio_pin_configure_dt(&dev_led0, GPIO_OUTPUT_INIT_LOW);
//     }
// }

void AD5940_RESET_SETUP(void)
{
    if (!device_is_ready(reset_dev.port))
    {
        // LOG_ERR("Couldn't find %s\n", reset_dev.port->name);
        printk("Couldn't find %s\n", reset_dev.port->name);
        return;
    }
    else
    {
        // LOG_WRN("GPIO Initialized\n\r");
        printk("GPIO Initialized\n\r");
        gpio_pin_configure_dt(&reset_dev, GPIO_OUTPUT);
    }
}

void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer, unsigned char *pRecvBuff, unsigned long length)
{
    const struct spi_buf tx_buf = {
        .buf = pSendBuffer,
        .len = length};
    const struct spi_buf_set tx = {
        .buffers = &tx_buf,
        .count = 1};
    const struct spi_buf rx_buf = {
        .buf = pRecvBuff,
        .len = length};
    const struct spi_buf_set rx = {
        .buffers = &rx_buf,
        .count = 1};

    if (spi_transceive_dt(&dev_spi, &tx, &rx))
    {

        // LOG_ERR("SPI transceive failed\n");
        printk("SPI transceive failed\n");
        return;
    }
}

void AD5940_CsClr(void)
{
    //   Do nothing - built in inside SPI API
}

void AD5940_CsSet(void)
{
    //   Do nothing - built in inside SPI API
}

void AD5940_RstSet(void)
{
    // Check it - maybe it has special flag
    if (gpio_pin_get_dt(&reset_dev) == 0)
    {
        // LOG_INF("Reset pin set\n");
        printk("nRF_MCU_Port: Reset pin set\n");
        gpio_pin_set_dt(&reset_dev, 1);
    }
}

void AD5940_RstClr(void)
{
    // Check it - maybe it has special flag
    if (gpio_pin_get_dt(&reset_dev) == 1)
    {
        // LOG_INF("nRF_MCU_Port: Reset pin clear\n");
        printk("nRF_MCU_Port: Reset pin clear\n");
        gpio_pin_set_dt(&reset_dev, 0);
    }
}

void AD5940_DATA_GUI(void)
{
    // gpio_pin_toggle_dt(&dev_led0);
}

void AD5940_Delay10us(uint32_t time)
{
    k_usleep(time * 10);
}

uint32_t AD5940_GetMCUIntFlag(void)
{
    return ucInterrupted;
}

uint32_t AD5940_ClrMCUIntFlag(void)
{
    ucInterrupted = 0;
    return 1;
}

uint32_t AD5940_MCUResourceInit(void)
{
    // LOG_WRN("AD5940_MCUResourceInit\n\r");
    printk("nRF_MCU_Port: AD5940_MCUResourceInit\n\r");
    AD5940_INT_SETUP();
    // AD5940_GUI_SETUP();
    AD5940_RESET_SETUP();
    AD5940_RstSet();
    if(!AD5940_SPI_SETUP())
    {
        // LOG_ERR("SPI Initialization failed\n\r");
        printk("SPI Initialization failed\n\r");
        while(1);
    }
    return 0;
}

nRF_MCU_Port.h

#ifndef NRF_MCU_PORT_H_
#define NRF_MCU_PORT_H_
uint32_t AD5940_MCUResourceInit(void);
void AD5940_DATA_GUI(void);
void set_interrupt(void);
#endif /* NRF_MCU_PORT_H_ */

Currently, it looks like the reset and interrupts are initializing well. The spi instance is "initialized," but I can't use the spi port as a sensor.

The evaluation board for this component is based on the Arduino R3 pinout.

The component is functioning ( I tested with the native MCU)

This is urgent for our project schedule; please help!

Thanks to all the helpers!

Parents
  • Hi,

    The spi instance is "initialized," but I can't use the spi port as a sensor.

    From what i can read from your post, this is the issue, right?

    Can you give some more details on this?

    Regards,
    Sigurd Hellesvik

  • Yes, it is.

    I see the log of successful initialization of the spi@a000 instance - but I do not see any visible connection. When I tried to listen to the signals with the logic analyzer - I saw some activity, with some responses from the MISO - but it didn't initialize the device's setup correctly.

  • There is a known bug with SPI communication. Before R/W, you should LSH the address bytes to get the correct address. Also, in reading - you should start reading the buffer from the 3rd byte (index 2) and not from the initial. Length in reading should be your_desired_lenght+2.

  • Hello, 
    Thank you for your input but I am quite not able to follow it as I am new to Zephyr & SPI protocol.
    I ran AD5940_SPI code from Analog Devices GitHub AD5940_SPI_Github.
    This is the output i got.

    22:33:04.553 -> Read ADIID register, got: 0x4144
    22:33:04.553 -> Read register test pass
    22:33:04.891 -> Read/Write has been done 1000 times, latest data is 0xf40f548e
    22:33:05.212 -> Read/Write has been done 2000 times, latest data is 0x7aeaacba
    22:33:05.541 -> Read/Write has been done 3000 times, latest data is 0x5b509ed3
    22:33:05.907 -> Read/Write has been done 4000 times, latest data is 0x521fb044
    22:33:06.232 -> Read/Write has been done 5000 times, latest data is 0x7e162e25
    22:33:06.594 -> Read/Write has been done 6000 times, latest data is 0xdbf72575
    22:33:06.928 -> Read/Write has been done 7000 times, latest data is 0xcf87c206
    22:33:07.286 -> Read/Write has been done 8000 times, latest data is 0x3c631b0d
    22:33:07.606 -> Read/Write has been done 9000 times, latest data is 0x71bb3463
    22:33:07.964 -> Read/Write has been done 10000 times, latest data is 0xebdebb73
    22:33:07.964 -> SPI read/write test completed


    I also have AD5940 Evaluation board and ran the same code to cross check the results.
    This is the output from AD5940 Evaluation board

    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Read ADIID register, got: 0x4144
    Read register test pass
    Read/Write has been done 1000 times, latest data is 0x831b4bd2
    Read/Write has been done 2000 times, latest data is 0x3bb3348a
    Read/Write has been done 3000 times, latest data is 0xf24b4342
    Read/Write has been done 4000 times, latest data is 0x26e3f7fa
    Read/Write has been done 5000 times, latest data is 0x597bd2b2
    Read/Write has been done 6000 times, latest data is 0x0a13536a
    Read/Write has been done 7000 times, latest data is 0xb8abfa22
    Read/Write has been done 8000 times, latest data is 0xe54346da
    Read/Write has been done 9000 times, latest data is 0x0fdbb992
    Read/Write has been done 10000 times, latest data is 0xb873d24a
    SPI read/write test completed       
    


    As you can see, Read and Write is happening but at different registers.
    Because of this when I try to run other application codes(such as amperometry), I am not getting results

    I have attached my NRF_Port.c and main.c

    NRF_Port.c
    #include "../AD5940_LIB/ad5940.h"
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/spi.h>
    
    
    //#include <>
    #define CS_PIN           20 // SPI3 CS PIN
    #define RESET_PIN        29 // SOFTWARE RESET PIN FOR AD5940
    #define INTERRUPT_PIN    3  // GPIO1_03()
    
    //#define SPI3_NODE   DT_NODELABEL(spi3)
      // CLOCK GATING THE SPI3
    const struct device *spi_dev;
    const struct device *GPIO0_PORT = DEVICE_DT_GET(DT_NODELABEL(gpio0)); // CLOCK GATING THE GPIO 0
    const struct device *GPIO1_PORT = DEVICE_DT_GET(DT_NODELABEL(gpio1)); // CLOCK GATING THE GPIO 1
    struct gpio_callback gpio_cb; 
    volatile uint32_t ucInterrupted = 0;       /* Flag to indicate interrupt occurred */
    
    
    //SPI CONFIGURATION    
    static struct spi_config spi_cfg = 
    {
      .frequency =13000000,
      .operation = SPI_OP_MODE_MASTER |  SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_LINES_DUAL ,
      .slave = 0,
      .cs = NULL,
    };
    
    static void print_buffer(const char *intro, const uint8_t *buffer, size_t size)
    {
        printk("%s: ", intro);
        for (size_t i = 0; i < size; i++)
        {
            printk("%X ", buffer[i]);
        }
        printk("\n");
    }
    
    //SPI READ WRITE
    void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer,unsigned char *pRecvBuff,unsigned long length)
    {
      /* STORE THE TX AND RX B*/
        struct spi_buf tx_buf = {
            .buf = pSendBuffer,
            .len = length,
        };
    
        struct spi_buf_set tx = {
            .buffers = &tx_buf,
            .count = 1,
        };
    
        struct spi_buf rx_buf = {
            .buf = pRecvBuff,
            .len = length,
        };
    
        struct spi_buf_set rx = {
            .buffers = &rx_buf,
            .count = 1,
        };
    /* Transmit and receive */
        int ret = spi_transceive(spi_dev, &spi_cfg, &tx, &rx);
        if (ret) {
            printk("SPI transceive failed: %d\n", ret);
            //return ret;
        }
        //    print_buffer("TX", pSendBuffer, length);
        //  print_buffer("RX", pRecvBuff, length);
    
        }
    
    /* CS PIN CONTROL SPI3*/
    void AD5940_CsClr(void)
    {  
      gpio_pin_set(GPIO0_PORT,CS_PIN,0);
    }
    void AD5940_CsSet(void)
    {
      gpio_pin_set(GPIO0_PORT,CS_PIN,1);
    }
    
    /* SOFTWARE RESET PIN FOR THE AD5940*/
    void AD5940_RstSet(void)
    {
      gpio_pin_set(GPIO0_PORT,RESET_PIN,1);
    }
    void AD5940_RstClr(void)
    {
      gpio_pin_set(GPIO0_PORT,RESET_PIN,0);
    }
    
    //DELAY FUNCTION
    void AD5940_Delay10us(uint32_t time)
    {
      k_usleep(time*10);
    }
    
    //RETURN THE FLAG 
    uint32_t AD5940_GetMCUIntFlag(void)
    {
      return ucInterrupted;
      return 1;
    }
    
    //CLEAR THE FLAG
    uint32_t AD5940_ClrMCUIntFlag(void)
    {
      ucInterrupted=0;
      return 1;
    }
    
    //CALL BACK FUNCTION WHEN THE INTERRUPT HAPPENED
    void GPIO1_03_isr()
    { ucInterrupted=1;
      printk("Inside Interrupt Callback \n");
      
    }
    
    uint32_t AD5940_MCUResourceInit(void *pCfg)
    {  
    spi_dev  = DEVICE_DT_GET(DT_NODELABEL(spi3));
      gpio_pin_configure(GPIO0_PORT, CS_PIN, GPIO_OUTPUT | GPIO_PUSH_PULL);
      gpio_pin_configure(GPIO0_PORT, RESET_PIN, GPIO_OUTPUT);
    
      /* #############################============##############################*/
      //          /*  CHECKIGN FOR ERRORS*/
      // if (!GPIO0_PORT) {
      //       printk("Error: Unable to get GPIO0 binding\n");
      //       return 0;
      //   }
    
      //   printk("GPIO_0 initialized successfully\n");
    
        
      //  if (!GPIO1_PORT) {
      //       printk("Error: Unable to get GPIO0 binding\n");
      //       return 0;
      //   }
    
      //   printk("GPIO_1 initialized successfully\n");  
    /*  ##############################=============################################# */
    
    /* ###############################=INTERRUPT_CONFIGURATION=############################## */
        // Configure GPIO pin
        
        gpio_pin_configure(GPIO1_PORT, INTERRUPT_PIN, GPIO_INPUT | GPIO_PULL_UP);
    
        // Initialize callback
        gpio_init_callback(&gpio_cb, GPIO1_03_isr, BIT(INTERRUPT_PIN));
    
        // Add callback to the GPIO pin
        gpio_add_callback(GPIO1_PORT, &gpio_cb);
       // Enable GPIO interrupt
        gpio_pin_interrupt_configure(GPIO1_PORT,INTERRUPT_PIN, GPIO_INT_EDGE_FALLING);
        
    
       
      AD5940_CsSet(); // SETTING THE CS PIN TO HIGH
      AD5940_RstSet();// ITS A ACTIVE HIGH AT AD5940 SO WE SET THE PIN IT TO HIGH
      return 0;
    }


    Main.c
    #include "AD5940_LIB/ad5940.h"
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/spi.h>
    #include <zephyr/drivers/uart.h>
    
    int uart_cfi_g(int Baud_rate);
    
    int main(void)
    {
             AD5940_MCUResourceInit(0);
            uart_cfi_g(230400);
            printk("Hello AD5940-Build Time:%s\n",__TIME__);
            AD5940_Main();
           // AD5940_CsClr();
            return 0;
    }
     
    
    int uart_cfi_g(int Baud_rate)
    {
    const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
    
    if (!device_is_ready(uart)) {
        return 0;
    }
            struct uart_config uart_cfg = {
                    .baudrate = Baud_rate,
                    .data_bits = UART_CFG_DATA_BITS_8,
                    .flow_ctrl= UART_CFG_FLOW_CTRL_NONE,
                    .stop_bits = UART_CFG_STOP_BITS_1,
                    .parity = UART_CFG_PARITY_NONE,
    
            };
    
    int err = uart_configure(uart, &uart_cfg);
    
    if (err == -ENOSYS) {
    	return -ENOSYS;
    }
    
    }


    Prj.conf
    CONFIG_GPIO = y
    CONFIG_SPI = y


    Kindly go through my code and let me know where I am making mistakes and how to rectify them in detail.
    Thanks a lot in advance.

  • You don't need the PORT file. Use Devicetree overlay instead with adx1345 configuration at the Arduino spi port.

    The only functions you need to add are the SPI read and SPI write for the AD5940

  • adx1345 has write and read functions separately, did you use them or write a new function to perform read and write operations?
    Also I am able to read and write using AD5940_SPI (https://github.com/analogdevicesinc/ad5940-examples/tree/master/examples/AD5940_SPI)
    Which means SPI communication is happening properly but when I try to run any application code such as Amperometry or CV, the MCU keeps rebooting every second.
    I did not change anything in NRF_Port.c or Main.c 
    I am not able to understand the reason for this behavior of MCU. 

  • Hi Amaram,

    Could you create a new ticket where you explain your issue and link to this ticket?
    I think that would be more tidy.

    Thanks!

Reply Children
No Data
Related