2012-01-31 66 views
1

我正在爲SparkFun Logomatic V2編寫自定義固件,它將二進制數據記錄到2GB micro-SD卡上的文件中。數據文件大小範圍從100 MB到1 GB。包裝二進制數據文件以自行轉換爲CSV?

二進制數據的格式隨着電路板固件的變化而變化(它實際上可以在運行時動態重新配置)。我寧願將每個版本的固件/配置都創建並維護一個單獨的解碼器/轉換器程序,我寧願通過用寫入數據文件的Bash腳本啓動數據文件來將數據文件自行轉換爲CSV格式數據記錄開始之前。

我知道如何創建一個Here文件,但我懷疑Bash將無法快速解析並轉換一個二進制數據的十億字節,所以我希望讓腳本首先編譯一些腳本C代碼(假設GCC存在並在路徑中),然後運行生成的程序,將二進制數據傳遞給stdin。

爲了使問題更加具體,假設固件將創建由4個16位整數值組成的二進制數據:一個時間戳(無符號),後面跟着3個加速度計軸(帶符號)。記錄之間沒有分隔符(主要是因爲我正在將SPI接口飽和到uSD卡上)。

所以,我覺得我需要一個腳本,這裏有兩個文件:一個用於C代碼(由擴展的Bash變量參數化),另一個用於二進制數據。這是我到目前爲止:

#! env bash 
# Produced by firmware version 0.0.0.0.0.1 alpha 
# Configuration for this data run: 
header_string = "Time, X, Y, Z" 
column_count = 4 
# Create the converter executable 
# Use "<<-" to permit code to be indented for readability. 
# Allow variable expansion/substitution. 
gcc -xc /tmp/convertit - <<-THE_C_CODE 
    #include <stdio.h> 
    int main (int argc, char **argv) { 
     // Write ${header_string} to stdout 
     while (1) { 
      // Read $(column_count} shorts from stdin 
      // Break if EOF 
      // Write $(column_count} comma-delimited values to stdout 
     } 
     // Close stdout 
     return 0; 
    } 
THE_C_CODE 
# Pass the binary data to the converter 
# Hard-quote the Here tag to prevent subsequent expansion/substitution 
/tmp/convertit >./$1.csv <<'THE_BINARY_DATA' 
... 
... hundreds of megabytes of semi-random data ... 
... 
THE_BINARY_DATA 
rm /tmp/convertit 
exit 0 

這是否看起來正確?我還沒有真正的數據文件來測試,但我想在進一步深入之前驗證這個想法。

如果結束行丟失,Bash會抱怨嗎?如果數據採集因電池或uSD卡鬆動而導致意外終止,可能會發生這種情況。或者如果固件borks。

我應該考慮更快還是更好的方法?例如,我想知道Bash是否會太慢,無法像C程序那樣快地複製二進制數據:C程序應該直接打開數據文件嗎?

TIA,

-BobC

回答

1

你可能想看看makeself。它允許您將任何.tar.gz歸檔文件更改爲獨立於平臺的自解壓文件(類似於包含here文檔的shell腳本)。這將允許您輕鬆分發您的數據和解碼器。它還允許您配置存檔中包含的腳本,以便在容器腳本運行時運行。通過這種方式,您可以使用makeself進行打包,並在歸檔文件中您可以將數據文件和解碼器用C或bash或任何您認爲合適的語言編寫。

雖然可以使用shell工具解碼二進制數據(例如使用od),但這非常麻煩且效率低下。我建議使用C程序或perl,它幾乎可以在任何機器上找到(檢查this page)。