Telefón SIP na STM32F7-Discovery

Ahoj všetci

Pred chvíľou sme писали o tom, ako sa nám podarilo spustiť telefón SIP na STM32F4-Discovery s 1 MB ROM a 192 KB RAM) na základe Embox. Tu treba povedať, že táto verzia bola minimálna a spájala dva telefóny priamo bez servera a s prenosom hlasu len jedným smerom. Preto sme sa rozhodli uviesť na trh kompletnejší telefón s hovorom cez server, prenosom hlasu v oboch smeroch, no zároveň zachovať čo najmenšiu veľkosť pamäte.


Pre telefón bolo rozhodnuté zvoliť aplikáciu simple_pjsua ako súčasť knižnice PJSIP. Toto je minimálna aplikácia, ktorá sa môže zaregistrovať na serveri, prijímať a prijímať hovory. Nižšie okamžite uvediem popis, ako ho spustiť na STM32F7-Discovery.

Ako behať

  1. Konfigurácia Emboxu
    make confload-platform/pjsip/stm32f7cube
  2. Nastavte požadovaný SIP účet v súbore conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    kde server je server SIP (napríklad sip.linphone.org), meno и heslo - používateľské meno a heslo účtu.

  3. Zostavenie Emboxu ako tímu činiť. O firmvéri dosky, ktorý máme wiki a článok.
  4. Spustite príkaz „simple_pjsua_imported“ v konzole Embox
    
    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. Nakoniec ostáva vložiť reproduktory alebo slúchadlá do audio výstupu a rozprávať do dvoch malých MEMS mikrofónov vedľa displeja. Z Linuxu voláme cez aplikáciu simple_pjsua, pjsua. Alebo môžete použiť akýkoľvek iný typ linphone.

Toto všetko je popísané na našom wiki.

Ako sme sa tam dostali

Pôvodne teda vyvstala otázka výberu hardvérovej platformy. Keďže bolo jasné, že STM32F4-Discovery sa z pamäte nezmestí, zvolili sme STM32F7-Discovery. Tá má 1 MB flash disk a 256 KB RAM (+ 64 špeciálnej rýchlej pamäte, ktorú využijeme aj my). Tiež nie je veľa hovorov cez server, ale rozhodli sme sa pokúsiť sa zapadnúť.

Podmienečne pre nich bola úloha rozdelená do niekoľkých etáp:

  • Spustenie PJSIP na QEMU. Bolo to pohodlné na ladenie, navyše sme tam už mali podporu pre kodek AC97.
  • Nahrávanie a prehrávanie hlasu na QEMU a STM32.
  • Portovanie aplikácie simple_pjsua z PJSIP. Umožňuje vám zaregistrovať sa na serveri SIP a uskutočňovať hovory.
  • Nasaďte svoj vlastný server založený na Asterisk a otestujte ho, potom vyskúšajte externé servery, napríklad sip.linphone.org

Zvuk v Emboxe funguje cez Portaudio, ktoré sa používa aj v PISIP. Na QEMU sa objavili prvé problémy - WAV hral dobre na 44100 Hz, no pri 8000 sa niečo zjavne pokazilo. Ukázalo sa, že išlo o nastavenie frekvencie – štandardne bola vo výbave 44100 a programovo sa to nezmenilo.

Tu možno stojí za to trochu vysvetliť, ako sa zvuk vo všeobecnosti prehráva. Zvukovú kartu je možné nastaviť na nejaký ukazovateľ na časť pamäte, z ktorej chcete prehrávať alebo nahrávať na vopred určenej frekvencii. Po ukončení vyrovnávacej pamäte sa vygeneruje prerušenie a vykonávanie pokračuje s ďalšou vyrovnávacou pamäťou. Faktom je, že tieto vyrovnávacie pamäte je potrebné naplniť vopred, kým sa prehráva predchádzajúci. S týmto problémom budeme ďalej čeliť na STM32F7.

Ďalej sme si prenajali server a nasadili naň Asterisk. Keďže bolo potrebné veľa ladiť, ale nechcelo sa mi veľmi rozprávať do mikrofónu, bolo potrebné urobiť automatické prehrávanie a nahrávanie. Aby sme to dosiahli, opravili sme simple_pjsua, aby ste mohli namiesto zvukových zariadení podsúvať súbory. V PJSIP sa to robí celkom jednoducho, pretože majú koncept portu, ktorým môže byť zariadenie alebo súbor. A tieto porty je možné flexibilne pripojiť k iným portom. Kód môžete vidieť v našom pjsip úložiská. V dôsledku toho bola schéma nasledovná. Na serveri Asterisk som založil dva účty - pre Linux a pre Embox. Ďalej sa príkaz vykoná na Emboxe simple_pjsua_imported, Embox sa zaregistruje na server, potom zavoláme Embox z Linuxu. V momente pripojenia skontrolujeme na serveri Asterisk, že je spojenie nadviazané a po chvíli by sme mali počuť zvuk z Linuxu v Emboxe a v Linuxe uložíme súbor, ktorý sa prehrá z Emboxu.

Keď to fungovalo na QEMU, prešli sme na portovanie na STM32F7-Discovery. Prvým problémom je, že sa nezmestili do 1 MB ROM bez povolenej optimalizácie kompilátora „-Os“ pre veľkosť obrázka. Preto sme zaradili „-Os“. Okrem toho patch zakázal podporu pre C ++, takže je potrebná iba pre pjsua a používame simple_pjsua.

