SIP phone sa STM32F7-Discovery

Kumusta lahat.

Kanina lang kami nagsulat tungkol sa kung paano namin nagawang maglunsad ng SIP phone sa STM32F4-Discovery na may 1 MB ROM at 192 KB RAM) batay sa Embox. Dito dapat sabihin na ang bersyon na iyon ay minimal at direktang konektado ang dalawang telepono nang walang server at may voice transmission sa isang direksyon lamang. Samakatuwid, nagpasya kaming maglunsad ng isang mas kumpletong telepono na may isang tawag sa pamamagitan ng server, voice transmission sa parehong direksyon, ngunit sa parehong oras panatilihin sa loob ng pinakamaliit na posibleng laki ng memorya.


Para sa telepono, napagpasyahan na pumili ng isang application simple_pjsua bilang bahagi ng PJSIP library. Ito ay isang minimal na application na maaaring magrehistro sa server, tumanggap at sumagot ng mga tawag. Sa ibaba ay magbibigay agad ako ng paglalarawan kung paano ito patakbuhin sa STM32F7-Discovery.

Paano tumakbo

  1. Pag-configure ng Embox
    make confload-platform/pjsip/stm32f7cube
  2. Itakda ang kinakailangang SIP account sa conf/mods.config file.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    saan server ay isang SIP server (halimbawa, sip.linphone.org), username ΠΈ password - username at password ng account.

  3. Pagtitipon ng Embox bilang isang koponan gumawa. Tungkol sa board firmware na mayroon kami wiki at Artikulo.
  4. Patakbuhin ang command na "simple_pjsua_imported" sa Embox console
    
    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. Sa wakas, nananatili itong magpasok ng mga speaker o headphone sa audio output, at magsalita sa dalawang maliliit na mikropono ng MEMS sa tabi ng display. Tumatawag kami mula sa Linux sa pamamagitan ng application na simple_pjsua, pjsua. Well, o maaari kang gumamit ng anumang iba pang uri ng linphone.

Ang lahat ng ito ay inilarawan sa aming wiki.

Paano kami nakarating doon

Kaya, sa una ay lumitaw ang tanong tungkol sa pagpili ng isang platform ng hardware. Dahil malinaw na hindi magkasya ang STM32F4-Discovery mula sa memorya, napili ang STM32F7-Discovery. Mayroon siyang 1 MB flash drive at 256 KB ng RAM (+ 64 espesyal na mabilis na memorya, na gagamitin din namin). Hindi rin marami para sa mga tawag sa pamamagitan ng server, ngunit nagpasya kaming subukang magkasya.

Sa kondisyon para sa kanilang sarili, ang gawain ay nahahati sa maraming yugto:

  • Pagpapatakbo ng PJSIP sa QEMU. Maginhawa ito para sa pag-debug, at mayroon na kaming suporta para sa AC97 codec doon.
  • Pag-record ng boses at pag-playback sa QEMU at sa STM32.
  • Pag-port ng isang application simple_pjsua mula sa PJSIP. Pinapayagan ka nitong magrehistro sa SIP server at tumawag.
  • I-deploy ang iyong sariling server na nakabatay sa Asterisk at subukan ito, pagkatapos ay subukan ang mga panlabas tulad ng sip.linphone.org

Gumagana ang tunog sa Embox sa pamamagitan ng Portaudio, na ginagamit din sa PISIP. Ang mga unang problema ay lumitaw sa QEMU - ang WAV ay naglaro nang maayos sa 44100 Hz, ngunit sa 8000 ay may malinaw na nagkamali. Ito ay naka-out na ito ay isang bagay ng pagtatakda ng dalas - sa pamamagitan ng default ito ay 44100 sa kagamitan, at hindi ito nagbago ng programmatically.

Dito, marahil, ito ay nagkakahalaga ng pagpapaliwanag nang kaunti kung paano nilalaro ang tunog sa pangkalahatan. Ang sound card ay maaaring itakda sa ilang pointer sa isang piraso ng memorya kung saan mo gustong i-play o i-record sa isang paunang natukoy na frequency. Matapos matapos ang buffer, magkakaroon ng interrupt at magpapatuloy ang pagpapatupad sa susunod na buffer. Ang katotohanan ay ang mga buffer na ito ay kailangang punan nang maaga habang nilalaro ang nauna. Haharapin pa natin ang problemang ito sa STM32F7.

