linux 进程 物理内存,linux多进程如何访问同一块物理内存?

mmap操作荔枝派gpio v3s Linux

转至https://blog.csdn.net/diqiyong3212/article/details/102053091

1.预备知识

https://baike.baidu.com/item/mmap/1322217?fr=aladdin 大家直接看百度百科,比较清楚了。

2.代码

gpio.c

#include "gpio.h"

unsigned int fd;

PIO_Map *PIO = NULL;

unsigned int *gpio_map;

unsigned int addr_start, addr_offset;

unsigned int PageSize, PageMask;

void GPIO_Init(void)

{

if ((fd = open("/dev/mem", O_RDWR)) == -1)

{

printf("open error\r\n");

return;

}

PageSize = sysconf(_SC_PAGESIZE); //使用sysconf查询系统页面大小

PageMask = (~(PageSize - 1));     //页掩码

printf("PageSize:%d,PageMask:0x%.8X\r\n", PageSize, PageMask);

addr_start = PIO_BASE_ADDRESS & PageMask;   //0x01C20800 & 0xfffff000 =  0x1C20000

addr_offset = PIO_BASE_ADDRESS & ~PageMask; //0x01C20800 & 0x00000100 = 0x800

printf("addr_start:%.8X,addr_offset:0x%.8X\r\n", addr_start, addr_offset);

//mmap(系统自动分配内存地址,映射区长度“内存页的整数倍”,选择可读可写,MAP_SHARED=与其他所有映射到这个对象的进程共享空间,文件句柄,被映射内容的起点)

//offest 映射物理内存的话,必须页对其!!!   所以这个起始地址应该是0x1000的整数倍,那么明显0x01C20800需要减去0x800才是整数倍!

if ((gpio_map = mmap(NULL, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start)) == NULL)

{

printf("mmap error\r\n");

close(fd);

return;

}

printf("gpio_map:%.8X\r\n", gpio_map);

//这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~

PIO = (PIO_Map *)((unsigned int)gpio_map + addr_offset);

printf("PIO:0x%.8X\r\n", PIO);

close(fd); //映射好之后就可以关闭文件?

}

void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode)

{

if (gpio_map == NULL)

return;

PIO->Pn[port].CFG[pin / 8] &= ~((unsigned int)0x07 << pin % 8 * 4);

PIO->Pn[port].CFG[pin / 8] |= ((unsigned int)mode << pin % 8 * 4);

printf("struct PIO_Struct size : %d",sizeof(PIO->Pn[port]));

}

void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level)

{

if (gpio_map == NULL)

return;

if (level)

PIO->Pn[port].DAT |= (1 << pin);

else

PIO->Pn[port].DAT &= ~(1 << pin);

}

int GPIO_Free(void)

{

if ((munmap(gpio_map, PageSize * 2)) == 0)//取消映射

{

printf("unmap success!\r\n");

}

else

{

printf("unmap failed!\r\n");

}

return 0;

}

gpio.h

#ifndef __GPIO_H__

#define __GPIO_H__

#include

#include

#include

#include

#include

#include

#define PIO_BASE_ADDRESS 0x01C20800

//unsigned int 4字节 一个PIO_Struct占36字节,对应十六进制就是0x24,正好是一个offset值。

typedef struct

{

unsigned int CFG[4];

unsigned int DAT;

unsigned int DRV0;

unsigned int DRV1;

unsigned int PUL0;

unsigned int PUL1;

} PIO_Struct;

typedef struct

{

PIO_Struct Pn[7];

} PIO_Map;

typedef enum {

PA = 0,

PB = 1,

PC = 2,

PD = 3,

PE = 4,

PF = 5,

PG = 6,

} PORT;

typedef enum {

IN = 0x00,

OUT = 0x01,

AUX = 0x02,

INT = 0x06,

DISABLE = 0x07,

} PIN_MODE;

extern PIO_Map *PIO;

void GPIO_Init(void);

void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode);

void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level);

unsigned int GPIO_GetPin(PORT port, unsigned int pin);

int GPIO_Free(void);

#endif

main.c

#include

#include

#include

#include

#include

#include

#include "gpio.h"

#include

int main()

{

int a=0,b=-1,i;

GPIO_Init();

GPIO_ConfigPin(PB,4,OUT);

GPIO_ConfigPin(PB,5,OUT);

for(i=0;i<20;i++)

{

GPIO_SetPin(PB,4,a=~a);//!!-1的取反是0 1的取反是-2....

GPIO_SetPin(PB,5,b=~b);

//usleep(100000);

sleep(1);

}

GPIO_Free();

}

makefile

TARGET        = myGPIO    #可执行文件名称

########################编译参数############################

CC            = arm-linux-gnueabihf-gcc

CXX           = arm-linux-gnueabihf-g++

DEFINES       =

CFLAGS        = -pipe -g -Wall -W -fPIE $(DEFINES)

CXXFLAGS      = -pipe -g -Wall -W -fPIE $(DEFINES)

INCPATH       = -I.

########################编译文件############################

SOURCES       = ./main.c ./gpio.c

OBJECTS       = main.o gpio.o

$(TARGET) : $(OBJECTS)

$(CC) -o $(TARGET) $(OBJECTS)

main.o : main.c gpio.h

$(CC) $(include) $(CFLAGS) -c main.c

gpio.o : gpio.c gpio.h

$(CC) $(include) $(CFLAGS) -c gpio.c

clean :

rm  $(OBJECTS) $(TARGET)

3.运行

将程序编译出来放到v3s上运行,那么pb4 pb5 会交替高低电平。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值