MMAP TOOL Design

本文介绍了一个用于嵌入式Linux系统的简单内存操作工具,该工具能够方便地读取和修改寄存器中的特定位,适用于从事嵌入式Linux系统开发的工程师。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hi guys, I am going to share my an easy tool which can operate memory from embedded linux system here to celebrate the second anniversary for my job. If you are engaged in doing embedded linux system, you should always compute the value of certain bit for a register, you know, it’s so annoying. Now, congratulations, you can read or edit the certain bit of register with my tool.

First of all, introduce the function of this tool, take the s3c2440 for an example.

[Test log]

[root@fred]# cat /proc/version 
Linux version 2.6.32.2 (root@fred) (gcc version 4.4.3 (ctng-1.6.1) ) #36 Tue Jun 28 22:30:19 CST 2016
[root@fred]# cat /proc/cpuinfo 
Processor       : ARM920T rev 0 (v4l)
BogoMIPS        : 201.93
Features        : swp half thumb 
CPU implementer : 0x41
CPU architecture: 4T
CPU variant     : 0x1
CPU part        : 0x920
CPU revision    : 0

Hardware        : MINI2440 By Fred
Revision        : 0000
Serial          : 0000000000000000
[root@fred]# mmap 
**********************************************
*              MMAP TOOL V1.0                *
**********************************************
Usage: mmap [OPTIONS...]
OPTIONS:
    -h/?      This help text
    -v        Print version
    -r/w      Read or write
    -a [hex]  Address
    -d [hex]  Data to write
    -l [dec]  Read length
    -b [dec]  Bit of data
    -e        Big endian
[root@fred]# mmap -v
version 1.0
[root@fred]# mmap -r -a 56000010
REG(0x56000010): 0x00295551
[root@fred]# mmap -r -a 56000010 -b 2
REG(0x56000010): 0x00295551 [2]=0
[root@fred]# mmap -r -a 56000010 -l 16
56000010: 00 29 55 51 00 00 02 00 00 00 07 ff 00 00 00 00    .)UQ............
[root@fred]# mmap -r -a 56000010 -l 16 -e
56000010: 51 55 29 00 00 02 00 00 ff 07 00 00 00 00 00 00    QU).............
[root@fred]# mmap -w -a 56000010 -d 0x00295555
 REG(0x56000010): 0x00295555
[root@fred]# mmap -w -a 56000010 -b 2 -d 0
REG(0x56000010): 0x00295551 [2]=0
[root@fred]# mmap -w -a 56000010 -b 2 -d 1
REG(0x56000010): 0x00295555 [2]=1

The following is to show my whole code here, you should only copy this code and cross compile it to your embedded system.

[Code]

/*
 * MMAP TOOL V1.0
 * Easy tool to read memory from embedded linux system
 * Fred 2016/08/13
 */

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>

#define TOOL_VERSION        "1.0"
#define MAP_SIZE            4096UL
#define MAP_MASK            (MAP_SIZE - 1)
#define DISP_LINE_LEN       16

typedef enum 
{
    READ_MMAP,
    WRITE_MMAP,
    END_OF_FUNCLIST
}mmap_cmds;

mmap_cmds cmd = END_OF_FUNCLIST;

void ShowHelp(char *str)
{
    printf("**********************************************\n");
    fprintf(stdout, "*              MMAP TOOL V%s                *\n", TOOL_VERSION);
    printf("**********************************************\n");
    printf("Usage: %s [OPTIONS...]\n", str);
    printf("OPTIONS:\n");
    printf("\t-h/?      This help text\n");
    printf("\t-v        Print version\n");
    printf("\t-r/w      Read or write\n");
    printf("\t-a [hex]  Address\n");
    printf("\t-d [hex]  Data to write\n");
    printf("\t-l [dec]  Read length\n");
    printf("\t-b [dec]  Bit of data\n");
    printf("\t-e        Big endian\n");
}

void ShowVersion(void)
{
    fprintf(stdout, "version %s\n", TOOL_VERSION);
}

inline uint32_t GetAlignedRegister(uint32_t reg, uint32_t align)
{
    return (uint32_t)(((reg + align) & ~(align - 1)) - align);
}

inline uint32_t EndianConvert(uint32_t val)
{
    return (uint32_t)(((val & 0xff) << 24) + (((val >> 8) & 0xff) << 16) + (((val >> 16) & 0xff) << 8) + ((val >> 24) & 0xff));
}

inline uint8_t ReadBitOfValue(uint32_t val, uint8_t bit)
{
    return (uint8_t)((val & (1 << bit)) >> bit);
}

inline uint32_t WriteBitOfValue(uint32_t val, uint8_t bit, uint8_t num)
{
    if(num)     
        return (uint32_t)(val | (1 << bit));
    else 
        return (uint32_t)(val & ~(1 << bit));      
}

inline uint32_t StringToNumber(char *str, uint8_t system)
{
    return (uint32_t)strtol(str, NULL, system);
}

static void *RegisterMap(uint32_t addr, int *fop)
{
    int fd;
    void *base, *virt_addr;

    fd = open("/dev/mem", O_RDWR | O_SYNC);

    if(fd < 0)
    {
        printf("open /dev/mem error!\n");
        return (void *)-1;
    }

    base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr & ~MAP_MASK);

    if(base == (void *)-1)
    {
        printf("map base is NULL!\n");
        return (void *)-1;
    }

    virt_addr = base + (addr & MAP_MASK);
    *fop = fd;

    return virt_addr;
}

