Runtime Error: undefined symbol: _ZN11IO_Expander14channel_selectEih

0

I have 3 files: a .cpp file containing definitions, a header file for declarations and macros and another file(.cc) that calls the header file. The problem I'm having is at runtime I seem to be getting an "undefined sysmbol error related to the function "channel select" that I'm trying to figure out. The error reads

error loading "/run/media/mmcblk0p2/opencpi/artifacts/local.I2C_IO_Expander.IO_Expander.rcc.0.xilinx19_2_aarch32.so": /run/media/mmcblk0p2/opencpi/artifacts/local.I2C_IO_Expander.IO_Expander.rcc.0.xilinx19_2_aarch32.so: undefined symbol: _ZN11IO_Expander14channel_selectEih

The code for the 3 files is shown below. The

i2c-dev-1.cpp- which contains function declarations as shown below:

    #include "i2c-dev_1.hpp"

    __s32 __s32 i2c_smbus_access(int file, char read_write, __u8 command, 
                                 int size, union i2c_smbus_data *data)
{
    struct i2c_smbus_ioctl_data args;

    args.read_write = read_write;
    args.command = command;
    args.size = size;
    args.data = data;
    return ioctl(file,I2C_SMBUS,&args);
}


__s32 IO_Expander::channel_select(int file, __u8 value)
{
    __u8 command = 0xE8; 
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}

__s32 IO_Expander::IO_config(int file, __u8 value)
{
    __u8 command = TCA6146_CONFIG_REG0;
        //__u8 value = 0x15; 
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}
__s32 IO_Expander::write_data(int file, __u8 value)
{
    
        __u8 command = TCA6146_OUTPUT_REG0;
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}
__s32 IO_Expander::read_data(int file)
{
    __u8 command = TCA6146_INPUT_REG0;
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
                         I2C_SMBUS_BYTE_DATA,&data))
        return -1;
    else
        return 0x0FF & data.byte;
          i2c_smbus_access(int file, char read_write, __u8 command, 
                                     int size, union i2c_smbus_data *data)
{
    struct i2c_smbus_ioctl_data args;

    args.read_write = read_write;
    args.command = command;
    args.size = size;
    args.data = data;
    return ioctl(file,I2C_SMBUS,&args);
}


__s32 IO_Expander::channel_select(int file, __u8 value)
{
    __u8 command = 0xE8; 
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}

__s32 IO_Expander::IO_config(int file, __u8 value)
{
    __u8 command = TCA6146_CONFIG_REG0;
        //__u8 value = 0x15; 
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}
__s32 IO_Expander::write_data(int file, __u8 value)
{
    
        __u8 command = TCA6146_OUTPUT_REG0;
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
                            I2C_SMBUS_BYTE_DATA, &data);
}
__s32 IO_Expander::read_data(int file)
{
    __u8 command = TCA6146_INPUT_REG0;
        ioctl(file, I2C_SLAVE, TCA6146_SLAVE_ADDR);
        union i2c_smbus_data data;
    if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
                         I2C_SMBUS_BYTE_DATA,&data))
        return -1;
    else
        return 0x0FF & data.byte;


      

i2c-dev_1.hpp - which contains macros and header files. This is the code.

#ifndef LIB_I2CDEV_H
#define LIB_I2CDEV_H

#include <linux/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/types.h>


/* -- i2c.h -- */


/*
 * I2C Message - used for pure i2c transaction, also from /dev interface
 */
struct i2c_msg {
    __u16 addr; /* slave address            */
    unsigned short flags;       
#define I2C_M_TEN   0x10    /* we have a ten bit chip address   */
#define I2C_M_RD    0x01
#define I2C_M_NOSTART   0x4000
#define I2C_M_REV_DIR_ADDR  0x2000
#define I2C_M_IGNORE_NAK    0x1000
#define I2C_M_NO_RD_ACK     0x0800
    short len;      /* msg length               */
    char *buf;      /* pointer to msg data          */
};

/* To determine what functionality is present */

#define I2C_FUNC_I2C            0x00000001
#define I2C_FUNC_10BIT_ADDR     0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING  0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
#define I2C_FUNC_SMBUS_PEC      0x00000008
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL  0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK        0x00010000 
#define I2C_FUNC_SMBUS_READ_BYTE    0x00020000 
#define I2C_FUNC_SMBUS_WRITE_BYTE   0x00040000 
#define I2C_FUNC_SMBUS_READ_BYTE_DATA   0x00080000 
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA  0x00100000 
#define I2C_FUNC_SMBUS_READ_WORD_DATA   0x00200000 
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA  0x00400000 
#define I2C_FUNC_SMBUS_PROC_CALL    0x00800000 
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA  0x01000000 
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK   0x04000000 /* I2C-like block xfer  */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK  0x08000000 /* w/ 1-byte reg. addr. */

#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
                             I2C_FUNC_SMBUS_WRITE_BYTE)
#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
                                  I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
                                  I2C_FUNC_SMBUS_WRITE_WORD_DATA)
#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
                                   I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
                                  I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)

/* Old name, for compatibility */
#define I2C_FUNC_SMBUS_HWPEC_CALC   I2C_FUNC_SMBUS_PEC

/* 
 * Data for SMBus Messages 
 */
