SIP telefon az STM32F7-Discovery-n

Üdvözlet mindenkinek.

Nemrég mi писали arról, hogyan sikerült elindítani egy SIP telefont STM32F4-Discovery-n 1 MB ROM-mal és 192 KB RAM-mal) Embox. Itt kell elmondani, hogy az a verzió minimális volt, és két telefont kötött közvetlenül szerver nélkül, és csak egy irányban hangátvitellel. Ezért úgy döntöttünk, hogy egy komplettebb telefont indítunk a szerveren keresztüli hívással, mindkét irányban hangátvitellel, ugyanakkor a lehető legkisebb memóriaméreten belül.


A telefonhoz úgy döntöttek, hogy egy alkalmazást választanak egyszerű_pjsua a PJSIP könyvtár részeként. Ez egy minimális alkalmazás, amely képes regisztrálni a szerveren, fogadni és fogadni hívásokat. Az alábbiakban azonnal leírom, hogyan kell futtatni az STM32F7-Discovery-n.

Hogyan kell futni

  1. Az Embox konfigurálása
    make confload-platform/pjsip/stm32f7cube
  2. Állítsa be a szükséges SIP-fiókot a conf/mods.config fájlban.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    ahol szerver egy SIP szerver (például sip.linphone.org), felhasználónév и jelszó - fiók felhasználóneve és jelszava.

  3. Az Embox összeállítása csapatként csinál. Az általunk használt tábla firmware-ről вики és cikk.
  4. Futtassa a „simple_pjsua_imported” parancsot az Embox konzolon
    
    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. Végül marad, hogy hangszórókat vagy fejhallgatót helyezzen be az audiokimenetbe, és beszéljen a kijelző melletti két kis MEMS-mikrofonba. Linuxról a simple_pjsua, pjsua alkalmazáson keresztül hívunk. Nos, vagy használhat bármilyen más típusú telefont.

Mindezt a mi oldalon ismertetjük вики.

Hogyan kerültünk oda

Tehát kezdetben felmerült a kérdés a hardverplatform kiválasztásával kapcsolatban. Mivel egyértelmű volt, hogy az STM32F4-Discovery nem fér el a memóriából, az STM32F7-Discovery-t választottuk. 1 MB-os flash meghajtója és 256 KB RAM-ja van (+ 64 speciális gyorsmemória, amit szintén használni fogunk). Szintén nem sok a szerveren keresztüli hívás, de úgy döntöttünk, hogy megpróbálunk beilleszkedni.

Feltételesen saját maguk számára a feladatot több szakaszra osztották:

  • PJSIP futtatása QEMU-n. Kényelmes volt a hibakeresés, ráadásul ott már támogattuk az AC97 kodeket.
  • Hangrögzítés és lejátszás QEMU-n és STM32-n.
  • Alkalmazás portolása egyszerű_pjsua a PJSIP-től. Lehetővé teszi a SIP szerveren való regisztrációt és hívások kezdeményezését.
  • Telepítse saját Asterisk-alapú szerverét, és tesztelje azt, majd próbáljon ki külső szervereket, például sip.linphone.org

A hang az Emboxban a Portaudion keresztül működik, amelyet a PISIP is használ. Az első problémák a QEMU-n jelentek meg – a WAV jól játszott 44100 Hz-en, de 8000-nél valami egyértelműen elromlott. Kiderült, hogy a frekvencia beállításáról van szó - alapból 44100 volt a berendezésben, és ez programszerűen nem változott.

Itt talán érdemes egy kicsit elmagyarázni, hogyan szólal meg általában a hang. A hangkártya beállítható valamilyen mutatóra, amely egy memóriadarabra mutat, ahonnan előre meghatározott frekvencián szeretne játszani vagy rögzíteni. A puffer vége után megszakítás jön létre, és a végrehajtás a következő pufferrel folytatódik. A helyzet az, hogy ezeket a puffereket előre fel kell tölteni az előző lejátszása közben. Ezzel a problémával a továbbiakban szembesülünk az STM32F7-en.

Ezután béreltünk egy szervert, és telepítettük rajta az Asterisket. Mivel sokat kellett debugolni, de nem nagyon akartam beleszólni a mikrofonba, szükség volt az automatikus lejátszásra és felvételre. Ehhez javítottuk a simple_pjsua fájlt, hogy az audioeszközök helyett fájlokat csúsztathasson. A PJSIP-ben ez egészen egyszerűen megtörténik, mivel rendelkeznek a port fogalmával, amely lehet eszköz vagy fájl. És ezek a portok rugalmasan csatlakoztathatók más portokhoz. A kódot a pjsip-ünkben láthatja adattárak. Ennek eredményeként a séma a következő volt. Az Asterisk szerveren elindítottam két fiókot – Linuxhoz és Emboxhoz. Ezután a parancs végrehajtásra kerül az Emboxon simple_pjsua_imported, Embox regisztrál a szerveren, ami után meghívjuk az Emboxot Linuxról. A csatlakozás pillanatában ellenőrizzük az Asterisk szerveren, hogy létrejött-e a kapcsolat, majd egy idő után az Emboxban hallani kell a Linux hangját, Linuxban pedig elmentjük az Emboxból lejátszott fájlt.

Miután működött a QEMU-n, áttértünk az STM32F7-Discovery-re történő portolásra. Az első probléma az, hogy nem fértek bele 1 MB ROM-ba, ha a kép méretéhez nincs engedélyezve a fordítóoptimalizálás „-Os”. Ezért vettük fel a "-Os"-t. Továbbá a javítás letiltotta a C ++ támogatását, így csak a pjsua-hoz van szükség, mi pedig a simple_pjsua-t használjuk.

