Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2012-06

Problems with fpioctl on ARM debian linux and FPC2.6

16 messages · 5 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Stefan Fischer

Hello,

I have a project, where I have to write a driver for /dev/spidev0.0, but I have problems with fpioctl.

I believe that I have problems with the parameter passing or type casting of fpioctl.
In some forums, I've found mysterios Pointer(PtrInt(xx) syntax like that: fpioctl(fd,funcnum, Pointer(PtrInt(xy)) :
I have no idea why this construction is necesary

My code snipet is below:

spi_ioc_transfer_t = record
    tx_buf_ptr   : pointer;
    rx_buf_ptr   : pointer;
    len    : longword;
    delay_usec  : word;
    speed_hz     : longword;
    bits_per_word : byte;
    cs_change  : byte;
    pad    : longword;
  end;
var xfer : array[0..1] of spi_ioc_transfer_t; rx0,tx0 : array[0..42] of
byte;
tx0 [ 0]:=$00; tx0 [ 1]:=$00;
xfer[0].len:=2; xfer[0].speed_hz:=500000; xfer[0].bits_per_word:=8;
xfer[0].tx_buf_ptr := addr(tx0[ 0]); xfer[0].rx_buf_ptr := addr(rx0[
0]);
fd:=fpOpen('/dev/spidev0.0',O_RdWr);
...
result := fpioctl(fd, (*SPI_IOC_MESSAGE(1)*) 1075866368, @xfer[0]);
(* function number 107.. 368 taken from operating c example *)

I get -1 as result
What's wrong.

Reply by email

Jonas Maebe
to Stefan Fischer

Stefan Fischer wrote on Tue, 19 Jun 2012:

Show quoted text 12 lines
My code snipet is below: spi_ioc_transfer_t = record tx_buf_ptr : pointer; rx_buf_ptr : pointer; len : longword; delay_usec : word; speed_hz : longword; bits_per_word : byte; cs_change : byte; pad : longword; end;

The speed_hz and delay_usec fields are switched around. Furthermore, make sure to add add {$packrecords C} to guarantee the same alignment as in a C compiler.

Jonas

Reply by email

Henry Vermaak
to Jonas Maebe
Jonas Maebe wrote 21 lines
Stefan Fischer wrote on Tue, 19 Jun 2012: > My code snipet is below: > > spi_ioc_transfer_t = record >    tx_buf_ptr   : pointer; >    rx_buf_ptr   : pointer; >    len    : longword; >    delay_usec  : word; >    speed_hz     : longword; >    bits_per_word : byte; >    cs_change  : byte; >    pad    : longword; >  end; The speed_hz and delay_usec fields are switched around. Furthermore, make sure to add add {$packrecords C} to guarantee the same alignment as in a C compiler.

Also, the buffers need to be u64. Is the pointer type in pascal always 64 bit?

Henry

Reply by email

Jonas Maebe
to Henry Vermaak

Henry Vermaak wrote on Tue, 19 Jun 2012:

Also, the buffers need to be u64. Is the pointer type in pascal always 64 bit?

u64 is defined as "unsigned long". "unsigned long" is the same size as a pointer on Linux.

Jonas

Reply by email

Stefan Fischer
to Jonas Maebe

I've changed to following:
added packrecord c
flipped speed_hz and delay_usec fields

same problem.
I don't know whats really wrong.
Is there any debug possibility?

Jonas Maebe wrote 12 lines
Henry Vermaak wrote on Tue, 19 Jun 2012: > Also, the buffers need to be u64. Is the pointer type in pascal always 64 bit? u64 is defined as "unsigned long". "unsigned long" is the same size as a pointer on Linux. Jonas _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Henry Vermaak
to Stefan Fischer
Stefan Fischer wrote 7 lines
I've changed to following: added packrecord c flipped speed_hz and delay_usec fields same problem. I don't know whats really wrong. Is there any debug possibility?

Have you tried looking at errno? Do any of the other ioctls succeed (e.g. SPI_IOC_WR_MAX_SPEED_HZ)? Do you have permissions to write to this file?

Henry

Reply by email

Ludo Brands
to Stefan Fischer: I've changed to following: added packrecord c flipped speed_hz and delay_usec fields same…
Show quoted text 9 lines
I've changed to following: added packrecord c flipped speed_hz and delay_usec fields same problem. I don't know whats really wrong. Is there any debug possibility?

Are you sure about the conversion (*SPI_IOC_MESSAGE(1)*) 1075866368? That is 40206B00 hex. 6B is the letter 'k' SPI_IOC_MAGIC but the 20 seems to indicate a size of 32 bytes while the record has only a size of 24 bytes on ARM (32 bit pointers). Also the 40 seems to be wrong as it corresponds to IOC_IN.

