Post Go back to editing

Using Adrv9002 IIO Device Driver and TES generated Code at the Same time on the ZED Eval Board

Category: Software
Product Number: ADRV9002

Is there any possibility to execute TES generated code on a System using the ADRV IIO Device Driver? (The ZED Board)

I'm not able to access the Spi Interface, which is necessary when using the TES generated Code. (Because the SPI Interface ist occupied by the IIO Driver)

The only solution I can come up with is to replace the IIO Device Driver with the e.g. spidev Driver to get access to the Spi Interface. Correct?

Background: I have the ZED Board and the Adrv9002 Eval Board and want to use the internal Loopback of the ADRV9002 which seems not possible with the IIO Device Driver, therefore I want to configure the Device with the TES generated Code. (The ZED Board ist unfortunatly not supported by TES itself)

Thanks!

  • Is there any possibility to execute TES generated code on a System using the ADRV IIO Device Driver? (The ZED Board)

    Nope, that is not possible. Sorry...

    However...

    Background: I have the ZED Board and the Adrv9002 Eval Board and want to use the internal Loopback of the ADRV9002 which seems not possible with the IIO Device Driver, therefore I want to configure the Device with the TES generated Code. (The ZED Board ist unfortunatly not supported by TES itself)

    You should be able to use the internal loopback through debugfs (/sys/kernel/debug/iio/iio:deviceX/). The name of the file is tx0_ssi_test_mode_loopback_en or tx1_ssi_test_mode_loopback_en. If this is enabled, then all transmitted data on that channel is loopedback. This is in debugfs since the primary usage we have for it is to test the SSI interface using some test signals.

    - Nuno Sá

  • Thanks for the immediate reply, i really appreciate that! 

    When I mentioned Loopback, I meant RX to TX datapath Loopback. 

    I tried to Loopback with the debugfs but wasnt successfull.

    But I will have a closer Look on it, thanks!

  • Update: I simply exchanged the IIO Device Driver with the SPIDEV Driver in the Device Tree. So I was able to use the TES generated Code with the ZED Board. Now I can switch between the IIO Device Driver and the TES generated code. (It still isn't possible to use this two variants at the same time, but maybe this solution is also helpful)

    /**
     * \file
     * \brief Template customer implementation of the ADRV9001 HAL
    * 
    * Copyright 2020 Analog Devices Inc.
    * Released under the ADRV9001 API license, for more information
    * see the "LICENSE.txt" file in this zip file.
     */
    
    #ifndef _ADI_ADRV9001_HAL_CUSTOMER_H_
    #define _ADI_ADRV9001_HAL_CUSTOMER_H_
    
    #include <stdint.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <getopt.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <linux/types.h>
    #include <linux/spi/spidev.h>
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    
    static void pabort(const char *s)
    {
    	perror(s);
    	abort();
    }
    
    static const char *device = "/dev/spidev0.0";
    static uint8_t mode = 0;
    static uint8_t bits = 8;
    static uint32_t speed = 10000000;
    static uint16_t delay;
    //static int fd;
    //static int valuefd, directionfd;
    
    /**
     * \copydoc adi_adrv9001_hal_open
     */
    int32_t customer_adi_adrv9001_hal_open(void *devHalCfg);
    
    /**
     * \copydoc adi_adrv9001_hal_close
     */
    int32_t customer_adi_adrv9001_hal_close(void *devHalCfg);
    
    /**
     * \copydoc adi_hal_SpiWrite
     */
    int32_t customer_adi_adrv9001_hal_spi_write(void *devHalCfg, const uint8_t txData[], uint32_t numTxBytes);
    
    /**
     * \copydoc adi_hal_SpiRead
     */
    int32_t customer_adi_adrv9001_hal_spi_read(void *devHalCfg, const uint8_t txData[], uint8_t rxData[], uint32_t numTxRxBytes);
    
    /**
     * \copydoc adi_adrv9001_hal_close
     */
    int32_t customer_adi_adrv9001_hal_resetbPin_set(void *devHalCfg, uint8_t pinLevel);
        
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    /**
     * \file
     * \brief Template customer implementation of the ADRV9001 HAL
    * 
    * Copyright 2020 Analog Devices Inc.
    * Released under the ADRV9001 API license, for more information
    * see the "LICENSE.txt" file in this zip file.
     */
    
    #include "adi_adrv9001_hal_customer.h"
    
    int32_t customer_adi_adrv9001_hal_open(void *devHalCfg)
    {
    	int ret = 0;
    	int exportfd = 0;
    	int directionfd;
    	int valuefd;
    	int fd;
    	
        /* Customer code goes here */
        printf("Customer Adi Adrv9001 hal open");
    
    	// Update the direction of the GPIO to be an output
        printf("Set GPIO1006 as Reset...\r\n");
        directionfd = open("/sys/class/gpio/gpio1006/direction", O_RDWR);
        if (directionfd < 0)
        {
            printf("Cannot open GPIO direction it, export GPIO PIN 1006...\n");
    		exportfd = open("/sys/class/gpio/export", O_WRONLY);
    		write(exportfd, "1006", 5);
    		close(exportfd);
    		usleep(1000);
    		printf("Retry GPIO1006 as Reset...\r\n");
        	directionfd = open("/sys/class/gpio/gpio1006/direction", O_RDWR);
    		if (directionfd < 0){
    			printf("Cannot open GPIO direction\n");
    			exit(1);
    		}
    		else
    		{
    			printf("Sucessfully Set GPIO1006 as Reset...\r\n");
    		}
        }
      
        write(directionfd, "out", 4);
        close(directionfd);
    	
    	valuefd = open("/sys/class/gpio/gpio1006/value", O_RDWR);
        if (valuefd < 0)
        {
            printf("Cannot open GPIO value\n");
            exit(1);
        }
        write(valuefd,"1", 2);
    	close(valuefd);
      
        printf("GPIO direction set as output successfully\n");
    
        fd = open(device, O_RDWR);
    	if (fd < 0){
    		printf("can't open device");
    		pabort("can't open device");
    	}
    	
    	/*
    	 * spi mode
    	 */
    	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
    	if (ret == -1)
    		pabort("can't set spi mode");
    
    	/*
    	 * bits per word
    	 */
    	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
    	if (ret == -1)
    		pabort("can't get spi mode");
    	
    	/*
    	 * max speed hz
    	 */
    	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    	if (ret == -1)
    		pabort("can't set max speed hz");
    
    	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
    	if (ret == -1)
    		pabort("can't get max speed hz");
    
    	printf("spi mode: %d\n", mode);
    	printf("bits per word: %d\n", bits);
    	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
    	close(fd);
    
    	printf("\n\n *** Test SPI Interface: *** \n\n");
    
    	uint8_t write_1_data[3] = {0x00, 0x01, 0x80};
    	customer_adi_adrv9001_hal_spi_write(devHalCfg, write_1_data, 3);
    
    	uint8_t write_2_data[3] = {0x00, 0x00, 0x3C};
        customer_adi_adrv9001_hal_spi_write(devHalCfg, write_2_data, 3);
    	    
        uint8_t read_1_data[3] = {0x80, 0x0B, 0x00};
        uint8_t rx_readback[3] = {0x00, 0x00, 0x00};
        
        customer_adi_adrv9001_hal_spi_read(devHalCfg, read_1_data, rx_readback, 3);
        printf("Read back from SPI: 0x%02X.\n", rx_readback[2]);
    
    	printf("The SPI has been initialised\r\n");
    
        return ret;
    }
    
    int32_t customer_adi_adrv9001_hal_close(void *devHalCfg)
    {
        /* Customer code goes here */
    	//close(fd);
        return 0;
    }
    
    int32_t customer_adi_adrv9001_hal_spi_write(void *devHalCfg, const uint8_t txData[], uint32_t numTxBytes)
    {
        // Customer code goes here 
    	int ret;
    	uint8_t rx[ARRAY_SIZE(txData)] = {0, };
    	//uint8_t rx[(uint8_t)numTxBytes] = {0, };
    	struct spi_ioc_transfer tr = {
    		.tx_buf = (unsigned long)txData,
    		.rx_buf = (unsigned long)rx,
    		.len = ARRAY_SIZE(txData),
    		.delay_usecs = delay,
    		.speed_hz = speed,
    		.bits_per_word = bits,
    	};
    	int fd;
    
    	fd = open(device, O_RDWR);
    	if (fd < 0){
    		printf("can't open device");
    		pabort("can't open device");
    	}
    	//printf("Send SPI bytes: %i", numTxBytes);
    	
    	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    	if (ret < 1)
    		pabort("can't send spi message");
    	
    	close(fd);
        return 0;
    }
    
    int32_t customer_adi_adrv9001_hal_spi_read(void *devHalCfg, const uint8_t txData[], uint8_t rxData[], uint32_t numTxRxBytes)
    {
        // Customer code goes here 
    	int ret;
    	struct spi_ioc_transfer tr = {
    		.tx_buf = (unsigned long)txData,
    		.rx_buf = (unsigned long)rxData,
    		.len = ARRAY_SIZE(txData),
    		.delay_usecs = delay,
    		.speed_hz = speed,
    		.bits_per_word = bits,
    	};
    	int fd;
    
    	fd = open(device, O_RDWR);
    	if (fd < 0){
    		printf("can't open device");
    		pabort("can't open device");
    	}
    	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    	if (ret < 1)
    		pabort("can't send spi message");
    
    	//for (ret = 0; ret < ARRAY_SIZE(txData); ret++) {
    	//	if (!(ret % 6))
    	//		puts("");
    	//	printf("%.2X ", rxData[ret]);
    	//}
    	//puts("");
    	close(fd);
    	
        return 0;
    }
    
    int32_t customer_adi_adrv9001_hal_resetbPin_set(void *devHalCfg, uint8_t pinLevel)
    {
        /* Customer code goes here */
    	int valuefd;
    
    	//printf("wait us");
    	//adi_common_hal_Wait_us(devHalCfg, 10000);
    	usleep(10000);
    
    	// Get the GPIO value ready to be toggled
    	//printf("open gpio1006");
        valuefd = open("/sys/class/gpio/gpio1006/value", O_RDWR);
        if (valuefd < 0)
        {
            printf("Cannot open GPIO value\n");
            exit(1);
        }
    	//write(valuefd,"1", 2);
        
        if (1 == pinLevel){
    		//printf("Release Reset");
        	write(valuefd,"1", 2);
        }
        else{
    		//printf("Reset ");
        	write(valuefd,"0", 2);
        }
    
    	close(valuefd);
    	
        return 0;
    }