关于双核通信通过共享内存交换数据ARM端程序的学习

本文介绍了一种通过/dev/mem接口实现物理内存映射的方法,详细展示了如何在C语言程序中映射特定物理地址范围,并提供了完整的代码示例。文中还解释了mmap函数参数及其意义,有助于理解内存映射原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "../shared/protocol.h"

static int map_addr(int *fd, off_t phy_addr, size_t length, void **map_base, void **virt_addr); 

int main(int argc, char **argv) {
	int fd = -1;
	void *map_base = NULL;
   	char *dest = NULL;
	off_t phy_addr = SHARED_BUFFER_ADDR;
	/*这个地址可以在protocol.h中查到*/
	size_t length = SHARED_BUFFER_SIZE; 
/*protocol.h中的内容:*/


----------


#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_

/*  Memory Map (see ../dsp/c6748.cmd and linux boot arguments)
 *
 *  1180_0000 - 1184_0000        4_0000  ( 256 KB) SHDSPL2RAM 
 *  8000_0000 - 8002_0000        2_0000  ( 128 KB) SHRAM
 *  C000_0000 - C7FF_FFFF      800_0000  ( 128 MB) External Memory (DDR2)
 *  ------------------------------------------------------------------------
 *     C000_0000 - C1FF_FFFF   200_0000  (  32 MB) Linux
 *     C200_0000 - C2FF_FFFF   100_0000  (  16 MB) -------- 
 *     C300_0000 - C37F_FFFF    80_0000  (   8 MB) DSP_PROG (code, data)
 *     C380_0000 - C3FF_FFFF    80_0000  (   8 MB) --------
 *     C400_0000 - C7FF_FFFF   400_0000  (  64 MB) Linux
 */

#define SHARED_BUFFER_ADDR 0xC2000000
#define SHARED_BUFFER_SIZE 0x1000

#endif


----------
/*从上面可以看出实际上所谓的共享内存是板子上DDR2上的一段地址*/

	if (map_addr(&fd, phy_addr, length, &map_base, (void **)&dest) < 0) {
        fprintf(stderr, "fail to map dest\n");
		close(fd);
		return -1;
    }

    while(1) {
        char src[] = "helloworld";
        memcpy(dest, src, sizeof(src)); 
        sleep(1);
    }    

	munmap(map_base, length); 
    close(fd);
    return 0;
}

static int map_addr(int *fd, off_t phy_addr, size_t length, void **map_base, void **virt_addr) 
{
	if ((*fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) 
	return -1;
	/*/dev/mem是物理内存的全映射,包括整个处理器的地址空间,具体包含地址总线上的所有可寻址空间和IO空
	间,但要保证这些物理地址是有效的,可以从这些地址上访问到数据。理论上可以映射0-0xffffffff的地址空间。*/
	off_t off_page = phy_addr & ~(sysconf(_SC_PAGE_SIZE) - 1); 
	/*sysconf(_SC_PAGE_SIZE)可以得到一页的大小,一般是4096k,因为映射的地址必须的是一页大小的整数倍,
	所以可以通过将0x111取反后做与运算,从而将0-3位清零。假如phy_addr是0xE8000020,经过运算之后就是0xE8000000*/
	*map_base = mmap(NULL, length + phy_addr - off_page, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, off_page);
	/*NULL表示不指定地址,内核根据需要分配地址,可以增加程序的可移植性
	PROT_READ:表示页可读取
	PROT_WRITE:表示页可写
	MAP_SHARED:表示与所有其他映射这个对象的进程共享映射空间
	*/
	
	if (*map_base == (void *) -1) {
		close(*fd);
		return -1;
	}
	*virt_addr = *map_base  + phy_addr - off_page;
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值