MMAP TOOL Design
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]
The following is to show my whole code here, you should only copy this code and cross compile it to your embedded system.
[Code]
Fixed some bugs, v1.1: http://download.csdn.net/detail/duanzhang512/9604016
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
#include
#include
#include
#include
#include
#include
#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("**********************************************
");
fprintf(stdout, "* MMAP TOOL V%s *\n", TOOL_VERSION);
printf("**********************************************
");
printf("Usage: %s [OPTIONS...]
", str);
printf("OPTIONS:
");
printf("\t-h/? This help text
");
printf("\t-v Print version
");
printf("\t-r/w Read or write
");
printf("\t-a [hex] Address
");
printf("\t-d [hex] Data to write
");
printf("\t-l [dec] Read length
");
printf("\t-b [dec] Bit of data
");
printf("\t-e Big endian
");
}
void ShowVersion(void)
{
fprintf(stdout, "version %s
", 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!
");
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!
");
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; iprintf(" %02x", *cp++);
reg++;
}
printf(" ");
cp = linebuf;
for (i=0; iif ((*cp < 0x20) || (*cp > 0x7e))
putchar('.');
else
printf("%c", *cp);
cp++;
}
putchar('
');
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
", GetAlignedRegister(addr, 4), val, bit, ReadBitOfValue(val, bit));
else
printf("REG(0x%08x): 0x%08x
", GetAlignedRegister(addr, 4), val);
}
else
{
printf("REG(0x%08x): 0x%08x
", 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
", GetAlignedRegister(addr, 4), val, bit, ReadBitOfValue(val, bit));
else
printf("REG(0x%08x): 0x%08x
", GetAlignedRegister(addr, 4), val);
}
else
{
WriteRegister(GetAlignedRegister(addr, 4), data);
val = ReadRegister(GetAlignedRegister(addr, 4));
printf(" REG(0x%08x): 0x%08x
", GetAlignedRegister(addr, 4), val);
}
}
return EXIT_SUCCESS;
}
Fixed some bugs, v1.1: http://download.csdn.net/detail/duanzhang512/9604016