英創公司推出了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