Home > Community > Blogs > System Design and Verification > accessing physical memory and registers in a virtual world
 
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more conveniennt.

Register | Membership benefits
Get email delivery of the System Design and Verification blog (individual posts).
 

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

Accessing Physical Memory and Registers in a Virtual World

Comments(0)Filed under: System Design and Verification, Registers, virtual platforms, Memory, Virtual

When working with Virtual Platforms that are running operating systems it's sometimes useful to be able to access a memory or peripheral from a normal user space program. This can help determine if the hardware is connected properly and it can help understand the state of the registers in a peripheral. Fortunately, this is quite easy to do. If you would like to try the ideas described here please refer to the Virtual Platform series of articles I wrote last year. This was a 5 part series around the ARM Integrator platform (Part 1 Part 2 Part 3 Part 4 Part 5) and can be used for additional study.

Accessing memory or a peripheral using a physical address requires a little extra programming to turn the physical address into a virtual address that can be accessed from a user space program. Let's say that a Virtual Platform model has a memory located at address 0x20000000 in the memory map. As usual, I assume the operating system is embedded Linux. To access the memory after the system boots, a small C program can be used. For bare metal applications something like

unsigned long *mem = (unsigned long *) 0x20000000;

unsigned long data;

data = *mem;

would work fine. Many hardware diagnostics are written like this to test the hardware behavior. If this code is tried on embedded Linux things will not go very well. In fact, the program will crash. What is needed is to map the physical address of the memory into the programs virtual memory space using mmap(). Here is a small C program that will perform the desired behavior, it's a small memory test just to demonstrate the concept:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

main()
{
    int   i, j;
    int   words = 10;
    int   devmem;
    off_t PageOffset, PageAddress;

    unsigned long *hw_addr = (unsigned long *) 0x20000000;
    unsigned long  read_data;

    devmem = open("/dev/mem", O_RDWR | O_SYNC);
    PageOffset = (off_t) hw_addr % getpagesize();
    PageAddress = (off_t) (hw_addr - PageOffset);

    hw_addr = (unsigned long *) mmap(0, 4, PROT_READ|PROT_WRITE, MAP_SHARED, devmem, PageAddress);

    for (i = 0, j = 0; i < words; i++, j+=4)
    {
        printf("Writing to hardware model\n");

        *(hw_addr+j) = 0xabcd0000+j;

        read_data = *(hw_addr+j);

        printf("Read from hardware %x\n",read_data);

    }
}

This program can be cross compiled for the ARM Integrator platform using:

%  arm-none-linux-gnueabi-gcc -o mem_access mem_access.c

Follow the steps in Part 4 of my previous series to put the program into the file system, boot Linux, and run the program.

Photobucket


Another useful capability is to use the same program to read the registers from a programmable peripheral. The write/read pattern is not useful, but reading the peripheral's registers can be done the same way. For the Integrator platform the address can be changed to 0x16000000 and all or some part of the UART 0 registers can be read and printed.

Although this is very simple concept, finding clear descriptions of how to apply system calls like open(), getpagesize(), and mmap() to accomplish the task takes a little digging. This approach is very useful when assembling new Virtual Platforms to provide a sanity check that the memory map is configured correctly and the peripherals can be accessed by software. If you are a Virtual Platform creator I'm sure it will come in handy to help trace system behavior.

Jason Andrews

 

Comments(0)

Leave a Comment


Name
E-mail (will not be published)
Comment
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.