static void RegisterUnmap(void *addr, int fd)
{
    munmap(addr, MAP_SIZE);
    close(fd);
}

uint32_t ReadRegister(uint32_t reg)
{
    void *scu_addr;
    int scu_fd;
    uint32_t val;
    uint32_t i;

    scu_addr = RegisterMap(reg, &scu_fd);
    val = *(volatile uint32_t *)scu_addr;

    RegisterUnmap(scu_addr, scu_fd);
    return (uint32_t)val;
}

void WriteRegister(uint32_t reg, uint32_t val)
{
    void *scu_addr;
    int scu_fd;

    scu_addr = RegisterMap(reg, &scu_fd);
    *(volatile uint32_t *)scu_addr = val;

    RegisterUnmap(scu_addr, scu_fd);
}

void PrintLine(uint32_t reg, uint32_t length, uint8_t big_endian)
{
    int i, nbytes, linebytes;
    uint8_t linebuf[DISP_LINE_LEN];
    uint8_t *cp;
    uint32_t val, line = 0;;

    nbytes = length * 4;

    do
    {
        linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
        for(i = 0;i < linebytes / 4;i++)
        {
            val = ReadRegister(GetAlignedRegister(reg + i * 4 + line * DISP_LINE_LEN, 4));
            if(big_endian)
            {
                linebuf[i*4]   = val & 0xff;
                linebuf[i*4+1] = (val>>8) & 0xff;
                linebuf[i*4+2] = (val>>16) & 0xff;
                linebuf[i*4+3] = (val>>24) & 0xff;
            }
            else
            {
                linebuf[i*4]   = (val>>24) & 0xff;
                linebuf[i*4+1] = (val>>16) & 0xff;
                linebuf[i*4+2] = (val>>8) & 0xff;
                linebuf[i*4+3] = val & 0xff;
            }
        }

        printf("%08x:", GetAlignedRegister(reg, 4));
        cp = linebuf;
        for (i=0; i<linebytes; i++) 
        {
            printf(" %02x", *cp++);
            reg++;
        }
        printf("    ");
        cp = linebuf;
        for (i=0; i<linebytes; i++) 
        {
            if ((*cp < 0x20) || (*cp > 0x7e))
                putchar('.');
            else
                printf("%c", *cp);
            cp++;
        }
        putchar('\n');

        line++;
        nbytes -= linebytes;
    }while(nbytes > 0);

}

static const char *optString = "a:d:l:b:rwev";

int main(int argc, char **argv)
{   
    char ch = 0;
    uint8_t bit = 0;
    uint8_t bit_mode = 0, list_mode = 0, big_endian_mode = 0; 
    uint32_t addr = 0, data = 0, val = 0, len = 1;

    opterr = 0;

    if(argc == 1)
    {
        ShowHelp(argv[0]);
        exit(EXIT_SUCCESS);
    }

    while((ch = getopt(argc, argv, optString)) != -1) 
    {
        switch(ch) 
        {
            case 'a':
                addr = StringToNumber(optarg, 16);
            break;
            case 'd':
                data = StringToNumber(optarg, 16);
            break;          
            case 'l':
                len = StringToNumber(optarg, 10);
                list_mode = 1;
            break;
            case 'b':
                bit = StringToNumber(optarg, 10);
                bit_mode = 1;
            break;
            case 'r':
                cmd = READ_MMAP;
            break;          
            case 'w':
                cmd = WRITE_MMAP;
            break;          
            case 'e':               
                big_endian_mode = 1;;
            break;
            case 'v':
                ShowVersion();
                exit(EXIT_SUCCESS);
            break;
            default:
                ShowHelp(argv[0]);
                exit(EXIT_SUCCESS);
            break;
        }
    }

    if(cmd == READ_MMAP)
    {
        if(list_mode)
        {
            PrintLine(addr, (len - 1) / 4 + 1, big_endian_mode);
        }
        else
        {
            val = ReadRegister(GetAlignedRegister(addr, 4));
            if(bit_mode)
            {
                if(bit < 32)
                    printf("REG(0x%08x): 0x%08x\t[%d]=%d\n", GetAlignedRegister(addr, 4), val, bit, ReadBitOfValue(val, bit));
                else
                    printf("REG(0x%08x): 0x%08x\n", GetAlignedRegister(addr, 4), val);              
            }           
            else
            {
                printf("REG(0x%08x): 0x%08x\n", GetAlignedRegister(addr, 4), val);
            }       
        }
    }
    else if(cmd == WRITE_MMAP)
    {
        if(bit_mode)
        {
            val = ReadRegister(GetAlignedRegister(addr, 4));
            WriteRegister(GetAlignedRegister(addr, 4), WriteBitOfValue(val, bit, data));

            val = ReadRegister(GetAlignedRegister(addr, 4));
            if(bit < 32)
                printf("REG(0x%08x): 0x%08x\t[%d]=%d\n", GetAlignedRegister(addr, 4), val, bit, ReadBitOfValue(val, bit));
            else
                printf("REG(0x%08x): 0x%08x\n", GetAlignedRegister(addr, 4), val);                          
        }
        else
        {
            WriteRegister(GetAlignedRegister(addr, 4), data);

            val = ReadRegister(GetAlignedRegister(addr, 4));            
            printf(" REG(0x%08x): 0x%08x\n", GetAlignedRegister(addr, 4), val);
        }
    }

    return EXIT_SUCCESS;
}

Fixed some bugs, v1.1: http://download.youkuaiyun.com/detail/duanzhang512/9604016

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值