SIP telefon na STM32F7-Discovery

Pozdravljeni vsi.

Pred časom smo писали o tem, kako nam je uspelo lansirati telefon SIP na STM32F4-Discovery z 1 MB ROM-a in 192 KB RAM-a), ki temelji na Embox. Pri tem je treba povedati, da je bila tista različica minimalna in je povezovala dva telefona neposredno brez strežnika in z govornim prenosom le v eno smer. Zato smo se odločili lansirati popolnejši telefon s klicem prek strežnika, prenosom govora v obe smeri, a hkrati ohraniti čim manjšo velikost pomnilnika.


Za telefon je bilo odločeno izbrati aplikacijo simple_pjsua v sklopu knjižnice PJSIP. To je minimalna aplikacija, ki se lahko registrira na strežniku, sprejema in sprejema klice. Spodaj bom takoj podal opis, kako ga zagnati na STM32F7-Discovery.

Kako teči

  1. Konfiguriranje Emboxa
    make confload-platform/pjsip/stm32f7cube
  2. Nastavite zahtevani račun SIP v datoteki conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    če strežnik je strežnik SIP (na primer sip.linphone.org), uporabniško ime и geslo - uporabniško ime in geslo za račun.

  3. Sestavljanje Emboxa kot ekipa Znamka. O vdelani programski opremi plošče, ki jo imamo wiki in članek.
  4. Zaženite ukaz “simple_pjsua_imported” v konzoli 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. Nazadnje ostane še, da v avdio izhod vstavite zvočnike ali slušalke in govorite v dva majhna mikrofona MEMS poleg zaslona. Iz Linuxa kličemo prek aplikacije simple_pjsua, pjsua. No, ali pa lahko uporabite katero koli drugo vrsto linphone.

Vse to je opisano na našem wiki.

Kako smo prišli tja

Torej, sprva se je pojavilo vprašanje o izbiri strojne platforme. Ker je bilo jasno, da STM32F4-Discovery ne bo ustrezal spominu, je bil izbran STM32F7-Discovery. Ima 1 MB flash disk in 256 KB RAM (+ 64 posebnega hitrega pomnilnika, ki ga bomo tudi uporabljali). Tudi za klice prek strežnika ni veliko, vendar smo se odločili, da se poskusimo prilagoditi.

Pogojno zase je bila naloga razdeljena na več stopenj:

  • Izvajanje PJSIP na QEMU. Bilo je priročno za odpravljanje napak, poleg tega smo tam že imeli podporo za kodek AC97.
  • Snemanje in predvajanje glasu na QEMU in STM32.
  • Prenos aplikacije simple_pjsua iz PJSIP. Omogoča vam registracijo na strežniku SIP in klicanje.
  • Namestite svoj strežnik, ki temelji na Asterisk, in ga preizkusite, nato poskusite z zunanjimi, kot je sip.linphone.org

Zvok v Emboxu deluje prek programa Portaudio, ki se uporablja tudi v programu PISIP. Prve težave so se pojavile na QEMU - WAV je igral dobro pri 44100 Hz, pri 8000 pa je šlo očitno nekaj narobe. Izkazalo se je, da je šlo za nastavitev frekvence - privzeto je bila v opremi 44100 in ta se programsko ni spremenila.

Tukaj je morda vredno malo razložiti, kako se zvok predvaja na splošno. Zvočno kartico lahko nastavite na nek kazalec na del pomnilnika, iz katerega želite predvajati ali snemati na vnaprej določeni frekvenci. Ko se medpomnilnik konča, se ustvari prekinitev in izvajanje se nadaljuje z naslednjim medpomnilnikom. Dejstvo je, da je treba te medpomnilnike napolniti vnaprej, medtem ko se prejšnji predvaja. S to težavo se bomo soočili naprej na STM32F7.

Nato smo najeli strežnik in nanj namestili Asterisk. Ker je bilo treba veliko odpravljati napake, vendar nisem želel veliko govoriti v mikrofon, je bilo potrebno samodejno predvajanje in snemanje. Da bi to naredili, smo popravili simple_pjsua, tako da lahko namesto zvočnih naprav potisnete datoteke. V PJSIP je to narejeno precej preprosto, saj imajo koncept vrat, ki so lahko naprava ali datoteka. In ta vrata je mogoče prilagodljivo povezati z drugimi vrati. Kodo si lahko ogledate v našem pjsipu repozitorije. Posledično je bila shema naslednja. Na strežniku Asterisk sem odprl dva računa - za Linux in za Embox. Nato se ukaz izvede na Emboxu simple_pjsua_imported, Embox je registriran na strežniku, nakar kličemo Embox iz Linuxa. V trenutku povezave preverimo na strežniku Asterisk, ali je povezava vzpostavljena in čez nekaj časa bi morali slišati zvok iz Linuxa v Emboxu, v Linuxu pa shranimo datoteko, ki se predvaja iz Emboxa.

Ko je delovalo na QEMU, smo prešli na prenos na STM32F7-Discovery. Prva težava je, da se niso prilegali v 1 MB ROM-a brez omogočene optimizacije prevajalnika »-Os« za velikost slike. Zato smo vključili "-Os". Poleg tega je popravek onemogočil podporo za C ++, zato je potreben samo za pjsua, mi pa uporabljamo simple_pjsua.

Po postavitvi simple_pjsua, se je odločil, da zdaj obstaja možnost, da ga lansira. A najprej se je bilo treba ukvarjati s snemanjem in predvajanjem glasu. Vprašanje je, kam napisati? Izbrali smo zunanji pomnilnik - SDRAM (128 MB). To lahko poskusite sami:

Ustvari stereo WAV s frekvenco 16000 Hz in trajanjem 10 sekund:


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

Izgubljamo:


play -m C0000000

Tukaj sta dve težavi. Uporablja se prvi s kodekom - WM8994, ki ima nekaj takega kot reža, in teh rež je 4. Torej, privzeto, če to ni konfigurirano, se pri predvajanju zvoka predvaja v vseh štirih režah . Zato smo pri frekvenci 16000 Hz prejeli 8000 Hz, pri 8000 Hz pa predvajanje preprosto ni delovalo. Ko sta bili izbrani le reži 0 in 2, je delovalo, kot bi moralo. Druga težava je bil zvočni vmesnik v STM32Cube, v katerem zvočni izhod deluje prek SAI (Serial Audio Interface) sinhrono z zvočnim vhodom (nisem razumel podrobnosti, vendar se je izkazalo, da imata skupno uro in ko zvočni izhod je inicializiran, zvok je nekako pritrjen na njegov vhod). To pomeni, da jih ne morete zagnati ločeno, zato smo naredili naslednje - zvočni vhod in zvočni izhod vedno delujeta (vključno s prekinitvami). Ko pa se v sistemu nič ne predvaja, takrat preprosto vtaknemo prazen medpomnilnik v avdio izhod, in ko se predvajanje začne, ga pošteno začnemo polniti.

Nadalje smo naleteli na dejstvo, da je bil zvok med snemanjem glasu zelo tih. To je posledica dejstva, da mikrofoni MEMS na STM32F7-Discovery nekako ne delujejo dobro pri frekvencah pod 16000 Hz. Zato nastavimo 16000 Hz, tudi če pride 8000 Hz. Za to pa je bilo treba dodati programsko pretvorbo ene frekvence v drugo.

Nato sem moral povečati velikost kopice, ki se nahaja v RAM-u. Po naših izračunih je pjsip zahteval okoli 190 KB, ostalo pa nam je le še okoli 100 KB. Tukaj sem moral uporabiti nekaj zunanjega pomnilnika - SDRAM (približno 128 KB).

Po vseh teh urejanjih sem videl prve pakete med Linuxom in Emboxom in slišal sem zvok! Toda zvok je bil grozen, sploh ne enak kot na QEMU, ni bilo mogoče ničesar razbrati. Potem smo razmišljali, kaj bi lahko bilo narobe. Odpravljanje napak je pokazalo, da Embox preprosto nima časa za polnjenje / razkladanje zvočnih medpomnilnikov. Medtem ko je pjsip obdeloval en okvir, sta se imeli čas zgoditi 2 prekinitvi o zaključku obdelave medpomnilnika, kar je preveč. Prva misel na hitrost je bila optimizacija prevajalnika, vendar je bila vključena že v PJSIP. Druga je strojna plavajoča vejica, o njej smo govorili v članek. Toda kot je pokazala praksa, FPU ni dal bistvenega povečanja hitrosti. Naslednji korak je bil določiti prednost niti. Embox ima različne strategije razporejanja in vključil sem tisto, ki podpira prioritete in nastavi zvočne tokove na najvišjo prednost. Tudi to ni pomagalo.

Naslednja ideja je bila, da delamo z zunanjim pomnilnikom in bi bilo lepo tja premakniti strukture, do katerih dostopamo izjemno pogosto. Naredil sem predhodno analizo, kdaj in pod čim simple_pjsua dodeljuje pomnilnik. Izkazalo se je, da je od 190 Kb prvih 90 Kb namenjenih internim potrebam PJSIP in se do njih ne dostopa prav pogosto. Nadalje se med dohodnim klicem pokliče funkcija pjsua_call_answer, v kateri se nato dodelijo medpomnilniki za delo z dohodnimi in odhodnimi okvirji. Bilo je še približno 100 Kb. In potem smo naredili naslednje. Podatke do trenutka klica hranimo v zunanjem pomnilniku. Takoj po klicu kup takoj zamenjamo z drugim - v RAM-u. Tako so se vsi »vroči« podatki prenesli v hitrejši in bolj predvidljiv pomnilnik.

Posledično je vse to skupaj omogočilo izstrelitev simple_pjsua in pokličite prek vašega strežnika. In nato prek drugih strežnikov, kot je sip.linphone.org.

Ugotovitve

Posledično je bilo mogoče zagnati simple_pjsua z govornim prenosom v obe smeri preko strežnika. Težavo z dodatno porabljenimi 128 KB SDRAM-a lahko rešimo z uporabo nekoliko zmogljivejšega Cortex-M7 (na primer STM32F769NI s 512 KB RAM-a), a hkrati še vedno nismo opustili upanja, da bi prišli v 256 KB 🙂 Veseli bomo, če koga zanima, ali še bolje, poskusite. Vsi viri so kot običajno v našem repozitorije.

Vir: www.habr.com

Dodaj komentar