#define I2C_SMBUS_BLOCK_MAX 32  /* As specified in SMBus standard */    
#define I2C_SMBUS_I2C_BLOCK_MAX 32  /* Not specified but we use same structure */

#define TCA6146_SLAVE_ADDR      0x21
#define TCA6146_OUTPUT_REG0     0X02
#define TCA6146_INPUT_REG0      0X00
#define TCA6146_CONFIG_REG0     0x06
#define PCA9548_SLAVE_ADDR      0x74
#define PCA9548_CHAN4_ENABLE        0x10
#define PCA9548_CHAN6_ENABLE        0x40
#define PCA9548_CHAN7_ENABLE        0x80
union i2c_smbus_data {
    __u8 byte;
    __u16 word;
    __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
                                                /* and one more for PEC */
};



/* smbus_access read or write markers */
#define I2C_SMBUS_READ  1
#define I2C_SMBUS_WRITE 0

/* SMBus transaction types (size parameter in the above functions) 
   Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
#define I2C_SMBUS_QUICK         0
#define I2C_SMBUS_BYTE          1
#define I2C_SMBUS_BYTE_DATA     2 
#define I2C_SMBUS_WORD_DATA     3
#define I2C_SMBUS_PROC_CALL     4
#define I2C_SMBUS_BLOCK_DATA        5
#define I2C_SMBUS_I2C_BLOCK_BROKEN  6
#define I2C_SMBUS_BLOCK_PROC_CALL   7       /* SMBus 2.0 */
#define I2C_SMBUS_I2C_BLOCK_DATA    8


/* ----- commands for the ioctl like i2c_command call:
 * note that additional calls are defined in the algorithm and hw 
 *  dependent layers - these can be listed here, or see the 
 *  corresponding header files.
 */
                /* -> bit-adapter specific ioctls   */
#define I2C_RETRIES 0x0701  /* number of times a device address      */
                /* should be polled when not            */
                                /* acknowledging            */
#define I2C_TIMEOUT 0x0702  /* set timeout - call with int      */


/* this is for i2c-dev.c    */
#define I2C_SLAVE   0x0703  /* Change slave address         */
                /* Attn.: Slave address is 7 or 10 bits */
#define I2C_SLAVE_FORCE 0x0706  /* Change slave address         */
                /* Attn.: Slave address is 7 or 10 bits */
                /* This changes the address, even if it */
                /* is already taken!            */
#define I2C_TENBIT  0x0704  /* 0 for 7 bit addrs, != 0 for 10 bit   */

#define I2C_FUNCS   0x0705  /* Get the adapter functionality */
#define I2C_RDWR    0x0707  /* Combined R/W transfer (one stop only)*/
#define I2C_PEC     0x0708  /* != 0 for SMBus PEC                   */

#define I2C_SMBUS   0x0720  /* SMBus-level access */

/* -- i2c.h -- */


/* Note: 10-bit addresses are NOT supported! */


/* This is the structure as used in the I2C_SMBUS ioctl call */
struct i2c_smbus_ioctl_data {
    char read_write;
    __u8 command;
    int size;
    union i2c_smbus_data *data;
};

__s32 i2c_smbus_access(int file, char read_write, __u8 command, 
                                     int size, union i2c_smbus_data *data);



// IO_Expander class used for powering of daughterboard on N310
class IO_Expander {
  public:

   

     __s32 channel_select(int file, __u8 value); //Selects the appropriate channel on the switch 

     __s32 IO_config(int file,__u8 value);//configuration of port expander

     __s32 write_data(int file, __u8 value);// Writing out data to port expander 

     __s32 read_data(int file); //Reading a byte of data
   
};  



#endif /* LIB_I2CDEV_H */

And a final file-IO_Expander.cc

#include <i2c-dev_1.hpp>

int main()
{
int i2cfd;
   __s32 num;
   int test_var;
   __u8 config;
   __u8 output_data;

       //opening bus 4 connected to the switch
       i2cfd =  open("/dev/i2c-4",O_RDWR); 
                if (i2cfd < 0) {
                printf("Error opening i2c bus 4");
                exit(1);

                }

//Instantiating an object of IO_Expander Class
IO_Expander object1;
     
    // selecting channel 4 for communication with I/O Expander  
       object1.channel_select(i2cfd,PCA9548_CHAN4_ENABLE);
        
       //Configuring the I/O expander ports 
       printf("Enter a hex value for IO Port configuration\n");
       scanf("%s", &config);
       object1.IO_config(i2cfd,config);

       // User is prompted to enter 0 or 1 for reading data or writing data to port expander
       printf("Enter 0: Write Data or 1: Read Data\n"); 
       scanf("%d", &test_var);
       if (test_var == 0){

       //Outputting data to the I/O Expander 
       printf("Enter a hex value for the output\n"); 
       scanf("%s", &output_data);
       object1.write_data(i2cfd,output_data);

      }
        
       else  {

       //Reading data from the I/O Expander
        num = object1.read_data(i2cfd);
          if (num < 0){
                    
                        printf("Error reading data");
                        close(i2cfd);
            exit(1);
                       }  
          else {
              
                 printf("The input value is %d:", num); 

               }
         
       }

       close(i2cfd); 
 
    return 0;
   };
c++
compiler-errors
linker
runtime-error
undefined-symbol
asked on Stack Overflow Apr 28, 2021 by Tellrell White

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0