python i2c ioctl
Tim Roberts
timr at probo.com
Fri Jun 15 02:39:39 EDT 2007
luca <sanluca78 at gmail.com> wrote:
>
> I was trying to make to work directly l i2c with python with the
>calls ioctl. But I have of the problems and I do not succeed to go
>ahead.
>
>[root at axis-00408c000001 /usr/local/wrap]129# python pcf8591_ioctl.py
>Reading from 4 ch 8 bit A/D converter PCF8591
>Traceback (most recent call last):
> File "pcf8591_ioctl.py", line 269, in ?
> main()
> File "pcf8591_ioctl.py", line 229, in main
> if i2c_open () < 0:
> File "pcf8591_ioctl.py", line 168, in i2c_open
> fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), 0,
>iomask)
>TypeError: ioctl requires a file or file descriptor, an integer and
>optionally a integer or buffer argument
The error message pretty much tells you the problem. One of the parameters
is not correct. Notice this:
>def IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask):
> ( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) &
>0xFF) )
>def IO_CFG_WRITE_MODE_VALUE(msb, data_mask, clk_mask):
> ( (((msb)&1) << 16) | (((data_mask) &0xFF) << 8) | ((clk_mask) &
>0xFF) )
Key question: what do these functions return?
Answer: nothing. You compute a value and then throw it away. Thus:
print IO_CFG_WRITE_MODE_VALUE( 15, 0xfff, 0x0f0 )
This will print "None". Add a "return" before the expression.
The same thing is true of all of these functions. You are thinking that a
Python "def" is like a C "#define". It's not. It's like a C function.
Nothing is returned unless you return it.
>def _IOC(dir,type,nr,size):
> (((dir) << _IOC_DIRSHIFT) |
> ((type) << _IOC_TYPESHIFT) |
> ((nr) << _IOC_NRSHIFT) |
> ((size) << _IOC_SIZESHIFT))
>
>def _IO(type,nr):
> _IOC(_IOC_NONE,(type),(nr),0)
>
>def _IOR(type,nr,size):
> _IOC(_IOC_READ,(type),(nr),sizeof(size))
>
>def _IOW(type,nr,size):
> _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
>
>def _IOWR(type,nr,size):
> _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
>
>def _IOC_DIR(nr):
> (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
>def _IOC_TYPE(nr):
> (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
>def _IOC_NR(nr):
> (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
>def _IOC_SIZE(nr):
> (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
>def IOC_IN():
> (_IOC_WRITE << _IOC_DIRSHIFT)
>
>def IOC_OUT():
> (_IOC_READ << _IOC_DIRSHIFT)
>def IOC_INOUT():
> ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
>def IOCSIZE_MASK():
> (_IOC_SIZEMASK << _IOC_SIZESHIFT)
>def IOCSIZE_SHIFT():
> (_IOC_SIZESHIFT)
However, there are more problems with this script. Example:
>#Get the SDA line state
>def i2c_getbit():
> value=fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS))
> if ((value&(I2C_DATA_LINE))==0):
> return 0
> else:
> return 1
This will produce a runtime error, because the name "i2c_fd" is not
defined. Notice this:
>#Open the GPIOB dev
>def i2c_open():
> i2c_fd = os.open("/dev/gpiog", os.O_RDWR)
> iomask = I2C_CLOCK_LINE
> fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), iomask)
> iomask = I2C_DATA_LINE
> fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), iomask)
> fcntl.ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS),
>I2C_DATA_LINE)
> i2c_dir_in()
> i2c_clk(1)
> return i2c_fd
The result of the open is bound in a LOCAL variable called "i2c_fd". As
soon as the function returns, that variable goes away. You do RETURN the
value, but you don't store it anywhere:
>#PCF8591 address scheme
>#| 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W |
>#| i2c_fixed | i2c_addr | 1/0 |
>def main ():
> i2c_fixed = 0x09
> i2c_addr = 0x01
>
> print "Reading from 4 ch 8 bit A/D converter PCF8591"
>
> if i2c_open () < 0:
> print "i2c open error"
> return 1
You should probably make this:
i2c_fd = i2c_open()
if i2c_fd < 0:
print "i2c open error"
return 1
But, of course, that's not enough either; i2c_fd is a local variable in
THIS function as well. You should change ALL of the functions so that they
accept an fd as the first parameter, and then pass i2c_fd into the
functions here.
Alternatively, you could create a wrapper class to hold the fd and make the
function methods on that class.
> while "azz":
> i2c_start ()
I'm curious. What do you think "while" statement is doing? The answer is
that it is an infinite loop; the string "azz" will always be true, so the
while statement will always loop. I can't guess what you really wanted
here.
--
Tim Roberts, timr at probo.com
Providenza & Boekelheide, Inc.
More information about the Python-list
mailing list