概要
RaspberryPiやらNanoPiやらSBC使っていると、直接レジスタ操作したくなってくる。
ので、ちょっとレジスタ操作用アプリ作ってみた。
コード
reg.c
# include <stdio.h>
# include <sys/mman.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h>
# include <stdint.h>
int main( int argc, char * argv[] )
{
int fd;
int num = 4;
int block_size = 16;
void* base_addr = 0;
void* base_addr2map;
void* map_addr;
void* map_addr_target;
unsigned int value;
int mode;
if( argc < 3 )
{
printf( "reg r32 <StartAddress> <num=16>\n");
printf( "reg w32 <Address> <data>\n");
return -1;
}
sscanf( argv[2], "%p", &base_addr );
if( 0 == strcmp( argv[1], "r32" ) )
{
mode = 'R';
num = 16;
if( 3 < argc )
{
sscanf( argv[3], "%d", &num );
}
block_size = num * 4;
}
else if( 0 == strcmp( argv[1], "w32") )
{
mode = 'W';
block_size = 4;
if( argc < 4 )
{
printf( "reg w32 <Address> <data>\n");
return -1;
}
sscanf( argv[3], "0x%x", &value );
}
fd = open( "/dev/mem", O_RDWR | O_SYNC );
if( fd == -1 )
{
printf( "ERROR! Cannot open /dev/mem\n" );
return -1;
}
base_addr2map = (void*)(((size_t)base_addr) >> 12 << 12);
block_size += (size_t)base_addr - (size_t)base_addr2map;
map_addr = mmap( NULL, block_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)base_addr2map );
if( map_addr == MAP_FAILED )
{
printf("ERROR! Cannot map physical addr to virtual addr. %p\n", base_addr );
return -1;
}
map_addr_target = (void*)((size_t)map_addr + (size_t)base_addr - (size_t)base_addr2map);
close( fd );
switch( mode )
{
case 'R':
{
uint32_t* addr = (uint32_t*)map_addr_target;
int i;
for( i = 0; i < num;i++ )
{
printf( "%p : 0x%08x\r\n", &((uint32_t*)base_addr)[i], addr[i] );
}
}
break;
case 'W':
{
uint32_t* addr = (uint32_t*)map_addr_target;
uint32_t org = addr[0];
addr[0] = value;
msync( map_addr_target, 4, MS_SYNC );
printf( "%p : 0x%08x --> w 0x%08x --> r 0x%08x\r\n", base_addr, org, value, addr[0] );
}
break;
}
munmap( map_addr, block_size );
return 0;
}
使い方
ソースゲット&コンパイル
git clone https://github.com/blue777/NanoPi-NEO/
cd NanoPi-NEO
gcc reg.c -o reg
レジスタ読み込み
reg r32 [PhysicalAddress] [Num=16]
r32 は、Read で 32bit単位読み出し。
r8とかは、まだない。
PhysicalAddressにレジスタのアドレスを入れる。
Numには、表示する個数
例
root@NanoPi-NEO-Plus2:~/NanoPi-NEO# ./reg r32 0x1c22000
0x1c22000 : 0x00060115
0x1c22004 : 0x00001f77
0x1c22008 : 0x00000000
0x1c2200c : 0x00000044
0x1c22010 : 0x00000000
0x1c22014 : 0x000400f4
0x1c22018 : 0x003e0000
0x1c2201c : 0x00000080
0x1c22020 : 0x00000000
0x1c22024 : 0x00000111
0x1c22028 : 0x00d73c06
0x1c2202c : 0x00000000
0x1c22030 : 0x00000001
0x1c22034 : 0x00001031
0x1c22038 : 0x00000000
0x1c2203c : 0x00000000
レジスタ書き込み
reg w32 [PhysicalAddress][Value]
w32 は、32bit単位書き込み。
w8とかは、まだない。
PhysicalAddressにレジスタのアドレスを入れる。
Valueに書き込む値を設定
例
root@NanoPi-NEO-Plus2:~/NanoPi-NEO# ./reg w32 0x01c22004 0x00001775
0x1c22004 : 0x00001f77 --> w 0x00001775 --> r 0x00001775
書く前に一回読みだして表示し、書き込んだ後、再度読み出して表示しています。
最後に
レジスタ操作等は、危険ですので理解したうえでご利用くださいませ。
最悪、壊れます。
あと、root権限必要となります。