linux-c-tina-'伪'裸机开发--寄存器操作篇

发布时间 2023-06-23 20:10:59作者: 悠闲的小莫

之所以叫伪裸机,是因为还是基于操作系统的,并不能真正的裸机开发。

/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灯然后两秒钟反复转换的例子,

可见非常成功

详细的mmap用法: