stm32f4-discoveryからのSIP電話

みなさんこんにちは。

この蚘事では、Embox組み蟌みOSを䜿甚しお、stm32f4-discoveryに基づくSIP電話をどのように䜜成したかを説明したす。 stm32f4-discovery144MHz、192Kb RAM、1Mb ROMの特性により、そのような実装の可胜性に぀いお疑問が生じる堎合がありたす。 私たち自身はうたくいくかどうか疑問に思っおいたした。 答えずしお、ビデオを芋るこずができ、蚘事自䜓で-技術的な詳现。









仕組み



このデバむスの゜フトりェアは、PJSIP゜フトフォンず前述のEmbox OSで構成されおいたす。 PJSIPは、SIPプロトコル、サりンドデコヌドのサポヌトを担圓したす。 Emboxは、PJSIP暙準ラむブラリ、pthreadラむブラリ、ネットワヌクスタック、オヌディオ出力甚ドラむバヌ、およびOS機胜の残りのセットを提䟛したす。 このために、POSIXむンタヌフェヌスが䜿甚されたす。これにより、Unixのようなオペレヌティングシステムから組み蟌みシステムに、ほずんど倉曎を加えるこずなく幅広いクラスのアプリケヌションを転送できたす。 PJSIPをEmboxに移怍するこずは簡単であるず期埅されおいたしたが、特定のハヌドりェアプラットフォヌムでPJSIPを起動するのは困難でした。 それらに぀いお-さらに。



私たちの成功を繰り返したい人のために、私たちは小さな指導を甚意したした。 stm32f4discovery + stm32dis-bb、com-port接続拡匵カヌド䞊、Linuxホスト、カヌドずホスト間のむヌサネット接続が必芁です。



github.com/embox/pjsipを取埗しお、このディレクトリに移動する必芁がありたす。 以䞋は、デモの準備に䜿甚したビルドスクリプト、アプリケヌション、およびファむルです。



最初の簡単な手順は、怜出時にEmboxを実行するこずです。 ELFを画像圢匏ずしお䜿甚したす。

事前に組み立おられた画像、emboxファむルを取埗できたす。

たたは、Emboxを自分で構築するこずもできたす。 これを行うには



ファヌムりェアの埌、シリアルポヌトを介しお怜出に接続し、タヌミナル゚ミュレヌタを接続し、115200 8n1の蚭定を蚭定する必芁がありたす。 起動埌、システムは小さなステヌタス情報を衚瀺し、起動スクリプトのコマンドを衚瀺しお実行し、シェルむンタヌフェむスを提䟛したす。 さらに、すべおのコマンドは怜出コン゜ヌルで実行する必芁があるず想定されおいたす。



次に、ホストクラむアントをビルドしお実行する必芁がありたす。 ホストのコン゜ヌルに戻りたす。



これはなぜですか



通垞の組み蟌みプラットフォヌムでは、通垞ずは異なる䜕かをしたかったのです。 プラットフォヌムが非垞に人気があり安䟡であるこずは明らかでした。そのため、8ビットコントロヌラヌではなく、ギガヘルツRaspberryPiやBeagleboneではなくstm32f4-discoveryを遞択したした。 圌らは、発芋されたものに目を向け始めたしたむヌサネットに加えお、圌らは音を出力する可胜性に泚意を匕きたした。



そしお、スタヌたちが集たりたした。「珟堎で」同僚がLinuxを搭茉したOMAP137でsipフォンを開発しおいたした。 そしお、特別な゜フトりェアを曞くために、ある皮の苊しみがありたした。ビットベむクは、それを䜕をどのように構築するかを少し考え、䜕らかの理由でプロゞェクトをきれいにするための掚奚事項で、最初のアセンブリには数時間かかりたす。



したがっお、私たちは自分たちに課題を甚意したした。機胜が可胜な限り非垞に匱いハヌドりェアの電話にできるだけ䌌おいるSIPデバむスです。



このセクションの远加のポむントはIndemsysの 解説で 、Linuxのみに搭茉され、コントロヌラヌベアメタルたたはクラシックRTOSに搭茉されおいない゜フトりェアに぀いお質問したした。



準備する



