UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Explorer
Explorer
18,075 Views
Registered: ‎11-16-2012

how to read/write from/to a register in Linux?

Jump to solution

Dear Colleague,

 

Thanking you all for your kind support !!

 

I have a design which is working well. Till now i am writing my c program in sdk for standalone version and launching through JTAG.

 

But now I would like to know that if I use linux OS and want to read and write to specific registers how could I do it ?

 

I am using Zynq-7000 APSoc Zc702 evalution board. 

 

Regards

 

0 Kudos
1 Solution

Accepted Solutions
29,894 Views
Registered: ‎03-27-2014

Re: how to read/write from/to a register in Linux?

Jump to solution

I have a design which is working well. Till now i am writing my c program in sdk for standalone version and launching through JTAG.

But now I would like to know that if I use linux OS and want to read and write to specific registers how could I do it ?

 

this subject has been discussed many times,

 

in a baremetal apps you can directly address physical addresses,

on Linux you can only use a virtual address mapped to the physical address.

 

That means you can't do stuff like this anymore

(unsigned int*)(FPGA_BASE+0x04) = 0x01; -- write example
val = (unsigned char *)(FPGA_BASE+0x00); -- reading one byte

 

you can use the /dev/mem driver which allows you to address physical addresses  from userspace

fd = open ("/dev/mem", O_RDWR);
page_addr = (fpga_base_addr & (~(page_size-1))); 
page_offset = fpga_base_addr - page_addr;
virtual_address = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr); //memory map

 see this page for nice tutorials mmap

 

this job is usually done in the kernel space by a driver, here's how to map a virtual pointer to a physical address retrieved from the devicetree

sdev->regs = devm_ioremap_resource(&pdev->dev, res);
if(IS_ERR(sdev->regs)){
     printk(KERN_ERR "devm_ioremap failed for %s\n",
          sdev->name);
     status = -ENOMEM;
     goto free_dev_name;
}

 

G.W.,
NIST - Time Frequency metrology
3 Replies
29,895 Views
Registered: ‎03-27-2014

Re: how to read/write from/to a register in Linux?

Jump to solution

I have a design which is working well. Till now i am writing my c program in sdk for standalone version and launching through JTAG.

But now I would like to know that if I use linux OS and want to read and write to specific registers how could I do it ?

 

this subject has been discussed many times,

 

in a baremetal apps you can directly address physical addresses,

on Linux you can only use a virtual address mapped to the physical address.

 

That means you can't do stuff like this anymore

(unsigned int*)(FPGA_BASE+0x04) = 0x01; -- write example
val = (unsigned char *)(FPGA_BASE+0x00); -- reading one byte

 

you can use the /dev/mem driver which allows you to address physical addresses  from userspace

fd = open ("/dev/mem", O_RDWR);
page_addr = (fpga_base_addr & (~(page_size-1))); 
page_offset = fpga_base_addr - page_addr;
virtual_address = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, page_addr); //memory map

 see this page for nice tutorials mmap

 

this job is usually done in the kernel space by a driver, here's how to map a virtual pointer to a physical address retrieved from the devicetree

sdev->regs = devm_ioremap_resource(&pdev->dev, res);
if(IS_ERR(sdev->regs)){
     printk(KERN_ERR "devm_ioremap failed for %s\n",
          sdev->name);
     status = -ENOMEM;
     goto free_dev_name;
}

 

G.W.,
NIST - Time Frequency metrology
Observer sconvertini
Observer
2,415 Views
Registered: ‎09-06-2018

Re: how to read/write from/to a register in Linux?

Jump to solution

Hi,

I followed your instructions to read the register of the global timer (physical address 0xF8F00200 defined in xparameter.h)

so, I open the /dev/mem file as follow:

 

int memfd;
	memfd = open("/dev/mem", O_RDWR | O_SYNC); // to open this, the program needs to be run as root
	if (memfd == -1) {
		printf("Can't open /dev/mem.\n");
		exit(0);
	}

to provide the virtual address, I use a custom function as follow:

 

 

void *getvaddr(int phys_addr, int memfd) {
	void *mapped_base;

	void *mapped_dev_base;
	off_t dev_base = phys_addr;



	// Map one page of memory into user space such that the device is in that page, but it may not
	// be at the start of the page

	mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd,
			dev_base & ~MAP_MASK);
	if (mapped_base == (void *) -1) {
		printf("Can't map the memory to user space.\n");
		exit(0);
	}

	// get the address of the device in user space which will be an offset from the base
	// that was mapped as memory is mapped at the start of the page

	mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
	return mapped_dev_base;
}

Then I initialized a variable as follow:

 

 

int *global_timer_addr = getvaddr(XPAR_PS7_GLOBALTIMER_0_S_AXI_BASEADDR, memfd);
	int *timer_0 = global_timer_addr;

I'm using a while statement to test the timer register as follow:

while (1) {
		if (*timer_0 > 333333333) {
			SetLedPin();
			*timer_0 = 0;
		}
		else
			ClearLedPin();
	}

I have no problem in reading *timer0 but whe I attempt to write 0 value in *timer, my MicroZed freezes and I need to hardware reset the board.

Do you have any idea how to solve it?

Thank you for your support.

 

0 Kudos
Explorer
Explorer
361 Views
Registered: ‎02-15-2019

Re: how to read/write from/to a register in Linux?

Jump to solution
有人解决这个问题吗?
0 Kudos