Po umiestnení simple_pjsua, sa rozhodol, že teraz je tu možnosť ho spustiť. Najprv však bolo potrebné vysporiadať sa s nahrávaním a prehrávaním hlasu. Otázka je, kam písať? Zvolili sme externú pamäť – SDRAM (128 MB). Môžete to vyskúšať sami:

Vytvára stereo WAV s frekvenciou 16000 10 Hz a trvaním XNUMX sekúnd:


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

Prehrali sme:


play -m C0000000

Sú tu dva problémy. Používa sa prvý s kodekom - WM8994 a má niečo ako slot a tieto sloty sú 4. Takže štandardne, ak toto nie je nakonfigurované, pri prehrávaní zvuku sa prehrávanie uskutoční vo všetkých štyroch slotoch . Preto sme pri frekvencii 16000 Hz dostali 8000 Hz, no pri 8000 Hz prehrávanie jednoducho nefungovalo. Keď boli vybrané iba sloty 0 a 2, fungovalo to tak, ako malo. Ďalším problémom bolo audio rozhranie v STM32Cube, v ktorom audio výstup funguje cez SAI (Serial Audio Interface) synchrónne s audio vstupom (nerozumel som detailom, ale ukázalo sa, že zdieľajú spoločné hodiny a keď sa zvukový výstup je inicializovaný, zvuk je nejakým spôsobom pripojený k jeho vstupu). To znamená, že ich nemôžete spustiť samostatne, takže sme urobili nasledovné - zvukový vstup a zvukový výstup vždy fungujú (vrátane generovania prerušení). Ale keď sa v systéme nič neprehráva, tak do audio výstupu jednoducho vsunieme prázdnu vyrovnávaciu pamäť a keď sa spustí prehrávanie, začneme ju poctivo plniť.

Ďalej sme sa stretli s tým, že zvuk pri nahrávaní hlasu bol veľmi tichý. Je to spôsobené tým, že MEMS mikrofóny na STM32F7-Discovery akosi nefungujú dobre pri frekvenciách pod 16000 Hz. Preto nastavíme 16000 Hz, aj keď príde 8000 Hz. K tomu však bolo potrebné pridať softvérovú konverziu jednej frekvencie na druhú.

Ďalej som musel zväčšiť veľkosť haldy, ktorá sa nachádza v RAM. Podľa našich výpočtov si pjsip vyžiadal asi 190 KB a nám zostalo len asi 100 KB. Tu som musel použiť nejakú externú pamäť – SDRAM (asi 128 KB).

Po všetkých týchto úpravách som videl prvé balíčky medzi Linuxom a Emboxom a počul som zvuk! Ale zvuk bol hrozný, vôbec nie taký ako na QEMU, nedalo sa nič rozoznať. Potom sme rozmýšľali, čo by sa mohlo stať. Ladenie ukázalo, že Embox jednoducho nemá čas naplniť / uvoľniť zvukové vyrovnávacie pamäte. Kým pjsip spracovával jeden rámec, 2 prerušenia mali čas na dokončenie spracovania vyrovnávacej pamäte, čo je príliš veľa. Prvou myšlienkou na rýchlosť bola optimalizácia kompilátora, ale to už bolo zahrnuté v PJSIP. Druhým je hardvér s pohyblivou rádovou čiarkou, hovorili sme o ňom článok. Ako však ukázala prax, FPU neprinieslo výrazné zvýšenie rýchlosti. Ďalším krokom bolo uprednostniť vlákna. Embox má rôzne stratégie plánovania a ja som zahrnul jednu, ktorá podporuje priority a nastavuje audio streamy na najvyššiu prioritu. Ani toto nepomohlo.

Ďalšia myšlienka bola, že pracujeme s externou pamäťou a bolo by pekné presunúť tam štruktúry, ku ktorým sa pristupuje extrémne často. Urobil som predbežný rozbor, kedy a za čo simple_pjsua alokuje pamäť. Ukázalo sa, že zo 190 Kb je prvých 90 Kb alokovaných pre interné potreby PJSIP a nie sú príliš často prístupné. Ďalej sa počas prichádzajúceho hovoru volá funkcia pjsua_call_answer, v ktorej sú potom alokované vyrovnávacie pamäte na prácu s prichádzajúcimi a odchádzajúcimi rámcami. Stále to bolo asi 100 Kb. A potom sme urobili nasledovné. Do momentu hovoru ukladáme dáta do externej pamäte. Akonáhle zavoláme, okamžite vymeníme haldu za inú - v RAM. Všetky „horúce“ dáta sa tak preniesli do rýchlejšej a predvídateľnejšej pamäte.

Vo výsledku to všetko dohromady umožnilo spustenie simple_pjsua a zavolajte cez váš server. A potom prostredníctvom iných serverov, ako je sip.linphone.org.

Závery

V dôsledku toho bolo možné spustiť simple_pjsua s prenosom hlasu v oboch smeroch cez server. Problém s dodatočne vynaloženými 128 KB SDRAM možno vyriešiť použitím o niečo výkonnejšieho Cortex-M7 (napríklad STM32F769NI s 512 KB RAM), no zároveň sme sa stále nevzdali nádeje dostať sa do 256 KB 🙂 Budeme radi, ak to niekoho zaujme, alebo ešte lepšie, vyskúšajte. Všetky zdroje, ako obvykle, sú v našom úložiská.

Zdroj: hab.com

Pridať komentár