打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Accessing Physical Memory and Registers in a Virtual World

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.


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

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
手把手教你玩转ARP包(二)【数据包的游戏系列之一】
Android4.0.1 源码下载,模拟器编译和运行
FrameBuffer编程一(数据结构)
ADROID 2.1 架构解析 3 亮度设置(二)
【转载】玩转ARP攻击
struct resource,struct platform_device和驱动的关系?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服