Az elhelyezés után egyszerű_pjsua, úgy döntött, hogy most van lehetőség elindítani. De először a hang rögzítésével és lejátszásával kellett foglalkozni. A kérdés az, hogy hova kell írni? Külső memóriát választottunk - SDRAM (128 MB). Ezt magad is kipróbálhatod:

Sztereó WAV-ot hoz létre 16000 Hz-es frekvenciával és 10 másodperc időtartammal:


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

Vesztettünk:


play -m C0000000

Itt két probléma van. Az első kodekkel - WM8994 van használva, és van benne olyan, hogy egy slot, és ebből van 4. Tehát alapértelmezés szerint, ha ez nincs beállítva, akkor hang lejátszásakor a lejátszás mind a négy slotban történik . Ezért 16000 Hz-es frekvencián 8000 Hz-et kaptunk, de 8000 Hz-en a lejátszás egyszerűen nem működött. Amikor csak a 0-s és 2-es helyet választották ki, akkor úgy működött, ahogy kell. További probléma volt az STM32Cube-ban található audio interfész, amelyben a hangkimenet SAI-n (Serial Audio Interface) keresztül működik szinkronban az audio bemenettel (a részleteket nem értettem, de kiderült, hogy közös az óra, és mikor Az audiokimenet inicializálva van, a hang valahogy hozzá van kapcsolva a bejárathoz). Ez azt jelenti, hogy nem lehet őket külön futtatni, ezért a következőket tettük - az audio bemenet és hangkimenet mindig működik (beleértve a megszakításokat is). De ha nem játszik le semmit a rendszerben, egyszerűen csak egy üres puffert csúsztatunk az audiokimenetbe, és amikor a lejátszás elindul, őszintén elkezdjük feltölteni.

Továbbá azt tapasztaltuk, hogy a hangfelvétel közben nagyon halk volt a hang. Ez annak a ténynek köszönhető, hogy az STM32F7-Discovery MEMS mikrofonjai valahogy nem működnek jól 16000 Hz alatti frekvenciákon. Ezért 16000 Hz-et állítunk be, még akkor is, ha 8000 Hz jön. Ehhez azonban szükség volt az egyik frekvencia szoftveres átalakítására a másikra.

Ezután meg kellett növelnem a kupac 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, nekünk pedig már csak körülbelül 100 KB maradt. Itt külső memóriát kellett használnom - SDRAM-ot (kb. 128 KB).

Mindezen szerkesztések után láttam az első csomagokat a Linux és az Embox között, és hallottam a hangot! De a hang szörnyű volt, egyáltalán nem olyan, mint a QEMU-n, nem lehetett kivenni semmit. Aztán azon gondolkodtunk, hogy mi lehet a baj. A hibakeresés azt mutatta, hogy az Emboxnak egyszerűen nincs ideje feltölteni / kiüríteni az audio puffereket. Amíg a pjsip egy keretet dolgozott fel, 2 megszakításnak volt ideje a pufferfeldolgozás befejezésekor, ami túl sok. Az első gondolat a gyorsítás érdekében a fordítóoptimalizálás volt, de ez már benne volt a PJSIP-ben. A második egy hardveres lebegőpontos, erről beszéltünk cikk. A gyakorlat azonban azt mutatja, hogy az FPU nem növelte jelentősen a sebességet. A következő lépés a szálak rangsorolása volt. Az Embox különböző ütemezési stratégiákkal rendelkezik, és beépítettem egyet, amely támogatja a prioritásokat, és a hangfolyamokat a legmagasabb prioritásra állítja. Ez sem segített.

A következő ötlet az volt, hogy külső memóriával dolgozunk, és jó lenne oda mozgatni a rendkívül gyakran elérhető struktúrákat. Előzetes elemzést készítettem, hogy mikor és mi alapján egyszerű_pjsua lefoglalja a memóriát. Kiderült, hogy a 190 Kb-ból az első 90 Kb a PJSIP belső igényeire van lefoglalva, és nem túl gyakran fér hozzá. Továbbá, egy bejövő hívás során a pjsua_call_answer függvény meghívásra kerül, amelyben ezután pufferek vannak lefoglalva a bejövő és kimenő keretekkel való munkavégzéshez. Még mindig 100 Kb körül volt. És akkor a következőket tettük. A hívás pillanatáig az adatokat külső memóriába helyezzük. A hívást követően azonnal cseréljük a kupacot egy másikkal - a RAM-ban. Így az összes „forró” adat gyorsabb és kiszámíthatóbb memóriába került.

Ennek eredményeként mindez együtt lehetővé tette az indulást egyszerű_pjsua és hívja a szerverén keresztül. Aztán más szervereken, például a sip.linphone.org oldalon keresztül.

Álláspontja

Ennek eredményeként sikerült elindítani egyszerű_pjsua hangátvitellel mindkét irányban a szerveren keresztül. A plusz 128 KB SDRAM problémája megoldható egy kicsit erősebb Cortex-M7 használatával (például STM32F769NI 512 KB RAM-mal), ugyanakkor még mindig nem adtuk fel a reményt, hogy bekerüljünk a 256-ba. KB 🙂 Örülünk, ha valakit érdekel, vagy még jobb, próbálja ki. Minden forrás, mint általában, a mi oldalunkon található adattárak.

Forrás: will.com

Hozzászólás