英创公司推出了ESM7000异构CPU的实时应用,由高性能的Cortex-A7双核完成人机交互、数据处理、通讯管理等复杂运算,而对于高速的数据采集、中断事件响应等实时任务交由i.MX7D的Cotex-M4完成,具体的介绍可以参考文章《ESM7000异构CPU架构实时应用简介》。基于ESM7000的异构CPU平台,英创公司实现了多通道的高速数采方案,该方案最高支持100kSPS采样率的AD转换。
关于M4端的AD操作的实现可以参考文章《ESM7000异构CPU实时应用之一 8通道并行100K 16bit AD采集》,本文主要介绍Linux系统中需要做的操作以及程序的实现,文章分为三个部分,第一部分是介绍如何将编译好的M4程序烧写到主板中,并设置自动启动。第二部分是介绍如何加载英创公司提供的RPMsg驱动,RPMsg驱动主要实现了ESM7000中Crotex-A7核心与M4核心之间的通讯。第三部分是介绍Linux系统端User app的实现和性能的测试结果,其中User app正是通过英创公司定义的RPMsg通讯协议来实现的,关于RPMsg和通讯协议具体的介绍可以参考文章《ESM7000异构CPU实时应用之二 基于rpmsg的通讯机制》。
本文测试硬件平台基于ESM2001工控机,感兴趣的客户可参考这里:EMX2000系列工控机。
M4应用程序的烧写
首先将编译好的M4应用程序(这里以英创公司提供的例程emx2001.bin为例)拷贝到主板中的,例如/mnt/mmc中,然后就可以通过英创公司提供的工具flash_opt将程序烧写到系统中,并设置好随系统自动启动。flash_opt工具已经集成在了主板中,可以直接在命令执行。
M4的应用程序可以选择三个区域烧写,分别是TCM、OCRAM 或 DDR 中运行,在TCM中的运行速度最快,但是代码空间最小,OCRAM中运行速度会慢一些,代码空间相对更大,而DDR中代码运行速度最慢,但是代码空间最大。各个区域提供的程序代码空间具体数据如下表所示:
Configure | 文件名 | CODE Size |
TCM | emx2001_tcm.bin | 32K |
OCRAM | emx2001_ocram.bin | 128K |
DDR | emx2001_ddr.bin | 1MB |
在烧写前需要根据不同的烧写区域对程序重命名,如果需要烧写到TCM 中,则程序需要命名为 emx2001_tcm.bin,如果烧写到 OCRAM 中,则命名为 emx2001_ocram.bin,如果是烧写到 DDR,则为 emx2001_ddr.bin。重命名只是为了满足 flash_opt 对命令格式的要求,程序在编译时必须根据运行的位置选择对应的 ESM7000_M4_*.ld 文件。
比如我们需要将emx2001.bin放在TCM中,则将程序命名为emx2001_tcm.bin,然后输入命令#>flash_opt m4 /mnt/mmc/ emx2001_tcm.bin,如下图:
完成之后,每次主板重启就都会自动启动烧写进去的M4应用程序。关于程序放在不同区域的具体的说明和对比,可以参考《ESM7000 Cortex-M4技术开发参考手册》,这里不再赘述。
RPMsg驱动的加载
RPMsg的驱动也同样集成在了系统中,可以直接通过命令加载,只需要一条命令#>modprobe emx_rpmsg_tty,加载后驱动会生成响应的设备节点/dev/ttyEMx同时会打印出关于AD的信息,如下图:
从驱动打印的信息可以看到AD的详细参数信息。驱动加载完成后,就可以运行User app来进行采集了。
User app的实现和测试
通过《ESM7000异构CPU实时应用之二 基于rpmsg的通讯机制》的介绍,我们已经了解了英创公司设计的基于RPMsg的通讯协议,本文介绍的User app正是使用这一套通讯协议来实现的。
驱动emx_rpmsg_tty.ko会虚拟出串口设备,所以通信部分的代码都是使用的串口的标准操作函数来实现的。首先是向M4发送消息,设置好AD的采样率,然后启动AD,通过write函数就可以向M4发送数据,英创公司已经封装好了函数供客户参考:
int EM_Adc::setup_adc( int freq ) { int ret; struct emx_rpmsg_t *msg_t; //打开虚拟串口ttyEMx,并建立好接收线程 ret = OpenPort(); if( ret<0 ) { printf( "ttyEMx open fail\n"); return -1; } //发送复位指令 ret = Send_cmd(CMD_CODE_RESET, NULL, 0); if( ret<0 ) { printf( "send failed\n"); } //发送设置指令,设置AD的采样率 ret = Send_cmd(CMD_CODE_SETUP, (void *)&freq, sizeof(freq)); if( ret<0 ) { printf( "send failed\n"); } //发送启动指令,开始采集 ret = Send_cmd(CMD_CODE_RUN, NULL, 0); if( ret<0 ) { printf( "send failed\n"); } Dflags = 1; return 0; }
启动了AD之后,M4就会开始进行数据采集,因为多通过告诉采集的数据量十分庞大,所以采用了共享内存的方式来发送数据。例程定义了两块32KB大小的共享区域,当M4采集的数据量达到16K之后,就会将数据写入共享内存中,然后根据通讯协议发送消息通知User app去读取。我们还是通过一个线程来专门接收采集数据,具体代码如下:
int EM_Adc::PackagePro( char* Buf, int len ) { int i1, num; int buf_len; char status_buf[100]; memcpy(&msg, (char *)Buf, sizeof(struct emx_rpmsg_t)); if(msg.cmd == CMD_CODE_DATA) { Mlen = msg.len; //判断数据存放在哪一块共享区域,然后将数据拷贝出来 if(msg.flags == 0) { memcpy(MemBuf, (void *)base0, msg.len); } else { memcpy(MemBuf, (void *)base1, msg.len); } //处理数据,这里是将每个通道的数据保存成文件 save_data(MemBuf, Mlen); } return 0; }
例程中数据的处理主要是把每个通道的数据分离出来,分别保存在不同的文件中。为了保证写文件的速度,一开始是写在内存中,当文件大小超过1MB,就关闭AD,并且将文件拷贝到/mnt/mmc中储存,处理数据的代码如下:
int EM_Adc::save_data(int16_t *data, int len) { FILE *fp; char filename[20]; int i1, i2, ret; for(i1=0; i1<8; i1++) { sprintf( filename, "/tmp/ch%d", i1); fp = fopen(filename, "ab+"); if( fp==NULL ) { printf("open %s fail!\n", filename); ret = -1; return ret; } //将每个通道的数据分离出来,分别保存在文件中 for(i2=0; i2<(len/16); i2++) { memcpy(&CHxBuf[i2], ((int16_t *)data + i1 + i2*8), sizeof(int16_t)); } fwrite( CHxBuf, (i2-1)*sizeof(int16_t), 1, fp ); //如果保存数据已经大于1M,则关闭AD,将文件移至/mnt/mmc目录保存,然后退出程序 if(i1 == 7) { fseek(fp, 0, SEEK_END); long length = ftell(fp); if(length > 1024*1024) { fclose(fp); system("cp /tmp/ch* /mnt/mmc"); stop_adc(); return 0; } } fclose(fp); } return 0; }
在实际测试的时候,我们将两路正弦波信号分别接入通道1和通道2,当采集完成后使用波形绘制工具读取保存的文件,效果如下:
从图中可以看到采集波形的效果,在实际应用中,客户可以根据需求自行修改对于数据处理的方式。
M4端应用程序采用的方式是每采集16000字节发送一次数据,为了验证这套方案能够满足应用需求,我们对M4通过RPMsg发出消息,到Linux系统中User app读取到共享内存数据的时间做了详细的测试,响应时间如下表:
采样率 | 平均时间(us) | 最长时间(us) |
5ksps | 298 | 495 |
10ksps | 300 | 489 |
50ksps | 287 | 488 |
100ksps | 287 | 469 |
按照100ksps的采样率计算,M4端每10us会采集一次,每个通道单次采集数据大小为2Byte,8个通道就为16Byte。所以在100Ksps采样率的情况下,每10ms就会发送一次数据。按照这个时间间隔来看,ESM7000异构CPU平台完全可以满足需求。
对这套方案感兴趣的客户可以和英创公司的工程师联系,索取相关例程的代码。
成都英创信息技术有限公司 028-8618 0660