uClinux を実行している AD Blackfin BF537 DSP で開発しています。合計 32MB の SD-RAM が利用可能です。への単純なブロッキング呼び出しを使用してアクセスできる ADC が接続されていread()
ます。
私のコードの最も興味深い部分は以下です。プログラムを実行すると問題なく動作するようです。SD カードからフェッチしてプロットできる素敵なデータ パッケージを取得します。ただし、float 計算部分をコメント アウトすると (コードに示されているように)、ft_all.raw ファイルでゼロしか得られません。最適化レベルを -O3 から -O0 に変更すると、同じことが起こります。
私はあらゆる種類のものの無数の組み合わせを試しましたが、うまくいくこともあれば、うまくいかないこともあります.以前は(以下に少し変更を加えると)、コードは最適化が無効になっている場合にのみ機能しました. ファイルのさらに下に何かを追加すると、壊れることもあります。
私の疑いは、関数によって転送されたデータがread()
完全に転送されていない可能性があることです (正しいバイト数が返されたとしても、それは可能ですか?)。直接メモリアドレスを使用してポインタを初期化するのもこれが初めてであり、コンパイラがこれにどのように反応するかわかりません。おそらく、ここで何かを見逃したのでしょうか?
私は今、この問題に何日も費やしてきましたが、必死になっています - この問題について助けていただければ幸いです! 前もって感謝します。
// Clear the top 16M memory for data processing
memset((int *)0x01000000,0x0000,(size_t)SIZE_16M);
/* Prep some pointers for data processing */
int16_t *buffer;
int16_t *buf16I, *buf16Q;
buffer = (int16_t *)(0x1000000);
buf16I = (int16_t *)(0x1600000);
buf16Q = (int16_t *)(0x1680000);
/* Read data from ADC */
int rbytes = read(Sportfd, (int16_t*)buffer, 0x200000);
if (rbytes != 0x200000) {
printf("could not sample data! %X\n",rbytes);
goto end;
} else {
printf("Read %X bytes\n",rbytes);
}
FILE *outfd;
int wbytes;
/* Commenting this region results in all zeroes in ft_all.raw */
float a,b;
int c;
b = 0;
for (c = 0; c < 1000; c++) {
a = c;
b = b+pow(a,3);
}
printf("b is %.2f\n",b);
/* Only 12 LSBs of each 32-bit word is actual data.
* First 20 bits of nothing, then 12 bits I, then 20 bits
* nothing, then 12 bits Q, etc...
* Below, the I and Q parts are scaled with a factor of 16
* and extracted to buf16I and buf16Q.
* */
int32_t *buf32;
buf32 = (int32_t *)buffer;
uint32_t i = 0;
uint32_t n = 0;
while (n < 0x80000) {
buf16I[i] = buf32[n] << 4;
n++;
buf16Q[i] = buf32[n] << 4;
i++;
n++;
}
printf("Saving to /mnt/sd/d/ft_all.raw...");
outfd = fopen("/mnt/sd/d/ft_all.raw", "w+");
if (outfd == NULL) {
printf("Could not open file.\n");
}
wbytes = fwrite((int*)0x1600000, 1, 0x100000, outfd);
fclose(outfd);
if (wbytes < 0x100000) {
printf("wbytes not correct (= %d) \n", (int)wbytes);
}
printf(" done.\n");
編集: read() を使用して ADC ではなく単純なファイルからデータを読み取ると、コードは完全に機能するようです。これにより、入力の I 部分と Q 部分を抽出するときのややハッキーなコードが意図したとおりに機能していると思われます。コンパイラによって生成されたアセンブリを調べると、これが確認されます。
ADC ドライバーの開発者に連絡して、この動作について説明があるかどうかを確認しようとしています。
ADC は SPORT を介して接続され、次のように開かれます。
sportfd = open("/dev/sport1", O_RDWR);
ioctl(sportfd, SPORT_IOC_CONFIG, spconf);
SPORT の設定時に使用するオプションは次のとおりです。
spconf->int_clk = 1;
spconf->word_len = 32;
spconf->serial_clk = SPORT_CLK;
spconf->fsync_clk = SPORT_CLK/34;
spconf->fsync = 1;
spconf->late_fsync = 1;
spconf->act_low = 1;
spconf->dma_enabled = 1;
spconf->tckfe = 0;
spconf->rckfe = 1;
spconf->txse = 0;
spconf->rxse = 1;
Analog Devices の bfin_sport.h ファイルも含まれています: https://gist.github.com/tausen/5516954
更新 プロジェクトの前の開発者との長い夜のデバッグの後、問題は上記のコードとはまったく関係がないことが判明しました。Chris が示唆したように、実際には SPORT ドライバーと ADC 構成の問題でした。
デバッグ中に、データが「壊れた」場合は常に次のエラー メッセージが表示されましたbfin_sport: sport ffc00900 status error: TUVF
。これはアプリケーションではあまり意味がありませんが、データの出力から何かが同期していないことは明らかでした:ステータス エラーが表示されるたびに0x12000000,0x34000000,...
ではなく、バッファー内のデータがフォーム上にありました。0x00000012,0x00000034,...
buf16I と buf16Q にゼロしか含まれていない理由は明らかです (12 個の LSB を抽出しているため)。
ADCの初期化と構成の段階の間にいくつかの呼び出しを入れるusleep()
と、問題が解決したようです-私はそれがそのままであることを望んでいます!