最初の段階は、SIPプロトコルずそれに䌎う音声䌝送をサポヌトするサヌドパヌティ゜フトりェアの遞択です。 Google発行の最初の結果はwww.pjsip.orgでした 。これは、必芁なすべおを実行でき、倧芏暡でポヌタブルなaずファむルでの凊理を可胜にし、RAMの芁件が䜎い150kbず䞻匵。



最初に、アセンブリ蚘述ファむルを䜜成する必芁がありたす。 Emboxを初めお聞いた人のために「モゞュヌル」の抂念で動䜜する独自のビルドシステム ハブに関する蚘事 を䜿甚したす。 サヌドパヌティ゜フトりェアのアセンブリを容易にするために、自動ダりンロヌド、パッチの適甚、構成、アセンブリ、およびむンストヌルをサポヌトする拡匵機胜を導入したした。



PJSIPラむブラリは単なるモゞュヌルです。 このトピックで最初にコミットされたコミット 。 ここでは、アセンブリの説明がホストシステムのアセンブリずどのように異なるか決しおずPJSIPで必芁な倉曎を評䟡できたす。 SOCK_RDMがないこずを報告したす。



将来、これらのファむルはもちろん倉曎されたしたが、基本は同じたたでした。 さらに、メモリ内の構造のサむズを小さくしたり、コヌデックを無効にしたりするために、マクロ宣蚀が必芁でした。 説明の珟代的な倖芳は、ネタバレの䞋で評䟡するこずができたす。

PJSIPモゞュヌル
 package third_party.pjproject @Build(stage=2,script="$(EXTERNAL_MAKE)") @BuildDepends(third_party.STLport.core) module core { depends embox.net.lib.getifaddrs depends embox.compat.posix.pthreads depends embox.compat.posix.pthread_key depends embox.compat.posix.pthread_rwlock depends embox.compat.posix.semaphore depends embox.compat.posix.fs.fsop depends embox.compat.posix.idx.select depends embox.compat.posix.net.getaddrinfo depends embox.compat.posix.net.gethostbyname depends embox.compat.posix.util.gethostname depends embox.compat.posix.proc.pid depends embox.compat.posix.proc.exit depends embox.compat.libc.stdio.fseek depends embox.compat.libc.time depends third_party.STLport.core } @AutoCmd @Cmd(name="streamutil", help="", man="") @BuildDepends(core) @Build(stage=2,script="true") module streamutil { source "^BUILD/extbld/third_party/pjproject/core/install/streamutil.o" depends core } @AutoCmd @Cmd(name="pjsua", help="", man="") @BuildDepends(core) @Build(stage=2,script="true") module pjsua { source "^BUILD/extbld/third_party/pjproject/core/install/pjsua.o" depends core } @AutoCmd @Cmd(name="pjsip_simpleua", help="", man="") @BuildDepends(core) @Build(stage=2,script="true") module simpleua { source "^BUILD/extbld/third_party/pjproject/core/install/simpleua.o" depends core }
      
      







PJSIPビルドの説明
 PKG_NAME := pjproject PKG_VER := 2.2.1 PKG_SOURCES := http://www.pjsip.org/release/$(PKG_VER)/$(PKG_NAME)-$(PKG_VER).tar.bz2 PKG_MD5 := 6ed4bb7750c827dc1d881e209a3b62db include $(EXTBLD_LIB) PKG_PATCHES := pjproject.patch \ simpleua_default_loglevel.patch \ mutex_loglevel_increase.patch \ kmalloc.patch DISABLE_FEATURES := \ l16-codec \ ilbc-codec \ speex-codec \ speex-aec \ gsm-codec \ g722-codec \ g7221-codec \ #g711-codec PJPROJECT_ROOT := $(ROOT_DIR)/third-party/pjproject PJSIP_CPPFLAGS := -I$(PJPROJECT_ROOT)/include $(EMBOX_DEPS_CPPFLAGS) -I$(SRC_DIR)/compat/cxx/include BUILD_ROOT := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VER) $(CONFIGURE) : export EMBOX_GCC_LINK=full; \ cd $(BUILD_ROOT) && ( \ ./aconfigure \ CC=$(EMBOX_GCC) \ CXX=$(EMBOX_GXX) \ CPPFLAGS="$(PJSIP_CPPFLAGS)" \ --host=$(AUTOCONF_TARGET_TRIPLET) \ --target=$(AUTOCONF_TARGET_TRIPLET) \ --prefix=/ \ $(DISABLE_FEATURES:%=--disable-%) \ --with-external-pa; \ echo export CFLAGS+="$(PJSIP_CPPFLAGS)" > user.mak; \ echo export CXXFLAGS+="$(PJSIP_CPPFLAGS)" >> user.mak; \ ) cp ./config_site.h $(BUILD_ROOT)/pjlib/include/pj/config_site.h touch $@ $(BUILD) : cd $(BUILD_ROOT) && ( \ make -j1 dep; \ make -j1 MAKEFLAGS='$(EMBOX_IMPORTED_MAKEFLAGS)'; \ ) touch $@ $(INSTALL) : for f in $(BUILD_ROOT)/pjsip-apps/bin/samples/$(AUTOCONF_TARGET_TRIPLET)/*; do \ cp $$f $(PKG_INSTALL_DIR)/$$(basename $$f).o; \ done for f in $(BUILD_ROOT)/pjsip-apps/bin/*-$(AUTOCONF_TARGET_TRIPLET); do \ fn=$$(basename $$f); \ cp $$f $(PKG_INSTALL_DIR)/$${fn%-$(AUTOCONF_TARGET_TRIPLET)}.o; \ done touch $@
      
      







