TDA4核间通信

传统的多核处理器一般为SMP架构,SMP即对称多处理器,在开发者看来就是一个单核处理器,写代码的时候只需要写一份程序,因此开发起来比较简单。但TDA4不一样,TDA4是AMP架构,AMP即非对称多处理器结构,简单理解为将好几种处理器集成在一块硅片上,并且不同的核运行不同的操作系统。TDA4一共有6个Cortex-R5F核,2个Cortex-A72核,2个C66核,1个C71核。如果把所有核都利用起来,需要写处于2个A72的Linux或者QNX的1份程序(其中openvx可以调用其他其他核的资源,OpenGL可以调用gpu的资源,2个A72是SMP架构,这里不做展开),处于6个R5F核的5份程序(mcu1_0核mcu1_1互为lockstep核),处于2个C66的2份程序,处于1个C71的1份程序。一共10份不同的程序,不同的程序为了完成同样目标,程序之间的数据交互就非常重要了。

基于共享内存的核间通信是最简单最高效的方法了,因为TDA4的所有核不管在硬件上还是软件上,在内存上都是互联互通的。举个例子,A72核把需要传输数据放在指定地址上,mcu1_0到指定的地址上取出数据,便完成了核间的数据交互,逻辑上非常简单,而且数据传输的时候甚至都没有经过拷贝,可见效率有多高。

实现共享内存首先得找到一块合适的内存用来交互数据,因为TDA4为了提高效率,大部分内存做了缓存(cacheable),如果做了缓存,因为内存的访问速度远远比cpu的高速缓存低,修改了变量的值后,并不会马上写入到内存上,而是先写入本地cpu的高速缓存中。这里我偷个懒,直接使用已经配置成non-cacheable的PCIE_QUEUE_SHARED_MEM作为共享内存的内存池,从宏名字上也可以看出这部分内存本来就是用来共享的。

/* Memory for IPC over PCIe using shared memory. MUST be non-cached or cache-coherent [ size 64.00 KB ] */
#define PCIE_QUEUE_SHARED_MEM_ADDR (0xB5FE0000u)
#define PCIE_QUEUE_SHARED_MEM_SIZE (0x00010000u)

下面通过把Linux的系统状态信息传输到mcu1_0上作为例子,实现A72与mcu1_0的数据交互。

首先定义一个用于数据传输的结构体。因为cpu架构不同,R5F是32位处理器,A72是64位处理器,因此注意结构体中不要有类似指针这样在不同架构中长度不同的成员。

struct tda4_st_hlos_status_t {

    int8_t service_status;
    int8_t sys_info_ret;
    uint32_t up_time;
    uint32_t cpu_usage;
    uint32_t average_load5;
    uint32_t average_load15;
    uint16_t total_ram;
    uint16_t free_ram;
    uint8_t rolling_counter;
    uint8_t version;
    uint8_t app_rolling_counter;

};

把PCIE_QUEUE_SHARED_MEM_ADDR强制转换成struct tda4_st_hlos_status_t结构体指针。

#define DIA_HLOS_STATUS ((struct tda4_st_hlos_status_t*)(PCIE_QUEUE_SHARED_MEM_ADDR))

需要注意的是,该地址是物理地址,只能在RTOS里访问,如果需要在Linux上访问,需要把物理地址映射成虚拟地址才能使用。

以上三段代码必须写到头文件里,不能是源文件。需要共享内存的核include这个头文件,确保各个核的地址、内存布局是一样的。

A72(Linux)端程序

通过LINUX_MAP_VIRPTR宏将物理地址映射成Linux能访问的虚拟地址,如何转换的?先挖个坑后面填

tda4_st_hlos_status_t* linux_hlos_status = (tda4_st_hlos_status_t*)LINUX_MAP_VIRPTR(DIA_HLOS_STATUS, sizeof(tda4_st_hlos_status_t));

把Linux的系统信息赋值给该结构体,Linux端部分程序。

int main(int argc, char* argv[]) {

    printf("%s version: %s %s%s\n", project, git_tag, git_commit, git_status);

	tda4_st_hlos_status_t* linux_hlos_status =
			(tda4_st_hlos_status_t*)LINUX_MAP_VIRPTR(DIA_HLOS_STATUS, sizeof(tda4_st_hlos_status_t));

	struct sysinfo s_info;
	int err;
	uint32_t mb = 1024*1024;
    uint32_t cpu_usage = 0;

	if(!linux_hlos_status) {
		return -1;
	}

	linux_hlos_status->service_status = 1;

	while(1) {
		err = sysinfo(&s_info);
		if(err) {
			linux_hlos_status->sys_info_ret = err;
			sleep(1);
			continue;
		}

		get_cpuoccupy(&cpu_usage);
		linux_hlos_status->cpu_usage = cpu_usage;
		linux_hlos_status->average_load5 = s_info.loads[1];
		linux_hlos_status->average_load15 = s_info.loads[2];
		linux_hlos_status->up_time = s_info.uptime;
		linux_hlos_status->free_ram = s_info.freeram/mb;
		linux_hlos_status->total_ram = s_info.totalram/mb;
		++linux_hlos_status->app_rolling_counter;

		sleep(1);

	}
	LINUX_UNMAP_VIRPTR(DIA_HLOS_STATUS, sizeof(tda4_st_hlos_status_t));
}

mcu1_0(RTOS)端程序

以up_time,cpu_usage,free_ram为例,把部分Linux的状态信息打印出来

while(1) {
    printf("Linux uptime %u, cpu usage %u, free ram %u\n",
    DIA_HLOS_STATUS->up_time, DIA_HLOS_STATUS->cpu_usage, DIA_HLOS_STATUS->free_ram);
    TaskP_sleep(1000);

}

验证

编译并且更新程序到TDA4上,上电后核对mcu1_0的打印与Linux端的信息一致,说明用共享内存的方式通信可行。

[MCU1_0]     54.074817 s: Linux uptime 48, cpu usage 0, free ram 1640
[MCU1_0]     55.074829 s: Linux uptime 49, cpu usage 0, free ram 1640
[MCU1_0]     56.074814 s: Linux uptime 50, cpu usage 0, free ram 1640
[MCU1_0]     57.074816 s: Linux uptime 51, cpu usage 0, free ram 1640
[MCU1_0]     58.074818 s: Linux uptime 52, cpu usage 0, free ram 1640
[MCU1_0]     59.074820 s: Linux uptime 53, cpu usage 0, free ram 1640
[MCU1_0]     60.074822 s: Linux uptime 54, cpu usage 0, free ram 1640
[MCU1_0]     61.074820 s: Linux uptime 55, cpu usage 0, free ram 1640
[MCU1_0]     62.074820 s: Linux uptime 56, cpu usage 0, free ram 1640
[MCU1_0]     63.074817 s: Linux uptime 57, cpu usage 0, free ram 1640
[MCU1_0]     64.074816 s: Linux uptime 58, cpu usage 0, free ram 1640
[MCU1_0]     65.074814 s: Linux uptime 59, cpu usage 0, free ram 1640

但这种通信方式也有一个很大的弊端,信息是异步更新的,只能周期地查询信息是否改变,对于有实时性要求的功能是没办法满足需求的。这个问题的解决办法在下一篇文档中解决。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值