質問:Freescale IMX8mを使用して、SAI(5)データラインを介して16チャンネルオーディオTDMストリームを送信します。ハードウェアにはコーデック終了はありません。データのみがTDMにカプセル化され、I2Sデータラインを介して送信されます。 Imx8mデータラインのもう一方の端からデータを受信し、それを複数のオーディオ出力ソースに逆多重化するFPGAがあります。
質問:8チャンネル(4つのステレオソース)を再生すると、TDMフレームが問題なくうまく機能しているようです。ただし、TDMフレームサイズを16チャンネル(8ステレオソース)に増やすと、再生が始まる前に停止することがあります。 poll() 関数に閉じ込められ、絶対に返されません。ポーリング関数は、/alsa-lib/src/pcm/pcm.c にある snd_pcm_write_areas() の最上位レベルで呼び出されます。
これは、aplay app / alsa-lib <=> alsa-pcm-snd-driver <==> fsl_saiドライバ> HW間でデバッグ中に見つかりました。
- 再生が正常になるとわかります。snd_pcm_direct.spcm->hw.ptrsnd_pcm_write_areasを呼び出すたびに、フレームサイズは* 1(またはそれ以上)ずつ増えます。このポインタは、送信する必要があるフレーム数を時間内に追跡するようです。境界が 0x40000000 の符号なし int 値です。境界に達すると、ptrが再び繰り返されます。 alsa-lib/src/pcm/pcm.cファイルから
static int snd_pcm_dshare_start_timer(snd_pcm_direct_t *dshare) { int err; snd_pcm_hwsync(dshare->spcm); dshare->slave_appl_ptr= dshare->slave_hw_ptr = *dshare->spcm->hw.ptr;
- ポーリング機能で再生が中断されると、ポインタが更新されず、期間サイズ(フレームサイズ* n)またはフレームサイズの一部の倍数で中断されることがわかりました。
- オンラインでalsa再生を停止するためのいくつかの投稿を見ましたが、回避策や指示はありません。
- Dshare/Dmix/Dsnoop プラグインを使用する場合、カーネル 4.14 から存在する alsa バグという記事も読んでください。
- 1.1.2からバージョン1.1.5または1.1.7にアップグレードしようとしましたが、成功しませんでした。明らかに、この問題はハードウェアカードを使用する場合には発生せず、上記のプラグインを使用した場合にのみ発生します。
どちらが他方の原因なのか、どちらが修正すべきバグなのか分からない。
タイマーが間違った状態に入り、ポーリング機能が中断されるか、タイマーが間違った状態に入り、ポーリング機能が中断されます。
TDMフレームの生成方法の詳細 私たちは16チャンネルオーディオ(8つの個々のステレオペア)を持っており、SAIデータライン(4本のデータライン)の1つに書き込まれるようにハードウェアにフレームを送信する必要があります。これら8つのソースは独立して再生でき、ソースはasound.conf設定ファイルで指定されたチャネルマッピングに従ってTDMフレームのタイムスロットを占めます。
これ美徳を共有するプラグインは、フレームが保存される共有バッファを生成するために使用されます。 confファイルに、各再生プロセスごとに1つずつ8つの仮想ソースを作成しました。各ソースは別々の再生プロセスで使用され、8つの異なるソースを再生できます。 8つのソースすべてを再生するバッチファイルを表示します。
aplay出力 -L/l
null
Discard all samples (playback) or generate zero samples (capture)
src1
TDM 0 channel 0/1 for audio playback
src2
TDM 1 channel 2/3 for audio playback
src3
TDM 2 channel 4/5 for audio playback
src4
TDM 3 channel 6/7 for audio playback
src5
TDM 4 channel 8/9 for audio playback
src6
TDM 5channel 10/11 for audio playback
src7
TDM 6 channel 12/13 for audio playback
src8
TDM 7 channel 14/15 for audio playback
default:CARD=<xxxxx>
Default Audio Device
sysdefault:CARD=<xxxxxxxx>
Default Audio Device
asound.confファイル
# NOTE: this is for sharing multiple channels on a single (TDM) audio device with multple ALSA clients
# shared buffer for playback
pcm_slave.tdmshare {
pcm "hw:0"
channels 16
rate 48000 # fixed, because all dshare devices must use the same samplerate.
format S24_LE
period_size 512
buffer_size 1024
}
# src1 shared pcm device and corresponding virtual playback device
pcm.src1_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 0
bindings.1 4
}
pcm.src1 {
type plug
slave.pcm "src1_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 0 channel 0/1 for audio playback"
}
}
# src2 shared pcm device and corresponding virtual playback device
pcm.src2_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 8
bindings.1 12
}
pcm.src2 {
type plug
slave.pcm "src2_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 1 channel 2/3 for audio playback"
}
}
# src3 shared pcm device and corresponding virtual playback device
pcm.src3_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 1
bindings.1 5
}
pcm.src3 {
type plug
slave.pcm "src3_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 2 channel 4/5 for audio playback"
}
}
# src4 shared pcm device and corresponding virtual playback device
pcm.src4_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 9
bindings.1 13
}
pcm.src4 {
type plug
slave.pcm "src4_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 3 channel 6/7 for audio playback"
}
}
# src5 shared pcm device and corresponding virtual playback device
pcm.src5_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 2
bindings.1 6
}
pcm.src5 {
type plug
slave.pcm "src5_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 4 channel 8/9 for audio playback"
}
}
# src6 shared pcm device and corresponding virtual playback device
pcm.src6_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 10
bindings.1 14
}
pcm.src6 {
type plug
slave.pcm "src6_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 5channel 10/11 for audio playback"
}
}
# src7 shared pcm device and corresponding virtual playback device
pcm.src7_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 3
bindings.1 7
}
pcm.src7 {
type plug
slave.pcm "src7_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 6 channel 12/13 for audio playback"
}
}
# src8 shared pcm device and corresponding virtual playback device
pcm.src8_dshare {
type dshare
ipc_key 43544553
slave tdmshare
bindings.0 11
bindings.1 15
}
pcm.src8 {
type plug
slave.pcm "src8_dshare"
hint {
show {
@func refer
name defaults.namehint.basic
}
description "TDM 7 channel 14/15 for audio playback"
}
}
8つのソースすべてを再生するためのバッチファイル
aplay -Dplug:src1 /data/PCMCH1-Ch2_1.wav&
aplay -Dplug:src2 /data/PCMCH3-Ch4_1.wav&
aplay -Dplug:src3 /data/PCMCH5-Ch6_1.wav&
aplay -Dplug:src4 /data/PCMCH7-Ch8_1.wav&
aplay -Dplug:src5 /data/PCMCH1-Ch2_1.wav&
aplay -Dplug:src6 /data/PCMCH3-Ch4_1.wav&
aplay -Dplug:src7 /data/PCMCH5-Ch6_1.wav&
aplay -Dplug:src8 /data/PCMCH7-Ch8_1.wav&
asound.confファイルに修正可能な内容があるか、またはalsa-libで16〜8チャンネルを再生するときに直面する制限が原因でこの問題が発生するかどうかを教えてください。
この問題に関して私が見た他のリンクは次のとおりです。非常に古いリンクであり、一部の人々は修正されたというのにどのように修正されたのか、パッチが何なのかよくわかりません。私たちのシステムはalsaバージョン1.1.6とカーネル4.14を使用しており、このバージョンにあります。この問題を解決する方法を示すパッチセットまたはリンクを教えてください。この分野についての知識が不足しており、現時点ではこの問題については行き詰まった路地にあります。
[https://bugzilla.redhat.com/show_bug.cgi?id=534130][1]
[https://www.raspberrypi.org/forums/viewtopic.php?t=64936][2]
[https://sourceforge.net/p/alsa/mailman/message/26464680/][3]
答え1
カーネルサウンドコアpcmドライバとpcmコアdmaエンジンで使用されている対応するsdmaコントローラをデバッグした後、DMAコントローラ(/drivers/dma/imx-sdma.c)とSAI FIFO(/sound/soc)が見つかりました。 /fsl /fsl_sai.c) チャネル数が 16 個、各チャネルの幅が 32 ビットのときに停止します。 asound.conf ファイルで指定された DMA バッファサイズも影響します。
Sdmaコントローラの割り込みハンドラは、上記の質問で述べたHW.ptrの割り込みハンドラを追加することです。 SDMA割り込みハンドラはalsaユーザースペースで生成されたタイマーをトリガーし、ユーザースペースはポーリング関数で待機し、DMAメモリーにマップされたバッファー領域に書き込むバッファーの数を知るためにそのタイマー(固定位置)がクリアされます。
dma割り込みハンドラはトリガされないため、HW.ptrは更新されず、タイマ割り込みハンドラもトリガされないため、ユーザ空間はポーリング機能で待機して返されません。
これは最終的な解決策ではないかもしれませんが、状況によっては、解決策はDMAコントローラのファームウェア/スクリプト内で修正されるか、DMAコントローラに接続されている周辺FIFOがどのように機能するかである可能性があります。どちらにしても、特定のプロセッサの基本的なハードウェアIP実装を理解する必要があります。