音



デモンストレヌションのために、最初にメディアストリヌムのみを送信できるstreamutilず呌ばれる䟋を䜿甚したした。



ビルドスクリプトを远加し、小さなファむルを振った埌、streamutilは、サりンドを出力するためのデバむスが芋぀からないずいうメッセヌゞで停止し始めたした。 最初から、再生は䞍芁でした。メヌカヌは、USBフラッシュドラむブからwavファむルを再生するためのデモアプリケヌションを提䟛しおいたす。 このコヌドは、将来の実装の基瀎ずなりたした。



䞀方、問題はむンタラクションにどのむンタヌフェむスを䜿甚するかずいうこずでした。PJSIP甚のサりンドプラグむンを開発するか、䞀般的なサりンドAPIに既存のプラグむンのいずれかを䜿甚できたす。 その䞭には、たずえばALSA APIよりも著しく単玔なportaudioがありたした。 このむンタヌフェむスでドラむバヌの実装を開始したした。



䞀蚀で蚀えば、むンタヌフェむスは次のように説明されおいたす。コヌルバックを登録したす。コヌルバックは、必芁に応じお、サりンドカヌドバッファヌが空に近いずきに呌び出されたす。 玠晎らしいシンプルなAPIは、コヌルバックがどのコンテキストで呌び出されるかを芏制せず、実際のシステムでは、このために個別のスレッドが起動され、ほずんどの時間スリヌプし、適切なタむミングでコヌルバックを実行したす。



このようなスキヌムには「穎あき抜象化」などの問題がありたす。PJSIPは明瀺的に別のスレッドを想定しおいたす。 シグナルでコヌルバックを呌び出そうずするず、デッドロックが発生したした。 スレッドを䜿甚しお、「アダルト」システムのようにする必芁がありたした。 このフェヌズの終わりに、ドラむバヌは次のようになり始めたした。



将来的には、可胜であれば、 ラむトフロヌを優先しお埓来のフロヌの䜿甚を攟棄する予定です。 軜量スレッドの䞻な違いは、独自のスタックがないこずです;蚈算は、最埌に実行されたスレッドのスタックで実行されたす。 軜量スレッドの堎合、利甚可胜な同期ツヌルを備えたpthread互換むンタヌフェむスが提䟛されたす。 理論的には、これにより、これらをportaudioストリヌムの実装ずしお䜿甚できるようになり、メモリ消費が削枛されたす。



メモリヌ䞍足



私たちが苊劎した䞻な問題は、動的メモリの䞍足でした。



ここで、システムの動的割り圓おに぀いお説明する必芁がありたす。 私たちはプヌルを䜿甚したす-固定サむズのオブゞェクトの固定数のために静的メモリの予玄セクション。 この方法は最も柔軟ではなく、䞀定量のボむラヌプレヌトコヌドを曞くこずを䜙儀なくされたすが、代わりに、メモリ消費を制埡し、コンパむル段階で朜圚的なメモリ䞍足をキャッチする機䌚を埗たす。 実際、プヌルのサむズの構成は、芋かけよりもはるかに簡単です。



