Difference between revisions of "FPGA registers access from Linux userspace"

From ArmadeusWiki
Jump to: navigation, search
m (The problem)
Line 72: Line 72:
 
== The problem ==
 
== The problem ==
  
By default, if the exact ARM920t name is not given, gcc will try to generate compatible read/write for all arm model when it access register in 16bits. Because not all ARM9 has 16bits read/write capabilities.
+
By default, if the specific ''arm920t'' target is not specified, ''arm-linux-gcc'' will try to generate compatible read/write for all ARM9 model when it access register in 16bits. Indeed it seems that not all ARM9 have 16bits read/write capabilities (''ldrh'' asm instruction).
  
But the interface between i.MX and fpga on apf9328 has no 8bits read/write capabilities, then each 8 bits access is recognized by fpga as 16bits access. On each 16bits access, i.MX will then do two 16bits access instead of 1.
+
As the interface between i.MXL and FPGA on APF9328 has no 8bits read/write capabilities, each 8 bits access is recognized by the FPGA as a 16bits access. So on each 16bits access of the i.MXL, FPGA will process two 16bits access instead of 1. That is a problem when accessing a FIFO for example.
  
 
To avoid this painful problem don't forget the ''-mcpu=arm920t'' option when compile ''fpgaregs'' for apf9328.
 
To avoid this painful problem don't forget the ''-mcpu=arm920t'' option when compile ''fpgaregs'' for apf9328.
 +
 +
==Links==
 +
* http://sources.redhat.com/ml/crossgcc/2005-08/msg00120.html : Explanation of the problem.

Revision as of 11:47, 19 November 2008


fpgaregs

compile

To access FPGA registers a tool named fpgaregs is available under target/linux/module/fpga/dev_tools/ directory. To compile it for apf9328, use the command above :

arm-linux-gcc -mcpu=arm920t fpgaregs.c -o fpgaregs

use

fpgaregs can be used to read and write 16 or 32 bits registers.

read 16 bits

fpgaregs w <address>

Where <address> is an address relative to fpga mapping in hexadecimal value.

write 16 bits

fpgaregs w <address> <value>

Where <value> is hexadecimal value to write.

read 32 bits

fpgaregs l <address>

write 32 bits

fpgaregs l <address> <value>

the mmap problem

To access fpga register, fpgaregs use the mmap() system call :

ptr_fpga = mmap (0, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, ffpga, FPGA_ADDRESS);

Thanks to this function, fpga registers are accessible directly on memory with pointer ptr_fpga. To read and write in 16bits or in 32 bits we will cast the pointer value in unsigned short or unsigned int :

16bits write

        *(unsigned short*)(ptr_fpga+(address)) = (unsigned short)value;

read

          value = *(unsigned short*)(ptr_fpga+(address));

32 bits write

        *(unsigned short*)(ptr_fpga+(address)) = (unsigned short)value;

read

          value = *(unsigned int*)(ptr_fpga+(address));

The problem

By default, if the specific arm920t target is not specified, arm-linux-gcc will try to generate compatible read/write for all ARM9 model when it access register in 16bits. Indeed it seems that not all ARM9 have 16bits read/write capabilities (ldrh asm instruction).

As the interface between i.MXL and FPGA on APF9328 has no 8bits read/write capabilities, each 8 bits access is recognized by the FPGA as a 16bits access. So on each 16bits access of the i.MXL, FPGA will process two 16bits access instead of 1. That is a problem when accessing a FIFO for example.

To avoid this painful problem don't forget the -mcpu=arm920t option when compile fpgaregs for apf9328.

Links