- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-16-2012 06:51 AM
We added a custom PL logic to Zynq. The xparameters.h of Bare-Metal BSP shows the base address of custom logic is mapped at:
#define XPAR_APB_LOGIC_BASEADDR 0x72800000
#define XPAR_APB_LOGIC_HIGHADDR 0x7287FFFF
And I was able to poke registers at that address region.
Xilinx SDK does not generate Zynq BSP for Linux.
How do I find out where the custom logic is mapped to if running Linux?
Access to above region from Linux kernel module caused kernel panic message below:
Unable to handle kernel paging request at virtual address 72800000
pgd = d680c000
[72800000] *pgd=00000000
Internal error: Oops: 5 [#1] PREEMPT SMP
Modules linked in: sevdev(+)
CPU: 0 Not tainted (3.0.0-01263-g16c45e2 #6)
PC is at sevdev_probe+0x1c0/0x200 [sevdev]
LR is at kobj_map+0xf4/0x104
pc : [<bf00120c>] lr : [<c01b1400>] psr: 60000013
sp : d78c1e00 ip : 00000001 fp : 00000000
r10: 00000001 r9 : bf001908 r8 : d7a34c34
r7 : bf001e78 r6 : 00000000 r5 : bf0019b8 r4 : d7a34c00
r3 : 00000000 r2 : 00000000 r1 : 72800000 r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 18c5387d Table: 1680c04a DAC: 00000015
Process modprobe (pid: 465, stack limit = 0xd78c02f0)
Stack: (0xd78c1e00 to 0xd78c2000)
1e00: bf0019f4 bf0019c0 bf0019c0 bf0019f4 bf001c6c bf001c6c 00000002 00000150
1e20: 00000150 c01b099c c01b0988 c01afae8 00000000 bf0019c0 bf0019f4 bf001c6c
1e40: 00000000 c01afc04 bf001c6c c01afba4 00000000 c01aed8c d784b5c0 d79d7758
1e60: bf001c6c d79d7120 c03e1cd8 c01af404 bf001580 bf001582 00000000 bf001c6c
1e80: 00000002 bf0019b8 bf001b08 00000002 00000150 c01b00e0 bf001e78 00000002
1ea0: bf0019b8 bf001b08 00000002 00000150 00000150 bf000ebc bf001580 bf001e78
1ec0: 00000005 0fc00000 bf001d38 bf001d80 00000001 bf000ca8 00000000 00000026
1ee0: 000005f0 c002c650 bf000ca8 00000000 00000001 bf001d38 bf001d38 bf001d80
1f00: 00000001 d7886c20 00000001 c0077ac0 bf001d44 00000000 c02d3064 000e070d
1f20: 000011bf d886c000 0000491f d886ea84 d886e8ff d8870384 d7a34c00 000020a0
1f40: 00002210 00000000 00000000 00000024 00000025 00000019 0000001d 00000014
1f60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 c0397a9c
1f80: d782e060 000fa0ca 00000000 00000000 00000080 c0031a84 d78c0000 00000000
1fa0: 000f2040 c0031900 000fa0ca 00000000 001060e8 0000491f 000e070d 00000000
1fc0: 000fa0ca 00000000 00000000 00000080 000fa0ca 000fa0d8 00000000 000f2040
1fe0: becbff70 becbf974 0002c420 402a6b54 60000010 001060e8 00000000 00000000
[<bf00120c>] (sevdev_probe+0x1c0/0x200 [sevdev]) from [<c01b099c>] (platform_drv
_probe+0x14/0x18)
[<c01b099c>] (platform_drv_probe+0x14/0x18) from [<c01afae8>] (driver_probe_devi
ce+0xc8/0x184)
[<c01afae8>] (driver_probe_device+0xc8/0x184) from [<c01afc04>] (__driver_attach
+0x60/0x84)
[<c01afc04>] (__driver_attach+0x60/0x84) from [<c01aed8c>] (bus_for_each_dev+0x4
8/0x74)
[<c01aed8c>] (bus_for_each_dev+0x48/0x74) from [<c01af404>] (bus_add_driver+0x98
/0x214)
[<c01af404>] (bus_add_driver+0x98/0x214) from [<c01b00e0>] (driver_register+0xa0
/0x124)
[<c01b00e0>] (driver_register+0xa0/0x124) from [<bf000ebc>] (sevdev_init+0x214/0
x244 [sevdev])
[<bf000ebc>] (sevdev_init+0x214/0x244 [sevdev]) from [<c002c650>] (do_one_initca
ll+0x94/0x164)
[<c002c650>] (do_one_initcall+0x94/0x164) from [<c0077ac0>] (sys_init_module+0x1
688/0x1850)
[<c0077ac0>] (sys_init_module+0x1688/0x1850) from [<c0031900>] (ret_fast_syscall
+0x0/0x30)
Code: eb46ade7 e3e00012 ea00000c e5941018 (e591e000)
---[ end trace e9d9a2adbd64c591 ]---
Segmentation fault
Solved! Go to Solution.
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-16-2012 08:32 AM
There has to be a mapping added to the MMU to go from that physical address to a virtual address (ioremap call). There are examples on how to get access via userspace using mmap also which is more of a prototype solution.
You can see http://wiki.xilinx.com/osl-user-mode-pseudo-driver which is the principal I'm referring to. You can also use devmem from the console to read/write the addresses, or use it from a bash script to peek and poke.
Thanks.
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-16-2012 10:17 AM
John,
I was trying to access the PL logic from a kernel module.
Do I have to map physical address to virtual address for kernel module too?
For example, can I access device registers in a kernel module as below:
/* Device's physical address */
#define XPAR_APB_LOGIC_BASEADDR 0x72800000
#define XPAR_APB_LOGIC_HIGHADDR 0x7287FFFF
uint32_t* regAddr = (uint32_t*)XPAR_APB_LOGIC_BASEADDR;
volatile uint32_t regData;
regData = (volatile uint32_t) *regAddr;
Thanks
Pullan
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-16-2012 10:18 AM
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-31-2012 06:02 AM
Hi Pullan,
I can't tell exactly what you are doing of course but as a helpful suggestion you may be able to write what is called a user space driver using he Linux mmap command to get what you need. I've done this for several simple periperals and it works well. A good reference is "Linux Device Drivers" by Alessandro Rubini and Jonathan Corbet. I believe this is available as a free download on the web. There are some limitations to what one can do with a user space driver but hopefully this helps you.
-Bob
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-31-2012 04:32 PM
The usual embedded Linux way is to use the "/dev/mem" to mmap() physical memory to user space virtual memory. This sort of thing is very dangerous on a PC but has become common practice on embedded platforms. Example source code is out there on the internet. Search for devmem2.c.
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
05-31-2012 09:30 PM
Dear Bob and Norman,
Thanks for the tips. I got it working in my kernel driver. As John said, I need to call ioremap() to map device's physical address into kernel space.
Pullan
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
10-19-2012 09:24 AM
A follow-up question on this topic. The example pseudo driver is given for GPIO. Will the same approach work if I have a custom IP connected using the AXI interconnect. How do I know what are the offsets, if any for the control signals (like the GPIO_DIRECTION_OFFSET value in the example driver) for the AXI interconnect? Wasn't quite clear to me how the value of GPIO_DIRECTION_OFFSET was derived. Is it documented somewhere?
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
10-23-2012 05:50 AM
Offsets are described in the documentation for the IP core you are using. For the GPIO example, the AXI GPIO core has the DATA register at offset 0x0 and 3-STATE register (or DIRECTION register) at offset 0x4 for channel 1.
For a custom core, you define the number of AXI-accessible registers and what each one does. If you only need to read and write single samples to registers, then this pseudo driver approach will work with custom PL. Generally, a full fledged driver is needed to support interrupts and more complex operations.
Re: ZC702: How to access custom PL logic from Linux Kernel Module
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
10-24-2012 05:51 AM
Just as a note, look up the devm_ioremap version of the call. It is better for new work.