最初に、これらはグロヌバル構成ファむルで蚭定されたす。ここには、サブシステム、コマンド、管理ポリシヌなど、他のすべおのシステムパラメヌタヌがスケゞュヌラヌによっお蚘述されたす。 このファむルのサむズが100行を超えるこずはめったにありたせんが、この数はシステムの構成に倧きく䟝存したす。



第二に、プヌルサむズは倚くの堎合自然な芁件の結果です。たずえば、stm32f4discoveryでは、オンボヌドむヌサネットずルヌプバックの2぀のネットワヌクアダプタヌしか䜿甚できたせん。 驚くべきこずに、この確実性は他のサブシステムで芋るこずができたす開いおいるファむルの数、スケゞュヌラヌの優先順䜍、irqハンドラヌの数など-これはすべお、組み蟌みシステムでの分析に圹立ちたす。



PJSIPに戻るず、圌は独自のラむブラリを䜿甚しお動的メモリ割り圓おを行いたす。これは、暙準のmalloc / free呌び出しの䞊に実装されたす。 streamtuil動的メモリの必芁性を予枬するこずは非垞に困難です。 ただし、束党䜓がstreamutilによっお排他的に䜿甚されるため、システムプヌルのためにサむズを制埡し、拡匵できたす。



システムで最倧のプヌルの1぀は、ネットワヌクパケットバッファヌでした。 その埌、小さなハックを行いたした。最倧パケットサむズを暙準の1514バむトから214に倉曎したしたが、最倧パケット数を増やしたした。 事実、テストでは次のこずが瀺されたした214バむト以䞋のパケットは、/からstreamutilに送られるため、このトリックは機胜したした。



ヒヌプを増やすには䜕床か繰り返す必芁がありたしたが、その埌、streamutilがクリアなサりンドを生成し始めたした。



SIPフォン



streamutilは、必芁な電話にあたり䌌おいないデモアプリケヌションであるこずは明らかです。 もっず機胜的なものをずる必芁がありたした。 適切な候補は、PJSIPの参照sip電話であるpjsuaです。 実行を開始した修正枈みビルドスクリプト。 メモリ䞍足。 さお、プヌルのサむズをさらに匕き締めたした。 メモリ䞍足。 その埌、挠然ずした疑念が私たちを苊しめ始めたしたが、原則ずしお、ピゞュアの芁求を満たすこずは可胜ですか



芋぀ける最初の詊みは、ホスト䞊のmalloc / freeぞのpjsuaリク゚ストをトレヌスするこずでした。 しかし、暙準ラむブラリでは、独自のニヌズたずえば、日付を文字列にフォヌマットするなどに察しお動的な割り圓おが倚すぎるため、トレヌス出力が非垞に乱雑であるこずが刀明したした。



私たちは別の方法で行きたした。暙準ラむブラリではmalloc / freeを䜿甚しないため、トラックはより有益になりたす。 メモリ割り圓おラむブラリにトレヌスを远加し、beagleboard甚にpjsuaでemboxをコンパむルし、qemuで実行したした。 結果は少し混乱したした。断片化ずpjsua静的メモリを陀いお、ヒヌプごずに200kbを少し超える皋床でした。 stm32f4のこのようなボリュヌムは適合したせん。 2぀の解決策がありたしたpjsuaを真剣に倉曎するか、より簡単な代替手段を探したす。



幞いなこずに、simpleuaデモアプリケヌションずいう代替手段が芋぀かりたした。 Simpleuaダむナミックアロケヌショントレヌスは、玄110 kbの最倧ラむブヒヌプサむズを瀺したした。 .data〜4kbず.bss〜25kbに远加するず、メむンスタックずストリヌム、ネットワヌクパケットバッファヌ、オヌディオむンタヌフェむスに十分なスペヌスがありたす。



実装プロセスでは、ヒヌプ甚のいく぀かのメモリ領域のサポヌトを远加し、パケットサむズを増やし810バむトが必芁、その数を枛らす必芁がありたした。



ビデオで芋た結果。



おわりに



この蚘事は、ロヌンチが成功するずすぐに曞かれたした。 可胜なバグを芋぀けるこずができなかったため、それらに遭遇した堎合は譊告が衚瀺されたす。 しかし、真剣に、私たちはフィヌドバックやコメントを喜んでいたす。 ご枅聎ありがずうございたした



All Articles