SIP telefon STM32F7-Discovery-n.

Helló mindenkinek.

Néhány idővel ezelőtt írták arról, hogyan sikerült egy SIP telefont indítani STM32F4-Discovery alaplapon, 1 MB ROM-mal és 192 KB RAM-mal, Embox. Meg kell említeni, hogy az a verzió minimális volt, és közvetlenül két telefont kapcsolt össze szerver nélkül, és csak egy irányú hangátvitellel. Ezért úgy döntöttünk, hogy egy teljesértékűbb telefont indítunk, amely azonosítókon keresztül hív, a hangátvitel pedig két irányban történik, de mégis a lehető legkisebb memória méretet szeretnénk elérni.

Videó lejátszása

A telefonhoz az alábbi alkalmazást választottuk: simple_pjsua a PJSIP könyvtár keretében. Ez egy minimális alkalmazás, amely képes a szerveren regisztrálni, hívásokat fogadni és hívni. Az alábbiakban azonnal bemutatom, hogyan lehet ezt elindítani STM32F7-Discovery-n.

Hogyan indítsuk el

  1. Konfiguráljuk az Embox-ot
    make confload-platform/pjsip/stm32f7cube
  2. A conf/mods.config fájlban beállítjuk a szükséges SIP fiókot.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server",
        sip_user="username",
        sip_passwd="password")
    

    ahol server — ez a SIP szerver (például sip.linphone.org), username és password — a felhasználónév és a jelszó, amely a fiókhoz tartozik.

  3. Az Embox-ot a következő parancs segítségével építjük: make. A táblák firmware-jéről van információnk a wiki és a a Spotify döntéshozatali módszertanáról. Egyre több felhasználó preferálja a zenehallgatást mobilon a streaming szolgáltatásban, de a cégnél túlnyomórészt webprogramozók dolgoznak. A Spotify elemezte ezt a helyzetet, és úgy döntött, hogy több mobilfejlesztőt vesz fel, valamint átnevezi a webes szakembereket új irányba:.
  4. Indítsuk el az Embox konzoljában a “simple_pjsua_imported” parancsot.
    
    00:00:12.870    pjsua_acc.c  ....A SIP outbound állapota a 0. fióknál nem aktív
    00:00:12.884    pjsua_acc.c  ....sip:alexk2222@sip.linphone.org: regisztráció sikeres, állapot=200 (Regisztráció siker
    00:00:12.911    pjsua_acc.c  ....Keep-alive időzítő indítva a 0. fióknál, cél: 91.121.209.194:5060, intervallum: 15s
    

  5. Végül csatlakoztatni kell a hangszórókat vagy a fülhallgatót a hangkimenethez, és beszéljek két apró MEMS mikrofonnal a kijelző mellett. Hívunk Linuxról a simple_pjsua, pjsua alkalmazáson keresztül. Vagy bármilyen más hasonlót, mint a linphone.

Mindez le van írva a wiki.

Hogyan jutottunk ide

Tehát először felmerült a kérdés, hogy melyik hardverplatformot válasszuk. Mivel világos volt, hogy az STM32F4-Discovery nem megfelelő memóriája miatt, az STM32F7-Discovery-t választottuk. Ennek 1 MB flash memóriája és 256 KB RAM-ja van (+ 64 KB speciális gyors memória, amit szintén használni fogunk). Ez sem sok a szerveren keresztüli hívásokhoz, de úgy döntöttünk, hogy megpróbálunk elférni.

Feltételesen több szakaszra osztottuk a feladatot:

  • A PJSIP futtatása QEMU-n. Ez kényelmes volt a hibakereséshez, plusz már volt AC97 codec támogatásunk ott.
  • A hang rögzítése és lejátszása QEMU-n és STM32-n.
  • Az alkalmazás portálása simple_pjsua a PJSIP keretében. Ez lehetővé teszi a SIP szerveren való regisztrálást és a hívást.
  • A saját Asterisk alapú szerverünk telepítése és tesztelése rajta, majd külső szerverek, mint a sip.linphone.org kipróbálása.

A hangzás az Embox-ban a Portaudio-n keresztül működik, amelyet a PISIP is használ. A QEMU-nál jelentkeztek az első problémák – a 44100 Hz-es WAV fájlok jól lejátszódtak, de 8000 Hz-en valami nyilvánvalóan nem működött. Kiderült, hogy a probléma a frekvencia beállításában volt – alapértelmezés szerint a hardver 44100 Hz-re volt konfigurálva, és ezt szoftveresen nem változtattuk meg.

Itt talán érdemes egy kicsit tisztázni, hogyan történik valójában a hang lejátszása. A hangkártyának meg lehet adni egy mutatót egy memória területre, ahonnan le kell játszani vagy amelyre rögzíteni kell egy előre beállított frekvencián. Miután a puffer elfogyott, megszakítás keletkezik, és a végrehajtás a következő pufferről folytatódik. A probléma az, hogy ezeket a puffereket előre kell tölteni, míg az előző lejátszás alatt vannak. Ezzel a problémával még találkozunk a STM32F7-nél.

Ezután béreltünk egy szervert, és telepítettük rá az Asterisk-t. Mivel sok mindent kellett debuggolni, és sokat beszélni a mikrofonnál nem akartunk, szükség volt automatikus lejátszásra és rögzítésre. Ehhez a simple_pjsua-t úgy módosítottuk, hogy fájlokat lehessen átkonfigurálni a hangkészülékek helyett. A PJSIP esetében ez viszonylag egyszerűen megoldható, mivel van elvük, hogy a port lehet akár egy eszköz, akár egy fájl. Ezeket a portokat rugalmasan csatlakoztathatjuk más portokhoz. A kódot meg lehet nézni a pjsip-nél. tárhelyen. A végső felállás a következő volt. Az Asterisk szerveren két fiókot hoztam létre – egyet Linux számára és egyet az Embox számára. Ezután az Embox-on a következő parancsot hajtjuk végre: simple_pjsua_imported, az Embox regisztrál a szerveren, majd Linuxról hívunk az Embox-ra. A kapcsolat kezdetén ellenőrizzük az Asterisk szerveren, hogy minden kapcsolat létrejött-e, és egy idő után hallanunk kell az Embox-on a Linuxból érkező hangot, miközben a Linuxon elmentjük azt a fájlt, amely az Embox-ból játszódik.

Miután ez működött a QEMU-n, átálltunk a STM32F7-Discovery-ra való portolásra. Az első probléma az volt, hogy 1 MB ROM-ba nem fért bele a méret miatt a fordító optimalizálásának "-Os" bekapcsolása nélkül. Ezért bekapcsoltuk az "-Os"-t. Továbbá, egy patch-kel letiltottuk a C++ támogatást, mivel arra csak a pjsua-nak van szüksége, míg mi a simple_pjsua-t használjuk.

Miután sikerült elhelyeznünk simple_pjsua, úgy döntöttünk, hogy most már van esély a sikeres indításra. De először meg kellett értenünk a hang rögzítését és lejátszását. A kérdés az volt – hova rögzítsünk? A külső memóriát választottuk – SDRAM (128 MB). Ezt ti is kipróbálhatjátok:

Stereó WAV létrehozása 16000 Hz-es frekvenciával és 10 másodperces hosszal:


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

Lejátszás:


play -m C0000000

Itt két probléma merült fel. Az első a kodekkel - a WM8994-et használják, amelynek van egy fogalmának, amely slotokra vonatkozik, és ezekből négy van. Tehát alapértelmezetten, ha ezt nem állítják be, akkor a playback mind a négy slotban történik. Ezért 16000 Hz-en 8000 Hz-et kaptunk, míg 8000 Hz esetén a lejátszás egyszerűen nem működött. Amikor csak a 0 és 2-es slotokat választottuk ki, akkor úgy működött, ahogy kellett. Egy másik probléma az audio interfész volt az STM32Cube-ben, ahol az audio kimenet az SAI (Sorozat Audio Interfész) révén szinkronban működik az audio bemenettel (nem merültünk el a részletekben, de úgy tűnik, hogy közös óra osztják meg, és amikor az audio kimenet inicializálódik, valahogy az audio bemenethez kapcsolódik). Tehát nem lehet őket külön-külön elindítani, ezért a következőket tettük - mindig működik (beleértve a megszakítások generálását) az audio bemenet és az audio kimenet. De amikor a rendszer nem játszik le semmit, akkor egyszerűen egy üres puffert adunk az audio kimenethez, és amikor a lejátszás elindul, őszintén elkezdjük feltölteni.

Ezután szembesültünk azzal, hogy a hang a hangfelvétel során nagyon halk volt. Ez azért történik, mert a MEMS mikrofonok az STM32F7-Discovery-n valahogy rosszul működnek 16000 Hz alatti frekvenciákon. Tehát 16000 Hz-re állítjuk be, ha még 8000 Hz érkezik is. Ehhez viszont szükség volt egy frekvencia átalakító program hozzáadására.

Ezután meg kellett növelni a halom méretét, amely a RAM-ban található. Számításaink szerint a pjsip körülbelül 190 Kb-ot igényelt, míg nekünk csak körülbelül 100 Kb maradt. Itt egy kis külső memóriát - SDRAM-ot (körülbelül 128 Kb) kellett igénybe venni.

Mindezek után láttam az első csomagokat a Linux és az Embox között, és hallottam a hangot! De a hang borzalmas volt, egyáltalán nem olyan, mint a QEMU-nál, semmit nem lehetett érteni. Akkor arra gondoltunk, mi lehet a probléma. A hibakeresés bemutatta, hogy az Embox egyszerűen nem tudja betölteni/kiszedni az audio puffereket. Amíg a pjsip egy keretet dolgoz fel, addig 2 megszakítás történt a pufferek feldolgozásának befejezéséről, ami túl sok. Az első gondolat a gyorsításra a fordító optimalizálása volt, de ez már be volt kapcsolva a PJSIP-ben. A második - hardveres lebegőpontos, amiről már beszéltünk. a Spotify döntéshozatali módszertanáról. Egyre több felhasználó preferálja a zenehallgatást mobilon a streaming szolgáltatásban, de a cégnél túlnyomórészt webprogramozók dolgoznak. A Spotify elemezte ezt a helyzetet, és úgy döntött, hogy több mobilfejlesztőt vesz fel, valamint átnevezi a webes szakembereket új irányba:. De a gyakorlat azt mutatta, hogy az FPU nem hozott jelentős sebességnövekedést. A következő lépés a szálak prioritásainak beállítása volt. Az Embox-ban különböző ütemezési stratégiák léteznek, és én aktiváltam azt, amelyik támogatja a prioritásokat, és a lehető legmagasabb prioritást adtam az audiós szálaknak. Ez sem segített.

A következő ötlet az volt, hogy külső memóriával dolgozunk, és jó lenne azokat a struktúrákat oda áthelyezni, amelyekhez rendkívül gyakran férünk hozzá. Elvégeztem egy előzetes elemzést arról, hogy mikor és mire simple_pjsua osztják ki a memóriát. Kiderült, hogy a 190 Kb-ból az első 90 Kb-ot a PJSIP belső szükségleteihez használják fel, és ezekhez a hozzáférés nem túl gyakori. Ezután a bejövő hívás során a pjsua_call_answer függvény hívódik meg, amelyben ezután a bejövő és kimenő keretekkel való munkához pufferelve kerülnek az adatok. Ez körülbelül további 100 Kb volt. Ekkor a következő módon jártunk el. A hívás pillanatáig az adatokat a külső memóriában helyezkednek el. Amint ki van választva a hívás, azonnal lecseréljük a kupacot egy másikra — a RAM-ban. Így minden "forró" adat gyorsabb és kiszámíthatóbb memóriába került.

Ennek eredményeként mindez lehetővé tette, hogy elindítsuk simple_pjsua és hívást indítsunk a saját szerverünkön. Aztán pedig más szervereken, például a sip.linphone.org-on keresztül.

Következtetések

A végeredmény egy sikeres elindítás lett simple_pjsua a hang átvitelével mindkét irányban a szerveren keresztül. A pluszban elhasználódott 128 Kb SDRAM problémáját egy kicsit erősebb Cortex-M7 (például STM32F769NI 512 Kb RAM-mal) használatával lehet megoldani, de még mindig nem adtuk fel a lehetőséget, hogy beférjünk a 256 Kb-ba 🙂 Örülnénk, ha valakit érdekelne, és még jobb lenne, ha próbálná is. Az összes forrást, mint mindig, megtalálják a tárhelyen.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster