cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
367 Views
Registered: ‎12-04-2019

Cannot Access PL registers via AXI-APB dridge

I am trying to read/write a set of PL registers from the PS on the Avnet Microzed 7020 SOM using /dev/mem but have been unsuccessful. They were previously accessed via gpio, which did work, but the implementation has been changed to use an axi-apb bridge.

The environment used is as below: 

Vivado 2019.1
Petalinux 2019.1
Ubuntu 18.04 LTS

compiler for the executable running in rootfs:
/tools/Xilinx/SDK/2019.1/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gcc

The following components have been created in the PL

AXI APB Master Ports
Slave Interface Offset Address Range High Address
APB_M_0 0x43c00000 64k 0x43c0ffff
APB_M2_0 0x43c10000 64k 0x43c1ffff

AXI APB Slave Ports
Slave Base Address High Address
Slave1 0x00000000 0x0fffffff
Slave2 0x10000000 0x1fffffff

APB_M2_0 and Slave 2 have not yet been fully implemented.

PL Register Block
0x00 - 0xFF. Various registers intended to be read/written by the PS.

 

I have tried using the following code to access the registers however I have had limited success being able to read some registers but either obtaining 0 or what appears to be random data.

I was told that the basic formula was simple to read: BaseAddress + PL Register Address. However if I use the PL register address I receive an alignment trap, I can only successfully read from register addresses that are divisible by 8/16/32 etc. Though the data does not look valid. 

uint16_t reg_addr = 0xff; 	// this is a known value: version number.
uint32_t BaseDeviceAddress = 0x43c00000;
int page_size=getpagesize(); // 4096
	
//size_t map_size = page_size;
size_t map_size = 0xffff; // 64k
	
off_t page_offset = (BaseDeviceAddress & (page_size-1));
	
int fd = open ("/dev/mem", O_RDWR);

off_t page_addr = BaseDeviceAddress & ~((typeof(BaseDeviceAddress))page_size-1);
	

void *map_base = mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr);

void *virt_addr = map_base + page_offset;
	
uint32_t read_result = *((volatile uint32_t *) (virt_addr + reg_addr));

 

I have also tried using /dev/uio instead of /dev/mem but unfortunately obtained the same results.

 

fd = open("/dev/uio0", O_RDWR);
void *map_base = mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
uint32_t read_result = *((volatile uint32_t *) (map_base + reg_addr));

 

I'm new to this and any help or advice on what I am doing wrong would be appreciated.

 

 

0 Kudos
2 Replies
shengjie
Moderator
Moderator
315 Views
Registered: ‎06-30-2019

Hi phil.merrick@sarclad.com ,

 

Can you write and read back data by using devmem command in shell?

write: devmem 0x43000000 32 0x12345678

read: devmem 0x43000000

Please refer to this link:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842412/Accessing+BRAM+In+Linux

-------------------------------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------------------------------
如果提供的信息能解决您的问题,请标记为“接受为解决方案”。
如果您认为帖子有帮助,请点击“奖励”。谢谢!
-------------------------------------------------------------------------------------------------
0 Kudos
296 Views
Registered: ‎12-04-2019

I've tried using the devmem2 application but got the same results.

I've not tried accessing any BRAM as there isn't any in the exported hw design I was given.

0 Kudos