#define SPI_MSGSIZE(N) \
((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) #define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) #define _IOC(inout,group,num,len) \
((unsigned long)(inout | ((len & IOCPARM_MASK) << 16) | ((group) <<
8) | (num)))
#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) #define IOC_OUT 0x40000000 /* copy out parameters */ #define IOC_IN 0x80000000

Ludo

Reply by email

Ludo Brands
to Henry Vermaak
Show quoted text 7 lines
> Are you sure about the conversion (*SPI_IOC_MESSAGE(1)*) 1075866368? > That is I can confirm that a c program spits out this number for SPI_IOC_MESSAGE(1).

And what is sizeof (struct spi_ioc_transfer) in c? Because that would indicate that u64 needs to be indeed 64 bits. I have seen u64 defined as typedef unsigned long long for ARM.

Ludo

Reply by email

Henry Vermaak
to Ludo Brands
Ludo Brands wrote
And what is sizeof (struct spi_ioc_transfer) in c?

32.

Because that would indicate that u64 needs to be indeed 64 bits. I have seen u64 defined as typedef unsigned long long for ARM.

"long" is 32 bits on my arm laptop, so that makes sense.

Henry

Reply by email

Ludo Brands
to Henry Vermaak
Show quoted text 7 lines
32. > Because that would indicate that u64 needs to be indeed 64 bits. I > have seen u64 defined as typedef unsigned long long for ARM. "long" is 32 bits on my arm laptop, so that makes sense.

So the struct should be translated as

spi_ioc_transfer_t = record
    tx_buf_ptr   : qword;
    rx_buf_ptr   : qword;
    len    : longword;
    speed_hz     : longword;
    delay_usec  : word;
    bits_per_word : byte;
    cs_change  : byte;
    pad    : longword;
  end;

Ludo

Reply by email

Henry Vermaak
to Ludo Brands
Ludo Brands wrote 12 lines
So the struct should be translated as spi_ioc_transfer_t = record    tx_buf_ptr   : qword;    rx_buf_ptr   : qword;    len    : longword;    speed_hz     : longword;    delay_usec  : word;    bits_per_word : byte;    cs_change  : byte;    pad    : longword;  end;

Yes, or use ctypes to make it more clear.

Henry

Reply by email

Stefan Fischer
to Stefan Fischer: I've changed to following: added packrecord c flipped speed_hz and delay_usec fields same…

after some experiments, tx.. and rx_buf_ptr has to be 64 bits. On fps on arm, the pointer type is translated to 32 Bits. Ludo's suggestions to use qword (64Bit) is correct.

Is there a possibility to use pointer type with 64 Bits? How ?

spi_ioc_transfer_t = record
    tx_buf_ptr,dummytx    : pointer;     (* <------------ 64 Bits              dummytx / dummyrx for spaceing *)
    rx_buf_ptr,dummyrx 	: pointer;
    len				: longword;
	speed_hz    	: longword;
    delay_usecs		: word;
    bits_per_word	: byte;
    cs_change		: byte;
    pad				: longword;
  end;
Stefan Fischer wrote 27 lines
I've changed to following: added packrecord c flipped speed_hz and delay_usec fields same problem. I don't know whats really wrong. Is there any debug possibility? Am 19.06.2012 um 15:24 schrieb Jonas Maebe: > > Henry Vermaak wrote on Tue, 19 Jun 2012: > >> Also, the buffers need to be u64. Is the pointer type in pascal always 64 bit? > > u64 is defined as "unsigned long". "unsigned long" is the same size as a pointer on Linux. > > > Jonas > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Sven Barth
to Stefan Fischer: after some experiments, tx.. and rx_buf_ptr has to be 64 bits. On fps on arm, the pointer…
Stefan Fischer wrote 18 lines
after some experiments, tx.. and rx_buf_ptr has to be 64 bits. On fps on arm, the pointer type is translated to 32 Bits. Ludo's suggestions to use qword (64Bit) is correct. Is there a possibility to use pointer type with 64 Bits? How ? spi_ioc_transfer_t = record tx_buf_ptr,dummytx : pointer; (* <------------ 64 Bits dummytx / dummyrx for spaceing *) rx_buf_ptr,dummyrx : pointer; len : longword; speed_hz : longword; delay_usecs : word; bits_per_word : byte; cs_change : byte; pad : longword; end;

I wouldn't do that. The kernel could use the part that you labeled as "dummy*x". Just simply cast a Pointer to QWord and be happy. As long as we don't have a 128-bit system this will work ;) (and C basically does the same)

Regards,
Sven

Reply by email