Susunod, nagrenta kami ng isang server at nag-deploy ng Asterisk dito. Dahil kailangan itong mag-debug ng marami, ngunit hindi ko gustong magsalita nang husto sa mikropono, kinakailangan na gumawa ng awtomatikong pag-playback at pag-record. Para magawa ito, nag-patch kami ng simple_pjsua para makalusot ka ng mga file sa halip na mga audio device. Sa PJSIP, ito ay ginagawa nang simple, dahil mayroon silang konsepto ng isang port, na maaaring maging isang aparato o isang file. At ang mga port na ito ay maaaring madaling konektado sa iba pang mga port. Maaari mong makita ang code sa aming pjsip mga repositoryo. Bilang resulta, ang scheme ay ang mga sumusunod. Sa server ng Asterisk, nagsimula ako ng dalawang account - para sa Linux at para sa Embox. Susunod, ang utos ay isinasagawa sa Embox simple_pjsua_imported, Ang Embox ay nakarehistro sa server, pagkatapos nito ay tinatawagan namin ang Embox mula sa Linux. Sa sandali ng koneksyon, sinusuri namin sa Asterisk server na ang koneksyon ay naitatag, at pagkaraan ng ilang sandali ay dapat naming marinig ang tunog mula sa Linux sa Embox, at sa Linux ay nai-save namin ang file na nilalaro mula sa Embox.

Matapos itong gumana sa QEMU, lumipat kami sa pag-port sa STM32F7-Discovery. Ang unang problema ay hindi sila magkasya sa 1 MB ng ROM nang walang pinaganang compiler optimization na "-Os" para sa laki ng larawan. Kaya naman isinama namin ang "-Os". Dagdag pa, hindi pinagana ng patch ang suporta para sa C ++, kaya kailangan lang ito para sa pjsua, at gumagamit kami ng simple_pjsua.

Matapos mailagay simple_pjsua, nagpasya na ngayon ay may pagkakataong ilunsad ito. Ngunit kailangan munang harapin ang pag-record at pag-playback ng boses. Ang tanong ay saan magsulat? Pinili namin ang panlabas na memorya - SDRAM (128 MB). Maaari mong subukan ito sa iyong sarili:

Lumilikha ng stereo WAV na may dalas na 16000 Hz at tagal na 10 segundo:


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

Talo tayo:


play -m C0000000

May dalawang problema dito. Ang una na may codec - WM8994 ay ginagamit, at mayroon itong isang bagay bilang isang puwang, at mayroong 4 sa mga puwang na ito. Kaya, bilang default, kung hindi ito na-configure, pagkatapos ay kapag nagpe-play ng audio, ang pag-playback ay nangyayari sa lahat ng apat na mga puwang . Samakatuwid, sa dalas ng 16000 Hz, nakatanggap kami ng 8000 Hz, ngunit para sa 8000 Hz, ang pag-playback ay hindi gumana. Kapag ang mga puwang 0 at 2 lamang ang napili, ito ay gumana ayon sa nararapat. Ang isa pang problema ay ang audio interface sa STM32Cube, kung saan gumagana ang audio output sa pamamagitan ng SAI (Serial Audio Interface) na kasabay ng audio input (hindi ko naiintindihan ang mga detalye, ngunit lumalabas na sila ay nagbabahagi ng isang karaniwang orasan at kapag ang ang audio output ay sinisimulan, ang audio ay kahit papaano ay nakakabit dito sa pasukan). Iyon ay, hindi mo maaaring patakbuhin ang mga ito nang hiwalay, kaya ginawa namin ang sumusunod - ang audio input at audio output ay palaging gumagana (kabilang ang mga pagkagambala ay nabuo). Ngunit kapag walang nilalaro sa system, magdadala lang kami ng walang laman na buffer sa output ng audio, at kapag nagsimula na ang pag-playback, tapat naming sinisimulan itong punan.

