之所以叫伪裸机,是因为还是基于操作系统的,并不能真正的裸机开发。
/dev/mem文件:
首先得了解一下什么是/dev/mem文件,有什么作用:
/dev/mem简单来说是作为一个linux内核几乎通用的硬件地址映射文件,可以通过这个向硬件寻址,从而操作寄存器。
由图可见,此文件大概占1bytes的大小。并且这个文件是需要在特权模式下才能使用的。
更详细的解释在这一篇文章中有写
对于/dev/mem的番外了解,挺有意思的一篇文章
sys/mman.h头文件:
在c语言库中的一个虚拟地址映射头文件,可以将文件以地址的方式打开,即不需要打开全部缓存即可修改文件。用这个即可打开mem从而改写地址然后可以操作寄存器。
mmap的函数有很多,但是常用的莫非就是mmap和munmap,以v831为例,
#include "io.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
void *map_bass=NULL;
unsigned long *io_ph1se;
unsigned long *io_phdat;
void io_init()
{
int fd=0;
fd = open("/dev/mem", O_RDWR | O_NDELAY); //可读可写非阻塞
if(fd<0)
{
printf("failed to open mem\n");
return -1;
}
map_bass=mmap(0,1,PROT_READ | PROT_WRITE,MAP_SHARED,fd,IO_BASE);//从0说明自动选择起始地址,可读可写,
//对映射区写数据同时会写入文件,且允许其他映射该文件的进程共享,fd,base应该是4096的倍数
if (NULL == map_bass)
{
printf("mmap failed\n");
return -1;
}
io_ph1se=(unsigned long *)(map_bass+IOH1_SELECT);
io_phdat=(unsigned long *)(map_bass+IOH_DAT);
close(fd); //映射成功,关掉文件
// unsigned long *p;
// p=munmap(&IOH1_SELECT,32);
//*io_ph1se=0x77755557;
printf("%x\n",*io_ph1se); //读取ph的数值
*io_ph1se=(*io_ph1se&0xf8ffffff)|0x01000000; //PH14设置成OUTPUT
printf("%x\n",*io_ph1se); //成功读取
//printf("%x\n",p);
//*p|=0x01000000; //PH14设置成OUTPUT
}
void io_turn()
{
if(*io_phdat&0x4000)
{
//printf("led turn off %x\n",*io_phdat);
*io_phdat&=~(0x00004000);
}
else
{
//printf("led turn on %x\n",*io_phdat);
*io_phdat|=0x00004000;
}
}
int io_driver()
{
io_init();
while (1)
{
io_turn();
printf("hellow world\n");
sleep(2);
}
return 0;
}
以上为读取v831的state灯然后两秒钟反复转换的例子,
可见非常成功