STM32F7-Discovery 上の SIP 電話機

こんにちは。

少し前に писали 32 MB ROM と 4 KB RAM を搭載した STM1F192-Discovery で SIP 電話機をどのように起動できたかについては、以下に基づいています。 エンボックス。 ここで、そのバージョンは最小限であり、サーバーを使用せずに XNUMX 台の電話を直接接続し、音声送信は一方向のみであると言わなければなりません。 したがって、サーバーを介した通話、双方向への音声送信を備えながら、同時にメモリ サイズを最小限に抑える、より完全な電話機を発売することにしました。


電話については、アプリケーションを選択することにしました simple_pjsua PJSIP ライブラリの一部として。 これは、サーバーに登録し、通話を受信して​​応答できる最小限のアプリケーションです。 以下、早速STM32F7-Discovery上で実行する方法を説明します。

走り方

  1. Embox の構成
    make confload-platform/pjsip/stm32f7cube
  2. 必要な SIP アカウントを conf/mods.config ファイルに設定します。
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    どこ SIP サーバー (sip.linphone.org など)、 ユーザ名 и password - アカウントのユーザー名とパスワード。

  3. Embox をチームとして組み立てる make。 搭載されているボードファームウェアについて викистатье.
  4. Embox コンソールで「simple_pjsua_imported」コマンドを実行します。
    
    00:00:12.870    pjsua_acc.c  ....SIP outbound status for acc 0 is not active
    00:00:12.884    pjsua_acc.c  ....sip:[email protected]: registration success, status=200 (Registration succes
    00:00:12.911    pjsua_acc.c  ....Keep-alive timer started for acc 0, destination:91.121.209.194:5060, interval:15s
    

  5. 最後に、スピーカーまたはヘッドフォンをオーディオ出力に挿入し、ディスプレイの隣にある XNUMX つの小さな MEMS マイクに向かって話します。 Linux からアプリケーション simple_pjsua、pjsua を介して呼び出します。 または、他のタイプの LINPHONE を使用することもできます。

これらすべてについては、 вики.

どうやってそこにたどり着いたのか

そこで、最初はハードウェア プラットフォームの選択について疑問が生じました。 STM32F4-Discovery がメモリに適合しないことが明らかだったので、STM32F7-Discovery が選択されました。 彼女は 1 MB のフラッシュ ドライブと 256 KB の RAM (+ 64 個の特別な高速メモリ、これも使用します) を持っています。 サーバー経由の呼び出しもそれほど多くはありませんが、それに合わせてみることにしました。

条件付きで、タスクはいくつかの段階に分割されました。

  • QEMU で PJSIP を実行します。 これはデバッグに便利で、さらに、AC97 コーデックがすでにサポートされていました。
  • QEMU および STM32 での音声の録音と再生。
  • アプリケーションの移植 simple_pjsua PJSIPより。 SIP サーバーに登録して電話をかけることができます。
  • 独自の Asterisk ベースのサーバーをデプロイしてテストし、sip.linphone.org などの外部サーバーを試してください。

Embox のサウンドは、PISIP でも使用される Portaudio を通じて機能します。 最初の問題は QEMU で発生しました。WAV は 44100 Hz では正常に再生されましたが、8000 Hz では明らかに問題が発生しました。 それは周波数の設定の問題であることが判明しました。機器のデフォルトでは 44100 であり、これはプログラム的に変更されませんでした。

おそらくここで、サウンドが一般的にどのように再生されるかを少し説明する価値があります。 サウンド カードは、所定の周波数で再生または録音したいメモリへのポインタに設定できます。 バッファが終了すると、割り込みが生成され、次のバッファで実行が続行されます。 実際のところ、これらのバッファは、前のバッファが再生されている間に事前に満たされている必要があります。 STM32F7 では、この問題にさらに直面することになります。

次に、サーバーをレンタルし、そこに Asterisk をデプロイしました。 デバッグはたくさん必要ですが、あまりマイクに向かって話したくないので、自動再生と録音をする必要がありました。 これを行うために、simple_pjsua にパッチを適用して、オーディオ デバイスの代わりにファイルをスリップできるようにしました。 PJSIP では、デバイスまたはファイルのいずれかであるポートの概念があるため、これは非常に簡単に行われます。 また、これらのポートは他のポートに柔軟に接続できます。 コードは pjsip で確認できます。 リポジトリ。 その結果、以下のようなスキームとなった。 Asterisk サーバー上で、Linux 用と Embox 用の XNUMX つのアカウントを開始しました。 次に Embox 上でコマンドが実行されます simple_pjsua_imported, Embox をサーバーに登録し、その後 Linux から Embox を呼び出します。 接続の瞬間に、Asterisk サーバーで接続が確立されていることを確認し、しばらくすると Embox で Linux からの音が聞こえるはずです。また、Linux では Embox から再生されるファイルを保存します。

QEMU で動作した後、STM32F7-Discovery への移植に進みました。 最初の問題は、イメージのサイズに対してコンパイラ最適化「-Os」を有効にしないと 1 MB の ROM に収まらないことです。 そのため、「-O」を含めました。 さらに、このパッチにより C++ のサポートが無効になったので、これは pjsua にのみ必要であり、simple_pjsua を使用します。

配置された後 simple_pjsua、今なら発売するチャンスがあると判断しました。 しかし、最初に音声の録音と再生に対処する必要がありました。 問題はどこに書くかです。 外部メモリ - SDRAM (128 MB) を選択しました。 これを自分で試すことができます。

周波数 16000 Hz、長さ 10 秒のステレオ WAV を作成します。


record -r 16000 -c 2 -d 10000 -m C0000000

私たちは負けます:


play -m C0000000

ここには 8994 つの問題があります。 最初のコーデック - WM4 が使用され、スロットのようなものがあり、これらのスロットが 16000 つあります。したがって、これが設定されていない場合、デフォルトでは、オーディオを再生するときに、8000 つのスロットすべてで再生が行われます。 。 したがって、8000 Hz の周波数では 0 Hz を受信しましたが、2 Hz では再生が機能しませんでした。 スロット 32 と XNUMX のみが選択されている場合は、正常に動作しました。 もう XNUMX つの問題は STMXNUMXCube のオーディオ インターフェイスで、オーディオ出力は SAI (シリアル オーディオ インターフェイス) 経由でオーディオ入力と同期して動作します (詳細はわかりませんでしたが、共通のクロックを共有していることがわかりました)。オーディオ出力が初期化され、オーディオが何らかの理由でその入り口に接続されています)。 つまり、これらを個別に実行することはできないため、次のようにしました。オーディオ入力とオーディオ出力は常に機能します (割り込みの生成も含む)。 しかし、システムで何も再生されていないときは、単に空のバッファをオーディオ出力に挿入し、再生が開始されると、正直にバッファを埋め始めます。

