Difference between revisions of "FPGA registers access from Linux userspace"
m |
(→use) |
||
Line 2: | Line 2: | ||
= fpgaregs = | = fpgaregs = | ||
− | == | + | ===Usage=== |
− | fpgaregs can be used to read and write 16 or 32 bits registers. | + | ''fpgaregs'' can be used to read and write 16 or 32 bits registers in the FPGA, from Linux Userspace. |
− | + | ====16 bits read==== | |
− | < | + | <pre class="apf"> |
− | fpgaregs w <address> | + | # fpgaregs w <address> |
− | </ | + | </pre> |
− | Where <address> is an address relative to | + | Where <address> is an address relative to FPGA's mapping in hexadecimal value. |
− | + | ====16 bits write==== | |
− | < | + | <pre class="apf"> |
− | fpgaregs w <address> <value> | + | # fpgaregs w <address> <value> |
− | </ | + | </pre> |
Where <value> is hexadecimal value to write. | Where <value> is hexadecimal value to write. | ||
− | + | ====32 bits read==== | |
− | < | + | <pre class="apf"> |
− | fpgaregs l <address> | + | # fpgaregs l <address> |
− | </ | + | </pre> |
− | + | ====32 bits write==== | |
− | < | + | <pre class="apf"> |
− | fpgaregs l <address> <value> | + | # fpgaregs l <address> <value> |
− | </ | + | </pre> |
= the mmap problem = | = the mmap problem = |
Revision as of 16:13, 14 April 2009
Contents
fpgaregs
Usage
fpgaregs can be used to read and write 16 or 32 bits registers in the FPGA, from Linux Userspace.
16 bits read
# fpgaregs w <address>
Where <address> is an address relative to FPGA's mapping in hexadecimal value.
16 bits write
# fpgaregs w <address> <value>
Where <value> is hexadecimal value to write.
32 bits read
# fpgaregs l <address>
32 bits write
# fpgaregs l <address> <value>
the mmap problem
First of all, you need to get a file descriptor for /dev/mem using the open() function
ffpga=open("/dev/mem",O_RDWR|O_SYNC);
Now you have a valid file descriptor to access your FPGA.
The O_SYNC option is recommended to avoid Linux to cache the content of /dev/mem and delay any modification done in this file.
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 int*)(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 compiling fpgaregs for APF9328.
Links
- http://sources.redhat.com/ml/crossgcc/2005-08/msg00120.html : Explanation of the problem.