Dagdag pa, nalaman namin ang katotohanan na ang tunog habang nagre-record ng boses ay napakatahimik. Ito ay dahil sa katotohanan na ang mga mikropono ng MEMS sa STM32F7-Discovery kahit papaano ay hindi gumagana nang maayos sa mga frequency na mas mababa sa 16000 Hz. Samakatuwid, itinakda namin ang 16000 Hz, kahit na dumating ang 8000 Hz. Upang gawin ito, gayunpaman, ito ay kinakailangan upang magdagdag ng isang software conversion ng isang dalas sa isa pa.

Susunod, kailangan kong dagdagan ang laki ng heap, na matatagpuan sa RAM. Ayon sa aming mga kalkulasyon, ang pjsip ay nangangailangan ng humigit-kumulang 190 KB, at mayroon na lamang kaming mga 100 KB na natitira. Dito kailangan kong gumamit ng ilang panlabas na memorya - SDRAM (mga 128 KB).

Pagkatapos ng lahat ng mga pag-edit na ito, nakita ko ang mga unang pakete sa pagitan ng Linux at Embox, at narinig ko ang tunog! Ngunit ang tunog ay kahila-hilakbot, hindi katulad ng sa QEMU, imposibleng gumawa ng anumang bagay. Pagkatapos ay iniisip namin kung ano ang maaaring mangyari. Ang pag-debug ay nagpakita na ang Embox ay walang oras upang punan / i-unload ang mga buffer ng audio. Habang pinoproseso ng pjsip ang isang frame, nagkaroon ng oras ang 2 interrupt tungkol sa pagkumpleto ng pagpoproseso ng buffer, na sobra-sobra. Ang unang naisip para sa bilis ay ang compiler optimization, ngunit ito ay kasama na sa PJSIP. Ang pangalawa ay isang hardware floating point, napag-usapan namin ito Artikulo. Ngunit tulad ng ipinakita ng kasanayan, ang FPU ay hindi nagbigay ng isang makabuluhang pagtaas sa bilis. Ang susunod na hakbang ay ang unahin ang mga thread. Ang Embox ay may iba't ibang mga diskarte sa pag-iiskedyul, at isinama ko ang isa na sumusuporta sa mga priyoridad at nagtatakda ng mga audio stream sa pinakamataas na priyoridad. Hindi rin ito nakatulong.

Ang susunod na ideya ay na kami ay nagtatrabaho sa panlabas na memorya at ito ay magiging maganda upang ilipat ang mga istraktura doon na napakadalas ma-access. Gumawa ako ng paunang pagsusuri kung kailan at sa ilalim ng ano simple_pjsua naglalaan ng memorya. Lumalabas na sa 190 Kb, ang unang 90 Kb ay inilalaan para sa mga panloob na pangangailangan ng PJSIP at hindi sila naa-access nang madalas. Dagdag pa, sa panahon ng isang papasok na tawag, ang pjsua_call_answer function ay tinatawag, kung saan ang mga buffer ay ilalaan para sa pagtatrabaho sa mga papasok at papalabas na frame. Mga 100 Kb pa rin iyon. At pagkatapos ay ginawa namin ang mga sumusunod. Hanggang sa sandali ng tawag, inilalagay namin ang data sa panlabas na memorya. Sa sandaling tumawag, agad naming pinapalitan ang heap ng isa pa - sa RAM. Kaya, ang lahat ng "mainit" na data ay inilipat sa mas mabilis at mas predictable na memorya.

Bilang isang resulta, ang lahat ng ito nang magkasama ay naging posible upang ilunsad simple_pjsua at tumawag sa pamamagitan ng iyong server. At pagkatapos ay sa pamamagitan ng iba pang mga server tulad ng sip.linphone.org.

Natuklasan

Bilang resulta, posible na ilunsad simple_pjsua na may voice transmission sa parehong direksyon sa pamamagitan ng server. Ang problema sa karagdagang 128 KB ng SDRAM ay malulutas sa pamamagitan ng paggamit ng bahagyang mas malakas na Cortex-M7 (halimbawa, STM32F769NI na may 512 KB ng RAM), ngunit sa parehong oras, hindi pa rin kami nawalan ng pag-asa na makapasok sa 256 KB πŸ™‚ Matutuwa kami kung may interesado, Or better yet, try it. Ang lahat ng mga mapagkukunan, gaya ng dati, ay nasa aming mga repositoryo.

Pinagmulan: www.habr.com

Magdagdag ng komento