さらに、音声録音時の音が非常に小さいという事実にも遭遇しました。 これは、STM32F7-Discovery の MEMS マイクが 16000 Hz 未満の周波数ではうまく機能しないことが原因です。 したがって、16000Hzが来ても8000Hzに設定します。 ただし、これを行うには、ある周波数から別の周波数へのソフトウェア変換を追加する必要がありました。

次に、RAM 内にあるヒープのサイズを増やす必要がありました。 計算によると、pjsip には約 190 KB が必要で、残りは約 100 KB のみです。 ここでは、外部メモリ - SDRAM (約 128 KB) を使用する必要がありました。

これらすべての編集を経て、Linux と Embox の間の最初のパッケージが表示され、音を聞くことができました。 しかし、音はひどいもので、QEMU のときとはまったく同じではなく、何も聞き取ることができませんでした。 それから私たちは何が問題なのか考えました。 デバッグの結果、Embox にはオーディオ バッファを埋める/アンロードする時間がないことがわかりました。 pjsipが2フレーム処理中にバッファ処理完了までにXNUMX回の割り込みが発生し、多すぎました。 速度について最初に考えられたのはコンパイラの最適化でしたが、それはすでに PJSIP に組み込まれていました。 XNUMX つ目はハードウェア浮動小数点です。これについては、次の記事で説明しました。 статье。 しかし、実践が示しているように、FPU では速度が大幅に向上しませんでした。 次のステップは、スレッドに優先順位を付けることでした。 Embox にはさまざまなスケジューリング戦略があり、優先順位をサポートし、オーディオ ストリームを最高の優先順位に設定するスケジュール戦略を含めました。 これも役に立ちませんでした。

次のアイデアは、外部メモリを使用しており、非常に頻繁にアクセスされる構造を外部メモリに移動できればよいというものでした。 いつ、どのような状況で行われたのかを予備分析しました simple_pjsua メモリを割り当てます。 190 Kb のうち、最初の 90 Kb は PJSIP の内部ニーズに割り当てられており、あまり頻繁にはアクセスされないことが判明しました。 さらに、着信中に pjsua_call_answer 関数が呼び出され、着信および発信フレームを処理するためにバッファが割り当てられます。 まだ100KBくらいでした。 そして、次のことを行いました。 通話の瞬間まで、データは外部メモリに保存されます。 呼び出し後すぐに、ヒープを RAM 内の別のヒープに置き換えます。 したがって、すべての「ホット」データは、より高速で予測可能なメモリに転送されました。

その結果、これらすべてが一緒になって起動することが可能になりました。 simple_pjsua そしてサーバー経由で呼び出します。 そして、sip.linphone.org などの他のサーバーを経由します。

所見

結果、起動できました simple_pjsua サーバーを介した双方向の音声伝送。 追加で 128 KB の SDRAM を消費するという問題は、もう少し強力な Cortex-M7 (たとえば、32 KB の RAM を搭載した STM769F512NI) を使用することで解決できますが、同時に 256 KB に達する希望をまだ捨てていません。 KB 🙂 興味のある方がいらっしゃいましたら、ぜひ試してみてください。 いつものように、すべてのソースは私たちのところにあります リポジトリ.

出所: habr.com

コメントを追加します